blob: 2a670eadca1cd70af6191d7399fb18813047db44 [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 Moine92dcffc2012-03-19 04:47:24 -030092 struct work_struct work;
93 struct workqueue_struct *work_thread;
94
95 u32 pktsz; /* (used by pkt_scan) */
96 u16 npkt;
97 s8 nchg;
Jean-François Moine4c632e42012-03-19 04:35:34 -030098 u8 fmt; /* (used for JPEG QTAB update */
99
Brian Johnson26e744b2009-07-19 05:52:58 -0300100#define MIN_AVG_LUM 80
101#define MAX_AVG_LUM 130
102 atomic_t avg_lum;
103 u8 old_step;
104 u8 older_step;
105 u8 exposure_step;
106
Brian Johnson26e744b2009-07-19 05:52:58 -0300107 u8 i2c_addr;
108 u8 sensor;
109 u8 hstart;
110 u8 vstart;
111
Jean-François Moine9a731a32010-06-04 05:26:42 -0300112 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300113
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300114 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300115};
116
Jean-François Moine92dcffc2012-03-19 04:47:24 -0300117static void qual_upd(struct work_struct *work);
118
Joe Perches58aa68c2009-09-02 01:12:13 -0300119struct i2c_reg_u8 {
120 u8 reg;
121 u8 val;
122};
123
124struct i2c_reg_u16 {
125 u8 reg;
126 u16 val;
127};
128
Brian Johnson7ddaac72010-03-16 13:58:27 -0300129static const struct dmi_system_id flip_dmi_table[] = {
130 {
131 .ident = "MSI MS-1034",
132 .matches = {
133 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
134 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
135 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
136 }
137 },
138 {
139 .ident = "MSI MS-1632",
140 .matches = {
141 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
142 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
143 }
144 },
Brian Johnsone077f862010-04-05 20:52:52 -0300145 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300146 .ident = "MSI MS-1633X",
147 .matches = {
148 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
149 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
150 }
151 },
152 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300153 .ident = "MSI MS-1635X",
154 .matches = {
155 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
156 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
157 }
158 },
159 {
Brian Johnsone077f862010-04-05 20:52:52 -0300160 .ident = "ASUSTeK W7J",
161 .matches = {
162 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
163 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
164 }
165 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300166 {}
167};
168
Jean-François Moinec5224d82012-03-19 04:30:07 -0300169static void set_cmatrix(struct gspca_dev *gspca_dev);
170static void set_gamma(struct gspca_dev *gspca_dev);
171static void set_redblue(struct gspca_dev *gspca_dev);
172static void set_hvflip(struct gspca_dev *gspca_dev);
173static void set_exposure(struct gspca_dev *gspca_dev);
174static void set_gain(struct gspca_dev *gspca_dev);
Jean-François Moine4c632e42012-03-19 04:35:34 -0300175static void set_quality(struct gspca_dev *gspca_dev);
Jean-François Moinec5224d82012-03-19 04:30:07 -0300176
177static const struct ctrl sd_ctrls[NCTRLS] = {
178[BRIGHTNESS] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300179 {
180 .id = V4L2_CID_BRIGHTNESS,
181 .type = V4L2_CTRL_TYPE_INTEGER,
182 .name = "Brightness",
183 .minimum = 0,
184 .maximum = 0xff,
185 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300186 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300187 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300188 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300189 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300190[CONTRAST] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300191 {
192 .id = V4L2_CID_CONTRAST,
193 .type = V4L2_CTRL_TYPE_INTEGER,
194 .name = "Contrast",
195 .minimum = 0,
196 .maximum = 0xff,
197 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300198 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300199 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300200 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300201 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300202[SATURATION] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300203 {
204 .id = V4L2_CID_SATURATION,
205 .type = V4L2_CTRL_TYPE_INTEGER,
206 .name = "Saturation",
207 .minimum = 0,
208 .maximum = 0xff,
209 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300210 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300211 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300212 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300213 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300214[HUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300215 {
216 .id = V4L2_CID_HUE,
217 .type = V4L2_CTRL_TYPE_INTEGER,
218 .name = "Hue",
219 .minimum = -180,
220 .maximum = 180,
221 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300222 .default_value = 0
Brian Johnson26e744b2009-07-19 05:52:58 -0300223 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300224 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300225 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300226[GAMMA] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300227 {
228 .id = V4L2_CID_GAMMA,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "Gamma",
231 .minimum = 0,
232 .maximum = 0xff,
233 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300234 .default_value = 0x10
Brian Johnson26e744b2009-07-19 05:52:58 -0300235 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300236 .set_control = set_gamma
Brian Johnson26e744b2009-07-19 05:52:58 -0300237 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300238[BLUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300239 {
240 .id = V4L2_CID_BLUE_BALANCE,
241 .type = V4L2_CTRL_TYPE_INTEGER,
242 .name = "Blue Balance",
243 .minimum = 0,
244 .maximum = 0x7f,
245 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300246 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300247 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300248 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300249 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300250[RED] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300251 {
252 .id = V4L2_CID_RED_BALANCE,
253 .type = V4L2_CTRL_TYPE_INTEGER,
254 .name = "Red Balance",
255 .minimum = 0,
256 .maximum = 0x7f,
257 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300258 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300259 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300260 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300261 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300262[HFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300263 {
264 .id = V4L2_CID_HFLIP,
265 .type = V4L2_CTRL_TYPE_BOOLEAN,
266 .name = "Horizontal Flip",
267 .minimum = 0,
268 .maximum = 1,
269 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300270 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300271 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300272 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300273 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300274[VFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300275 {
276 .id = V4L2_CID_VFLIP,
277 .type = V4L2_CTRL_TYPE_BOOLEAN,
278 .name = "Vertical Flip",
279 .minimum = 0,
280 .maximum = 1,
281 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300282 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300283 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300284 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300285 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300286[EXPOSURE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300287 {
288 .id = V4L2_CID_EXPOSURE,
289 .type = V4L2_CTRL_TYPE_INTEGER,
290 .name = "Exposure",
291 .minimum = 0,
292 .maximum = 0x1780,
293 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300294 .default_value = 0x33,
Brian Johnson26e744b2009-07-19 05:52:58 -0300295 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300296 .set_control = set_exposure
Brian Johnson26e744b2009-07-19 05:52:58 -0300297 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300298[GAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300299 {
300 .id = V4L2_CID_GAIN,
301 .type = V4L2_CTRL_TYPE_INTEGER,
302 .name = "Gain",
303 .minimum = 0,
304 .maximum = 28,
305 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300306 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300307 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300308 .set_control = set_gain
Brian Johnson26e744b2009-07-19 05:52:58 -0300309 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300310[AUTOGAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300311 {
312 .id = V4L2_CID_AUTOGAIN,
313 .type = V4L2_CTRL_TYPE_BOOLEAN,
314 .name = "Auto Exposure",
315 .minimum = 0,
316 .maximum = 1,
317 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300318 .default_value = 1,
Brian Johnson26e744b2009-07-19 05:52:58 -0300319 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300320 },
Jean-François Moine4c632e42012-03-19 04:35:34 -0300321[QUALITY] = {
322 {
323 .id = V4L2_CID_JPEG_COMPRESSION_QUALITY,
324 .type = V4L2_CTRL_TYPE_INTEGER,
325 .name = "Compression Quality",
326#define QUALITY_MIN 50
327#define QUALITY_MAX 90
328#define QUALITY_DEF 80
329 .minimum = QUALITY_MIN,
330 .maximum = QUALITY_MAX,
331 .step = 1,
332 .default_value = QUALITY_DEF,
333 },
334 .set_control = set_quality
335 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300336};
337
338static const struct v4l2_pix_format vga_mode[] = {
339 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300340 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300341 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300342 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300343 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300344 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
345 .bytesperline = 160,
346 .sizeimage = 160 * 120,
347 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300348 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300349 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300350 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300351 .sizeimage = 240 * 120,
352 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300353 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300354 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300355 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300356 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300357 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300358 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300359 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
360 .bytesperline = 320,
361 .sizeimage = 320 * 240 ,
362 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300363 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300364 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300365 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300366 .sizeimage = 480 * 240 ,
367 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300368 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300369 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300370 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300371 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300372 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300373 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300374 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
375 .bytesperline = 640,
376 .sizeimage = 640 * 480,
377 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300378 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300379 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300380 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300381 .sizeimage = 960 * 480,
382 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300383 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300384};
385
386static const struct v4l2_pix_format sxga_mode[] = {
387 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300388 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300389 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300390 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300391 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300392 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
393 .bytesperline = 160,
394 .sizeimage = 160 * 120,
395 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300396 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300397 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300398 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300399 .sizeimage = 240 * 120,
400 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300401 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300402 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300403 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300404 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300405 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300406 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300407 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
408 .bytesperline = 320,
409 .sizeimage = 320 * 240 ,
410 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300411 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300412 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300413 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300414 .sizeimage = 480 * 240 ,
415 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300416 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300417 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300418 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300419 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300420 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300421 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300422 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
423 .bytesperline = 640,
424 .sizeimage = 640 * 480,
425 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300426 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300427 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300428 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300429 .sizeimage = 960 * 480,
430 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300431 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300432 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
433 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300434 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300435 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300436 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300437};
438
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300439static const struct v4l2_pix_format mono_mode[] = {
440 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
441 .bytesperline = 160,
442 .sizeimage = 160 * 120,
443 .colorspace = V4L2_COLORSPACE_SRGB,
444 .priv = SCALE_160x120 | MODE_RAW},
445 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
446 .bytesperline = 320,
447 .sizeimage = 320 * 240 ,
448 .colorspace = V4L2_COLORSPACE_SRGB,
449 .priv = SCALE_320x240 | MODE_RAW},
450 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
451 .bytesperline = 640,
452 .sizeimage = 640 * 480,
453 .colorspace = V4L2_COLORSPACE_SRGB,
454 .priv = SCALE_640x480 | MODE_RAW},
455 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
456 .bytesperline = 1280,
457 .sizeimage = 1280 * 1024,
458 .colorspace = V4L2_COLORSPACE_SRGB,
459 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
460};
461
Joe Perches58aa68c2009-09-02 01:12:13 -0300462static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300463 41, 44, 46, 48, 50, 52, 54, 56,
464 58, 60, 62, 64, 66, 68, 70, 72,
465 74, 76, 78, 80, 81, 83, 85, 87,
466 88, 90, 92, 93, 95, 97, 98, 100,
467 101, 102, 104, 105, 107, 108, 109, 110,
468 112, 113, 114, 115, 116, 117, 118, 119,
469 120, 121, 122, 123, 123, 124, 125, 125,
470 126, 127, 127, 128, 128, 129, 129, 129,
471 130, 130, 130, 130, 131, 131, 131, 131,
472 131, 131, 131, 131, 130, 130, 130, 130,
473 129, 129, 129, 128, 128, 127, 127, 126,
474 125, 125, 124, 123, 122, 122, 121, 120,
475 119, 118, 117, 116, 115, 114, 112, 111,
476 110, 109, 107, 106, 105, 103, 102, 101,
477 99, 98, 96, 94, 93, 91, 90, 88,
478 86, 84, 83, 81, 79, 77, 75, 74,
479 72, 70, 68, 66, 64, 62, 60, 58,
480 56, 54, 52, 49, 47, 45, 43, 41,
481 39, 36, 34, 32, 30, 28, 25, 23,
482 21, 19, 16, 14, 12, 9, 7, 5,
483 3, 0, -1, -3, -6, -8, -10, -12,
484 -15, -17, -19, -22, -24, -26, -28, -30,
485 -33, -35, -37, -39, -41, -44, -46, -48,
486 -50, -52, -54, -56, -58, -60, -62, -64,
487 -66, -68, -70, -72, -74, -76, -78, -80,
488 -81, -83, -85, -87, -88, -90, -92, -93,
489 -95, -97, -98, -100, -101, -102, -104, -105,
490 -107, -108, -109, -110, -112, -113, -114, -115,
491 -116, -117, -118, -119, -120, -121, -122, -123,
492 -123, -124, -125, -125, -126, -127, -127, -128,
493 -128, -128, -128, -128, -128, -128, -128, -128,
494 -128, -128, -128, -128, -128, -128, -128, -128,
495 -128, -128, -128, -128, -128, -128, -128, -128,
496 -128, -127, -127, -126, -125, -125, -124, -123,
497 -122, -122, -121, -120, -119, -118, -117, -116,
498 -115, -114, -112, -111, -110, -109, -107, -106,
499 -105, -103, -102, -101, -99, -98, -96, -94,
500 -93, -91, -90, -88, -86, -84, -83, -81,
501 -79, -77, -75, -74, -72, -70, -68, -66,
502 -64, -62, -60, -58, -56, -54, -52, -49,
503 -47, -45, -43, -41, -39, -36, -34, -32,
504 -30, -28, -25, -23, -21, -19, -16, -14,
505 -12, -9, -7, -5, -3, 0, 1, 3,
506 6, 8, 10, 12, 15, 17, 19, 22,
507 24, 26, 28, 30, 33, 35, 37, 39, 41
508};
509
Joe Perches58aa68c2009-09-02 01:12:13 -0300510static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300511 82, 80, 78, 76, 74, 73, 71, 69,
512 67, 65, 63, 61, 58, 56, 54, 52,
513 50, 48, 46, 44, 41, 39, 37, 35,
514 32, 30, 28, 26, 23, 21, 19, 16,
515 14, 12, 10, 7, 5, 3, 0, -1,
516 -3, -6, -8, -10, -13, -15, -17, -19,
517 -22, -24, -26, -29, -31, -33, -35, -38,
518 -40, -42, -44, -46, -48, -51, -53, -55,
519 -57, -59, -61, -63, -65, -67, -69, -71,
520 -73, -75, -77, -79, -81, -82, -84, -86,
521 -88, -89, -91, -93, -94, -96, -98, -99,
522 -101, -102, -104, -105, -106, -108, -109, -110,
523 -112, -113, -114, -115, -116, -117, -119, -120,
524 -120, -121, -122, -123, -124, -125, -126, -126,
525 -127, -128, -128, -128, -128, -128, -128, -128,
526 -128, -128, -128, -128, -128, -128, -128, -128,
527 -128, -128, -128, -128, -128, -128, -128, -128,
528 -128, -128, -128, -128, -128, -128, -128, -128,
529 -127, -127, -126, -125, -125, -124, -123, -122,
530 -121, -120, -119, -118, -117, -116, -115, -114,
531 -113, -111, -110, -109, -107, -106, -105, -103,
532 -102, -100, -99, -97, -96, -94, -92, -91,
533 -89, -87, -85, -84, -82, -80, -78, -76,
534 -74, -73, -71, -69, -67, -65, -63, -61,
535 -58, -56, -54, -52, -50, -48, -46, -44,
536 -41, -39, -37, -35, -32, -30, -28, -26,
537 -23, -21, -19, -16, -14, -12, -10, -7,
538 -5, -3, 0, 1, 3, 6, 8, 10,
539 13, 15, 17, 19, 22, 24, 26, 29,
540 31, 33, 35, 38, 40, 42, 44, 46,
541 48, 51, 53, 55, 57, 59, 61, 63,
542 65, 67, 69, 71, 73, 75, 77, 79,
543 81, 82, 84, 86, 88, 89, 91, 93,
544 94, 96, 98, 99, 101, 102, 104, 105,
545 106, 108, 109, 110, 112, 113, 114, 115,
546 116, 117, 119, 120, 120, 121, 122, 123,
547 124, 125, 126, 126, 127, 128, 128, 129,
548 129, 130, 130, 131, 131, 131, 131, 132,
549 132, 132, 132, 132, 132, 132, 132, 132,
550 132, 132, 132, 131, 131, 131, 130, 130,
551 130, 129, 129, 128, 127, 127, 126, 125,
552 125, 124, 123, 122, 121, 120, 119, 118,
553 117, 116, 115, 114, 113, 111, 110, 109,
554 107, 106, 105, 103, 102, 100, 99, 97,
555 96, 94, 92, 91, 89, 87, 85, 84, 82
556};
557
Joe Perches58aa68c2009-09-02 01:12:13 -0300558static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300559 -124, -124, -125, -125, -125, -125, -125, -125,
560 -125, -126, -126, -125, -125, -125, -125, -125,
561 -125, -124, -124, -124, -123, -123, -122, -122,
562 -121, -121, -120, -120, -119, -118, -117, -117,
563 -116, -115, -114, -113, -112, -111, -110, -109,
564 -108, -107, -105, -104, -103, -102, -100, -99,
565 -98, -96, -95, -93, -92, -91, -89, -87,
566 -86, -84, -83, -81, -79, -77, -76, -74,
567 -72, -70, -69, -67, -65, -63, -61, -59,
568 -57, -55, -53, -51, -49, -47, -45, -43,
569 -41, -39, -37, -35, -33, -30, -28, -26,
570 -24, -22, -20, -18, -15, -13, -11, -9,
571 -7, -4, -2, 0, 1, 3, 6, 8,
572 10, 12, 14, 17, 19, 21, 23, 25,
573 27, 29, 32, 34, 36, 38, 40, 42,
574 44, 46, 48, 50, 52, 54, 56, 58,
575 60, 62, 64, 66, 68, 70, 71, 73,
576 75, 77, 78, 80, 82, 83, 85, 87,
577 88, 90, 91, 93, 94, 96, 97, 98,
578 100, 101, 102, 104, 105, 106, 107, 108,
579 109, 111, 112, 113, 113, 114, 115, 116,
580 117, 118, 118, 119, 120, 120, 121, 122,
581 122, 123, 123, 124, 124, 124, 125, 125,
582 125, 125, 125, 125, 125, 126, 126, 125,
583 125, 125, 125, 125, 125, 124, 124, 124,
584 123, 123, 122, 122, 121, 121, 120, 120,
585 119, 118, 117, 117, 116, 115, 114, 113,
586 112, 111, 110, 109, 108, 107, 105, 104,
587 103, 102, 100, 99, 98, 96, 95, 93,
588 92, 91, 89, 87, 86, 84, 83, 81,
589 79, 77, 76, 74, 72, 70, 69, 67,
590 65, 63, 61, 59, 57, 55, 53, 51,
591 49, 47, 45, 43, 41, 39, 37, 35,
592 33, 30, 28, 26, 24, 22, 20, 18,
593 15, 13, 11, 9, 7, 4, 2, 0,
594 -1, -3, -6, -8, -10, -12, -14, -17,
595 -19, -21, -23, -25, -27, -29, -32, -34,
596 -36, -38, -40, -42, -44, -46, -48, -50,
597 -52, -54, -56, -58, -60, -62, -64, -66,
598 -68, -70, -71, -73, -75, -77, -78, -80,
599 -82, -83, -85, -87, -88, -90, -91, -93,
600 -94, -96, -97, -98, -100, -101, -102, -104,
601 -105, -106, -107, -108, -109, -111, -112, -113,
602 -113, -114, -115, -116, -117, -118, -118, -119,
603 -120, -120, -121, -122, -122, -123, -123, -124, -124
604};
605
Joe Perches58aa68c2009-09-02 01:12:13 -0300606static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300607 -100, -99, -98, -97, -95, -94, -93, -91,
608 -90, -89, -87, -86, -84, -83, -81, -80,
609 -78, -76, -75, -73, -71, -70, -68, -66,
610 -64, -63, -61, -59, -57, -55, -53, -51,
611 -49, -48, -46, -44, -42, -40, -38, -36,
612 -34, -32, -30, -27, -25, -23, -21, -19,
613 -17, -15, -13, -11, -9, -7, -4, -2,
614 0, 1, 3, 5, 7, 9, 11, 14,
615 16, 18, 20, 22, 24, 26, 28, 30,
616 32, 34, 36, 38, 40, 42, 44, 46,
617 48, 50, 52, 54, 56, 58, 59, 61,
618 63, 65, 67, 68, 70, 72, 74, 75,
619 77, 78, 80, 82, 83, 85, 86, 88,
620 89, 90, 92, 93, 95, 96, 97, 98,
621 100, 101, 102, 103, 104, 105, 106, 107,
622 108, 109, 110, 111, 112, 112, 113, 114,
623 115, 115, 116, 116, 117, 117, 118, 118,
624 119, 119, 119, 120, 120, 120, 120, 120,
625 121, 121, 121, 121, 121, 121, 120, 120,
626 120, 120, 120, 119, 119, 119, 118, 118,
627 117, 117, 116, 116, 115, 114, 114, 113,
628 112, 111, 111, 110, 109, 108, 107, 106,
629 105, 104, 103, 102, 100, 99, 98, 97,
630 95, 94, 93, 91, 90, 89, 87, 86,
631 84, 83, 81, 80, 78, 76, 75, 73,
632 71, 70, 68, 66, 64, 63, 61, 59,
633 57, 55, 53, 51, 49, 48, 46, 44,
634 42, 40, 38, 36, 34, 32, 30, 27,
635 25, 23, 21, 19, 17, 15, 13, 11,
636 9, 7, 4, 2, 0, -1, -3, -5,
637 -7, -9, -11, -14, -16, -18, -20, -22,
638 -24, -26, -28, -30, -32, -34, -36, -38,
639 -40, -42, -44, -46, -48, -50, -52, -54,
640 -56, -58, -59, -61, -63, -65, -67, -68,
641 -70, -72, -74, -75, -77, -78, -80, -82,
642 -83, -85, -86, -88, -89, -90, -92, -93,
643 -95, -96, -97, -98, -100, -101, -102, -103,
644 -104, -105, -106, -107, -108, -109, -110, -111,
645 -112, -112, -113, -114, -115, -115, -116, -116,
646 -117, -117, -118, -118, -119, -119, -119, -120,
647 -120, -120, -120, -120, -121, -121, -121, -121,
648 -121, -121, -120, -120, -120, -120, -120, -119,
649 -119, -119, -118, -118, -117, -117, -116, -116,
650 -115, -114, -114, -113, -112, -111, -111, -110,
651 -109, -108, -107, -106, -105, -104, -103, -102, -100
652};
653
Joe Perches58aa68c2009-09-02 01:12:13 -0300654static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300655 112, 113, 114, 114, 115, 116, 117, 117,
656 118, 118, 119, 119, 120, 120, 120, 121,
657 121, 121, 122, 122, 122, 122, 122, 122,
658 122, 122, 122, 122, 122, 122, 121, 121,
659 121, 120, 120, 120, 119, 119, 118, 118,
660 117, 116, 116, 115, 114, 113, 113, 112,
661 111, 110, 109, 108, 107, 106, 105, 104,
662 103, 102, 100, 99, 98, 97, 95, 94,
663 93, 91, 90, 88, 87, 85, 84, 82,
664 80, 79, 77, 76, 74, 72, 70, 69,
665 67, 65, 63, 61, 60, 58, 56, 54,
666 52, 50, 48, 46, 44, 42, 40, 38,
667 36, 34, 32, 30, 28, 26, 24, 22,
668 19, 17, 15, 13, 11, 9, 7, 5,
669 2, 0, -1, -3, -5, -7, -9, -12,
670 -14, -16, -18, -20, -22, -24, -26, -28,
671 -31, -33, -35, -37, -39, -41, -43, -45,
672 -47, -49, -51, -53, -54, -56, -58, -60,
673 -62, -64, -66, -67, -69, -71, -73, -74,
674 -76, -78, -79, -81, -83, -84, -86, -87,
675 -89, -90, -92, -93, -94, -96, -97, -98,
676 -99, -101, -102, -103, -104, -105, -106, -107,
677 -108, -109, -110, -111, -112, -113, -114, -114,
678 -115, -116, -117, -117, -118, -118, -119, -119,
679 -120, -120, -120, -121, -121, -121, -122, -122,
680 -122, -122, -122, -122, -122, -122, -122, -122,
681 -122, -122, -121, -121, -121, -120, -120, -120,
682 -119, -119, -118, -118, -117, -116, -116, -115,
683 -114, -113, -113, -112, -111, -110, -109, -108,
684 -107, -106, -105, -104, -103, -102, -100, -99,
685 -98, -97, -95, -94, -93, -91, -90, -88,
686 -87, -85, -84, -82, -80, -79, -77, -76,
687 -74, -72, -70, -69, -67, -65, -63, -61,
688 -60, -58, -56, -54, -52, -50, -48, -46,
689 -44, -42, -40, -38, -36, -34, -32, -30,
690 -28, -26, -24, -22, -19, -17, -15, -13,
691 -11, -9, -7, -5, -2, 0, 1, 3,
692 5, 7, 9, 12, 14, 16, 18, 20,
693 22, 24, 26, 28, 31, 33, 35, 37,
694 39, 41, 43, 45, 47, 49, 51, 53,
695 54, 56, 58, 60, 62, 64, 66, 67,
696 69, 71, 73, 74, 76, 78, 79, 81,
697 83, 84, 86, 87, 89, 90, 92, 93,
698 94, 96, 97, 98, 99, 101, 102, 103,
699 104, 105, 106, 107, 108, 109, 110, 111, 112
700};
701
Joe Perches58aa68c2009-09-02 01:12:13 -0300702static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300703 -11, -13, -15, -17, -19, -21, -23, -25,
704 -27, -29, -31, -33, -35, -37, -39, -41,
705 -43, -45, -46, -48, -50, -52, -54, -55,
706 -57, -59, -61, -62, -64, -66, -67, -69,
707 -71, -72, -74, -75, -77, -78, -80, -81,
708 -83, -84, -86, -87, -88, -90, -91, -92,
709 -93, -95, -96, -97, -98, -99, -100, -101,
710 -102, -103, -104, -105, -106, -106, -107, -108,
711 -109, -109, -110, -111, -111, -112, -112, -113,
712 -113, -114, -114, -114, -115, -115, -115, -115,
713 -116, -116, -116, -116, -116, -116, -116, -116,
714 -116, -115, -115, -115, -115, -114, -114, -114,
715 -113, -113, -112, -112, -111, -111, -110, -110,
716 -109, -108, -108, -107, -106, -105, -104, -103,
717 -102, -101, -100, -99, -98, -97, -96, -95,
718 -94, -93, -91, -90, -89, -88, -86, -85,
719 -84, -82, -81, -79, -78, -76, -75, -73,
720 -71, -70, -68, -67, -65, -63, -62, -60,
721 -58, -56, -55, -53, -51, -49, -47, -45,
722 -44, -42, -40, -38, -36, -34, -32, -30,
723 -28, -26, -24, -22, -20, -18, -16, -14,
724 -12, -10, -8, -6, -4, -2, 0, 1,
725 3, 5, 7, 9, 11, 13, 15, 17,
726 19, 21, 23, 25, 27, 29, 31, 33,
727 35, 37, 39, 41, 43, 45, 46, 48,
728 50, 52, 54, 55, 57, 59, 61, 62,
729 64, 66, 67, 69, 71, 72, 74, 75,
730 77, 78, 80, 81, 83, 84, 86, 87,
731 88, 90, 91, 92, 93, 95, 96, 97,
732 98, 99, 100, 101, 102, 103, 104, 105,
733 106, 106, 107, 108, 109, 109, 110, 111,
734 111, 112, 112, 113, 113, 114, 114, 114,
735 115, 115, 115, 115, 116, 116, 116, 116,
736 116, 116, 116, 116, 116, 115, 115, 115,
737 115, 114, 114, 114, 113, 113, 112, 112,
738 111, 111, 110, 110, 109, 108, 108, 107,
739 106, 105, 104, 103, 102, 101, 100, 99,
740 98, 97, 96, 95, 94, 93, 91, 90,
741 89, 88, 86, 85, 84, 82, 81, 79,
742 78, 76, 75, 73, 71, 70, 68, 67,
743 65, 63, 62, 60, 58, 56, 55, 53,
744 51, 49, 47, 45, 44, 42, 40, 38,
745 36, 34, 32, 30, 28, 26, 24, 22,
746 20, 18, 16, 14, 12, 10, 8, 6,
747 4, 2, 0, -1, -3, -5, -7, -9, -11
748};
749
750static u16 i2c_ident[] = {
751 V4L2_IDENT_OV9650,
752 V4L2_IDENT_OV9655,
753 V4L2_IDENT_SOI968,
754 V4L2_IDENT_OV7660,
755 V4L2_IDENT_OV7670,
756 V4L2_IDENT_MT9V011,
757 V4L2_IDENT_MT9V111,
758 V4L2_IDENT_MT9V112,
759 V4L2_IDENT_MT9M001C12ST,
760 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300761 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300762 V4L2_IDENT_HV7131R,
763};
764
765static u16 bridge_init[][2] = {
766 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
767 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
768 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
769 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
770 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
771 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
772 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
773 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
774 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
775 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
776 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
777 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
778 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
779 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
780 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
781 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
782 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
783 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300784 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
785 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300786};
787
788/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
789static u8 ov_gain[] = {
790 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
791 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
792 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
793 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
794 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
795 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
796 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
797 0x70 /* 8x */
798};
799
800/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
801static u16 micron1_gain[] = {
802 /* 1x 1.25x 1.5x 1.75x */
803 0x0020, 0x0028, 0x0030, 0x0038,
804 /* 2x 2.25x 2.5x 2.75x */
805 0x00a0, 0x00a4, 0x00a8, 0x00ac,
806 /* 3x 3.25x 3.5x 3.75x */
807 0x00b0, 0x00b4, 0x00b8, 0x00bc,
808 /* 4x 4.25x 4.5x 4.75x */
809 0x00c0, 0x00c4, 0x00c8, 0x00cc,
810 /* 5x 5.25x 5.5x 5.75x */
811 0x00d0, 0x00d4, 0x00d8, 0x00dc,
812 /* 6x 6.25x 6.5x 6.75x */
813 0x00e0, 0x00e4, 0x00e8, 0x00ec,
814 /* 7x 7.25x 7.5x 7.75x */
815 0x00f0, 0x00f4, 0x00f8, 0x00fc,
816 /* 8x */
817 0x01c0
818};
819
820/* mt9m001 sensor uses a different gain formula then other micron sensors */
821/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
822static u16 micron2_gain[] = {
823 /* 1x 1.25x 1.5x 1.75x */
824 0x0008, 0x000a, 0x000c, 0x000e,
825 /* 2x 2.25x 2.5x 2.75x */
826 0x0010, 0x0012, 0x0014, 0x0016,
827 /* 3x 3.25x 3.5x 3.75x */
828 0x0018, 0x001a, 0x001c, 0x001e,
829 /* 4x 4.25x 4.5x 4.75x */
830 0x0020, 0x0051, 0x0052, 0x0053,
831 /* 5x 5.25x 5.5x 5.75x */
832 0x0054, 0x0055, 0x0056, 0x0057,
833 /* 6x 6.25x 6.5x 6.75x */
834 0x0058, 0x0059, 0x005a, 0x005b,
835 /* 7x 7.25x 7.5x 7.75x */
836 0x005c, 0x005d, 0x005e, 0x005f,
837 /* 8x */
838 0x0060
839};
840
841/* Gain = .5 + bit[7:0] / 16 */
842static u8 hv7131r_gain[] = {
843 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
844 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
845 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
846 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
847 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
848 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
849 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
850 0x78 /* 8x */
851};
852
Joe Perches58aa68c2009-09-02 01:12:13 -0300853static struct i2c_reg_u8 soi968_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300854 {0x0c, 0x00}, {0x0f, 0x1f},
Brian Johnson26e744b2009-07-19 05:52:58 -0300855 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
856 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
857 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
858 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
859 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300860 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300861 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
862 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
863 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
864 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
865};
866
Joe Perches58aa68c2009-09-02 01:12:13 -0300867static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300868 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
869 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
870 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300871 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
872 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
873 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300874 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
875 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
876 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
877};
878
Joe Perches58aa68c2009-09-02 01:12:13 -0300879static struct i2c_reg_u8 ov7670_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300880 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300881 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
882 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
883 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
884 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
885 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
886 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
887 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
888 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
889 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
890 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
891 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
892 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
893 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
894 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
895 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
896 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
897 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
898 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
899 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
900 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
901 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
902 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
903 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
904 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
905 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
906 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
907 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
908 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
909 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
910 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
911 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
912 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
913 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
914 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
915 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
916 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
917 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
918 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
919 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
920 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
921 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
922 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
923 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
924 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
925 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
926 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
927 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
928 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
929 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
930 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
931 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
932 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
933 {0x93, 0x00},
934};
935
Joe Perches58aa68c2009-09-02 01:12:13 -0300936static struct i2c_reg_u8 ov9650_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300937 {0x00, 0x00}, {0x01, 0x78},
Brian Johnson26e744b2009-07-19 05:52:58 -0300938 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
939 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
940 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
941 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
942 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
943 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
944 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
945 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
946 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
947 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
948 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
949 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
950 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
951 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
952 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
953 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
954 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
955 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
956 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
957 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
958 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
959 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
960 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
961 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
962 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
963 {0xaa, 0x92}, {0xab, 0x0a},
964};
965
Joe Perches58aa68c2009-09-02 01:12:13 -0300966static struct i2c_reg_u8 ov9655_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300967 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300968 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
969 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
970 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
971 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
972 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
973 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
974 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
975 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
976 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
977 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
978 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
979 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
980 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
981 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
982 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300983 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300984 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
985 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300986 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300987 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
988 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
989 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
990 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300991};
992
Joe Perches58aa68c2009-09-02 01:12:13 -0300993static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300994 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
995 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
996 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
997 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
998 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
999 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1000 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1001 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1002 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1003 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1004 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1005 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1006 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1007 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1008 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1009 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1010};
1011
Joe Perches58aa68c2009-09-02 01:12:13 -03001012static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001013 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001014 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1015 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1016 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1017 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1018 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1019 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001020};
1021
Joe Perches58aa68c2009-09-02 01:12:13 -03001022static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001023 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1024 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1025 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1026 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1027 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1028 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1029 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1030 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1031 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1032 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1033 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1034 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1035 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1036 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1037 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1038 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1039 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1040 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1041 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1042 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1043 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1044 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1045 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1046 {0x06, 0x0029}, {0x05, 0x0009},
1047};
1048
Joe Perches58aa68c2009-09-02 01:12:13 -03001049static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001050 {0x0d, 0x0001},
1051 {0x0d, 0x0000},
1052 {0x04, 0x0500}, /* hres = 1280 */
1053 {0x03, 0x0400}, /* vres = 1024 */
1054 {0x20, 0x1100},
1055 {0x06, 0x0010},
1056 {0x2b, 0x0024},
1057 {0x2e, 0x0024},
1058 {0x35, 0x0024},
1059 {0x2d, 0x0020},
1060 {0x2c, 0x0020},
1061 {0x09, 0x0ad4},
1062 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001063};
1064
Joe Perches58aa68c2009-09-02 01:12:13 -03001065static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001066 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1067 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001068 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1069 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001070};
1071
Brian Johnsone99ac542010-03-16 13:58:28 -03001072static struct i2c_reg_u16 mt9m112_init[] = {
1073 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1074 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1075 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1076 {0xf0, 0x0000},
1077};
1078
Joe Perches58aa68c2009-09-02 01:12:13 -03001079static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001080 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1081 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1082 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1083 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1084 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1085 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1086 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1087 {0x23, 0x09}, {0x01, 0x08},
1088};
1089
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001090static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001091{
1092 struct usb_device *dev = gspca_dev->dev;
1093 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001094
1095 if (gspca_dev->usb_err < 0)
1096 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001097 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1098 0x00,
1099 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1100 reg,
1101 0x00,
1102 gspca_dev->usb_buf,
1103 length,
1104 500);
1105 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001106 pr_err("Read register %02x failed %d\n", reg, result);
1107 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001108 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001109}
1110
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001111static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
Joe Perches58aa68c2009-09-02 01:12:13 -03001112 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001113{
1114 struct usb_device *dev = gspca_dev->dev;
1115 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001116
1117 if (gspca_dev->usb_err < 0)
1118 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001119 memcpy(gspca_dev->usb_buf, buffer, length);
1120 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1121 0x08,
1122 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1123 reg,
1124 0x00,
1125 gspca_dev->usb_buf,
1126 length,
1127 500);
1128 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001129 pr_err("Write register %02x failed %d\n", reg, result);
1130 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001131 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001132}
1133
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001134static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001135{
1136 u8 data[1] = {value};
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001137 reg_w(gspca_dev, reg, data, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001138}
1139
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001140static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001141{
1142 int i;
1143 reg_w(gspca_dev, 0x10c0, buffer, 8);
1144 for (i = 0; i < 5; i++) {
1145 reg_r(gspca_dev, 0x10c0, 1);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001146 if (gspca_dev->usb_err < 0)
1147 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001148 if (gspca_dev->usb_buf[0] & 0x04) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001149 if (gspca_dev->usb_buf[0] & 0x08) {
1150 pr_err("i2c_w error\n");
1151 gspca_dev->usb_err = -EIO;
1152 }
1153 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001154 }
Jean-François Moinee71389b2012-03-19 04:45:20 -03001155 msleep(10);
Brian Johnson26e744b2009-07-19 05:52:58 -03001156 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001157 pr_err("i2c_w reg %02x no response\n", buffer[2]);
1158/* gspca_dev->usb_err = -EIO; fixme: may occur */
Brian Johnson26e744b2009-07-19 05:52:58 -03001159}
1160
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001161static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001162{
1163 struct sd *sd = (struct sd *) gspca_dev;
1164
1165 u8 row[8];
1166
1167 /*
1168 * from the point of view of the bridge, the length
1169 * includes the address
1170 */
1171 row[0] = 0x81 | (2 << 4);
1172 row[1] = sd->i2c_addr;
1173 row[2] = reg;
1174 row[3] = val;
1175 row[4] = 0x00;
1176 row[5] = 0x00;
1177 row[6] = 0x00;
1178 row[7] = 0x10;
1179
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001180 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001181}
1182
Jean-François Moined4689b72012-03-19 04:42:45 -03001183static void i2c_w1_buf(struct gspca_dev *gspca_dev,
1184 struct i2c_reg_u8 *buf, int sz)
1185{
1186 while (--sz >= 0) {
1187 i2c_w1(gspca_dev, buf->reg, buf->val);
1188 buf++;
1189 }
1190}
1191
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001192static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001193{
1194 struct sd *sd = (struct sd *) gspca_dev;
1195 u8 row[8];
1196
1197 /*
1198 * from the point of view of the bridge, the length
1199 * includes the address
1200 */
1201 row[0] = 0x81 | (3 << 4);
1202 row[1] = sd->i2c_addr;
1203 row[2] = reg;
1204 row[3] = (val >> 8) & 0xff;
1205 row[4] = val & 0xff;
1206 row[5] = 0x00;
1207 row[6] = 0x00;
1208 row[7] = 0x10;
1209
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001210 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001211}
1212
Jean-François Moined4689b72012-03-19 04:42:45 -03001213static void i2c_w2_buf(struct gspca_dev *gspca_dev,
1214 struct i2c_reg_u16 *buf, int sz)
1215{
1216 while (--sz >= 0) {
1217 i2c_w2(gspca_dev, buf->reg, buf->val);
1218 buf++;
1219 }
1220}
1221
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001222static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001223{
1224 struct sd *sd = (struct sd *) gspca_dev;
1225 u8 row[8];
1226
Brian Johnson00b581e2009-07-23 05:55:43 -03001227 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001228 row[1] = sd->i2c_addr;
1229 row[2] = reg;
1230 row[3] = 0;
1231 row[4] = 0;
1232 row[5] = 0;
1233 row[6] = 0;
1234 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001235 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001236 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001237 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001238 i2c_w(gspca_dev, row);
1239 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001240 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001241}
1242
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001243static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001244{
1245 struct sd *sd = (struct sd *) gspca_dev;
1246 u8 row[8];
1247
Brian Johnson00b581e2009-07-23 05:55:43 -03001248 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001249 row[1] = sd->i2c_addr;
1250 row[2] = reg;
1251 row[3] = 0;
1252 row[4] = 0;
1253 row[5] = 0;
1254 row[6] = 0;
1255 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001256 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001257 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001258 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001259 i2c_w(gspca_dev, row);
1260 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001261 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001262}
1263
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001264static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001265{
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001266 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001267 struct sd *sd = (struct sd *) gspca_dev;
1268
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001269 i2c_r2(gspca_dev, 0x1c, &id);
1270 if (gspca_dev->usb_err < 0)
1271 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001272
1273 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001274 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001275 gspca_dev->usb_err = -ENODEV;
1276 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001277 }
1278
Jean-François Moine92884f82012-03-19 04:33:30 -03001279 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1280 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001281 i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
1282 if (gspca_dev->usb_err < 0)
1283 pr_err("OV9650 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001284 sd->hstart = 1;
1285 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001286}
1287
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001288static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001289{
Brian Johnson26e744b2009-07-19 05:52:58 -03001290 struct sd *sd = (struct sd *) gspca_dev;
1291
Jean-François Moine92884f82012-03-19 04:33:30 -03001292 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1293 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001294 i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
1295 if (gspca_dev->usb_err < 0)
1296 pr_err("OV9655 sensor initialization failed\n");
1297
Brian Johnson26e744b2009-07-19 05:52:58 -03001298 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001299 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001300 sd->hstart = 1;
1301 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001302}
1303
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001304static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001305{
Brian Johnson26e744b2009-07-19 05:52:58 -03001306 struct sd *sd = (struct sd *) gspca_dev;
1307
Jean-François Moine92884f82012-03-19 04:33:30 -03001308 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1309 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001310 i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
1311 if (gspca_dev->usb_err < 0)
1312 pr_err("SOI968 sensor initialization failed\n");
1313
Brian Johnson26e744b2009-07-19 05:52:58 -03001314 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001315 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1316 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001317 sd->hstart = 60;
1318 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001319}
1320
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001321static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001322{
Brian Johnson26e744b2009-07-19 05:52:58 -03001323 struct sd *sd = (struct sd *) gspca_dev;
1324
Jean-François Moine92884f82012-03-19 04:33:30 -03001325 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1326 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001327 i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
1328 if (gspca_dev->usb_err < 0)
1329 pr_err("OV7660 sensor initialization failed\n");
Hans de Goede8bc50f32011-02-16 07:11:14 -03001330 sd->hstart = 3;
1331 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001332}
1333
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001334static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001335{
Brian Johnson26e744b2009-07-19 05:52:58 -03001336 struct sd *sd = (struct sd *) gspca_dev;
1337
Jean-François Moine92884f82012-03-19 04:33:30 -03001338 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1339 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001340 i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
1341 if (gspca_dev->usb_err < 0)
1342 pr_err("OV7670 sensor initialization failed\n");
1343
Brian Johnson26e744b2009-07-19 05:52:58 -03001344 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001345 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001346 sd->hstart = 0;
1347 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001348}
1349
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001350static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001351{
1352 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson26e744b2009-07-19 05:52:58 -03001353 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001354
1355 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001356 i2c_r2(gspca_dev, 0xff, &value);
1357 if (gspca_dev->usb_err >= 0
1358 && value == 0x8243) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001359 i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
1360 if (gspca_dev->usb_err < 0) {
1361 pr_err("MT9V011 sensor initialization failed\n");
1362 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001363 }
1364 sd->hstart = 2;
1365 sd->vstart = 2;
1366 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001367 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001368 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001369 }
1370
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001371 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001372 sd->i2c_addr = 0x5c;
1373 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001374 i2c_r2(gspca_dev, 0xff, &value);
1375 if (gspca_dev->usb_err >= 0
1376 && value == 0x823a) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001377 i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
1378 if (gspca_dev->usb_err < 0) {
1379 pr_err("MT9V111 sensor initialization failed\n");
1380 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001381 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001382 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1383 | (1 << AUTOGAIN)
1384 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001385 sd->hstart = 2;
1386 sd->vstart = 2;
1387 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001388 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001389 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001390 }
1391
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001392 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001393 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001394 i2c_w2(gspca_dev, 0xf0, 0x0000);
1395 if (gspca_dev->usb_err < 0) {
1396 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001397 sd->i2c_addr = 0x48;
1398 i2c_w2(gspca_dev, 0xf0, 0x0000);
1399 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001400 i2c_r2(gspca_dev, 0x00, &value);
1401 if (gspca_dev->usb_err >= 0
1402 && value == 0x1229) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001403 i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
1404 if (gspca_dev->usb_err < 0) {
1405 pr_err("MT9V112 sensor initialization failed\n");
1406 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001407 }
1408 sd->hstart = 6;
1409 sd->vstart = 2;
1410 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001411 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001412 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001413 }
1414
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001415 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001416}
1417
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001418static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001419{
1420 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001421
1422 i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
1423 if (gspca_dev->usb_err < 0)
1424 pr_err("MT9M112 sensor initialization failed\n");
1425
Jean-François Moinec5224d82012-03-19 04:30:07 -03001426 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1427 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001428 sd->hstart = 0;
1429 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001430}
1431
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001432static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001433{
1434 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001435
1436 i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
1437 if (gspca_dev->usb_err < 0)
1438 pr_err("MT9M111 sensor initialization failed\n");
1439
Jean-François Moinec5224d82012-03-19 04:30:07 -03001440 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1441 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001442 sd->hstart = 0;
1443 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001444}
1445
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001446static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001447{
1448 struct sd *sd = (struct sd *) gspca_dev;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001449 u16 id;
1450
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001451 i2c_r2(gspca_dev, 0x00, &id);
1452 if (gspca_dev->usb_err < 0)
1453 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001454
1455 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1456 switch (id) {
1457 case 0x8411:
1458 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001459 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001460 break;
1461 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001462 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001463 break;
1464 default:
Joe Perches91f58422011-08-21 19:56:55 -03001465 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001466 gspca_dev->usb_err = -ENODEV;
1467 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001468 }
1469
Jean-François Moined4689b72012-03-19 04:42:45 -03001470 i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
1471 if (gspca_dev->usb_err < 0)
1472 pr_err("MT9M001 sensor initialization failed\n");
1473
Brian Johnson26e744b2009-07-19 05:52:58 -03001474 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001475 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001476 sd->hstart = 1;
1477 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001478}
1479
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001480static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001481{
Brian Johnson26e744b2009-07-19 05:52:58 -03001482 struct sd *sd = (struct sd *) gspca_dev;
1483
Jean-François Moined4689b72012-03-19 04:42:45 -03001484 i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
1485 if (gspca_dev->usb_err < 0)
1486 pr_err("HV7131R Sensor initialization failed\n");
1487
Brian Johnson26e744b2009-07-19 05:52:58 -03001488 sd->hstart = 0;
1489 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001490}
1491
Jean-François Moinec5224d82012-03-19 04:30:07 -03001492static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001493{
1494 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001495 int satur;
1496 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001497 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001498
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001499 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001500 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1502 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001503 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001504
Jean-François Moinec5224d82012-03-19 04:30:07 -03001505 satur = sd->ctrls[SATURATION].val;
1506 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001507 cmatrix[6] = hue_coord;
1508 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001509
Jean-François Moinec5224d82012-03-19 04:30:07 -03001510 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001511 cmatrix[8] = hue_coord;
1512 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001513
Jean-François Moinec5224d82012-03-19 04:30:07 -03001514 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001515 cmatrix[10] = hue_coord;
1516 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001517
Jean-François Moinec5224d82012-03-19 04:30:07 -03001518 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001519 cmatrix[12] = hue_coord;
1520 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001521
Jean-François Moinec5224d82012-03-19 04:30:07 -03001522 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001523 cmatrix[14] = hue_coord;
1524 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001525
Jean-François Moinec5224d82012-03-19 04:30:07 -03001526 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001527 cmatrix[16] = hue_coord;
1528 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001529
Jean-François Moinec5224d82012-03-19 04:30:07 -03001530 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001531}
1532
Jean-François Moinec5224d82012-03-19 04:30:07 -03001533static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001537 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001538
1539 gamma[0] = 0x0a;
1540 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1541 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1542 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1543 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1544 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1545 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1546 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1547 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1548 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1549 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1550 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1551 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1552 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1553 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1554 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1555 gamma[16] = 0xf5;
1556
Jean-François Moinec5224d82012-03-19 04:30:07 -03001557 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001558}
1559
Jean-François Moinec5224d82012-03-19 04:30:07 -03001560static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001561{
1562 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001563
1564 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1565 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001566}
1567
Jean-François Moinec5224d82012-03-19 04:30:07 -03001568static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001569{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001570 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001571 u16 value2;
1572 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001573
1574 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001575 hflip = !sd->ctrls[HFLIP].val;
1576 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001577 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001578 hflip = sd->ctrls[HFLIP].val;
1579 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001580 }
1581
Brian Johnson26e744b2009-07-19 05:52:58 -03001582 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001583 case SENSOR_OV7660:
1584 value = 0x01;
1585 if (hflip)
1586 value |= 0x20;
1587 if (vflip) {
1588 value |= 0x10;
1589 sd->vstart = 2;
1590 } else
1591 sd->vstart = 3;
1592 reg_w1(gspca_dev, 0x1182, sd->vstart);
1593 i2c_w1(gspca_dev, 0x1e, value);
1594 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001595 case SENSOR_OV9650:
1596 i2c_r1(gspca_dev, 0x1e, &value);
1597 value &= ~0x30;
1598 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001599 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001600 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001601 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001602 value |= 0x10;
1603 tslb = 0x49;
1604 }
1605 i2c_w1(gspca_dev, 0x1e, value);
1606 i2c_w1(gspca_dev, 0x3a, tslb);
1607 break;
1608 case SENSOR_MT9V111:
1609 case SENSOR_MT9V011:
1610 i2c_r2(gspca_dev, 0x20, &value2);
1611 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001612 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001613 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001614 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001615 value2 |= 0x4020;
1616 i2c_w2(gspca_dev, 0x20, value2);
1617 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001618 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001619 case SENSOR_MT9M111:
1620 case SENSOR_MT9V112:
1621 i2c_r2(gspca_dev, 0x20, &value2);
1622 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001623 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001624 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001625 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001626 value2 |= 0x0001;
1627 i2c_w2(gspca_dev, 0x20, value2);
1628 break;
1629 case SENSOR_HV7131R:
1630 i2c_r1(gspca_dev, 0x01, &value);
1631 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001632 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001633 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001634 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001635 value |= 0x02;
1636 i2c_w1(gspca_dev, 0x01, value);
1637 break;
1638 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001639}
1640
Jean-François Moinec5224d82012-03-19 04:30:07 -03001641static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001642{
1643 struct sd *sd = (struct sd *) gspca_dev;
1644 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001645 int expo;
1646
1647 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001648 switch (sd->sensor) {
1649 case SENSOR_OV7660:
1650 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001651 case SENSOR_OV9655:
1652 case SENSOR_OV9650:
1653 exp[0] |= (3 << 4);
1654 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001655 exp[3] = expo;
1656 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001657 break;
1658 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001659 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001660 case SENSOR_MT9V011:
1661 exp[0] |= (3 << 4);
1662 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001663 exp[3] = expo >> 8;
1664 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001665 break;
1666 case SENSOR_HV7131R:
1667 exp[0] |= (4 << 4);
1668 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001669 exp[3] = expo >> 5;
1670 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001671 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001672 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001673 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001674 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001675 }
1676 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001677}
1678
Jean-François Moinec5224d82012-03-19 04:30:07 -03001679static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001680{
1681 struct sd *sd = (struct sd *) gspca_dev;
1682 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001683 int g;
1684
1685 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 switch (sd->sensor) {
1687 case SENSOR_OV7660:
1688 case SENSOR_OV7670:
1689 case SENSOR_SOI968:
1690 case SENSOR_OV9655:
1691 case SENSOR_OV9650:
1692 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001693 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001694 break;
1695 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001696 gain[0] |= (3 << 4);
1697 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001698 gain[3] = micron1_gain[g] >> 8;
1699 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001700 break;
1701 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001702 gain[0] |= (3 << 4);
1703 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001704 gain[3] = micron1_gain[g] >> 8;
1705 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001706 break;
1707 case SENSOR_MT9M001:
1708 gain[0] |= (3 << 4);
1709 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001710 gain[3] = micron2_gain[g] >> 8;
1711 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001712 break;
1713 case SENSOR_HV7131R:
1714 gain[0] |= (2 << 4);
1715 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001716 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001717 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001718 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001719 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001720 }
1721 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001722}
1723
Jean-François Moine4c632e42012-03-19 04:35:34 -03001724static void set_quality(struct gspca_dev *gspca_dev)
1725{
1726 struct sd *sd = (struct sd *) gspca_dev;
1727
1728 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
1729 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1730 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1731 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1732 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1733 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1734 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1735 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1736 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1737}
1738
Brian Johnson26e744b2009-07-19 05:52:58 -03001739#ifdef CONFIG_VIDEO_ADV_DEBUG
1740static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1741 struct v4l2_dbg_register *reg)
1742{
1743 struct sd *sd = (struct sd *) gspca_dev;
1744 switch (reg->match.type) {
1745 case V4L2_CHIP_MATCH_HOST:
1746 if (reg->match.addr != 0)
1747 return -EINVAL;
1748 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1749 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001750 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001751 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001752 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001753 case V4L2_CHIP_MATCH_I2C_ADDR:
1754 if (reg->match.addr != sd->i2c_addr)
1755 return -EINVAL;
1756 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001757 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001758 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001759 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001760 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001761 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001762 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001763 }
1764 return -EINVAL;
1765}
1766
1767static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1768 struct v4l2_dbg_register *reg)
1769{
1770 struct sd *sd = (struct sd *) gspca_dev;
1771 switch (reg->match.type) {
1772 case V4L2_CHIP_MATCH_HOST:
1773 if (reg->match.addr != 0)
1774 return -EINVAL;
1775 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1776 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001777 reg_w1(gspca_dev, reg->reg, reg->val);
1778 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001779 case V4L2_CHIP_MATCH_I2C_ADDR:
1780 if (reg->match.addr != sd->i2c_addr)
1781 return -EINVAL;
1782 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001783 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001784 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001785 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001786 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001787 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001788 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001789 }
1790 return -EINVAL;
1791}
1792#endif
1793
1794static int sd_chip_ident(struct gspca_dev *gspca_dev,
1795 struct v4l2_dbg_chip_ident *chip)
1796{
1797 struct sd *sd = (struct sd *) gspca_dev;
1798
1799 switch (chip->match.type) {
1800 case V4L2_CHIP_MATCH_HOST:
1801 if (chip->match.addr != 0)
1802 return -EINVAL;
1803 chip->revision = 0;
1804 chip->ident = V4L2_IDENT_SN9C20X;
1805 return 0;
1806 case V4L2_CHIP_MATCH_I2C_ADDR:
1807 if (chip->match.addr != sd->i2c_addr)
1808 return -EINVAL;
1809 chip->revision = 0;
1810 chip->ident = i2c_ident[sd->sensor];
1811 return 0;
1812 }
1813 return -EINVAL;
1814}
1815
1816static int sd_config(struct gspca_dev *gspca_dev,
1817 const struct usb_device_id *id)
1818{
1819 struct sd *sd = (struct sd *) gspca_dev;
1820 struct cam *cam;
1821
1822 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001823 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001824
1825 sd->sensor = (id->driver_info >> 8) & 0xff;
1826 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001827 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001828
1829 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001830 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001831 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001832 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001833 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001834 cam->cam_mode = sxga_mode;
1835 cam->nmodes = ARRAY_SIZE(sxga_mode);
1836 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001837 case SENSOR_MT9M001:
1838 cam->cam_mode = mono_mode;
1839 cam->nmodes = ARRAY_SIZE(mono_mode);
1840 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001841 default:
1842 cam->cam_mode = vga_mode;
1843 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001844 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001845 }
1846
1847 sd->old_step = 0;
1848 sd->older_step = 0;
1849 sd->exposure_step = 16;
1850
Jean-François Moinec5224d82012-03-19 04:30:07 -03001851 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001852
Jean-François Moine92dcffc2012-03-19 04:47:24 -03001853 INIT_WORK(&sd->work, qual_upd);
Brian Johnson26e744b2009-07-19 05:52:58 -03001854
Brian Johnson26e744b2009-07-19 05:52:58 -03001855 return 0;
1856}
1857
1858static int sd_init(struct gspca_dev *gspca_dev)
1859{
1860 struct sd *sd = (struct sd *) gspca_dev;
1861 int i;
1862 u8 value;
1863 u8 i2c_init[9] =
1864 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1865
1866 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1867 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001868 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1869 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001870 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001871 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001872 }
1873 }
1874
Brian Johnson0c045eb2010-03-16 13:58:27 -03001875 if (sd->flags & LED_REVERSE)
1876 reg_w1(gspca_dev, 0x1006, 0x00);
1877 else
1878 reg_w1(gspca_dev, 0x1006, 0x20);
1879
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001880 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1881 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001882 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001883 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001884 }
1885
1886 switch (sd->sensor) {
1887 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001888 ov9650_init_sensor(gspca_dev);
1889 if (gspca_dev->usb_err < 0)
1890 break;
Joe Perches91f58422011-08-21 19:56:55 -03001891 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001892 break;
1893 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001894 ov9655_init_sensor(gspca_dev);
1895 if (gspca_dev->usb_err < 0)
1896 break;
Joe Perches91f58422011-08-21 19:56:55 -03001897 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001898 break;
1899 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001900 soi968_init_sensor(gspca_dev);
1901 if (gspca_dev->usb_err < 0)
1902 break;
Joe Perches91f58422011-08-21 19:56:55 -03001903 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001904 break;
1905 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001906 ov7660_init_sensor(gspca_dev);
1907 if (gspca_dev->usb_err < 0)
1908 break;
Joe Perches91f58422011-08-21 19:56:55 -03001909 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001910 break;
1911 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001912 ov7670_init_sensor(gspca_dev);
1913 if (gspca_dev->usb_err < 0)
1914 break;
Joe Perches91f58422011-08-21 19:56:55 -03001915 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001916 break;
1917 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001918 mt9v_init_sensor(gspca_dev);
1919 if (gspca_dev->usb_err < 0)
1920 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001921 break;
1922 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001923 mt9m111_init_sensor(gspca_dev);
1924 if (gspca_dev->usb_err < 0)
1925 break;
Joe Perches91f58422011-08-21 19:56:55 -03001926 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001927 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001928 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001929 mt9m112_init_sensor(gspca_dev);
1930 if (gspca_dev->usb_err < 0)
1931 break;
Joe Perches91f58422011-08-21 19:56:55 -03001932 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001933 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001934 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001935 mt9m001_init_sensor(gspca_dev);
1936 if (gspca_dev->usb_err < 0)
1937 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001938 break;
1939 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001940 hv7131r_init_sensor(gspca_dev);
1941 if (gspca_dev->usb_err < 0)
1942 break;
Joe Perches91f58422011-08-21 19:56:55 -03001943 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001944 break;
1945 default:
Joe Perches91f58422011-08-21 19:56:55 -03001946 pr_info("Unsupported Sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001947 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001948 }
1949
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001950 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001951}
1952
1953static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1954{
1955 struct sd *sd = (struct sd *) gspca_dev;
1956 u8 value;
1957 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001958 case SENSOR_SOI968:
1959 if (mode & MODE_SXGA) {
1960 i2c_w1(gspca_dev, 0x17, 0x1d);
1961 i2c_w1(gspca_dev, 0x18, 0xbd);
1962 i2c_w1(gspca_dev, 0x19, 0x01);
1963 i2c_w1(gspca_dev, 0x1a, 0x81);
1964 i2c_w1(gspca_dev, 0x12, 0x00);
1965 sd->hstart = 140;
1966 sd->vstart = 19;
1967 } else {
1968 i2c_w1(gspca_dev, 0x17, 0x13);
1969 i2c_w1(gspca_dev, 0x18, 0x63);
1970 i2c_w1(gspca_dev, 0x19, 0x01);
1971 i2c_w1(gspca_dev, 0x1a, 0x79);
1972 i2c_w1(gspca_dev, 0x12, 0x40);
1973 sd->hstart = 60;
1974 sd->vstart = 11;
1975 }
1976 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001977 case SENSOR_OV9650:
1978 if (mode & MODE_SXGA) {
1979 i2c_w1(gspca_dev, 0x17, 0x1b);
1980 i2c_w1(gspca_dev, 0x18, 0xbc);
1981 i2c_w1(gspca_dev, 0x19, 0x01);
1982 i2c_w1(gspca_dev, 0x1a, 0x82);
1983 i2c_r1(gspca_dev, 0x12, &value);
1984 i2c_w1(gspca_dev, 0x12, value & 0x07);
1985 } else {
1986 i2c_w1(gspca_dev, 0x17, 0x24);
1987 i2c_w1(gspca_dev, 0x18, 0xc5);
1988 i2c_w1(gspca_dev, 0x19, 0x00);
1989 i2c_w1(gspca_dev, 0x1a, 0x3c);
1990 i2c_r1(gspca_dev, 0x12, &value);
1991 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1992 }
1993 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001994 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001995 case SENSOR_MT9M111:
1996 if (mode & MODE_SXGA) {
1997 i2c_w2(gspca_dev, 0xf0, 0x0002);
1998 i2c_w2(gspca_dev, 0xc8, 0x970b);
1999 i2c_w2(gspca_dev, 0xf0, 0x0000);
2000 } else {
2001 i2c_w2(gspca_dev, 0xf0, 0x0002);
2002 i2c_w2(gspca_dev, 0xc8, 0x8000);
2003 i2c_w2(gspca_dev, 0xf0, 0x0000);
2004 }
2005 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002006 }
2007}
2008
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002009static int sd_isoc_init(struct gspca_dev *gspca_dev)
2010{
2011 struct usb_interface *intf;
2012 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2013
2014 /*
2015 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2016 * than our regular bandwidth calculations reserve, so we force the
2017 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2018 */
2019 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2020 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2021
2022 if (intf->num_altsetting != 9) {
2023 pr_warn("sn9c20x camera with unknown number of alt "
2024 "settings (%d), please report!\n",
2025 intf->num_altsetting);
2026 gspca_dev->alt = intf->num_altsetting;
2027 return 0;
2028 }
2029
2030 switch (gspca_dev->width) {
2031 case 160: /* 160x120 */
2032 gspca_dev->alt = 2;
2033 break;
2034 case 320: /* 320x240 */
2035 gspca_dev->alt = 6;
2036 break;
2037 default: /* >= 640x480 */
2038 gspca_dev->alt = 9;
2039 }
2040 }
2041
2042 return 0;
2043}
2044
Brian Johnson26e744b2009-07-19 05:52:58 -03002045#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002046((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002047(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2048(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2049
2050#define CLR_WIN(width, height) \
2051((const u8 [])\
2052{0, width >> 2, 0, height >> 1,\
2053((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2054
2055static int sd_start(struct gspca_dev *gspca_dev)
2056{
2057 struct sd *sd = (struct sd *) gspca_dev;
2058 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2059 int width = gspca_dev->width;
2060 int height = gspca_dev->height;
2061 u8 fmt, scale = 0;
2062
Brian Johnson26e744b2009-07-19 05:52:58 -03002063 jpeg_define(sd->jpeg_hdr, height, width,
2064 0x21);
Jean-François Moine4c632e42012-03-19 04:35:34 -03002065 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03002066
2067 if (mode & MODE_RAW)
2068 fmt = 0x2d;
2069 else if (mode & MODE_JPEG)
Jean-François Moine4c632e42012-03-19 04:35:34 -03002070 fmt = 0x24;
Brian Johnson26e744b2009-07-19 05:52:58 -03002071 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002072 fmt = 0x2f; /* YUV 420 */
Jean-François Moine4c632e42012-03-19 04:35:34 -03002073 sd->fmt = fmt;
Brian Johnson26e744b2009-07-19 05:52:58 -03002074
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002075 switch (mode & SCALE_MASK) {
2076 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002077 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002078 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002079 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002080 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002081 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002082 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002083 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002084 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002085 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002086 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002087 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002088 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002089 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002090 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002091 break;
2092 }
2093
2094 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002095 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2096 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002097 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2098 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2099 reg_w1(gspca_dev, 0x1189, scale);
2100 reg_w1(gspca_dev, 0x10e0, fmt);
2101
2102 set_cmatrix(gspca_dev);
2103 set_gamma(gspca_dev);
2104 set_redblue(gspca_dev);
2105 set_gain(gspca_dev);
2106 set_exposure(gspca_dev);
2107 set_hvflip(gspca_dev);
2108
Brian Johnson0c045eb2010-03-16 13:58:27 -03002109 reg_w1(gspca_dev, 0x1007, 0x20);
2110
Brian Johnson26e744b2009-07-19 05:52:58 -03002111 reg_r(gspca_dev, 0x1061, 1);
2112 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002113
2114 /* if JPEG, prepare the compression quality update */
2115 if (mode & MODE_JPEG) {
2116 sd->pktsz = sd->npkt = 0;
2117 sd->nchg = 0;
2118 sd->work_thread =
2119 create_singlethread_workqueue(KBUILD_MODNAME);
2120 }
2121
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002122 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002123}
2124
2125static void sd_stopN(struct gspca_dev *gspca_dev)
2126{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002127 reg_w1(gspca_dev, 0x1007, 0x00);
2128
Brian Johnson26e744b2009-07-19 05:52:58 -03002129 reg_r(gspca_dev, 0x1061, 1);
2130 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2131}
2132
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002133/* called on streamoff with alt==0 and on disconnect */
2134/* the usb_lock is held at entry - restore on exit */
2135static void sd_stop0(struct gspca_dev *gspca_dev)
2136{
2137 struct sd *sd = (struct sd *) gspca_dev;
2138
2139 if (sd->work_thread != NULL) {
2140 mutex_unlock(&gspca_dev->usb_lock);
2141 destroy_workqueue(sd->work_thread);
2142 mutex_lock(&gspca_dev->usb_lock);
2143 sd->work_thread = NULL;
2144 }
2145}
2146
Brian Johnsone1430472009-09-02 12:39:41 -03002147static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002148{
2149 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002150 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002151
2152 /*
2153 * some hardcoded values are present
2154 * like those for maximal/minimal exposure
2155 * and exposure steps
2156 */
2157 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002158 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002159 return;
2160
Jean-François Moinec5224d82012-03-19 04:30:07 -03002161 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002162 if (new_exp > 0x1770)
2163 new_exp = 0x1770;
2164 if (new_exp < 0x10)
2165 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002166 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002167 set_exposure(gspca_dev);
2168
2169 sd->older_step = sd->old_step;
2170 sd->old_step = 1;
2171
2172 if (sd->old_step ^ sd->older_step)
2173 sd->exposure_step /= 2;
2174 else
2175 sd->exposure_step += 2;
2176 }
2177 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002178 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002179 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002180 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002181 if (new_exp > 0x1700)
2182 new_exp = 0x1770;
2183 if (new_exp < 0x10)
2184 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002185 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002186 set_exposure(gspca_dev);
2187 sd->older_step = sd->old_step;
2188 sd->old_step = 0;
2189
2190 if (sd->old_step ^ sd->older_step)
2191 sd->exposure_step /= 2;
2192 else
2193 sd->exposure_step += 2;
2194 }
2195}
2196
Brian Johnsone1430472009-09-02 12:39:41 -03002197static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2198{
2199 struct sd *sd = (struct sd *) gspca_dev;
2200
2201 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002202 if (sd->ctrls[GAIN].val + 1 <= 28) {
2203 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002204 set_gain(gspca_dev);
2205 }
2206 }
2207 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002208 if (sd->ctrls[GAIN].val > 0) {
2209 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002210 set_gain(gspca_dev);
2211 }
2212 }
2213}
2214
2215static void sd_dqcallback(struct gspca_dev *gspca_dev)
2216{
2217 struct sd *sd = (struct sd *) gspca_dev;
2218 int avg_lum;
2219
Jean-François Moinec5224d82012-03-19 04:30:07 -03002220 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002221 return;
2222
2223 avg_lum = atomic_read(&sd->avg_lum);
2224 if (sd->sensor == SENSOR_SOI968)
2225 do_autogain(gspca_dev, avg_lum);
2226 else
2227 do_autoexposure(gspca_dev, avg_lum);
2228}
2229
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002230/* JPEG quality update */
2231/* This function is executed from a work queue. */
2232static void qual_upd(struct work_struct *work)
2233{
2234 struct sd *sd = container_of(work, struct sd, work);
2235 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2236
2237 mutex_lock(&gspca_dev->usb_lock);
2238 PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val);
2239 set_quality(gspca_dev);
2240 mutex_unlock(&gspca_dev->usb_lock);
2241}
2242
Jean-François Moine28566432010-10-01 07:33:26 -03002243#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002244static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2245 u8 *data, /* interrupt packet */
2246 int len) /* interrupt packet length */
2247{
2248 struct sd *sd = (struct sd *) gspca_dev;
2249 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002250 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002251 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2252 input_sync(gspca_dev->input_dev);
2253 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2254 input_sync(gspca_dev->input_dev);
2255 ret = 0;
2256 }
2257 return ret;
2258}
2259#endif
2260
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002261/* check the JPEG compression */
2262static void transfer_check(struct gspca_dev *gspca_dev,
2263 u8 *data)
2264{
2265 struct sd *sd = (struct sd *) gspca_dev;
2266 int new_qual, r;
2267
2268 new_qual = 0;
2269
2270 /* if USB error, discard the frame and decrease the quality */
2271 if (data[6] & 0x08) { /* USB FIFO full */
2272 gspca_dev->last_packet_type = DISCARD_PACKET;
2273 new_qual = -5;
2274 } else {
2275
2276 /* else, compute the filling rate and a new JPEG quality */
2277 r = (sd->pktsz * 100) /
2278 (sd->npkt *
2279 gspca_dev->urb[0]->iso_frame_desc[0].length);
2280 if (r >= 85)
2281 new_qual = -3;
2282 else if (r < 75)
2283 new_qual = 2;
2284 }
2285 if (new_qual != 0) {
2286 sd->nchg += new_qual;
2287 if (sd->nchg < -6 || sd->nchg >= 12) {
2288 sd->nchg = 0;
2289 new_qual += sd->ctrls[QUALITY].val;
2290 if (new_qual < QUALITY_MIN)
2291 new_qual = QUALITY_MIN;
2292 else if (new_qual > QUALITY_MAX)
2293 new_qual = QUALITY_MAX;
2294 if (new_qual != sd->ctrls[QUALITY].val) {
2295 sd->ctrls[QUALITY].val = new_qual;
2296 queue_work(sd->work_thread, &sd->work);
2297 }
2298 }
2299 } else {
2300 sd->nchg = 0;
2301 }
2302 sd->pktsz = sd->npkt = 0;
2303}
2304
Brian Johnson26e744b2009-07-19 05:52:58 -03002305static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002306 u8 *data, /* isoc packet */
2307 int len) /* iso packet length */
2308{
2309 struct sd *sd = (struct sd *) gspca_dev;
2310 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002311 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002312 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002313 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002314 avg_lum = ((data[35] >> 2) & 3) |
2315 (data[20] << 2) |
2316 (data[19] << 10);
2317 avg_lum += ((data[35] >> 4) & 3) |
2318 (data[22] << 2) |
2319 (data[21] << 10);
2320 avg_lum += ((data[35] >> 6) & 3) |
2321 (data[24] << 2) |
2322 (data[23] << 10);
2323 avg_lum += (data[36] & 3) |
2324 (data[26] << 2) |
2325 (data[25] << 10);
2326 avg_lum += ((data[36] >> 2) & 3) |
2327 (data[28] << 2) |
2328 (data[27] << 10);
2329 avg_lum += ((data[36] >> 4) & 3) |
2330 (data[30] << 2) |
2331 (data[29] << 10);
2332 avg_lum += ((data[36] >> 6) & 3) |
2333 (data[32] << 2) |
2334 (data[31] << 10);
2335 avg_lum += ((data[44] >> 4) & 3) |
2336 (data[34] << 2) |
2337 (data[33] << 10);
2338 avg_lum >>= 9;
2339 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002340
2341 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2342 & MODE_JPEG)
2343 transfer_check(gspca_dev, data);
2344
Jean-François Moine04d174e2010-09-13 05:22:37 -03002345 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002346 len -= 64;
2347 if (len == 0)
2348 return;
2349 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002350 }
2351 if (gspca_dev->last_packet_type == LAST_PACKET) {
2352 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2353 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002354 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002355 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002356 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002357 data, len);
2358 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002359 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002360 data, len);
2361 }
2362 } else {
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002363 /* if JPEG, count the packets and their size */
2364 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2365 & MODE_JPEG) {
2366 sd->npkt++;
2367 sd->pktsz += len;
2368 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002369 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002370 }
2371}
2372
2373/* sub-driver description */
2374static const struct sd_desc sd_desc = {
2375 .name = MODULE_NAME,
2376 .ctrls = sd_ctrls,
2377 .nctrls = ARRAY_SIZE(sd_ctrls),
2378 .config = sd_config,
2379 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002380 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002381 .start = sd_start,
2382 .stopN = sd_stopN,
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002383 .stop0 = sd_stop0,
Brian Johnson26e744b2009-07-19 05:52:58 -03002384 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002385#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002386 .int_pkt_scan = sd_int_pkt_scan,
2387#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002388 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002389#ifdef CONFIG_VIDEO_ADV_DEBUG
2390 .set_register = sd_dbg_s_register,
2391 .get_register = sd_dbg_g_register,
2392#endif
2393 .get_chip_ident = sd_chip_ident,
2394};
2395
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002396#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002397 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002398 | (SENSOR_ ## sensor << 8) \
2399 | (i2c_addr)
2400
Jean-François Moine95c967c2011-01-13 05:20:29 -03002401static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002402 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2403 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2404 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002405 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002406 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2407 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2408 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002409 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2410 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2411 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2412 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002413 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002414 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2415 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2416 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2417 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002418 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002419 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002420 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2421 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2422 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2423 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002424 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002425 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002426 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2427 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2428 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2429 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002430 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2431 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002432 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2433 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2434 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2435 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002436 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002437 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2438 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2439 {}
2440};
2441MODULE_DEVICE_TABLE(usb, device_table);
2442
2443/* -- device connect -- */
2444static int sd_probe(struct usb_interface *intf,
2445 const struct usb_device_id *id)
2446{
2447 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2448 THIS_MODULE);
2449}
2450
Brian Johnson26e744b2009-07-19 05:52:58 -03002451static struct usb_driver sd_driver = {
2452 .name = MODULE_NAME,
2453 .id_table = device_table,
2454 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002455 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002456#ifdef CONFIG_PM
2457 .suspend = gspca_suspend,
2458 .resume = gspca_resume,
2459 .reset_resume = gspca_resume,
2460#endif
2461};
2462
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002463module_usb_driver(sd_driver);