blob: 26ee3c92f56da6080850ddc3c59fcc1b53384a60 [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,
Jean-François Moine4c632e42012-03-19 04:35:34 -030082 QUALITY,
Jean-François Moinec5224d82012-03-19 04:30:07 -030083 NCTRLS /* number of controls */
84};
85
Brian Johnson26e744b2009-07-19 05:52:58 -030086/* specific webcam descriptor */
87struct sd {
88 struct gspca_dev gspca_dev;
89
Jean-François Moinec5224d82012-03-19 04:30:07 -030090 struct gspca_ctrl ctrls[NCTRLS];
91
Jean-François Moine4c632e42012-03-19 04:35:34 -030092 u8 fmt; /* (used for JPEG QTAB update */
93
Brian Johnson26e744b2009-07-19 05:52:58 -030094#define MIN_AVG_LUM 80
95#define MAX_AVG_LUM 130
96 atomic_t avg_lum;
97 u8 old_step;
98 u8 older_step;
99 u8 exposure_step;
100
Brian Johnson26e744b2009-07-19 05:52:58 -0300101 u8 i2c_addr;
102 u8 sensor;
103 u8 hstart;
104 u8 vstart;
105
Jean-François Moine9a731a32010-06-04 05:26:42 -0300106 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300107
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300108 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300109};
110
Joe Perches58aa68c2009-09-02 01:12:13 -0300111struct i2c_reg_u8 {
112 u8 reg;
113 u8 val;
114};
115
116struct i2c_reg_u16 {
117 u8 reg;
118 u16 val;
119};
120
Brian Johnson7ddaac72010-03-16 13:58:27 -0300121static const struct dmi_system_id flip_dmi_table[] = {
122 {
123 .ident = "MSI MS-1034",
124 .matches = {
125 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
126 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
127 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
128 }
129 },
130 {
131 .ident = "MSI MS-1632",
132 .matches = {
133 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
134 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
135 }
136 },
Brian Johnsone077f862010-04-05 20:52:52 -0300137 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300138 .ident = "MSI MS-1633X",
139 .matches = {
140 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
141 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
142 }
143 },
144 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300145 .ident = "MSI MS-1635X",
146 .matches = {
147 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
148 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
149 }
150 },
151 {
Brian Johnsone077f862010-04-05 20:52:52 -0300152 .ident = "ASUSTeK W7J",
153 .matches = {
154 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
155 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
156 }
157 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300158 {}
159};
160
Jean-François Moinec5224d82012-03-19 04:30:07 -0300161static void set_cmatrix(struct gspca_dev *gspca_dev);
162static void set_gamma(struct gspca_dev *gspca_dev);
163static void set_redblue(struct gspca_dev *gspca_dev);
164static void set_hvflip(struct gspca_dev *gspca_dev);
165static void set_exposure(struct gspca_dev *gspca_dev);
166static void set_gain(struct gspca_dev *gspca_dev);
Jean-François Moine4c632e42012-03-19 04:35:34 -0300167static void set_quality(struct gspca_dev *gspca_dev);
Jean-François Moinec5224d82012-03-19 04:30:07 -0300168
169static const struct ctrl sd_ctrls[NCTRLS] = {
170[BRIGHTNESS] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300171 {
172 .id = V4L2_CID_BRIGHTNESS,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "Brightness",
175 .minimum = 0,
176 .maximum = 0xff,
177 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300178 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300179 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300180 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300181 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300182[CONTRAST] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300183 {
184 .id = V4L2_CID_CONTRAST,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "Contrast",
187 .minimum = 0,
188 .maximum = 0xff,
189 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300190 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300191 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300192 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300193 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300194[SATURATION] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300195 {
196 .id = V4L2_CID_SATURATION,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "Saturation",
199 .minimum = 0,
200 .maximum = 0xff,
201 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300202 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300203 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300204 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300205 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300206[HUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300207 {
208 .id = V4L2_CID_HUE,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "Hue",
211 .minimum = -180,
212 .maximum = 180,
213 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300214 .default_value = 0
Brian Johnson26e744b2009-07-19 05:52:58 -0300215 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300216 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300217 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300218[GAMMA] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300219 {
220 .id = V4L2_CID_GAMMA,
221 .type = V4L2_CTRL_TYPE_INTEGER,
222 .name = "Gamma",
223 .minimum = 0,
224 .maximum = 0xff,
225 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300226 .default_value = 0x10
Brian Johnson26e744b2009-07-19 05:52:58 -0300227 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300228 .set_control = set_gamma
Brian Johnson26e744b2009-07-19 05:52:58 -0300229 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300230[BLUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300231 {
232 .id = V4L2_CID_BLUE_BALANCE,
233 .type = V4L2_CTRL_TYPE_INTEGER,
234 .name = "Blue Balance",
235 .minimum = 0,
236 .maximum = 0x7f,
237 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300238 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300239 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300240 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300241 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300242[RED] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300243 {
244 .id = V4L2_CID_RED_BALANCE,
245 .type = V4L2_CTRL_TYPE_INTEGER,
246 .name = "Red Balance",
247 .minimum = 0,
248 .maximum = 0x7f,
249 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300250 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300251 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300252 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300253 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300254[HFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300255 {
256 .id = V4L2_CID_HFLIP,
257 .type = V4L2_CTRL_TYPE_BOOLEAN,
258 .name = "Horizontal Flip",
259 .minimum = 0,
260 .maximum = 1,
261 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300262 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300263 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300264 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300265 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300266[VFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300267 {
268 .id = V4L2_CID_VFLIP,
269 .type = V4L2_CTRL_TYPE_BOOLEAN,
270 .name = "Vertical Flip",
271 .minimum = 0,
272 .maximum = 1,
273 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300274 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300275 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300276 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300277 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300278[EXPOSURE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300279 {
280 .id = V4L2_CID_EXPOSURE,
281 .type = V4L2_CTRL_TYPE_INTEGER,
282 .name = "Exposure",
283 .minimum = 0,
284 .maximum = 0x1780,
285 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300286 .default_value = 0x33,
Brian Johnson26e744b2009-07-19 05:52:58 -0300287 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300288 .set_control = set_exposure
Brian Johnson26e744b2009-07-19 05:52:58 -0300289 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300290[GAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300291 {
292 .id = V4L2_CID_GAIN,
293 .type = V4L2_CTRL_TYPE_INTEGER,
294 .name = "Gain",
295 .minimum = 0,
296 .maximum = 28,
297 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300298 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300299 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300300 .set_control = set_gain
Brian Johnson26e744b2009-07-19 05:52:58 -0300301 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300302[AUTOGAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300303 {
304 .id = V4L2_CID_AUTOGAIN,
305 .type = V4L2_CTRL_TYPE_BOOLEAN,
306 .name = "Auto Exposure",
307 .minimum = 0,
308 .maximum = 1,
309 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300310 .default_value = 1,
Brian Johnson26e744b2009-07-19 05:52:58 -0300311 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300312 },
Jean-François Moine4c632e42012-03-19 04:35:34 -0300313[QUALITY] = {
314 {
315 .id = V4L2_CID_JPEG_COMPRESSION_QUALITY,
316 .type = V4L2_CTRL_TYPE_INTEGER,
317 .name = "Compression Quality",
318#define QUALITY_MIN 50
319#define QUALITY_MAX 90
320#define QUALITY_DEF 80
321 .minimum = QUALITY_MIN,
322 .maximum = QUALITY_MAX,
323 .step = 1,
324 .default_value = QUALITY_DEF,
325 },
326 .set_control = set_quality
327 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300328};
329
330static const struct v4l2_pix_format vga_mode[] = {
331 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300332 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300333 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300334 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300335 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300336 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
337 .bytesperline = 160,
338 .sizeimage = 160 * 120,
339 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300340 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300341 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300342 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300343 .sizeimage = 240 * 120,
344 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300345 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300346 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300347 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300348 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300349 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300350 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300351 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
352 .bytesperline = 320,
353 .sizeimage = 320 * 240 ,
354 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300355 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300356 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300357 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300358 .sizeimage = 480 * 240 ,
359 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300360 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300361 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300362 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300363 .sizeimage = 640 * 480 * 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_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300366 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
367 .bytesperline = 640,
368 .sizeimage = 640 * 480,
369 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300370 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300371 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300372 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300373 .sizeimage = 960 * 480,
374 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300375 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300376};
377
378static const struct v4l2_pix_format sxga_mode[] = {
379 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300380 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300381 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300382 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300383 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300384 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
385 .bytesperline = 160,
386 .sizeimage = 160 * 120,
387 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300388 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300389 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300390 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300391 .sizeimage = 240 * 120,
392 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300393 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300394 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300395 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300396 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300397 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300398 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300399 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
400 .bytesperline = 320,
401 .sizeimage = 320 * 240 ,
402 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300403 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300404 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300405 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 .sizeimage = 480 * 240 ,
407 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300408 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300409 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300410 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300411 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300412 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300413 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300414 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
415 .bytesperline = 640,
416 .sizeimage = 640 * 480,
417 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300418 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300419 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300420 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300421 .sizeimage = 960 * 480,
422 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300423 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300424 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
425 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300426 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300427 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300428 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300429};
430
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300431static const struct v4l2_pix_format mono_mode[] = {
432 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
433 .bytesperline = 160,
434 .sizeimage = 160 * 120,
435 .colorspace = V4L2_COLORSPACE_SRGB,
436 .priv = SCALE_160x120 | MODE_RAW},
437 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
438 .bytesperline = 320,
439 .sizeimage = 320 * 240 ,
440 .colorspace = V4L2_COLORSPACE_SRGB,
441 .priv = SCALE_320x240 | MODE_RAW},
442 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
443 .bytesperline = 640,
444 .sizeimage = 640 * 480,
445 .colorspace = V4L2_COLORSPACE_SRGB,
446 .priv = SCALE_640x480 | MODE_RAW},
447 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
448 .bytesperline = 1280,
449 .sizeimage = 1280 * 1024,
450 .colorspace = V4L2_COLORSPACE_SRGB,
451 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
452};
453
Joe Perches58aa68c2009-09-02 01:12:13 -0300454static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300455 41, 44, 46, 48, 50, 52, 54, 56,
456 58, 60, 62, 64, 66, 68, 70, 72,
457 74, 76, 78, 80, 81, 83, 85, 87,
458 88, 90, 92, 93, 95, 97, 98, 100,
459 101, 102, 104, 105, 107, 108, 109, 110,
460 112, 113, 114, 115, 116, 117, 118, 119,
461 120, 121, 122, 123, 123, 124, 125, 125,
462 126, 127, 127, 128, 128, 129, 129, 129,
463 130, 130, 130, 130, 131, 131, 131, 131,
464 131, 131, 131, 131, 130, 130, 130, 130,
465 129, 129, 129, 128, 128, 127, 127, 126,
466 125, 125, 124, 123, 122, 122, 121, 120,
467 119, 118, 117, 116, 115, 114, 112, 111,
468 110, 109, 107, 106, 105, 103, 102, 101,
469 99, 98, 96, 94, 93, 91, 90, 88,
470 86, 84, 83, 81, 79, 77, 75, 74,
471 72, 70, 68, 66, 64, 62, 60, 58,
472 56, 54, 52, 49, 47, 45, 43, 41,
473 39, 36, 34, 32, 30, 28, 25, 23,
474 21, 19, 16, 14, 12, 9, 7, 5,
475 3, 0, -1, -3, -6, -8, -10, -12,
476 -15, -17, -19, -22, -24, -26, -28, -30,
477 -33, -35, -37, -39, -41, -44, -46, -48,
478 -50, -52, -54, -56, -58, -60, -62, -64,
479 -66, -68, -70, -72, -74, -76, -78, -80,
480 -81, -83, -85, -87, -88, -90, -92, -93,
481 -95, -97, -98, -100, -101, -102, -104, -105,
482 -107, -108, -109, -110, -112, -113, -114, -115,
483 -116, -117, -118, -119, -120, -121, -122, -123,
484 -123, -124, -125, -125, -126, -127, -127, -128,
485 -128, -128, -128, -128, -128, -128, -128, -128,
486 -128, -128, -128, -128, -128, -128, -128, -128,
487 -128, -128, -128, -128, -128, -128, -128, -128,
488 -128, -127, -127, -126, -125, -125, -124, -123,
489 -122, -122, -121, -120, -119, -118, -117, -116,
490 -115, -114, -112, -111, -110, -109, -107, -106,
491 -105, -103, -102, -101, -99, -98, -96, -94,
492 -93, -91, -90, -88, -86, -84, -83, -81,
493 -79, -77, -75, -74, -72, -70, -68, -66,
494 -64, -62, -60, -58, -56, -54, -52, -49,
495 -47, -45, -43, -41, -39, -36, -34, -32,
496 -30, -28, -25, -23, -21, -19, -16, -14,
497 -12, -9, -7, -5, -3, 0, 1, 3,
498 6, 8, 10, 12, 15, 17, 19, 22,
499 24, 26, 28, 30, 33, 35, 37, 39, 41
500};
501
Joe Perches58aa68c2009-09-02 01:12:13 -0300502static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300503 82, 80, 78, 76, 74, 73, 71, 69,
504 67, 65, 63, 61, 58, 56, 54, 52,
505 50, 48, 46, 44, 41, 39, 37, 35,
506 32, 30, 28, 26, 23, 21, 19, 16,
507 14, 12, 10, 7, 5, 3, 0, -1,
508 -3, -6, -8, -10, -13, -15, -17, -19,
509 -22, -24, -26, -29, -31, -33, -35, -38,
510 -40, -42, -44, -46, -48, -51, -53, -55,
511 -57, -59, -61, -63, -65, -67, -69, -71,
512 -73, -75, -77, -79, -81, -82, -84, -86,
513 -88, -89, -91, -93, -94, -96, -98, -99,
514 -101, -102, -104, -105, -106, -108, -109, -110,
515 -112, -113, -114, -115, -116, -117, -119, -120,
516 -120, -121, -122, -123, -124, -125, -126, -126,
517 -127, -128, -128, -128, -128, -128, -128, -128,
518 -128, -128, -128, -128, -128, -128, -128, -128,
519 -128, -128, -128, -128, -128, -128, -128, -128,
520 -128, -128, -128, -128, -128, -128, -128, -128,
521 -127, -127, -126, -125, -125, -124, -123, -122,
522 -121, -120, -119, -118, -117, -116, -115, -114,
523 -113, -111, -110, -109, -107, -106, -105, -103,
524 -102, -100, -99, -97, -96, -94, -92, -91,
525 -89, -87, -85, -84, -82, -80, -78, -76,
526 -74, -73, -71, -69, -67, -65, -63, -61,
527 -58, -56, -54, -52, -50, -48, -46, -44,
528 -41, -39, -37, -35, -32, -30, -28, -26,
529 -23, -21, -19, -16, -14, -12, -10, -7,
530 -5, -3, 0, 1, 3, 6, 8, 10,
531 13, 15, 17, 19, 22, 24, 26, 29,
532 31, 33, 35, 38, 40, 42, 44, 46,
533 48, 51, 53, 55, 57, 59, 61, 63,
534 65, 67, 69, 71, 73, 75, 77, 79,
535 81, 82, 84, 86, 88, 89, 91, 93,
536 94, 96, 98, 99, 101, 102, 104, 105,
537 106, 108, 109, 110, 112, 113, 114, 115,
538 116, 117, 119, 120, 120, 121, 122, 123,
539 124, 125, 126, 126, 127, 128, 128, 129,
540 129, 130, 130, 131, 131, 131, 131, 132,
541 132, 132, 132, 132, 132, 132, 132, 132,
542 132, 132, 132, 131, 131, 131, 130, 130,
543 130, 129, 129, 128, 127, 127, 126, 125,
544 125, 124, 123, 122, 121, 120, 119, 118,
545 117, 116, 115, 114, 113, 111, 110, 109,
546 107, 106, 105, 103, 102, 100, 99, 97,
547 96, 94, 92, 91, 89, 87, 85, 84, 82
548};
549
Joe Perches58aa68c2009-09-02 01:12:13 -0300550static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300551 -124, -124, -125, -125, -125, -125, -125, -125,
552 -125, -126, -126, -125, -125, -125, -125, -125,
553 -125, -124, -124, -124, -123, -123, -122, -122,
554 -121, -121, -120, -120, -119, -118, -117, -117,
555 -116, -115, -114, -113, -112, -111, -110, -109,
556 -108, -107, -105, -104, -103, -102, -100, -99,
557 -98, -96, -95, -93, -92, -91, -89, -87,
558 -86, -84, -83, -81, -79, -77, -76, -74,
559 -72, -70, -69, -67, -65, -63, -61, -59,
560 -57, -55, -53, -51, -49, -47, -45, -43,
561 -41, -39, -37, -35, -33, -30, -28, -26,
562 -24, -22, -20, -18, -15, -13, -11, -9,
563 -7, -4, -2, 0, 1, 3, 6, 8,
564 10, 12, 14, 17, 19, 21, 23, 25,
565 27, 29, 32, 34, 36, 38, 40, 42,
566 44, 46, 48, 50, 52, 54, 56, 58,
567 60, 62, 64, 66, 68, 70, 71, 73,
568 75, 77, 78, 80, 82, 83, 85, 87,
569 88, 90, 91, 93, 94, 96, 97, 98,
570 100, 101, 102, 104, 105, 106, 107, 108,
571 109, 111, 112, 113, 113, 114, 115, 116,
572 117, 118, 118, 119, 120, 120, 121, 122,
573 122, 123, 123, 124, 124, 124, 125, 125,
574 125, 125, 125, 125, 125, 126, 126, 125,
575 125, 125, 125, 125, 125, 124, 124, 124,
576 123, 123, 122, 122, 121, 121, 120, 120,
577 119, 118, 117, 117, 116, 115, 114, 113,
578 112, 111, 110, 109, 108, 107, 105, 104,
579 103, 102, 100, 99, 98, 96, 95, 93,
580 92, 91, 89, 87, 86, 84, 83, 81,
581 79, 77, 76, 74, 72, 70, 69, 67,
582 65, 63, 61, 59, 57, 55, 53, 51,
583 49, 47, 45, 43, 41, 39, 37, 35,
584 33, 30, 28, 26, 24, 22, 20, 18,
585 15, 13, 11, 9, 7, 4, 2, 0,
586 -1, -3, -6, -8, -10, -12, -14, -17,
587 -19, -21, -23, -25, -27, -29, -32, -34,
588 -36, -38, -40, -42, -44, -46, -48, -50,
589 -52, -54, -56, -58, -60, -62, -64, -66,
590 -68, -70, -71, -73, -75, -77, -78, -80,
591 -82, -83, -85, -87, -88, -90, -91, -93,
592 -94, -96, -97, -98, -100, -101, -102, -104,
593 -105, -106, -107, -108, -109, -111, -112, -113,
594 -113, -114, -115, -116, -117, -118, -118, -119,
595 -120, -120, -121, -122, -122, -123, -123, -124, -124
596};
597
Joe Perches58aa68c2009-09-02 01:12:13 -0300598static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300599 -100, -99, -98, -97, -95, -94, -93, -91,
600 -90, -89, -87, -86, -84, -83, -81, -80,
601 -78, -76, -75, -73, -71, -70, -68, -66,
602 -64, -63, -61, -59, -57, -55, -53, -51,
603 -49, -48, -46, -44, -42, -40, -38, -36,
604 -34, -32, -30, -27, -25, -23, -21, -19,
605 -17, -15, -13, -11, -9, -7, -4, -2,
606 0, 1, 3, 5, 7, 9, 11, 14,
607 16, 18, 20, 22, 24, 26, 28, 30,
608 32, 34, 36, 38, 40, 42, 44, 46,
609 48, 50, 52, 54, 56, 58, 59, 61,
610 63, 65, 67, 68, 70, 72, 74, 75,
611 77, 78, 80, 82, 83, 85, 86, 88,
612 89, 90, 92, 93, 95, 96, 97, 98,
613 100, 101, 102, 103, 104, 105, 106, 107,
614 108, 109, 110, 111, 112, 112, 113, 114,
615 115, 115, 116, 116, 117, 117, 118, 118,
616 119, 119, 119, 120, 120, 120, 120, 120,
617 121, 121, 121, 121, 121, 121, 120, 120,
618 120, 120, 120, 119, 119, 119, 118, 118,
619 117, 117, 116, 116, 115, 114, 114, 113,
620 112, 111, 111, 110, 109, 108, 107, 106,
621 105, 104, 103, 102, 100, 99, 98, 97,
622 95, 94, 93, 91, 90, 89, 87, 86,
623 84, 83, 81, 80, 78, 76, 75, 73,
624 71, 70, 68, 66, 64, 63, 61, 59,
625 57, 55, 53, 51, 49, 48, 46, 44,
626 42, 40, 38, 36, 34, 32, 30, 27,
627 25, 23, 21, 19, 17, 15, 13, 11,
628 9, 7, 4, 2, 0, -1, -3, -5,
629 -7, -9, -11, -14, -16, -18, -20, -22,
630 -24, -26, -28, -30, -32, -34, -36, -38,
631 -40, -42, -44, -46, -48, -50, -52, -54,
632 -56, -58, -59, -61, -63, -65, -67, -68,
633 -70, -72, -74, -75, -77, -78, -80, -82,
634 -83, -85, -86, -88, -89, -90, -92, -93,
635 -95, -96, -97, -98, -100, -101, -102, -103,
636 -104, -105, -106, -107, -108, -109, -110, -111,
637 -112, -112, -113, -114, -115, -115, -116, -116,
638 -117, -117, -118, -118, -119, -119, -119, -120,
639 -120, -120, -120, -120, -121, -121, -121, -121,
640 -121, -121, -120, -120, -120, -120, -120, -119,
641 -119, -119, -118, -118, -117, -117, -116, -116,
642 -115, -114, -114, -113, -112, -111, -111, -110,
643 -109, -108, -107, -106, -105, -104, -103, -102, -100
644};
645
Joe Perches58aa68c2009-09-02 01:12:13 -0300646static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300647 112, 113, 114, 114, 115, 116, 117, 117,
648 118, 118, 119, 119, 120, 120, 120, 121,
649 121, 121, 122, 122, 122, 122, 122, 122,
650 122, 122, 122, 122, 122, 122, 121, 121,
651 121, 120, 120, 120, 119, 119, 118, 118,
652 117, 116, 116, 115, 114, 113, 113, 112,
653 111, 110, 109, 108, 107, 106, 105, 104,
654 103, 102, 100, 99, 98, 97, 95, 94,
655 93, 91, 90, 88, 87, 85, 84, 82,
656 80, 79, 77, 76, 74, 72, 70, 69,
657 67, 65, 63, 61, 60, 58, 56, 54,
658 52, 50, 48, 46, 44, 42, 40, 38,
659 36, 34, 32, 30, 28, 26, 24, 22,
660 19, 17, 15, 13, 11, 9, 7, 5,
661 2, 0, -1, -3, -5, -7, -9, -12,
662 -14, -16, -18, -20, -22, -24, -26, -28,
663 -31, -33, -35, -37, -39, -41, -43, -45,
664 -47, -49, -51, -53, -54, -56, -58, -60,
665 -62, -64, -66, -67, -69, -71, -73, -74,
666 -76, -78, -79, -81, -83, -84, -86, -87,
667 -89, -90, -92, -93, -94, -96, -97, -98,
668 -99, -101, -102, -103, -104, -105, -106, -107,
669 -108, -109, -110, -111, -112, -113, -114, -114,
670 -115, -116, -117, -117, -118, -118, -119, -119,
671 -120, -120, -120, -121, -121, -121, -122, -122,
672 -122, -122, -122, -122, -122, -122, -122, -122,
673 -122, -122, -121, -121, -121, -120, -120, -120,
674 -119, -119, -118, -118, -117, -116, -116, -115,
675 -114, -113, -113, -112, -111, -110, -109, -108,
676 -107, -106, -105, -104, -103, -102, -100, -99,
677 -98, -97, -95, -94, -93, -91, -90, -88,
678 -87, -85, -84, -82, -80, -79, -77, -76,
679 -74, -72, -70, -69, -67, -65, -63, -61,
680 -60, -58, -56, -54, -52, -50, -48, -46,
681 -44, -42, -40, -38, -36, -34, -32, -30,
682 -28, -26, -24, -22, -19, -17, -15, -13,
683 -11, -9, -7, -5, -2, 0, 1, 3,
684 5, 7, 9, 12, 14, 16, 18, 20,
685 22, 24, 26, 28, 31, 33, 35, 37,
686 39, 41, 43, 45, 47, 49, 51, 53,
687 54, 56, 58, 60, 62, 64, 66, 67,
688 69, 71, 73, 74, 76, 78, 79, 81,
689 83, 84, 86, 87, 89, 90, 92, 93,
690 94, 96, 97, 98, 99, 101, 102, 103,
691 104, 105, 106, 107, 108, 109, 110, 111, 112
692};
693
Joe Perches58aa68c2009-09-02 01:12:13 -0300694static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300695 -11, -13, -15, -17, -19, -21, -23, -25,
696 -27, -29, -31, -33, -35, -37, -39, -41,
697 -43, -45, -46, -48, -50, -52, -54, -55,
698 -57, -59, -61, -62, -64, -66, -67, -69,
699 -71, -72, -74, -75, -77, -78, -80, -81,
700 -83, -84, -86, -87, -88, -90, -91, -92,
701 -93, -95, -96, -97, -98, -99, -100, -101,
702 -102, -103, -104, -105, -106, -106, -107, -108,
703 -109, -109, -110, -111, -111, -112, -112, -113,
704 -113, -114, -114, -114, -115, -115, -115, -115,
705 -116, -116, -116, -116, -116, -116, -116, -116,
706 -116, -115, -115, -115, -115, -114, -114, -114,
707 -113, -113, -112, -112, -111, -111, -110, -110,
708 -109, -108, -108, -107, -106, -105, -104, -103,
709 -102, -101, -100, -99, -98, -97, -96, -95,
710 -94, -93, -91, -90, -89, -88, -86, -85,
711 -84, -82, -81, -79, -78, -76, -75, -73,
712 -71, -70, -68, -67, -65, -63, -62, -60,
713 -58, -56, -55, -53, -51, -49, -47, -45,
714 -44, -42, -40, -38, -36, -34, -32, -30,
715 -28, -26, -24, -22, -20, -18, -16, -14,
716 -12, -10, -8, -6, -4, -2, 0, 1,
717 3, 5, 7, 9, 11, 13, 15, 17,
718 19, 21, 23, 25, 27, 29, 31, 33,
719 35, 37, 39, 41, 43, 45, 46, 48,
720 50, 52, 54, 55, 57, 59, 61, 62,
721 64, 66, 67, 69, 71, 72, 74, 75,
722 77, 78, 80, 81, 83, 84, 86, 87,
723 88, 90, 91, 92, 93, 95, 96, 97,
724 98, 99, 100, 101, 102, 103, 104, 105,
725 106, 106, 107, 108, 109, 109, 110, 111,
726 111, 112, 112, 113, 113, 114, 114, 114,
727 115, 115, 115, 115, 116, 116, 116, 116,
728 116, 116, 116, 116, 116, 115, 115, 115,
729 115, 114, 114, 114, 113, 113, 112, 112,
730 111, 111, 110, 110, 109, 108, 108, 107,
731 106, 105, 104, 103, 102, 101, 100, 99,
732 98, 97, 96, 95, 94, 93, 91, 90,
733 89, 88, 86, 85, 84, 82, 81, 79,
734 78, 76, 75, 73, 71, 70, 68, 67,
735 65, 63, 62, 60, 58, 56, 55, 53,
736 51, 49, 47, 45, 44, 42, 40, 38,
737 36, 34, 32, 30, 28, 26, 24, 22,
738 20, 18, 16, 14, 12, 10, 8, 6,
739 4, 2, 0, -1, -3, -5, -7, -9, -11
740};
741
742static u16 i2c_ident[] = {
743 V4L2_IDENT_OV9650,
744 V4L2_IDENT_OV9655,
745 V4L2_IDENT_SOI968,
746 V4L2_IDENT_OV7660,
747 V4L2_IDENT_OV7670,
748 V4L2_IDENT_MT9V011,
749 V4L2_IDENT_MT9V111,
750 V4L2_IDENT_MT9V112,
751 V4L2_IDENT_MT9M001C12ST,
752 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300753 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300754 V4L2_IDENT_HV7131R,
755};
756
757static u16 bridge_init[][2] = {
758 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
759 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
760 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
761 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
762 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
763 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
764 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
765 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
766 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
767 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
768 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
769 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
770 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
771 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
772 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
773 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
774 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
775 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300776 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
777 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300778};
779
780/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
781static u8 ov_gain[] = {
782 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
783 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
784 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
785 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
786 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
787 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
788 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
789 0x70 /* 8x */
790};
791
792/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
793static u16 micron1_gain[] = {
794 /* 1x 1.25x 1.5x 1.75x */
795 0x0020, 0x0028, 0x0030, 0x0038,
796 /* 2x 2.25x 2.5x 2.75x */
797 0x00a0, 0x00a4, 0x00a8, 0x00ac,
798 /* 3x 3.25x 3.5x 3.75x */
799 0x00b0, 0x00b4, 0x00b8, 0x00bc,
800 /* 4x 4.25x 4.5x 4.75x */
801 0x00c0, 0x00c4, 0x00c8, 0x00cc,
802 /* 5x 5.25x 5.5x 5.75x */
803 0x00d0, 0x00d4, 0x00d8, 0x00dc,
804 /* 6x 6.25x 6.5x 6.75x */
805 0x00e0, 0x00e4, 0x00e8, 0x00ec,
806 /* 7x 7.25x 7.5x 7.75x */
807 0x00f0, 0x00f4, 0x00f8, 0x00fc,
808 /* 8x */
809 0x01c0
810};
811
812/* mt9m001 sensor uses a different gain formula then other micron sensors */
813/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
814static u16 micron2_gain[] = {
815 /* 1x 1.25x 1.5x 1.75x */
816 0x0008, 0x000a, 0x000c, 0x000e,
817 /* 2x 2.25x 2.5x 2.75x */
818 0x0010, 0x0012, 0x0014, 0x0016,
819 /* 3x 3.25x 3.5x 3.75x */
820 0x0018, 0x001a, 0x001c, 0x001e,
821 /* 4x 4.25x 4.5x 4.75x */
822 0x0020, 0x0051, 0x0052, 0x0053,
823 /* 5x 5.25x 5.5x 5.75x */
824 0x0054, 0x0055, 0x0056, 0x0057,
825 /* 6x 6.25x 6.5x 6.75x */
826 0x0058, 0x0059, 0x005a, 0x005b,
827 /* 7x 7.25x 7.5x 7.75x */
828 0x005c, 0x005d, 0x005e, 0x005f,
829 /* 8x */
830 0x0060
831};
832
833/* Gain = .5 + bit[7:0] / 16 */
834static u8 hv7131r_gain[] = {
835 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
836 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
837 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
838 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
839 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
840 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
841 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
842 0x78 /* 8x */
843};
844
Joe Perches58aa68c2009-09-02 01:12:13 -0300845static struct i2c_reg_u8 soi968_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300846 {0x0c, 0x00}, {0x0f, 0x1f},
Brian Johnson26e744b2009-07-19 05:52:58 -0300847 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
848 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
849 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
850 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
851 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300852 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300853 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
854 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
855 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
856 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
857};
858
Joe Perches58aa68c2009-09-02 01:12:13 -0300859static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300860 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
861 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
862 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300863 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
864 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
865 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300866 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
867 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
868 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
869};
870
Joe Perches58aa68c2009-09-02 01:12:13 -0300871static struct i2c_reg_u8 ov7670_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300872 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300873 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
874 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
875 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
876 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
877 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
878 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
879 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
880 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
881 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
882 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
883 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
884 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
885 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
886 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
887 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
888 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
889 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
890 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
891 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
892 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
893 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
894 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
895 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
896 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
897 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
898 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
899 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
900 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
901 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
902 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
903 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
904 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
905 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
906 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
907 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
908 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
909 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
910 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
911 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
912 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
913 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
914 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
915 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
916 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
917 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
918 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
919 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
920 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
921 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
922 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
923 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
924 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
925 {0x93, 0x00},
926};
927
Joe Perches58aa68c2009-09-02 01:12:13 -0300928static struct i2c_reg_u8 ov9650_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300929 {0x00, 0x00}, {0x01, 0x78},
Brian Johnson26e744b2009-07-19 05:52:58 -0300930 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
931 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
932 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
933 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
934 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
935 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
936 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
937 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
938 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
939 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
940 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
941 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
942 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
943 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
944 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
945 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
946 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
947 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
948 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
949 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
950 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
951 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
952 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
953 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
954 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
955 {0xaa, 0x92}, {0xab, 0x0a},
956};
957
Joe Perches58aa68c2009-09-02 01:12:13 -0300958static struct i2c_reg_u8 ov9655_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300959 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300960 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
961 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
962 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
963 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
964 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
965 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
966 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
967 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
968 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
969 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
970 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
971 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
972 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
973 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
974 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300975 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300976 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
977 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300978 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300979 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
980 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
981 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
982 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300983};
984
Joe Perches58aa68c2009-09-02 01:12:13 -0300985static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300986 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
987 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
988 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
989 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
990 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
991 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
992 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
993 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
994 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
995 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
996 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
997 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
998 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
999 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1000 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1001 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1002};
1003
Joe Perches58aa68c2009-09-02 01:12:13 -03001004static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001005 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001006 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1007 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1008 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1009 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1010 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1011 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001012};
1013
Joe Perches58aa68c2009-09-02 01:12:13 -03001014static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001015 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1016 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1017 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1018 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1019 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1020 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1021 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1022 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1023 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1024 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1025 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1026 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1027 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1028 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1029 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1030 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1031 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1032 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1033 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1034 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1035 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1036 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1037 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1038 {0x06, 0x0029}, {0x05, 0x0009},
1039};
1040
Joe Perches58aa68c2009-09-02 01:12:13 -03001041static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001042 {0x0d, 0x0001},
1043 {0x0d, 0x0000},
1044 {0x04, 0x0500}, /* hres = 1280 */
1045 {0x03, 0x0400}, /* vres = 1024 */
1046 {0x20, 0x1100},
1047 {0x06, 0x0010},
1048 {0x2b, 0x0024},
1049 {0x2e, 0x0024},
1050 {0x35, 0x0024},
1051 {0x2d, 0x0020},
1052 {0x2c, 0x0020},
1053 {0x09, 0x0ad4},
1054 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001055};
1056
Joe Perches58aa68c2009-09-02 01:12:13 -03001057static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001058 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1059 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001060 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1061 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001062};
1063
Brian Johnsone99ac542010-03-16 13:58:28 -03001064static struct i2c_reg_u16 mt9m112_init[] = {
1065 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1066 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1067 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1068 {0xf0, 0x0000},
1069};
1070
Joe Perches58aa68c2009-09-02 01:12:13 -03001071static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001072 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1073 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1074 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1075 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1076 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1077 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1078 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1079 {0x23, 0x09}, {0x01, 0x08},
1080};
1081
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001082static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001083{
1084 struct usb_device *dev = gspca_dev->dev;
1085 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001086
1087 if (gspca_dev->usb_err < 0)
1088 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001089 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1090 0x00,
1091 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1092 reg,
1093 0x00,
1094 gspca_dev->usb_buf,
1095 length,
1096 500);
1097 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001098 pr_err("Read register %02x failed %d\n", reg, result);
1099 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001100 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001101}
1102
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001103static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
Joe Perches58aa68c2009-09-02 01:12:13 -03001104 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001105{
1106 struct usb_device *dev = gspca_dev->dev;
1107 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001108
1109 if (gspca_dev->usb_err < 0)
1110 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001111 memcpy(gspca_dev->usb_buf, buffer, length);
1112 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1113 0x08,
1114 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1115 reg,
1116 0x00,
1117 gspca_dev->usb_buf,
1118 length,
1119 500);
1120 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001121 pr_err("Write register %02x failed %d\n", reg, result);
1122 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001123 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001124}
1125
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001126static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001127{
1128 u8 data[1] = {value};
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001129 reg_w(gspca_dev, reg, data, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001130}
1131
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001132static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001133{
1134 int i;
1135 reg_w(gspca_dev, 0x10c0, buffer, 8);
1136 for (i = 0; i < 5; i++) {
1137 reg_r(gspca_dev, 0x10c0, 1);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001138 if (gspca_dev->usb_err < 0)
1139 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001140 if (gspca_dev->usb_buf[0] & 0x04) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001141 if (gspca_dev->usb_buf[0] & 0x08) {
1142 pr_err("i2c_w error\n");
1143 gspca_dev->usb_err = -EIO;
1144 }
1145 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001146 }
Jean-François Moinee71389b2012-03-19 04:45:20 -03001147 msleep(10);
Brian Johnson26e744b2009-07-19 05:52:58 -03001148 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001149 pr_err("i2c_w reg %02x no response\n", buffer[2]);
1150/* gspca_dev->usb_err = -EIO; fixme: may occur */
Brian Johnson26e744b2009-07-19 05:52:58 -03001151}
1152
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001153static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001154{
1155 struct sd *sd = (struct sd *) gspca_dev;
1156
1157 u8 row[8];
1158
1159 /*
1160 * from the point of view of the bridge, the length
1161 * includes the address
1162 */
1163 row[0] = 0x81 | (2 << 4);
1164 row[1] = sd->i2c_addr;
1165 row[2] = reg;
1166 row[3] = val;
1167 row[4] = 0x00;
1168 row[5] = 0x00;
1169 row[6] = 0x00;
1170 row[7] = 0x10;
1171
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001172 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001173}
1174
Jean-François Moined4689b72012-03-19 04:42:45 -03001175static void i2c_w1_buf(struct gspca_dev *gspca_dev,
1176 struct i2c_reg_u8 *buf, int sz)
1177{
1178 while (--sz >= 0) {
1179 i2c_w1(gspca_dev, buf->reg, buf->val);
1180 buf++;
1181 }
1182}
1183
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001184static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001185{
1186 struct sd *sd = (struct sd *) gspca_dev;
1187 u8 row[8];
1188
1189 /*
1190 * from the point of view of the bridge, the length
1191 * includes the address
1192 */
1193 row[0] = 0x81 | (3 << 4);
1194 row[1] = sd->i2c_addr;
1195 row[2] = reg;
1196 row[3] = (val >> 8) & 0xff;
1197 row[4] = val & 0xff;
1198 row[5] = 0x00;
1199 row[6] = 0x00;
1200 row[7] = 0x10;
1201
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001202 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001203}
1204
Jean-François Moined4689b72012-03-19 04:42:45 -03001205static void i2c_w2_buf(struct gspca_dev *gspca_dev,
1206 struct i2c_reg_u16 *buf, int sz)
1207{
1208 while (--sz >= 0) {
1209 i2c_w2(gspca_dev, buf->reg, buf->val);
1210 buf++;
1211 }
1212}
1213
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001214static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001215{
1216 struct sd *sd = (struct sd *) gspca_dev;
1217 u8 row[8];
1218
Brian Johnson00b581e2009-07-23 05:55:43 -03001219 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001220 row[1] = sd->i2c_addr;
1221 row[2] = reg;
1222 row[3] = 0;
1223 row[4] = 0;
1224 row[5] = 0;
1225 row[6] = 0;
1226 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001227 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001228 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001229 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001230 i2c_w(gspca_dev, row);
1231 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001232 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001233}
1234
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001235static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001236{
1237 struct sd *sd = (struct sd *) gspca_dev;
1238 u8 row[8];
1239
Brian Johnson00b581e2009-07-23 05:55:43 -03001240 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001241 row[1] = sd->i2c_addr;
1242 row[2] = reg;
1243 row[3] = 0;
1244 row[4] = 0;
1245 row[5] = 0;
1246 row[6] = 0;
1247 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001248 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001249 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001250 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001251 i2c_w(gspca_dev, row);
1252 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001253 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001254}
1255
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001256static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001257{
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001258 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001259 struct sd *sd = (struct sd *) gspca_dev;
1260
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001261 i2c_r2(gspca_dev, 0x1c, &id);
1262 if (gspca_dev->usb_err < 0)
1263 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001264
1265 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001266 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001267 gspca_dev->usb_err = -ENODEV;
1268 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001269 }
1270
Jean-François Moine92884f82012-03-19 04:33:30 -03001271 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1272 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001273 i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
1274 if (gspca_dev->usb_err < 0)
1275 pr_err("OV9650 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001276 sd->hstart = 1;
1277 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001278}
1279
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001280static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001281{
Brian Johnson26e744b2009-07-19 05:52:58 -03001282 struct sd *sd = (struct sd *) gspca_dev;
1283
Jean-François Moine92884f82012-03-19 04:33:30 -03001284 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1285 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001286 i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
1287 if (gspca_dev->usb_err < 0)
1288 pr_err("OV9655 sensor initialization failed\n");
1289
Brian Johnson26e744b2009-07-19 05:52:58 -03001290 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001291 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001292 sd->hstart = 1;
1293 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001294}
1295
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001296static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001297{
Brian Johnson26e744b2009-07-19 05:52:58 -03001298 struct sd *sd = (struct sd *) gspca_dev;
1299
Jean-François Moine92884f82012-03-19 04:33:30 -03001300 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1301 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001302 i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
1303 if (gspca_dev->usb_err < 0)
1304 pr_err("SOI968 sensor initialization failed\n");
1305
Brian Johnson26e744b2009-07-19 05:52:58 -03001306 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001307 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1308 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001309 sd->hstart = 60;
1310 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001311}
1312
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001313static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001314{
Brian Johnson26e744b2009-07-19 05:52:58 -03001315 struct sd *sd = (struct sd *) gspca_dev;
1316
Jean-François Moine92884f82012-03-19 04:33:30 -03001317 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1318 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001319 i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
1320 if (gspca_dev->usb_err < 0)
1321 pr_err("OV7660 sensor initialization failed\n");
Hans de Goede8bc50f32011-02-16 07:11:14 -03001322 sd->hstart = 3;
1323 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001324}
1325
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001326static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001327{
Brian Johnson26e744b2009-07-19 05:52:58 -03001328 struct sd *sd = (struct sd *) gspca_dev;
1329
Jean-François Moine92884f82012-03-19 04:33:30 -03001330 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1331 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001332 i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
1333 if (gspca_dev->usb_err < 0)
1334 pr_err("OV7670 sensor initialization failed\n");
1335
Brian Johnson26e744b2009-07-19 05:52:58 -03001336 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001337 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001338 sd->hstart = 0;
1339 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001340}
1341
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001342static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001343{
1344 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson26e744b2009-07-19 05:52:58 -03001345 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001346
1347 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001348 i2c_r2(gspca_dev, 0xff, &value);
1349 if (gspca_dev->usb_err >= 0
1350 && value == 0x8243) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001351 i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
1352 if (gspca_dev->usb_err < 0) {
1353 pr_err("MT9V011 sensor initialization failed\n");
1354 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001355 }
1356 sd->hstart = 2;
1357 sd->vstart = 2;
1358 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001359 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001360 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001361 }
1362
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001363 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001364 sd->i2c_addr = 0x5c;
1365 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001366 i2c_r2(gspca_dev, 0xff, &value);
1367 if (gspca_dev->usb_err >= 0
1368 && value == 0x823a) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001369 i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
1370 if (gspca_dev->usb_err < 0) {
1371 pr_err("MT9V111 sensor initialization failed\n");
1372 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001373 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001374 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1375 | (1 << AUTOGAIN)
1376 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001377 sd->hstart = 2;
1378 sd->vstart = 2;
1379 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001380 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001381 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001382 }
1383
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001384 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001385 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001386 i2c_w2(gspca_dev, 0xf0, 0x0000);
1387 if (gspca_dev->usb_err < 0) {
1388 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001389 sd->i2c_addr = 0x48;
1390 i2c_w2(gspca_dev, 0xf0, 0x0000);
1391 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001392 i2c_r2(gspca_dev, 0x00, &value);
1393 if (gspca_dev->usb_err >= 0
1394 && value == 0x1229) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001395 i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
1396 if (gspca_dev->usb_err < 0) {
1397 pr_err("MT9V112 sensor initialization failed\n");
1398 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001399 }
1400 sd->hstart = 6;
1401 sd->vstart = 2;
1402 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001403 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001404 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001405 }
1406
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001407 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001408}
1409
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001410static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001411{
1412 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001413
1414 i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
1415 if (gspca_dev->usb_err < 0)
1416 pr_err("MT9M112 sensor initialization failed\n");
1417
Jean-François Moinec5224d82012-03-19 04:30:07 -03001418 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1419 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001420 sd->hstart = 0;
1421 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001422}
1423
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001424static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001425{
1426 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001427
1428 i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
1429 if (gspca_dev->usb_err < 0)
1430 pr_err("MT9M111 sensor initialization failed\n");
1431
Jean-François Moinec5224d82012-03-19 04:30:07 -03001432 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1433 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001434 sd->hstart = 0;
1435 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001436}
1437
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001438static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001439{
1440 struct sd *sd = (struct sd *) gspca_dev;
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
Jean-François Moined4689b72012-03-19 04:42:45 -03001462 i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
1463 if (gspca_dev->usb_err < 0)
1464 pr_err("MT9M001 sensor initialization failed\n");
1465
Brian Johnson26e744b2009-07-19 05:52:58 -03001466 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001467 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001468 sd->hstart = 1;
1469 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001470}
1471
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001472static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001473{
Brian Johnson26e744b2009-07-19 05:52:58 -03001474 struct sd *sd = (struct sd *) gspca_dev;
1475
Jean-François Moined4689b72012-03-19 04:42:45 -03001476 i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
1477 if (gspca_dev->usb_err < 0)
1478 pr_err("HV7131R Sensor initialization failed\n");
1479
Brian Johnson26e744b2009-07-19 05:52:58 -03001480 sd->hstart = 0;
1481 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001482}
1483
Jean-François Moinec5224d82012-03-19 04:30:07 -03001484static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001485{
1486 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001487 int satur;
1488 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001489 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001490
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001491 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001492 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001493 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1494 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001495 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001496
Jean-François Moinec5224d82012-03-19 04:30:07 -03001497 satur = sd->ctrls[SATURATION].val;
1498 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001499 cmatrix[6] = hue_coord;
1500 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501
Jean-François Moinec5224d82012-03-19 04:30:07 -03001502 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001503 cmatrix[8] = hue_coord;
1504 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001505
Jean-François Moinec5224d82012-03-19 04:30:07 -03001506 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001507 cmatrix[10] = hue_coord;
1508 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001509
Jean-François Moinec5224d82012-03-19 04:30:07 -03001510 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001511 cmatrix[12] = hue_coord;
1512 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001513
Jean-François Moinec5224d82012-03-19 04:30:07 -03001514 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001515 cmatrix[14] = hue_coord;
1516 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001517
Jean-François Moinec5224d82012-03-19 04:30:07 -03001518 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001519 cmatrix[16] = hue_coord;
1520 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001521
Jean-François Moinec5224d82012-03-19 04:30:07 -03001522 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001523}
1524
Jean-François Moinec5224d82012-03-19 04:30:07 -03001525static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001529 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001530
1531 gamma[0] = 0x0a;
1532 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1533 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1534 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1535 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1536 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1537 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1538 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1539 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1540 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1541 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1542 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1543 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1544 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1545 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1546 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1547 gamma[16] = 0xf5;
1548
Jean-François Moinec5224d82012-03-19 04:30:07 -03001549 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001550}
1551
Jean-François Moinec5224d82012-03-19 04:30:07 -03001552static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001553{
1554 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001555
1556 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1557 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001558}
1559
Jean-François Moinec5224d82012-03-19 04:30:07 -03001560static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001561{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001562 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001563 u16 value2;
1564 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001565
1566 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001567 hflip = !sd->ctrls[HFLIP].val;
1568 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001569 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001570 hflip = sd->ctrls[HFLIP].val;
1571 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001572 }
1573
Brian Johnson26e744b2009-07-19 05:52:58 -03001574 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001575 case SENSOR_OV7660:
1576 value = 0x01;
1577 if (hflip)
1578 value |= 0x20;
1579 if (vflip) {
1580 value |= 0x10;
1581 sd->vstart = 2;
1582 } else
1583 sd->vstart = 3;
1584 reg_w1(gspca_dev, 0x1182, sd->vstart);
1585 i2c_w1(gspca_dev, 0x1e, value);
1586 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001587 case SENSOR_OV9650:
1588 i2c_r1(gspca_dev, 0x1e, &value);
1589 value &= ~0x30;
1590 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001591 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001592 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001593 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001594 value |= 0x10;
1595 tslb = 0x49;
1596 }
1597 i2c_w1(gspca_dev, 0x1e, value);
1598 i2c_w1(gspca_dev, 0x3a, tslb);
1599 break;
1600 case SENSOR_MT9V111:
1601 case SENSOR_MT9V011:
1602 i2c_r2(gspca_dev, 0x20, &value2);
1603 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001604 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001605 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001606 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001607 value2 |= 0x4020;
1608 i2c_w2(gspca_dev, 0x20, value2);
1609 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001610 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001611 case SENSOR_MT9M111:
1612 case SENSOR_MT9V112:
1613 i2c_r2(gspca_dev, 0x20, &value2);
1614 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001615 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001616 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001617 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001618 value2 |= 0x0001;
1619 i2c_w2(gspca_dev, 0x20, value2);
1620 break;
1621 case SENSOR_HV7131R:
1622 i2c_r1(gspca_dev, 0x01, &value);
1623 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001624 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001625 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001626 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001627 value |= 0x02;
1628 i2c_w1(gspca_dev, 0x01, value);
1629 break;
1630 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001631}
1632
Jean-François Moinec5224d82012-03-19 04:30:07 -03001633static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001634{
1635 struct sd *sd = (struct sd *) gspca_dev;
1636 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001637 int expo;
1638
1639 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001640 switch (sd->sensor) {
1641 case SENSOR_OV7660:
1642 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001643 case SENSOR_OV9655:
1644 case SENSOR_OV9650:
1645 exp[0] |= (3 << 4);
1646 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001647 exp[3] = expo;
1648 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001649 break;
1650 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001651 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001652 case SENSOR_MT9V011:
1653 exp[0] |= (3 << 4);
1654 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001655 exp[3] = expo >> 8;
1656 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001657 break;
1658 case SENSOR_HV7131R:
1659 exp[0] |= (4 << 4);
1660 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001661 exp[3] = expo >> 5;
1662 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001663 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001664 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001665 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001666 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001667 }
1668 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001669}
1670
Jean-François Moinec5224d82012-03-19 04:30:07 -03001671static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001672{
1673 struct sd *sd = (struct sd *) gspca_dev;
1674 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001675 int g;
1676
1677 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001678 switch (sd->sensor) {
1679 case SENSOR_OV7660:
1680 case SENSOR_OV7670:
1681 case SENSOR_SOI968:
1682 case SENSOR_OV9655:
1683 case SENSOR_OV9650:
1684 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001685 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 break;
1687 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001688 gain[0] |= (3 << 4);
1689 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001690 gain[3] = micron1_gain[g] >> 8;
1691 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001692 break;
1693 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001694 gain[0] |= (3 << 4);
1695 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001696 gain[3] = micron1_gain[g] >> 8;
1697 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001698 break;
1699 case SENSOR_MT9M001:
1700 gain[0] |= (3 << 4);
1701 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001702 gain[3] = micron2_gain[g] >> 8;
1703 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001704 break;
1705 case SENSOR_HV7131R:
1706 gain[0] |= (2 << 4);
1707 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001708 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001709 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001710 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001711 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001712 }
1713 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001714}
1715
Jean-François Moine4c632e42012-03-19 04:35:34 -03001716static void set_quality(struct gspca_dev *gspca_dev)
1717{
1718 struct sd *sd = (struct sd *) gspca_dev;
1719
1720 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
1721 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1722 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1723 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1724 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1725 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1726 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1727 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1728 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1729}
1730
Brian Johnson26e744b2009-07-19 05:52:58 -03001731#ifdef CONFIG_VIDEO_ADV_DEBUG
1732static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1733 struct v4l2_dbg_register *reg)
1734{
1735 struct sd *sd = (struct sd *) gspca_dev;
1736 switch (reg->match.type) {
1737 case V4L2_CHIP_MATCH_HOST:
1738 if (reg->match.addr != 0)
1739 return -EINVAL;
1740 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1741 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001742 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001743 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001744 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001745 case V4L2_CHIP_MATCH_I2C_ADDR:
1746 if (reg->match.addr != sd->i2c_addr)
1747 return -EINVAL;
1748 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001749 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001750 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001751 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001752 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001753 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001754 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001755 }
1756 return -EINVAL;
1757}
1758
1759static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1760 struct v4l2_dbg_register *reg)
1761{
1762 struct sd *sd = (struct sd *) gspca_dev;
1763 switch (reg->match.type) {
1764 case V4L2_CHIP_MATCH_HOST:
1765 if (reg->match.addr != 0)
1766 return -EINVAL;
1767 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1768 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001769 reg_w1(gspca_dev, reg->reg, reg->val);
1770 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001771 case V4L2_CHIP_MATCH_I2C_ADDR:
1772 if (reg->match.addr != sd->i2c_addr)
1773 return -EINVAL;
1774 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001775 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001776 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001777 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001778 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001779 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001780 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001781 }
1782 return -EINVAL;
1783}
1784#endif
1785
1786static int sd_chip_ident(struct gspca_dev *gspca_dev,
1787 struct v4l2_dbg_chip_ident *chip)
1788{
1789 struct sd *sd = (struct sd *) gspca_dev;
1790
1791 switch (chip->match.type) {
1792 case V4L2_CHIP_MATCH_HOST:
1793 if (chip->match.addr != 0)
1794 return -EINVAL;
1795 chip->revision = 0;
1796 chip->ident = V4L2_IDENT_SN9C20X;
1797 return 0;
1798 case V4L2_CHIP_MATCH_I2C_ADDR:
1799 if (chip->match.addr != sd->i2c_addr)
1800 return -EINVAL;
1801 chip->revision = 0;
1802 chip->ident = i2c_ident[sd->sensor];
1803 return 0;
1804 }
1805 return -EINVAL;
1806}
1807
1808static int sd_config(struct gspca_dev *gspca_dev,
1809 const struct usb_device_id *id)
1810{
1811 struct sd *sd = (struct sd *) gspca_dev;
1812 struct cam *cam;
1813
1814 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001815 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001816
1817 sd->sensor = (id->driver_info >> 8) & 0xff;
1818 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001819 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001820
1821 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001822 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001823 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001824 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001825 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001826 cam->cam_mode = sxga_mode;
1827 cam->nmodes = ARRAY_SIZE(sxga_mode);
1828 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001829 case SENSOR_MT9M001:
1830 cam->cam_mode = mono_mode;
1831 cam->nmodes = ARRAY_SIZE(mono_mode);
1832 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001833 default:
1834 cam->cam_mode = vga_mode;
1835 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001836 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001837 }
1838
1839 sd->old_step = 0;
1840 sd->older_step = 0;
1841 sd->exposure_step = 16;
1842
Jean-François Moinec5224d82012-03-19 04:30:07 -03001843 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001844
Brian Johnson26e744b2009-07-19 05:52:58 -03001845
Brian Johnson26e744b2009-07-19 05:52:58 -03001846 return 0;
1847}
1848
1849static int sd_init(struct gspca_dev *gspca_dev)
1850{
1851 struct sd *sd = (struct sd *) gspca_dev;
1852 int i;
1853 u8 value;
1854 u8 i2c_init[9] =
1855 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1856
1857 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1858 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001859 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1860 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001861 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001862 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001863 }
1864 }
1865
Brian Johnson0c045eb2010-03-16 13:58:27 -03001866 if (sd->flags & LED_REVERSE)
1867 reg_w1(gspca_dev, 0x1006, 0x00);
1868 else
1869 reg_w1(gspca_dev, 0x1006, 0x20);
1870
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001871 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1872 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001873 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001874 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001875 }
1876
1877 switch (sd->sensor) {
1878 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001879 ov9650_init_sensor(gspca_dev);
1880 if (gspca_dev->usb_err < 0)
1881 break;
Joe Perches91f58422011-08-21 19:56:55 -03001882 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001883 break;
1884 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001885 ov9655_init_sensor(gspca_dev);
1886 if (gspca_dev->usb_err < 0)
1887 break;
Joe Perches91f58422011-08-21 19:56:55 -03001888 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001889 break;
1890 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001891 soi968_init_sensor(gspca_dev);
1892 if (gspca_dev->usb_err < 0)
1893 break;
Joe Perches91f58422011-08-21 19:56:55 -03001894 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001895 break;
1896 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001897 ov7660_init_sensor(gspca_dev);
1898 if (gspca_dev->usb_err < 0)
1899 break;
Joe Perches91f58422011-08-21 19:56:55 -03001900 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001901 break;
1902 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001903 ov7670_init_sensor(gspca_dev);
1904 if (gspca_dev->usb_err < 0)
1905 break;
Joe Perches91f58422011-08-21 19:56:55 -03001906 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001907 break;
1908 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001909 mt9v_init_sensor(gspca_dev);
1910 if (gspca_dev->usb_err < 0)
1911 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001912 break;
1913 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001914 mt9m111_init_sensor(gspca_dev);
1915 if (gspca_dev->usb_err < 0)
1916 break;
Joe Perches91f58422011-08-21 19:56:55 -03001917 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001918 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001919 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001920 mt9m112_init_sensor(gspca_dev);
1921 if (gspca_dev->usb_err < 0)
1922 break;
Joe Perches91f58422011-08-21 19:56:55 -03001923 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001924 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001925 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001926 mt9m001_init_sensor(gspca_dev);
1927 if (gspca_dev->usb_err < 0)
1928 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001929 break;
1930 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001931 hv7131r_init_sensor(gspca_dev);
1932 if (gspca_dev->usb_err < 0)
1933 break;
Joe Perches91f58422011-08-21 19:56:55 -03001934 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001935 break;
1936 default:
Joe Perches91f58422011-08-21 19:56:55 -03001937 pr_info("Unsupported Sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001938 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001939 }
1940
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001941 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001942}
1943
1944static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1945{
1946 struct sd *sd = (struct sd *) gspca_dev;
1947 u8 value;
1948 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001949 case SENSOR_SOI968:
1950 if (mode & MODE_SXGA) {
1951 i2c_w1(gspca_dev, 0x17, 0x1d);
1952 i2c_w1(gspca_dev, 0x18, 0xbd);
1953 i2c_w1(gspca_dev, 0x19, 0x01);
1954 i2c_w1(gspca_dev, 0x1a, 0x81);
1955 i2c_w1(gspca_dev, 0x12, 0x00);
1956 sd->hstart = 140;
1957 sd->vstart = 19;
1958 } else {
1959 i2c_w1(gspca_dev, 0x17, 0x13);
1960 i2c_w1(gspca_dev, 0x18, 0x63);
1961 i2c_w1(gspca_dev, 0x19, 0x01);
1962 i2c_w1(gspca_dev, 0x1a, 0x79);
1963 i2c_w1(gspca_dev, 0x12, 0x40);
1964 sd->hstart = 60;
1965 sd->vstart = 11;
1966 }
1967 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001968 case SENSOR_OV9650:
1969 if (mode & MODE_SXGA) {
1970 i2c_w1(gspca_dev, 0x17, 0x1b);
1971 i2c_w1(gspca_dev, 0x18, 0xbc);
1972 i2c_w1(gspca_dev, 0x19, 0x01);
1973 i2c_w1(gspca_dev, 0x1a, 0x82);
1974 i2c_r1(gspca_dev, 0x12, &value);
1975 i2c_w1(gspca_dev, 0x12, value & 0x07);
1976 } else {
1977 i2c_w1(gspca_dev, 0x17, 0x24);
1978 i2c_w1(gspca_dev, 0x18, 0xc5);
1979 i2c_w1(gspca_dev, 0x19, 0x00);
1980 i2c_w1(gspca_dev, 0x1a, 0x3c);
1981 i2c_r1(gspca_dev, 0x12, &value);
1982 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1983 }
1984 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001985 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001986 case SENSOR_MT9M111:
1987 if (mode & MODE_SXGA) {
1988 i2c_w2(gspca_dev, 0xf0, 0x0002);
1989 i2c_w2(gspca_dev, 0xc8, 0x970b);
1990 i2c_w2(gspca_dev, 0xf0, 0x0000);
1991 } else {
1992 i2c_w2(gspca_dev, 0xf0, 0x0002);
1993 i2c_w2(gspca_dev, 0xc8, 0x8000);
1994 i2c_w2(gspca_dev, 0xf0, 0x0000);
1995 }
1996 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001997 }
1998}
1999
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002000static int sd_isoc_init(struct gspca_dev *gspca_dev)
2001{
2002 struct usb_interface *intf;
2003 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2004
2005 /*
2006 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2007 * than our regular bandwidth calculations reserve, so we force the
2008 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2009 */
2010 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2011 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2012
2013 if (intf->num_altsetting != 9) {
2014 pr_warn("sn9c20x camera with unknown number of alt "
2015 "settings (%d), please report!\n",
2016 intf->num_altsetting);
2017 gspca_dev->alt = intf->num_altsetting;
2018 return 0;
2019 }
2020
2021 switch (gspca_dev->width) {
2022 case 160: /* 160x120 */
2023 gspca_dev->alt = 2;
2024 break;
2025 case 320: /* 320x240 */
2026 gspca_dev->alt = 6;
2027 break;
2028 default: /* >= 640x480 */
2029 gspca_dev->alt = 9;
2030 }
2031 }
2032
2033 return 0;
2034}
2035
Brian Johnson26e744b2009-07-19 05:52:58 -03002036#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002037((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002038(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2039(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2040
2041#define CLR_WIN(width, height) \
2042((const u8 [])\
2043{0, width >> 2, 0, height >> 1,\
2044((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2045
2046static int sd_start(struct gspca_dev *gspca_dev)
2047{
2048 struct sd *sd = (struct sd *) gspca_dev;
2049 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2050 int width = gspca_dev->width;
2051 int height = gspca_dev->height;
2052 u8 fmt, scale = 0;
2053
Brian Johnson26e744b2009-07-19 05:52:58 -03002054 jpeg_define(sd->jpeg_hdr, height, width,
2055 0x21);
Jean-François Moine4c632e42012-03-19 04:35:34 -03002056 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03002057
2058 if (mode & MODE_RAW)
2059 fmt = 0x2d;
2060 else if (mode & MODE_JPEG)
Jean-François Moine4c632e42012-03-19 04:35:34 -03002061 fmt = 0x24;
Brian Johnson26e744b2009-07-19 05:52:58 -03002062 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002063 fmt = 0x2f; /* YUV 420 */
Jean-François Moine4c632e42012-03-19 04:35:34 -03002064 sd->fmt = fmt;
Brian Johnson26e744b2009-07-19 05:52:58 -03002065
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002066 switch (mode & SCALE_MASK) {
2067 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002068 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002069 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002070 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002071 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002072 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002073 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002074 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002075 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002076 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002077 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002078 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002079 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002080 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002081 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002082 break;
2083 }
2084
2085 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002086 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2087 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002088 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2089 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2090 reg_w1(gspca_dev, 0x1189, scale);
2091 reg_w1(gspca_dev, 0x10e0, fmt);
2092
2093 set_cmatrix(gspca_dev);
2094 set_gamma(gspca_dev);
2095 set_redblue(gspca_dev);
2096 set_gain(gspca_dev);
2097 set_exposure(gspca_dev);
2098 set_hvflip(gspca_dev);
2099
Brian Johnson0c045eb2010-03-16 13:58:27 -03002100 reg_w1(gspca_dev, 0x1007, 0x20);
2101
Brian Johnson26e744b2009-07-19 05:52:58 -03002102 reg_r(gspca_dev, 0x1061, 1);
2103 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002104 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002105}
2106
2107static void sd_stopN(struct gspca_dev *gspca_dev)
2108{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002109 reg_w1(gspca_dev, 0x1007, 0x00);
2110
Brian Johnson26e744b2009-07-19 05:52:58 -03002111 reg_r(gspca_dev, 0x1061, 1);
2112 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2113}
2114
Brian Johnsone1430472009-09-02 12:39:41 -03002115static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002116{
2117 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002118 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002119
2120 /*
2121 * some hardcoded values are present
2122 * like those for maximal/minimal exposure
2123 * and exposure steps
2124 */
2125 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002126 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002127 return;
2128
Jean-François Moinec5224d82012-03-19 04:30:07 -03002129 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002130 if (new_exp > 0x1770)
2131 new_exp = 0x1770;
2132 if (new_exp < 0x10)
2133 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002134 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002135 set_exposure(gspca_dev);
2136
2137 sd->older_step = sd->old_step;
2138 sd->old_step = 1;
2139
2140 if (sd->old_step ^ sd->older_step)
2141 sd->exposure_step /= 2;
2142 else
2143 sd->exposure_step += 2;
2144 }
2145 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002146 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002147 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002148 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002149 if (new_exp > 0x1700)
2150 new_exp = 0x1770;
2151 if (new_exp < 0x10)
2152 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002153 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002154 set_exposure(gspca_dev);
2155 sd->older_step = sd->old_step;
2156 sd->old_step = 0;
2157
2158 if (sd->old_step ^ sd->older_step)
2159 sd->exposure_step /= 2;
2160 else
2161 sd->exposure_step += 2;
2162 }
2163}
2164
Brian Johnsone1430472009-09-02 12:39:41 -03002165static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2166{
2167 struct sd *sd = (struct sd *) gspca_dev;
2168
2169 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002170 if (sd->ctrls[GAIN].val + 1 <= 28) {
2171 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002172 set_gain(gspca_dev);
2173 }
2174 }
2175 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002176 if (sd->ctrls[GAIN].val > 0) {
2177 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002178 set_gain(gspca_dev);
2179 }
2180 }
2181}
2182
2183static void sd_dqcallback(struct gspca_dev *gspca_dev)
2184{
2185 struct sd *sd = (struct sd *) gspca_dev;
2186 int avg_lum;
2187
Jean-François Moinec5224d82012-03-19 04:30:07 -03002188 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002189 return;
2190
2191 avg_lum = atomic_read(&sd->avg_lum);
2192 if (sd->sensor == SENSOR_SOI968)
2193 do_autogain(gspca_dev, avg_lum);
2194 else
2195 do_autoexposure(gspca_dev, avg_lum);
2196}
2197
Jean-François Moine28566432010-10-01 07:33:26 -03002198#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002199static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2200 u8 *data, /* interrupt packet */
2201 int len) /* interrupt packet length */
2202{
2203 struct sd *sd = (struct sd *) gspca_dev;
2204 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002205 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002206 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2207 input_sync(gspca_dev->input_dev);
2208 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2209 input_sync(gspca_dev->input_dev);
2210 ret = 0;
2211 }
2212 return ret;
2213}
2214#endif
2215
Brian Johnson26e744b2009-07-19 05:52:58 -03002216static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002217 u8 *data, /* isoc packet */
2218 int len) /* iso packet length */
2219{
2220 struct sd *sd = (struct sd *) gspca_dev;
2221 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002222 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002223 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002224 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002225 avg_lum = ((data[35] >> 2) & 3) |
2226 (data[20] << 2) |
2227 (data[19] << 10);
2228 avg_lum += ((data[35] >> 4) & 3) |
2229 (data[22] << 2) |
2230 (data[21] << 10);
2231 avg_lum += ((data[35] >> 6) & 3) |
2232 (data[24] << 2) |
2233 (data[23] << 10);
2234 avg_lum += (data[36] & 3) |
2235 (data[26] << 2) |
2236 (data[25] << 10);
2237 avg_lum += ((data[36] >> 2) & 3) |
2238 (data[28] << 2) |
2239 (data[27] << 10);
2240 avg_lum += ((data[36] >> 4) & 3) |
2241 (data[30] << 2) |
2242 (data[29] << 10);
2243 avg_lum += ((data[36] >> 6) & 3) |
2244 (data[32] << 2) |
2245 (data[31] << 10);
2246 avg_lum += ((data[44] >> 4) & 3) |
2247 (data[34] << 2) |
2248 (data[33] << 10);
2249 avg_lum >>= 9;
2250 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002251 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002252 len -= 64;
2253 if (len == 0)
2254 return;
2255 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002256 }
2257 if (gspca_dev->last_packet_type == LAST_PACKET) {
2258 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2259 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002260 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002261 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002262 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002263 data, len);
2264 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002265 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002266 data, len);
2267 }
2268 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002269 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002270 }
2271}
2272
2273/* sub-driver description */
2274static const struct sd_desc sd_desc = {
2275 .name = MODULE_NAME,
2276 .ctrls = sd_ctrls,
2277 .nctrls = ARRAY_SIZE(sd_ctrls),
2278 .config = sd_config,
2279 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002280 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002281 .start = sd_start,
2282 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002283 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002284#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002285 .int_pkt_scan = sd_int_pkt_scan,
2286#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002287 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002288#ifdef CONFIG_VIDEO_ADV_DEBUG
2289 .set_register = sd_dbg_s_register,
2290 .get_register = sd_dbg_g_register,
2291#endif
2292 .get_chip_ident = sd_chip_ident,
2293};
2294
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002295#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002296 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002297 | (SENSOR_ ## sensor << 8) \
2298 | (i2c_addr)
2299
Jean-François Moine95c967c2011-01-13 05:20:29 -03002300static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002301 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2302 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2303 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002304 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002305 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2306 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2307 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002308 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2309 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2310 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2311 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002312 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002313 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2314 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2315 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2316 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002317 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002318 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002319 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2320 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2321 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2322 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002323 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002324 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002325 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2326 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2327 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2328 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002329 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2330 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002331 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2332 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2333 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2334 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002335 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002336 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2337 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2338 {}
2339};
2340MODULE_DEVICE_TABLE(usb, device_table);
2341
2342/* -- device connect -- */
2343static int sd_probe(struct usb_interface *intf,
2344 const struct usb_device_id *id)
2345{
2346 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2347 THIS_MODULE);
2348}
2349
Brian Johnson26e744b2009-07-19 05:52:58 -03002350static struct usb_driver sd_driver = {
2351 .name = MODULE_NAME,
2352 .id_table = device_table,
2353 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002354 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002355#ifdef CONFIG_PM
2356 .suspend = gspca_suspend,
2357 .resume = gspca_resume,
2358 .reset_resume = gspca_resume,
2359#endif
2360};
2361
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002362module_usb_driver(sd_driver);