blob: 0894a3d2c336980dc614cf0e85e92327b5777427 [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 }
1147 msleep(1);
1148 }
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 Moinefe86ec72012-03-19 04:32:15 -03001175static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001176{
1177 struct sd *sd = (struct sd *) gspca_dev;
1178 u8 row[8];
1179
1180 /*
1181 * from the point of view of the bridge, the length
1182 * includes the address
1183 */
1184 row[0] = 0x81 | (3 << 4);
1185 row[1] = sd->i2c_addr;
1186 row[2] = reg;
1187 row[3] = (val >> 8) & 0xff;
1188 row[4] = val & 0xff;
1189 row[5] = 0x00;
1190 row[6] = 0x00;
1191 row[7] = 0x10;
1192
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001193 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001194}
1195
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001196static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001197{
1198 struct sd *sd = (struct sd *) gspca_dev;
1199 u8 row[8];
1200
Brian Johnson00b581e2009-07-23 05:55:43 -03001201 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001202 row[1] = sd->i2c_addr;
1203 row[2] = reg;
1204 row[3] = 0;
1205 row[4] = 0;
1206 row[5] = 0;
1207 row[6] = 0;
1208 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001209 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001210 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001211 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001212 i2c_w(gspca_dev, row);
1213 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001214 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001215}
1216
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001217static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001218{
1219 struct sd *sd = (struct sd *) gspca_dev;
1220 u8 row[8];
1221
Brian Johnson00b581e2009-07-23 05:55:43 -03001222 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001223 row[1] = sd->i2c_addr;
1224 row[2] = reg;
1225 row[3] = 0;
1226 row[4] = 0;
1227 row[5] = 0;
1228 row[6] = 0;
1229 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001230 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001231 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001232 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001233 i2c_w(gspca_dev, row);
1234 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001235 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001236}
1237
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001238static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001239{
1240 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001241 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001242 struct sd *sd = (struct sd *) gspca_dev;
1243
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001244 i2c_r2(gspca_dev, 0x1c, &id);
1245 if (gspca_dev->usb_err < 0)
1246 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001247
1248 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001249 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001250 gspca_dev->usb_err = -ENODEV;
1251 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001252 }
1253
Jean-François Moine92884f82012-03-19 04:33:30 -03001254 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1255 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001256 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001257 i2c_w1(gspca_dev, ov9650_init[i].reg,
1258 ov9650_init[i].val);
1259 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001260 pr_err("OV9650 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001261 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001262 }
1263 }
1264 sd->hstart = 1;
1265 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001266}
1267
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001268static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001269{
1270 int i;
1271 struct sd *sd = (struct sd *) gspca_dev;
1272
Jean-François Moine92884f82012-03-19 04:33:30 -03001273 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1274 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001275 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001276 i2c_w1(gspca_dev, ov9655_init[i].reg,
1277 ov9655_init[i].val);
1278 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001279 pr_err("OV9655 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001280 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001281 }
1282 }
1283 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001284 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001285 sd->hstart = 1;
1286 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001287}
1288
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001289static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001290{
1291 int i;
1292 struct sd *sd = (struct sd *) gspca_dev;
1293
Jean-François Moine92884f82012-03-19 04:33:30 -03001294 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1295 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001296 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001297 i2c_w1(gspca_dev, soi968_init[i].reg,
1298 soi968_init[i].val);
1299 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001300 pr_err("SOI968 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001301 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001302 }
1303 }
1304 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001305 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1306 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001307 sd->hstart = 60;
1308 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001309}
1310
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001311static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001312{
1313 int i;
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
Jean-François Moine92884f82012-03-19 04:33:30 -03001316 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1317 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001318 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001319 i2c_w1(gspca_dev, ov7660_init[i].reg,
1320 ov7660_init[i].val);
1321 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001322 pr_err("OV7660 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001323 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001324 }
1325 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001326 sd->hstart = 3;
1327 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001328}
1329
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001330static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001331{
1332 int i;
1333 struct sd *sd = (struct sd *) gspca_dev;
1334
Jean-François Moine92884f82012-03-19 04:33:30 -03001335 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1336 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001337 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001338 i2c_w1(gspca_dev, ov7670_init[i].reg,
1339 ov7670_init[i].val);
1340 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001341 pr_err("OV7670 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001342 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001343 }
1344 }
1345 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001346 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001347 sd->hstart = 0;
1348 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001349}
1350
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001351static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001352{
1353 struct sd *sd = (struct sd *) gspca_dev;
1354 int i;
1355 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001356
1357 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001358 i2c_r2(gspca_dev, 0xff, &value);
1359 if (gspca_dev->usb_err >= 0
1360 && value == 0x8243) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001361 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001362 i2c_w2(gspca_dev, mt9v011_init[i].reg,
1363 mt9v011_init[i].val);
1364 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001365 pr_err("MT9V011 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001366 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001367 }
1368 }
1369 sd->hstart = 2;
1370 sd->vstart = 2;
1371 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001372 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001373 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001374 }
1375
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001376 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001377 sd->i2c_addr = 0x5c;
1378 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001379 i2c_r2(gspca_dev, 0xff, &value);
1380 if (gspca_dev->usb_err >= 0
1381 && value == 0x823a) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001382 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001383 i2c_w2(gspca_dev, mt9v111_init[i].reg,
1384 mt9v111_init[i].val);
1385 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001386 pr_err("MT9V111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001387 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001388 }
1389 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001390 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1391 | (1 << AUTOGAIN)
1392 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001393 sd->hstart = 2;
1394 sd->vstart = 2;
1395 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001396 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001397 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001398 }
1399
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001400 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001401 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001402 i2c_w2(gspca_dev, 0xf0, 0x0000);
1403 if (gspca_dev->usb_err < 0) {
1404 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001405 sd->i2c_addr = 0x48;
1406 i2c_w2(gspca_dev, 0xf0, 0x0000);
1407 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001408 i2c_r2(gspca_dev, 0x00, &value);
1409 if (gspca_dev->usb_err >= 0
1410 && value == 0x1229) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001411 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001412 i2c_w2(gspca_dev, mt9v112_init[i].reg,
1413 mt9v112_init[i].val);
1414 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001415 pr_err("MT9V112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001416 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001417 }
1418 }
1419 sd->hstart = 6;
1420 sd->vstart = 2;
1421 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001422 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001423 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001424 }
1425
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001426 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001427}
1428
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001429static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001430{
1431 struct sd *sd = (struct sd *) gspca_dev;
1432 int i;
1433 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001434 i2c_w2(gspca_dev, mt9m112_init[i].reg,
1435 mt9m112_init[i].val);
1436 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001437 pr_err("MT9M112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001438 return;
Brian Johnsone99ac542010-03-16 13:58:28 -03001439 }
1440 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001441 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1442 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001443 sd->hstart = 0;
1444 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001445}
1446
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001447static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001448{
1449 struct sd *sd = (struct sd *) gspca_dev;
1450 int i;
1451 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001452 i2c_w2(gspca_dev, mt9m111_init[i].reg,
1453 mt9m111_init[i].val);
1454 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001455 pr_err("MT9M111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001456 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001457 }
1458 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001459 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1460 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001461 sd->hstart = 0;
1462 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001463}
1464
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001465static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001466{
1467 struct sd *sd = (struct sd *) gspca_dev;
1468 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001469 u16 id;
1470
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001471 i2c_r2(gspca_dev, 0x00, &id);
1472 if (gspca_dev->usb_err < 0)
1473 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001474
1475 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1476 switch (id) {
1477 case 0x8411:
1478 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001479 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001480 break;
1481 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001482 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001483 break;
1484 default:
Joe Perches91f58422011-08-21 19:56:55 -03001485 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001486 gspca_dev->usb_err = -ENODEV;
1487 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001488 }
1489
Brian Johnson26e744b2009-07-19 05:52:58 -03001490 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001491 i2c_w2(gspca_dev, mt9m001_init[i].reg,
1492 mt9m001_init[i].val);
1493 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001494 pr_err("MT9M001 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001495 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001496 }
1497 }
1498 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001499 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001500 sd->hstart = 1;
1501 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001502}
1503
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001504static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001505{
1506 int i;
1507 struct sd *sd = (struct sd *) gspca_dev;
1508
1509 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001510 i2c_w1(gspca_dev, hv7131r_init[i].reg,
1511 hv7131r_init[i].val);
1512 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001513 pr_err("HV7131R Sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001514 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001515 }
1516 }
1517 sd->hstart = 0;
1518 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001519}
1520
Jean-François Moinec5224d82012-03-19 04:30:07 -03001521static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001522{
1523 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001524 int satur;
1525 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001526 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001527
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001528 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001529 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001530 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1531 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001532 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001533
Jean-François Moinec5224d82012-03-19 04:30:07 -03001534 satur = sd->ctrls[SATURATION].val;
1535 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001536 cmatrix[6] = hue_coord;
1537 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001538
Jean-François Moinec5224d82012-03-19 04:30:07 -03001539 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001540 cmatrix[8] = hue_coord;
1541 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001542
Jean-François Moinec5224d82012-03-19 04:30:07 -03001543 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001544 cmatrix[10] = hue_coord;
1545 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001546
Jean-François Moinec5224d82012-03-19 04:30:07 -03001547 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001548 cmatrix[12] = hue_coord;
1549 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001550
Jean-François Moinec5224d82012-03-19 04:30:07 -03001551 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001552 cmatrix[14] = hue_coord;
1553 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001554
Jean-François Moinec5224d82012-03-19 04:30:07 -03001555 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001556 cmatrix[16] = hue_coord;
1557 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001558
Jean-François Moinec5224d82012-03-19 04:30:07 -03001559 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001560}
1561
Jean-François Moinec5224d82012-03-19 04:30:07 -03001562static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001563{
1564 struct sd *sd = (struct sd *) gspca_dev;
1565 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001566 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001567
1568 gamma[0] = 0x0a;
1569 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1570 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1571 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1572 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1573 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1574 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1575 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1576 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1577 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1578 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1579 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1580 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1581 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1582 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1583 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1584 gamma[16] = 0xf5;
1585
Jean-François Moinec5224d82012-03-19 04:30:07 -03001586 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001587}
1588
Jean-François Moinec5224d82012-03-19 04:30:07 -03001589static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001590{
1591 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001592
1593 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1594 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001595}
1596
Jean-François Moinec5224d82012-03-19 04:30:07 -03001597static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001598{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001599 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001600 u16 value2;
1601 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001602
1603 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001604 hflip = !sd->ctrls[HFLIP].val;
1605 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001606 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001607 hflip = sd->ctrls[HFLIP].val;
1608 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001609 }
1610
Brian Johnson26e744b2009-07-19 05:52:58 -03001611 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001612 case SENSOR_OV7660:
1613 value = 0x01;
1614 if (hflip)
1615 value |= 0x20;
1616 if (vflip) {
1617 value |= 0x10;
1618 sd->vstart = 2;
1619 } else
1620 sd->vstart = 3;
1621 reg_w1(gspca_dev, 0x1182, sd->vstart);
1622 i2c_w1(gspca_dev, 0x1e, value);
1623 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001624 case SENSOR_OV9650:
1625 i2c_r1(gspca_dev, 0x1e, &value);
1626 value &= ~0x30;
1627 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001628 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001629 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001630 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001631 value |= 0x10;
1632 tslb = 0x49;
1633 }
1634 i2c_w1(gspca_dev, 0x1e, value);
1635 i2c_w1(gspca_dev, 0x3a, tslb);
1636 break;
1637 case SENSOR_MT9V111:
1638 case SENSOR_MT9V011:
1639 i2c_r2(gspca_dev, 0x20, &value2);
1640 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001641 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001642 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001643 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001644 value2 |= 0x4020;
1645 i2c_w2(gspca_dev, 0x20, value2);
1646 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001647 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001648 case SENSOR_MT9M111:
1649 case SENSOR_MT9V112:
1650 i2c_r2(gspca_dev, 0x20, &value2);
1651 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001652 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001653 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001654 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001655 value2 |= 0x0001;
1656 i2c_w2(gspca_dev, 0x20, value2);
1657 break;
1658 case SENSOR_HV7131R:
1659 i2c_r1(gspca_dev, 0x01, &value);
1660 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001661 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001662 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001663 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001664 value |= 0x02;
1665 i2c_w1(gspca_dev, 0x01, value);
1666 break;
1667 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001668}
1669
Jean-François Moinec5224d82012-03-19 04:30:07 -03001670static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001671{
1672 struct sd *sd = (struct sd *) gspca_dev;
1673 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001674 int expo;
1675
1676 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001677 switch (sd->sensor) {
1678 case SENSOR_OV7660:
1679 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001680 case SENSOR_OV9655:
1681 case SENSOR_OV9650:
1682 exp[0] |= (3 << 4);
1683 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001684 exp[3] = expo;
1685 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 break;
1687 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001688 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001689 case SENSOR_MT9V011:
1690 exp[0] |= (3 << 4);
1691 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001692 exp[3] = expo >> 8;
1693 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001694 break;
1695 case SENSOR_HV7131R:
1696 exp[0] |= (4 << 4);
1697 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001698 exp[3] = expo >> 5;
1699 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001700 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001701 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001702 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001703 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001704 }
1705 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001706}
1707
Jean-François Moinec5224d82012-03-19 04:30:07 -03001708static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001709{
1710 struct sd *sd = (struct sd *) gspca_dev;
1711 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001712 int g;
1713
1714 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001715 switch (sd->sensor) {
1716 case SENSOR_OV7660:
1717 case SENSOR_OV7670:
1718 case SENSOR_SOI968:
1719 case SENSOR_OV9655:
1720 case SENSOR_OV9650:
1721 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001722 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001723 break;
1724 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001725 gain[0] |= (3 << 4);
1726 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001727 gain[3] = micron1_gain[g] >> 8;
1728 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001729 break;
1730 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001731 gain[0] |= (3 << 4);
1732 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001733 gain[3] = micron1_gain[g] >> 8;
1734 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001735 break;
1736 case SENSOR_MT9M001:
1737 gain[0] |= (3 << 4);
1738 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001739 gain[3] = micron2_gain[g] >> 8;
1740 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001741 break;
1742 case SENSOR_HV7131R:
1743 gain[0] |= (2 << 4);
1744 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001745 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001746 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001747 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001748 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001749 }
1750 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001751}
1752
Jean-François Moine4c632e42012-03-19 04:35:34 -03001753static void set_quality(struct gspca_dev *gspca_dev)
1754{
1755 struct sd *sd = (struct sd *) gspca_dev;
1756
1757 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
1758 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1759 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1760 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1761 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1762 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1763 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1764 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1765 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1766}
1767
Brian Johnson26e744b2009-07-19 05:52:58 -03001768#ifdef CONFIG_VIDEO_ADV_DEBUG
1769static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1770 struct v4l2_dbg_register *reg)
1771{
1772 struct sd *sd = (struct sd *) gspca_dev;
1773 switch (reg->match.type) {
1774 case V4L2_CHIP_MATCH_HOST:
1775 if (reg->match.addr != 0)
1776 return -EINVAL;
1777 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1778 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001779 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001780 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001781 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001782 case V4L2_CHIP_MATCH_I2C_ADDR:
1783 if (reg->match.addr != sd->i2c_addr)
1784 return -EINVAL;
1785 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001786 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001787 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001788 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001789 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001790 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001791 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001792 }
1793 return -EINVAL;
1794}
1795
1796static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1797 struct v4l2_dbg_register *reg)
1798{
1799 struct sd *sd = (struct sd *) gspca_dev;
1800 switch (reg->match.type) {
1801 case V4L2_CHIP_MATCH_HOST:
1802 if (reg->match.addr != 0)
1803 return -EINVAL;
1804 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1805 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001806 reg_w1(gspca_dev, reg->reg, reg->val);
1807 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001808 case V4L2_CHIP_MATCH_I2C_ADDR:
1809 if (reg->match.addr != sd->i2c_addr)
1810 return -EINVAL;
1811 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001812 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001813 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001814 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001815 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001816 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001817 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001818 }
1819 return -EINVAL;
1820}
1821#endif
1822
1823static int sd_chip_ident(struct gspca_dev *gspca_dev,
1824 struct v4l2_dbg_chip_ident *chip)
1825{
1826 struct sd *sd = (struct sd *) gspca_dev;
1827
1828 switch (chip->match.type) {
1829 case V4L2_CHIP_MATCH_HOST:
1830 if (chip->match.addr != 0)
1831 return -EINVAL;
1832 chip->revision = 0;
1833 chip->ident = V4L2_IDENT_SN9C20X;
1834 return 0;
1835 case V4L2_CHIP_MATCH_I2C_ADDR:
1836 if (chip->match.addr != sd->i2c_addr)
1837 return -EINVAL;
1838 chip->revision = 0;
1839 chip->ident = i2c_ident[sd->sensor];
1840 return 0;
1841 }
1842 return -EINVAL;
1843}
1844
1845static int sd_config(struct gspca_dev *gspca_dev,
1846 const struct usb_device_id *id)
1847{
1848 struct sd *sd = (struct sd *) gspca_dev;
1849 struct cam *cam;
1850
1851 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001852 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001853
1854 sd->sensor = (id->driver_info >> 8) & 0xff;
1855 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001856 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001857
1858 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001859 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001860 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001861 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001862 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001863 cam->cam_mode = sxga_mode;
1864 cam->nmodes = ARRAY_SIZE(sxga_mode);
1865 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001866 case SENSOR_MT9M001:
1867 cam->cam_mode = mono_mode;
1868 cam->nmodes = ARRAY_SIZE(mono_mode);
1869 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001870 default:
1871 cam->cam_mode = vga_mode;
1872 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001873 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001874 }
1875
1876 sd->old_step = 0;
1877 sd->older_step = 0;
1878 sd->exposure_step = 16;
1879
Jean-François Moinec5224d82012-03-19 04:30:07 -03001880 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001881
Brian Johnson26e744b2009-07-19 05:52:58 -03001882
Brian Johnson26e744b2009-07-19 05:52:58 -03001883 return 0;
1884}
1885
1886static int sd_init(struct gspca_dev *gspca_dev)
1887{
1888 struct sd *sd = (struct sd *) gspca_dev;
1889 int i;
1890 u8 value;
1891 u8 i2c_init[9] =
1892 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1893
1894 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1895 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001896 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1897 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001898 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001899 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001900 }
1901 }
1902
Brian Johnson0c045eb2010-03-16 13:58:27 -03001903 if (sd->flags & LED_REVERSE)
1904 reg_w1(gspca_dev, 0x1006, 0x00);
1905 else
1906 reg_w1(gspca_dev, 0x1006, 0x20);
1907
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001908 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1909 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001910 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001911 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001912 }
1913
1914 switch (sd->sensor) {
1915 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001916 ov9650_init_sensor(gspca_dev);
1917 if (gspca_dev->usb_err < 0)
1918 break;
Joe Perches91f58422011-08-21 19:56:55 -03001919 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001920 break;
1921 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001922 ov9655_init_sensor(gspca_dev);
1923 if (gspca_dev->usb_err < 0)
1924 break;
Joe Perches91f58422011-08-21 19:56:55 -03001925 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001926 break;
1927 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001928 soi968_init_sensor(gspca_dev);
1929 if (gspca_dev->usb_err < 0)
1930 break;
Joe Perches91f58422011-08-21 19:56:55 -03001931 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001932 break;
1933 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001934 ov7660_init_sensor(gspca_dev);
1935 if (gspca_dev->usb_err < 0)
1936 break;
Joe Perches91f58422011-08-21 19:56:55 -03001937 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001938 break;
1939 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001940 ov7670_init_sensor(gspca_dev);
1941 if (gspca_dev->usb_err < 0)
1942 break;
Joe Perches91f58422011-08-21 19:56:55 -03001943 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001944 break;
1945 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001946 mt9v_init_sensor(gspca_dev);
1947 if (gspca_dev->usb_err < 0)
1948 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001949 break;
1950 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001951 mt9m111_init_sensor(gspca_dev);
1952 if (gspca_dev->usb_err < 0)
1953 break;
Joe Perches91f58422011-08-21 19:56:55 -03001954 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001955 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001956 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001957 mt9m112_init_sensor(gspca_dev);
1958 if (gspca_dev->usb_err < 0)
1959 break;
Joe Perches91f58422011-08-21 19:56:55 -03001960 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001961 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001962 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001963 mt9m001_init_sensor(gspca_dev);
1964 if (gspca_dev->usb_err < 0)
1965 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001966 break;
1967 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001968 hv7131r_init_sensor(gspca_dev);
1969 if (gspca_dev->usb_err < 0)
1970 break;
Joe Perches91f58422011-08-21 19:56:55 -03001971 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001972 break;
1973 default:
Joe Perches91f58422011-08-21 19:56:55 -03001974 pr_info("Unsupported Sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001975 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001976 }
1977
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001978 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001979}
1980
1981static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1982{
1983 struct sd *sd = (struct sd *) gspca_dev;
1984 u8 value;
1985 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001986 case SENSOR_SOI968:
1987 if (mode & MODE_SXGA) {
1988 i2c_w1(gspca_dev, 0x17, 0x1d);
1989 i2c_w1(gspca_dev, 0x18, 0xbd);
1990 i2c_w1(gspca_dev, 0x19, 0x01);
1991 i2c_w1(gspca_dev, 0x1a, 0x81);
1992 i2c_w1(gspca_dev, 0x12, 0x00);
1993 sd->hstart = 140;
1994 sd->vstart = 19;
1995 } else {
1996 i2c_w1(gspca_dev, 0x17, 0x13);
1997 i2c_w1(gspca_dev, 0x18, 0x63);
1998 i2c_w1(gspca_dev, 0x19, 0x01);
1999 i2c_w1(gspca_dev, 0x1a, 0x79);
2000 i2c_w1(gspca_dev, 0x12, 0x40);
2001 sd->hstart = 60;
2002 sd->vstart = 11;
2003 }
2004 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002005 case SENSOR_OV9650:
2006 if (mode & MODE_SXGA) {
2007 i2c_w1(gspca_dev, 0x17, 0x1b);
2008 i2c_w1(gspca_dev, 0x18, 0xbc);
2009 i2c_w1(gspca_dev, 0x19, 0x01);
2010 i2c_w1(gspca_dev, 0x1a, 0x82);
2011 i2c_r1(gspca_dev, 0x12, &value);
2012 i2c_w1(gspca_dev, 0x12, value & 0x07);
2013 } else {
2014 i2c_w1(gspca_dev, 0x17, 0x24);
2015 i2c_w1(gspca_dev, 0x18, 0xc5);
2016 i2c_w1(gspca_dev, 0x19, 0x00);
2017 i2c_w1(gspca_dev, 0x1a, 0x3c);
2018 i2c_r1(gspca_dev, 0x12, &value);
2019 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2020 }
2021 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002022 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002023 case SENSOR_MT9M111:
2024 if (mode & MODE_SXGA) {
2025 i2c_w2(gspca_dev, 0xf0, 0x0002);
2026 i2c_w2(gspca_dev, 0xc8, 0x970b);
2027 i2c_w2(gspca_dev, 0xf0, 0x0000);
2028 } else {
2029 i2c_w2(gspca_dev, 0xf0, 0x0002);
2030 i2c_w2(gspca_dev, 0xc8, 0x8000);
2031 i2c_w2(gspca_dev, 0xf0, 0x0000);
2032 }
2033 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002034 }
2035}
2036
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002037static int sd_isoc_init(struct gspca_dev *gspca_dev)
2038{
2039 struct usb_interface *intf;
2040 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2041
2042 /*
2043 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2044 * than our regular bandwidth calculations reserve, so we force the
2045 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2046 */
2047 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2048 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2049
2050 if (intf->num_altsetting != 9) {
2051 pr_warn("sn9c20x camera with unknown number of alt "
2052 "settings (%d), please report!\n",
2053 intf->num_altsetting);
2054 gspca_dev->alt = intf->num_altsetting;
2055 return 0;
2056 }
2057
2058 switch (gspca_dev->width) {
2059 case 160: /* 160x120 */
2060 gspca_dev->alt = 2;
2061 break;
2062 case 320: /* 320x240 */
2063 gspca_dev->alt = 6;
2064 break;
2065 default: /* >= 640x480 */
2066 gspca_dev->alt = 9;
2067 }
2068 }
2069
2070 return 0;
2071}
2072
Brian Johnson26e744b2009-07-19 05:52:58 -03002073#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002074((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002075(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2076(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2077
2078#define CLR_WIN(width, height) \
2079((const u8 [])\
2080{0, width >> 2, 0, height >> 1,\
2081((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2082
2083static int sd_start(struct gspca_dev *gspca_dev)
2084{
2085 struct sd *sd = (struct sd *) gspca_dev;
2086 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2087 int width = gspca_dev->width;
2088 int height = gspca_dev->height;
2089 u8 fmt, scale = 0;
2090
Brian Johnson26e744b2009-07-19 05:52:58 -03002091 jpeg_define(sd->jpeg_hdr, height, width,
2092 0x21);
Jean-François Moine4c632e42012-03-19 04:35:34 -03002093 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03002094
2095 if (mode & MODE_RAW)
2096 fmt = 0x2d;
2097 else if (mode & MODE_JPEG)
Jean-François Moine4c632e42012-03-19 04:35:34 -03002098 fmt = 0x24;
Brian Johnson26e744b2009-07-19 05:52:58 -03002099 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002100 fmt = 0x2f; /* YUV 420 */
Jean-François Moine4c632e42012-03-19 04:35:34 -03002101 sd->fmt = fmt;
Brian Johnson26e744b2009-07-19 05:52:58 -03002102
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002103 switch (mode & SCALE_MASK) {
2104 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002105 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002106 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002107 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002108 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002109 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002110 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002111 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002112 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002113 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002114 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002115 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002116 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002117 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002118 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002119 break;
2120 }
2121
2122 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002123 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2124 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002125 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2126 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2127 reg_w1(gspca_dev, 0x1189, scale);
2128 reg_w1(gspca_dev, 0x10e0, fmt);
2129
2130 set_cmatrix(gspca_dev);
2131 set_gamma(gspca_dev);
2132 set_redblue(gspca_dev);
2133 set_gain(gspca_dev);
2134 set_exposure(gspca_dev);
2135 set_hvflip(gspca_dev);
2136
Brian Johnson0c045eb2010-03-16 13:58:27 -03002137 reg_w1(gspca_dev, 0x1007, 0x20);
2138
Brian Johnson26e744b2009-07-19 05:52:58 -03002139 reg_r(gspca_dev, 0x1061, 1);
2140 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002141 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002142}
2143
2144static void sd_stopN(struct gspca_dev *gspca_dev)
2145{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002146 reg_w1(gspca_dev, 0x1007, 0x00);
2147
Brian Johnson26e744b2009-07-19 05:52:58 -03002148 reg_r(gspca_dev, 0x1061, 1);
2149 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2150}
2151
Brian Johnsone1430472009-09-02 12:39:41 -03002152static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002153{
2154 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002155 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002156
2157 /*
2158 * some hardcoded values are present
2159 * like those for maximal/minimal exposure
2160 * and exposure steps
2161 */
2162 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002163 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002164 return;
2165
Jean-François Moinec5224d82012-03-19 04:30:07 -03002166 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002167 if (new_exp > 0x1770)
2168 new_exp = 0x1770;
2169 if (new_exp < 0x10)
2170 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002171 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002172 set_exposure(gspca_dev);
2173
2174 sd->older_step = sd->old_step;
2175 sd->old_step = 1;
2176
2177 if (sd->old_step ^ sd->older_step)
2178 sd->exposure_step /= 2;
2179 else
2180 sd->exposure_step += 2;
2181 }
2182 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002183 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002184 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002185 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002186 if (new_exp > 0x1700)
2187 new_exp = 0x1770;
2188 if (new_exp < 0x10)
2189 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002190 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002191 set_exposure(gspca_dev);
2192 sd->older_step = sd->old_step;
2193 sd->old_step = 0;
2194
2195 if (sd->old_step ^ sd->older_step)
2196 sd->exposure_step /= 2;
2197 else
2198 sd->exposure_step += 2;
2199 }
2200}
2201
Brian Johnsone1430472009-09-02 12:39:41 -03002202static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2203{
2204 struct sd *sd = (struct sd *) gspca_dev;
2205
2206 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002207 if (sd->ctrls[GAIN].val + 1 <= 28) {
2208 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002209 set_gain(gspca_dev);
2210 }
2211 }
2212 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002213 if (sd->ctrls[GAIN].val > 0) {
2214 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002215 set_gain(gspca_dev);
2216 }
2217 }
2218}
2219
2220static void sd_dqcallback(struct gspca_dev *gspca_dev)
2221{
2222 struct sd *sd = (struct sd *) gspca_dev;
2223 int avg_lum;
2224
Jean-François Moinec5224d82012-03-19 04:30:07 -03002225 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002226 return;
2227
2228 avg_lum = atomic_read(&sd->avg_lum);
2229 if (sd->sensor == SENSOR_SOI968)
2230 do_autogain(gspca_dev, avg_lum);
2231 else
2232 do_autoexposure(gspca_dev, avg_lum);
2233}
2234
Jean-François Moine28566432010-10-01 07:33:26 -03002235#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002236static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2237 u8 *data, /* interrupt packet */
2238 int len) /* interrupt packet length */
2239{
2240 struct sd *sd = (struct sd *) gspca_dev;
2241 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002242 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002243 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2244 input_sync(gspca_dev->input_dev);
2245 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2246 input_sync(gspca_dev->input_dev);
2247 ret = 0;
2248 }
2249 return ret;
2250}
2251#endif
2252
Brian Johnson26e744b2009-07-19 05:52:58 -03002253static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002254 u8 *data, /* isoc packet */
2255 int len) /* iso packet length */
2256{
2257 struct sd *sd = (struct sd *) gspca_dev;
2258 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002259 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002260 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002261 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002262 avg_lum = ((data[35] >> 2) & 3) |
2263 (data[20] << 2) |
2264 (data[19] << 10);
2265 avg_lum += ((data[35] >> 4) & 3) |
2266 (data[22] << 2) |
2267 (data[21] << 10);
2268 avg_lum += ((data[35] >> 6) & 3) |
2269 (data[24] << 2) |
2270 (data[23] << 10);
2271 avg_lum += (data[36] & 3) |
2272 (data[26] << 2) |
2273 (data[25] << 10);
2274 avg_lum += ((data[36] >> 2) & 3) |
2275 (data[28] << 2) |
2276 (data[27] << 10);
2277 avg_lum += ((data[36] >> 4) & 3) |
2278 (data[30] << 2) |
2279 (data[29] << 10);
2280 avg_lum += ((data[36] >> 6) & 3) |
2281 (data[32] << 2) |
2282 (data[31] << 10);
2283 avg_lum += ((data[44] >> 4) & 3) |
2284 (data[34] << 2) |
2285 (data[33] << 10);
2286 avg_lum >>= 9;
2287 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002288 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002289 len -= 64;
2290 if (len == 0)
2291 return;
2292 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002293 }
2294 if (gspca_dev->last_packet_type == LAST_PACKET) {
2295 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2296 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002297 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002298 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002299 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002300 data, len);
2301 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002302 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002303 data, len);
2304 }
2305 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002306 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002307 }
2308}
2309
2310/* sub-driver description */
2311static const struct sd_desc sd_desc = {
2312 .name = MODULE_NAME,
2313 .ctrls = sd_ctrls,
2314 .nctrls = ARRAY_SIZE(sd_ctrls),
2315 .config = sd_config,
2316 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002317 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002318 .start = sd_start,
2319 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002320 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002321#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002322 .int_pkt_scan = sd_int_pkt_scan,
2323#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002324 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002325#ifdef CONFIG_VIDEO_ADV_DEBUG
2326 .set_register = sd_dbg_s_register,
2327 .get_register = sd_dbg_g_register,
2328#endif
2329 .get_chip_ident = sd_chip_ident,
2330};
2331
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002332#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002333 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002334 | (SENSOR_ ## sensor << 8) \
2335 | (i2c_addr)
2336
Jean-François Moine95c967c2011-01-13 05:20:29 -03002337static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002338 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2339 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2340 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002341 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002342 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2343 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2344 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002345 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2346 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2347 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2348 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002349 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002350 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2351 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2352 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2353 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002354 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002355 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002356 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2357 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2358 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2359 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002360 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002361 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002362 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2363 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2364 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2365 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002366 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2367 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002368 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2369 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2370 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2371 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002372 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002373 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2374 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2375 {}
2376};
2377MODULE_DEVICE_TABLE(usb, device_table);
2378
2379/* -- device connect -- */
2380static int sd_probe(struct usb_interface *intf,
2381 const struct usb_device_id *id)
2382{
2383 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2384 THIS_MODULE);
2385}
2386
Brian Johnson26e744b2009-07-19 05:52:58 -03002387static struct usb_driver sd_driver = {
2388 .name = MODULE_NAME,
2389 .id_table = device_table,
2390 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002391 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002392#ifdef CONFIG_PM
2393 .suspend = gspca_suspend,
2394 .resume = gspca_resume,
2395 .reset_resume = gspca_resume,
2396#endif
2397};
2398
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002399module_usb_driver(sd_driver);