blob: 5285a519c1f34c8c4d6ce69fba0f9e4bd2dfcd29 [file] [log] [blame]
Brian Johnson26e744b2009-07-19 05:52:58 -03001/*
2 * Sonix sn9c201 sn9c202 library
Jean-François Moineff38d582012-03-19 04:55:16 -03003 *
4 * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
Brian Johnson26e744b2009-07-19 05:52:58 -03005 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
6 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
Joe Perches91f58422011-08-21 19:56:55 -030023#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
Brian Johnson26e744b2009-07-19 05:52:58 -030025#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030026
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030027#include "gspca.h"
28#include "jpeg.h"
29
30#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030031#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030032
Brian Johnson26e744b2009-07-19 05:52:58 -030033MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
34 "microdia project <microdia@googlegroups.com>");
35MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
36MODULE_LICENSE("GPL");
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
Jean-François Moine9637c652012-03-24 09:16:14 -030062#define SENSOR_MT9VPRB 12
Brian Johnson26e744b2009-07-19 05:52:58 -030063
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;
Jean-François Moinec4407fe2012-03-24 09:23:56 -0300108 u8 i2c_intf;
Brian Johnson26e744b2009-07-19 05:52:58 -0300109 u8 sensor;
110 u8 hstart;
111 u8 vstart;
112
Jean-François Moine9a731a32010-06-04 05:26:42 -0300113 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300114
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300115 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300116};
117
Jean-François Moine92dcffc2012-03-19 04:47:24 -0300118static void qual_upd(struct work_struct *work);
119
Joe Perches58aa68c2009-09-02 01:12:13 -0300120struct i2c_reg_u8 {
121 u8 reg;
122 u8 val;
123};
124
125struct i2c_reg_u16 {
126 u8 reg;
127 u16 val;
128};
129
Brian Johnson7ddaac72010-03-16 13:58:27 -0300130static const struct dmi_system_id flip_dmi_table[] = {
131 {
132 .ident = "MSI MS-1034",
133 .matches = {
134 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
135 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
136 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
137 }
138 },
139 {
140 .ident = "MSI MS-1632",
141 .matches = {
142 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
143 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
144 }
145 },
Brian Johnsone077f862010-04-05 20:52:52 -0300146 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300147 .ident = "MSI MS-1633X",
148 .matches = {
149 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
150 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
151 }
152 },
153 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300154 .ident = "MSI MS-1635X",
155 .matches = {
156 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
157 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
158 }
159 },
160 {
Brian Johnsone077f862010-04-05 20:52:52 -0300161 .ident = "ASUSTeK W7J",
162 .matches = {
163 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
164 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
165 }
166 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300167 {}
168};
169
Jean-François Moinec5224d82012-03-19 04:30:07 -0300170static void set_cmatrix(struct gspca_dev *gspca_dev);
171static void set_gamma(struct gspca_dev *gspca_dev);
172static void set_redblue(struct gspca_dev *gspca_dev);
173static void set_hvflip(struct gspca_dev *gspca_dev);
174static void set_exposure(struct gspca_dev *gspca_dev);
175static void set_gain(struct gspca_dev *gspca_dev);
Jean-François Moine4c632e42012-03-19 04:35:34 -0300176static void set_quality(struct gspca_dev *gspca_dev);
Jean-François Moinec5224d82012-03-19 04:30:07 -0300177
178static const struct ctrl sd_ctrls[NCTRLS] = {
179[BRIGHTNESS] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300180 {
181 .id = V4L2_CID_BRIGHTNESS,
182 .type = V4L2_CTRL_TYPE_INTEGER,
183 .name = "Brightness",
184 .minimum = 0,
185 .maximum = 0xff,
186 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300187 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300188 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300189 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300190 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300191[CONTRAST] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300192 {
193 .id = V4L2_CID_CONTRAST,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Contrast",
196 .minimum = 0,
197 .maximum = 0xff,
198 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300199 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300200 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300201 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300202 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300203[SATURATION] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300204 {
205 .id = V4L2_CID_SATURATION,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Saturation",
208 .minimum = 0,
209 .maximum = 0xff,
210 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300211 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300212 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300213 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300214 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300215[HUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300216 {
217 .id = V4L2_CID_HUE,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 .name = "Hue",
220 .minimum = -180,
221 .maximum = 180,
222 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300223 .default_value = 0
Brian Johnson26e744b2009-07-19 05:52:58 -0300224 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300225 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300226 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300227[GAMMA] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300228 {
229 .id = V4L2_CID_GAMMA,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Gamma",
232 .minimum = 0,
233 .maximum = 0xff,
234 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300235 .default_value = 0x10
Brian Johnson26e744b2009-07-19 05:52:58 -0300236 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300237 .set_control = set_gamma
Brian Johnson26e744b2009-07-19 05:52:58 -0300238 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300239[BLUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300240 {
241 .id = V4L2_CID_BLUE_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Blue Balance",
244 .minimum = 0,
245 .maximum = 0x7f,
246 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300247 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300248 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300249 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300250 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300251[RED] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300252 {
253 .id = V4L2_CID_RED_BALANCE,
254 .type = V4L2_CTRL_TYPE_INTEGER,
255 .name = "Red Balance",
256 .minimum = 0,
257 .maximum = 0x7f,
258 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300259 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300260 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300261 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300262 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300263[HFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300264 {
265 .id = V4L2_CID_HFLIP,
266 .type = V4L2_CTRL_TYPE_BOOLEAN,
267 .name = "Horizontal Flip",
268 .minimum = 0,
269 .maximum = 1,
270 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300271 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300272 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300273 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300274 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300275[VFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300276 {
277 .id = V4L2_CID_VFLIP,
278 .type = V4L2_CTRL_TYPE_BOOLEAN,
279 .name = "Vertical Flip",
280 .minimum = 0,
281 .maximum = 1,
282 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300283 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300284 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300285 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300286 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300287[EXPOSURE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300288 {
289 .id = V4L2_CID_EXPOSURE,
290 .type = V4L2_CTRL_TYPE_INTEGER,
291 .name = "Exposure",
292 .minimum = 0,
293 .maximum = 0x1780,
294 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300295 .default_value = 0x33,
Brian Johnson26e744b2009-07-19 05:52:58 -0300296 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300297 .set_control = set_exposure
Brian Johnson26e744b2009-07-19 05:52:58 -0300298 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300299[GAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300300 {
301 .id = V4L2_CID_GAIN,
302 .type = V4L2_CTRL_TYPE_INTEGER,
303 .name = "Gain",
304 .minimum = 0,
305 .maximum = 28,
306 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300307 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300308 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300309 .set_control = set_gain
Brian Johnson26e744b2009-07-19 05:52:58 -0300310 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300311[AUTOGAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300312 {
313 .id = V4L2_CID_AUTOGAIN,
314 .type = V4L2_CTRL_TYPE_BOOLEAN,
315 .name = "Auto Exposure",
316 .minimum = 0,
317 .maximum = 1,
318 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300319 .default_value = 1,
Brian Johnson26e744b2009-07-19 05:52:58 -0300320 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300321 },
Jean-François Moine4c632e42012-03-19 04:35:34 -0300322[QUALITY] = {
323 {
324 .id = V4L2_CID_JPEG_COMPRESSION_QUALITY,
325 .type = V4L2_CTRL_TYPE_INTEGER,
326 .name = "Compression Quality",
327#define QUALITY_MIN 50
328#define QUALITY_MAX 90
329#define QUALITY_DEF 80
330 .minimum = QUALITY_MIN,
331 .maximum = QUALITY_MAX,
332 .step = 1,
333 .default_value = QUALITY_DEF,
334 },
335 .set_control = set_quality
336 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300337};
338
339static const struct v4l2_pix_format vga_mode[] = {
340 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300341 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300342 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300343 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300344 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300345 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
346 .bytesperline = 160,
347 .sizeimage = 160 * 120,
348 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300349 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300350 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300351 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300352 .sizeimage = 240 * 120,
353 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300354 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300355 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300356 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300357 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300358 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300359 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300360 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
361 .bytesperline = 320,
362 .sizeimage = 320 * 240 ,
363 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300364 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300365 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300366 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300367 .sizeimage = 480 * 240 ,
368 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300369 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300370 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300371 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300372 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300373 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300374 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300375 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
376 .bytesperline = 640,
377 .sizeimage = 640 * 480,
378 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300379 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300380 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300381 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300382 .sizeimage = 960 * 480,
383 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300384 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300385};
386
387static const struct v4l2_pix_format sxga_mode[] = {
388 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300389 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300390 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300391 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300392 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300393 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
394 .bytesperline = 160,
395 .sizeimage = 160 * 120,
396 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300397 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300398 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300399 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300400 .sizeimage = 240 * 120,
401 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300402 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300403 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300404 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300405 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300407 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300408 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
409 .bytesperline = 320,
410 .sizeimage = 320 * 240 ,
411 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300412 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300413 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300414 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300415 .sizeimage = 480 * 240 ,
416 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300417 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300418 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300419 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300420 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300421 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300422 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300423 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
424 .bytesperline = 640,
425 .sizeimage = 640 * 480,
426 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300427 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300428 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300429 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300430 .sizeimage = 960 * 480,
431 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300432 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300433 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
434 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300435 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300436 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300437 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300438};
439
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300440static const struct v4l2_pix_format mono_mode[] = {
441 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
442 .bytesperline = 160,
443 .sizeimage = 160 * 120,
444 .colorspace = V4L2_COLORSPACE_SRGB,
445 .priv = SCALE_160x120 | MODE_RAW},
446 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
447 .bytesperline = 320,
448 .sizeimage = 320 * 240 ,
449 .colorspace = V4L2_COLORSPACE_SRGB,
450 .priv = SCALE_320x240 | MODE_RAW},
451 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
452 .bytesperline = 640,
453 .sizeimage = 640 * 480,
454 .colorspace = V4L2_COLORSPACE_SRGB,
455 .priv = SCALE_640x480 | MODE_RAW},
456 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
457 .bytesperline = 1280,
458 .sizeimage = 1280 * 1024,
459 .colorspace = V4L2_COLORSPACE_SRGB,
460 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
461};
462
Joe Perches58aa68c2009-09-02 01:12:13 -0300463static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300464 41, 44, 46, 48, 50, 52, 54, 56,
465 58, 60, 62, 64, 66, 68, 70, 72,
466 74, 76, 78, 80, 81, 83, 85, 87,
467 88, 90, 92, 93, 95, 97, 98, 100,
468 101, 102, 104, 105, 107, 108, 109, 110,
469 112, 113, 114, 115, 116, 117, 118, 119,
470 120, 121, 122, 123, 123, 124, 125, 125,
471 126, 127, 127, 128, 128, 129, 129, 129,
472 130, 130, 130, 130, 131, 131, 131, 131,
473 131, 131, 131, 131, 130, 130, 130, 130,
474 129, 129, 129, 128, 128, 127, 127, 126,
475 125, 125, 124, 123, 122, 122, 121, 120,
476 119, 118, 117, 116, 115, 114, 112, 111,
477 110, 109, 107, 106, 105, 103, 102, 101,
478 99, 98, 96, 94, 93, 91, 90, 88,
479 86, 84, 83, 81, 79, 77, 75, 74,
480 72, 70, 68, 66, 64, 62, 60, 58,
481 56, 54, 52, 49, 47, 45, 43, 41,
482 39, 36, 34, 32, 30, 28, 25, 23,
483 21, 19, 16, 14, 12, 9, 7, 5,
484 3, 0, -1, -3, -6, -8, -10, -12,
485 -15, -17, -19, -22, -24, -26, -28, -30,
486 -33, -35, -37, -39, -41, -44, -46, -48,
487 -50, -52, -54, -56, -58, -60, -62, -64,
488 -66, -68, -70, -72, -74, -76, -78, -80,
489 -81, -83, -85, -87, -88, -90, -92, -93,
490 -95, -97, -98, -100, -101, -102, -104, -105,
491 -107, -108, -109, -110, -112, -113, -114, -115,
492 -116, -117, -118, -119, -120, -121, -122, -123,
493 -123, -124, -125, -125, -126, -127, -127, -128,
494 -128, -128, -128, -128, -128, -128, -128, -128,
495 -128, -128, -128, -128, -128, -128, -128, -128,
496 -128, -128, -128, -128, -128, -128, -128, -128,
497 -128, -127, -127, -126, -125, -125, -124, -123,
498 -122, -122, -121, -120, -119, -118, -117, -116,
499 -115, -114, -112, -111, -110, -109, -107, -106,
500 -105, -103, -102, -101, -99, -98, -96, -94,
501 -93, -91, -90, -88, -86, -84, -83, -81,
502 -79, -77, -75, -74, -72, -70, -68, -66,
503 -64, -62, -60, -58, -56, -54, -52, -49,
504 -47, -45, -43, -41, -39, -36, -34, -32,
505 -30, -28, -25, -23, -21, -19, -16, -14,
506 -12, -9, -7, -5, -3, 0, 1, 3,
507 6, 8, 10, 12, 15, 17, 19, 22,
508 24, 26, 28, 30, 33, 35, 37, 39, 41
509};
510
Joe Perches58aa68c2009-09-02 01:12:13 -0300511static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300512 82, 80, 78, 76, 74, 73, 71, 69,
513 67, 65, 63, 61, 58, 56, 54, 52,
514 50, 48, 46, 44, 41, 39, 37, 35,
515 32, 30, 28, 26, 23, 21, 19, 16,
516 14, 12, 10, 7, 5, 3, 0, -1,
517 -3, -6, -8, -10, -13, -15, -17, -19,
518 -22, -24, -26, -29, -31, -33, -35, -38,
519 -40, -42, -44, -46, -48, -51, -53, -55,
520 -57, -59, -61, -63, -65, -67, -69, -71,
521 -73, -75, -77, -79, -81, -82, -84, -86,
522 -88, -89, -91, -93, -94, -96, -98, -99,
523 -101, -102, -104, -105, -106, -108, -109, -110,
524 -112, -113, -114, -115, -116, -117, -119, -120,
525 -120, -121, -122, -123, -124, -125, -126, -126,
526 -127, -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 -128, -128, -128, -128, -128, -128, -128, -128,
530 -127, -127, -126, -125, -125, -124, -123, -122,
531 -121, -120, -119, -118, -117, -116, -115, -114,
532 -113, -111, -110, -109, -107, -106, -105, -103,
533 -102, -100, -99, -97, -96, -94, -92, -91,
534 -89, -87, -85, -84, -82, -80, -78, -76,
535 -74, -73, -71, -69, -67, -65, -63, -61,
536 -58, -56, -54, -52, -50, -48, -46, -44,
537 -41, -39, -37, -35, -32, -30, -28, -26,
538 -23, -21, -19, -16, -14, -12, -10, -7,
539 -5, -3, 0, 1, 3, 6, 8, 10,
540 13, 15, 17, 19, 22, 24, 26, 29,
541 31, 33, 35, 38, 40, 42, 44, 46,
542 48, 51, 53, 55, 57, 59, 61, 63,
543 65, 67, 69, 71, 73, 75, 77, 79,
544 81, 82, 84, 86, 88, 89, 91, 93,
545 94, 96, 98, 99, 101, 102, 104, 105,
546 106, 108, 109, 110, 112, 113, 114, 115,
547 116, 117, 119, 120, 120, 121, 122, 123,
548 124, 125, 126, 126, 127, 128, 128, 129,
549 129, 130, 130, 131, 131, 131, 131, 132,
550 132, 132, 132, 132, 132, 132, 132, 132,
551 132, 132, 132, 131, 131, 131, 130, 130,
552 130, 129, 129, 128, 127, 127, 126, 125,
553 125, 124, 123, 122, 121, 120, 119, 118,
554 117, 116, 115, 114, 113, 111, 110, 109,
555 107, 106, 105, 103, 102, 100, 99, 97,
556 96, 94, 92, 91, 89, 87, 85, 84, 82
557};
558
Joe Perches58aa68c2009-09-02 01:12:13 -0300559static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300560 -124, -124, -125, -125, -125, -125, -125, -125,
561 -125, -126, -126, -125, -125, -125, -125, -125,
562 -125, -124, -124, -124, -123, -123, -122, -122,
563 -121, -121, -120, -120, -119, -118, -117, -117,
564 -116, -115, -114, -113, -112, -111, -110, -109,
565 -108, -107, -105, -104, -103, -102, -100, -99,
566 -98, -96, -95, -93, -92, -91, -89, -87,
567 -86, -84, -83, -81, -79, -77, -76, -74,
568 -72, -70, -69, -67, -65, -63, -61, -59,
569 -57, -55, -53, -51, -49, -47, -45, -43,
570 -41, -39, -37, -35, -33, -30, -28, -26,
571 -24, -22, -20, -18, -15, -13, -11, -9,
572 -7, -4, -2, 0, 1, 3, 6, 8,
573 10, 12, 14, 17, 19, 21, 23, 25,
574 27, 29, 32, 34, 36, 38, 40, 42,
575 44, 46, 48, 50, 52, 54, 56, 58,
576 60, 62, 64, 66, 68, 70, 71, 73,
577 75, 77, 78, 80, 82, 83, 85, 87,
578 88, 90, 91, 93, 94, 96, 97, 98,
579 100, 101, 102, 104, 105, 106, 107, 108,
580 109, 111, 112, 113, 113, 114, 115, 116,
581 117, 118, 118, 119, 120, 120, 121, 122,
582 122, 123, 123, 124, 124, 124, 125, 125,
583 125, 125, 125, 125, 125, 126, 126, 125,
584 125, 125, 125, 125, 125, 124, 124, 124,
585 123, 123, 122, 122, 121, 121, 120, 120,
586 119, 118, 117, 117, 116, 115, 114, 113,
587 112, 111, 110, 109, 108, 107, 105, 104,
588 103, 102, 100, 99, 98, 96, 95, 93,
589 92, 91, 89, 87, 86, 84, 83, 81,
590 79, 77, 76, 74, 72, 70, 69, 67,
591 65, 63, 61, 59, 57, 55, 53, 51,
592 49, 47, 45, 43, 41, 39, 37, 35,
593 33, 30, 28, 26, 24, 22, 20, 18,
594 15, 13, 11, 9, 7, 4, 2, 0,
595 -1, -3, -6, -8, -10, -12, -14, -17,
596 -19, -21, -23, -25, -27, -29, -32, -34,
597 -36, -38, -40, -42, -44, -46, -48, -50,
598 -52, -54, -56, -58, -60, -62, -64, -66,
599 -68, -70, -71, -73, -75, -77, -78, -80,
600 -82, -83, -85, -87, -88, -90, -91, -93,
601 -94, -96, -97, -98, -100, -101, -102, -104,
602 -105, -106, -107, -108, -109, -111, -112, -113,
603 -113, -114, -115, -116, -117, -118, -118, -119,
604 -120, -120, -121, -122, -122, -123, -123, -124, -124
605};
606
Joe Perches58aa68c2009-09-02 01:12:13 -0300607static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300608 -100, -99, -98, -97, -95, -94, -93, -91,
609 -90, -89, -87, -86, -84, -83, -81, -80,
610 -78, -76, -75, -73, -71, -70, -68, -66,
611 -64, -63, -61, -59, -57, -55, -53, -51,
612 -49, -48, -46, -44, -42, -40, -38, -36,
613 -34, -32, -30, -27, -25, -23, -21, -19,
614 -17, -15, -13, -11, -9, -7, -4, -2,
615 0, 1, 3, 5, 7, 9, 11, 14,
616 16, 18, 20, 22, 24, 26, 28, 30,
617 32, 34, 36, 38, 40, 42, 44, 46,
618 48, 50, 52, 54, 56, 58, 59, 61,
619 63, 65, 67, 68, 70, 72, 74, 75,
620 77, 78, 80, 82, 83, 85, 86, 88,
621 89, 90, 92, 93, 95, 96, 97, 98,
622 100, 101, 102, 103, 104, 105, 106, 107,
623 108, 109, 110, 111, 112, 112, 113, 114,
624 115, 115, 116, 116, 117, 117, 118, 118,
625 119, 119, 119, 120, 120, 120, 120, 120,
626 121, 121, 121, 121, 121, 121, 120, 120,
627 120, 120, 120, 119, 119, 119, 118, 118,
628 117, 117, 116, 116, 115, 114, 114, 113,
629 112, 111, 111, 110, 109, 108, 107, 106,
630 105, 104, 103, 102, 100, 99, 98, 97,
631 95, 94, 93, 91, 90, 89, 87, 86,
632 84, 83, 81, 80, 78, 76, 75, 73,
633 71, 70, 68, 66, 64, 63, 61, 59,
634 57, 55, 53, 51, 49, 48, 46, 44,
635 42, 40, 38, 36, 34, 32, 30, 27,
636 25, 23, 21, 19, 17, 15, 13, 11,
637 9, 7, 4, 2, 0, -1, -3, -5,
638 -7, -9, -11, -14, -16, -18, -20, -22,
639 -24, -26, -28, -30, -32, -34, -36, -38,
640 -40, -42, -44, -46, -48, -50, -52, -54,
641 -56, -58, -59, -61, -63, -65, -67, -68,
642 -70, -72, -74, -75, -77, -78, -80, -82,
643 -83, -85, -86, -88, -89, -90, -92, -93,
644 -95, -96, -97, -98, -100, -101, -102, -103,
645 -104, -105, -106, -107, -108, -109, -110, -111,
646 -112, -112, -113, -114, -115, -115, -116, -116,
647 -117, -117, -118, -118, -119, -119, -119, -120,
648 -120, -120, -120, -120, -121, -121, -121, -121,
649 -121, -121, -120, -120, -120, -120, -120, -119,
650 -119, -119, -118, -118, -117, -117, -116, -116,
651 -115, -114, -114, -113, -112, -111, -111, -110,
652 -109, -108, -107, -106, -105, -104, -103, -102, -100
653};
654
Joe Perches58aa68c2009-09-02 01:12:13 -0300655static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300656 112, 113, 114, 114, 115, 116, 117, 117,
657 118, 118, 119, 119, 120, 120, 120, 121,
658 121, 121, 122, 122, 122, 122, 122, 122,
659 122, 122, 122, 122, 122, 122, 121, 121,
660 121, 120, 120, 120, 119, 119, 118, 118,
661 117, 116, 116, 115, 114, 113, 113, 112,
662 111, 110, 109, 108, 107, 106, 105, 104,
663 103, 102, 100, 99, 98, 97, 95, 94,
664 93, 91, 90, 88, 87, 85, 84, 82,
665 80, 79, 77, 76, 74, 72, 70, 69,
666 67, 65, 63, 61, 60, 58, 56, 54,
667 52, 50, 48, 46, 44, 42, 40, 38,
668 36, 34, 32, 30, 28, 26, 24, 22,
669 19, 17, 15, 13, 11, 9, 7, 5,
670 2, 0, -1, -3, -5, -7, -9, -12,
671 -14, -16, -18, -20, -22, -24, -26, -28,
672 -31, -33, -35, -37, -39, -41, -43, -45,
673 -47, -49, -51, -53, -54, -56, -58, -60,
674 -62, -64, -66, -67, -69, -71, -73, -74,
675 -76, -78, -79, -81, -83, -84, -86, -87,
676 -89, -90, -92, -93, -94, -96, -97, -98,
677 -99, -101, -102, -103, -104, -105, -106, -107,
678 -108, -109, -110, -111, -112, -113, -114, -114,
679 -115, -116, -117, -117, -118, -118, -119, -119,
680 -120, -120, -120, -121, -121, -121, -122, -122,
681 -122, -122, -122, -122, -122, -122, -122, -122,
682 -122, -122, -121, -121, -121, -120, -120, -120,
683 -119, -119, -118, -118, -117, -116, -116, -115,
684 -114, -113, -113, -112, -111, -110, -109, -108,
685 -107, -106, -105, -104, -103, -102, -100, -99,
686 -98, -97, -95, -94, -93, -91, -90, -88,
687 -87, -85, -84, -82, -80, -79, -77, -76,
688 -74, -72, -70, -69, -67, -65, -63, -61,
689 -60, -58, -56, -54, -52, -50, -48, -46,
690 -44, -42, -40, -38, -36, -34, -32, -30,
691 -28, -26, -24, -22, -19, -17, -15, -13,
692 -11, -9, -7, -5, -2, 0, 1, 3,
693 5, 7, 9, 12, 14, 16, 18, 20,
694 22, 24, 26, 28, 31, 33, 35, 37,
695 39, 41, 43, 45, 47, 49, 51, 53,
696 54, 56, 58, 60, 62, 64, 66, 67,
697 69, 71, 73, 74, 76, 78, 79, 81,
698 83, 84, 86, 87, 89, 90, 92, 93,
699 94, 96, 97, 98, 99, 101, 102, 103,
700 104, 105, 106, 107, 108, 109, 110, 111, 112
701};
702
Joe Perches58aa68c2009-09-02 01:12:13 -0300703static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300704 -11, -13, -15, -17, -19, -21, -23, -25,
705 -27, -29, -31, -33, -35, -37, -39, -41,
706 -43, -45, -46, -48, -50, -52, -54, -55,
707 -57, -59, -61, -62, -64, -66, -67, -69,
708 -71, -72, -74, -75, -77, -78, -80, -81,
709 -83, -84, -86, -87, -88, -90, -91, -92,
710 -93, -95, -96, -97, -98, -99, -100, -101,
711 -102, -103, -104, -105, -106, -106, -107, -108,
712 -109, -109, -110, -111, -111, -112, -112, -113,
713 -113, -114, -114, -114, -115, -115, -115, -115,
714 -116, -116, -116, -116, -116, -116, -116, -116,
715 -116, -115, -115, -115, -115, -114, -114, -114,
716 -113, -113, -112, -112, -111, -111, -110, -110,
717 -109, -108, -108, -107, -106, -105, -104, -103,
718 -102, -101, -100, -99, -98, -97, -96, -95,
719 -94, -93, -91, -90, -89, -88, -86, -85,
720 -84, -82, -81, -79, -78, -76, -75, -73,
721 -71, -70, -68, -67, -65, -63, -62, -60,
722 -58, -56, -55, -53, -51, -49, -47, -45,
723 -44, -42, -40, -38, -36, -34, -32, -30,
724 -28, -26, -24, -22, -20, -18, -16, -14,
725 -12, -10, -8, -6, -4, -2, 0, 1,
726 3, 5, 7, 9, 11, 13, 15, 17,
727 19, 21, 23, 25, 27, 29, 31, 33,
728 35, 37, 39, 41, 43, 45, 46, 48,
729 50, 52, 54, 55, 57, 59, 61, 62,
730 64, 66, 67, 69, 71, 72, 74, 75,
731 77, 78, 80, 81, 83, 84, 86, 87,
732 88, 90, 91, 92, 93, 95, 96, 97,
733 98, 99, 100, 101, 102, 103, 104, 105,
734 106, 106, 107, 108, 109, 109, 110, 111,
735 111, 112, 112, 113, 113, 114, 114, 114,
736 115, 115, 115, 115, 116, 116, 116, 116,
737 116, 116, 116, 116, 116, 115, 115, 115,
738 115, 114, 114, 114, 113, 113, 112, 112,
739 111, 111, 110, 110, 109, 108, 108, 107,
740 106, 105, 104, 103, 102, 101, 100, 99,
741 98, 97, 96, 95, 94, 93, 91, 90,
742 89, 88, 86, 85, 84, 82, 81, 79,
743 78, 76, 75, 73, 71, 70, 68, 67,
744 65, 63, 62, 60, 58, 56, 55, 53,
745 51, 49, 47, 45, 44, 42, 40, 38,
746 36, 34, 32, 30, 28, 26, 24, 22,
747 20, 18, 16, 14, 12, 10, 8, 6,
748 4, 2, 0, -1, -3, -5, -7, -9, -11
749};
750
Jean-François Moinedae1de62012-03-24 09:20:25 -0300751static const u16 i2c_ident[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300752 V4L2_IDENT_OV9650,
753 V4L2_IDENT_OV9655,
754 V4L2_IDENT_SOI968,
755 V4L2_IDENT_OV7660,
756 V4L2_IDENT_OV7670,
757 V4L2_IDENT_MT9V011,
758 V4L2_IDENT_MT9V111,
759 V4L2_IDENT_MT9V112,
760 V4L2_IDENT_MT9M001C12ST,
761 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300762 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300763 V4L2_IDENT_HV7131R,
Jean-François Moinebed37382012-03-24 09:17:37 -0300764[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN,
Brian Johnson26e744b2009-07-19 05:52:58 -0300765};
766
Jean-François Moinedae1de62012-03-24 09:20:25 -0300767static const u16 bridge_init[][2] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300768 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
769 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
770 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
771 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
772 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
773 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
774 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
775 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
776 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
777 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
778 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
779 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
780 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
781 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
782 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
783 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
784 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
785 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300786 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
787 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300788};
789
790/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
Jean-François Moinedae1de62012-03-24 09:20:25 -0300791static const u8 ov_gain[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300792 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
793 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
794 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
795 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
796 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
797 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
798 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
799 0x70 /* 8x */
800};
801
802/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
Jean-François Moinedae1de62012-03-24 09:20:25 -0300803static const u16 micron1_gain[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300804 /* 1x 1.25x 1.5x 1.75x */
805 0x0020, 0x0028, 0x0030, 0x0038,
806 /* 2x 2.25x 2.5x 2.75x */
807 0x00a0, 0x00a4, 0x00a8, 0x00ac,
808 /* 3x 3.25x 3.5x 3.75x */
809 0x00b0, 0x00b4, 0x00b8, 0x00bc,
810 /* 4x 4.25x 4.5x 4.75x */
811 0x00c0, 0x00c4, 0x00c8, 0x00cc,
812 /* 5x 5.25x 5.5x 5.75x */
813 0x00d0, 0x00d4, 0x00d8, 0x00dc,
814 /* 6x 6.25x 6.5x 6.75x */
815 0x00e0, 0x00e4, 0x00e8, 0x00ec,
816 /* 7x 7.25x 7.5x 7.75x */
817 0x00f0, 0x00f4, 0x00f8, 0x00fc,
818 /* 8x */
819 0x01c0
820};
821
822/* mt9m001 sensor uses a different gain formula then other micron sensors */
823/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
Jean-François Moinedae1de62012-03-24 09:20:25 -0300824static const u16 micron2_gain[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300825 /* 1x 1.25x 1.5x 1.75x */
826 0x0008, 0x000a, 0x000c, 0x000e,
827 /* 2x 2.25x 2.5x 2.75x */
828 0x0010, 0x0012, 0x0014, 0x0016,
829 /* 3x 3.25x 3.5x 3.75x */
830 0x0018, 0x001a, 0x001c, 0x001e,
831 /* 4x 4.25x 4.5x 4.75x */
832 0x0020, 0x0051, 0x0052, 0x0053,
833 /* 5x 5.25x 5.5x 5.75x */
834 0x0054, 0x0055, 0x0056, 0x0057,
835 /* 6x 6.25x 6.5x 6.75x */
836 0x0058, 0x0059, 0x005a, 0x005b,
837 /* 7x 7.25x 7.5x 7.75x */
838 0x005c, 0x005d, 0x005e, 0x005f,
839 /* 8x */
840 0x0060
841};
842
843/* Gain = .5 + bit[7:0] / 16 */
Jean-François Moinedae1de62012-03-24 09:20:25 -0300844static const u8 hv7131r_gain[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300845 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
846 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
847 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
848 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
849 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
850 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
851 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
852 0x78 /* 8x */
853};
854
Jean-François Moinedae1de62012-03-24 09:20:25 -0300855static const struct i2c_reg_u8 soi968_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300856 {0x0c, 0x00}, {0x0f, 0x1f},
Brian Johnson26e744b2009-07-19 05:52:58 -0300857 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
858 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
859 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
860 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
861 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300862 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300863 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
864 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
865 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
866 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
867};
868
Jean-François Moinedae1de62012-03-24 09:20:25 -0300869static const struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300870 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
871 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
872 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300873 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
874 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
875 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300876 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
Jean-François Moinea1ac5dc2012-03-24 09:33:42 -0300877 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
878 {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
Brian Johnson26e744b2009-07-19 05:52:58 -0300879};
880
Jean-François Moinedae1de62012-03-24 09:20:25 -0300881static const struct i2c_reg_u8 ov7670_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300882 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300883 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
884 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
885 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
886 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
887 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
888 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
889 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
890 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
891 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
892 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
893 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
894 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
895 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
896 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
897 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
898 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
899 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
900 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
901 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
902 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
903 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
904 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
905 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
906 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
907 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
908 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
909 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
910 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
911 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
912 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
913 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
914 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
915 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
916 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
917 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
918 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
919 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
920 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
921 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
922 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
923 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
924 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
925 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
926 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
927 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
928 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
929 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
930 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
931 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
932 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
933 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
934 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
935 {0x93, 0x00},
936};
937
Jean-François Moinedae1de62012-03-24 09:20:25 -0300938static const struct i2c_reg_u8 ov9650_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300939 {0x00, 0x00}, {0x01, 0x78},
Brian Johnson26e744b2009-07-19 05:52:58 -0300940 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
941 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
942 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
943 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
944 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
945 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
946 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
947 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
948 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
949 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
950 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
951 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
952 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
953 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
954 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
955 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
956 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
957 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
958 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
959 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
960 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
961 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
962 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
963 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
964 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
965 {0xaa, 0x92}, {0xab, 0x0a},
966};
967
Jean-François Moinedae1de62012-03-24 09:20:25 -0300968static const struct i2c_reg_u8 ov9655_init[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300969 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300970 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
971 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
972 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
973 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
974 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
975 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
976 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
977 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
978 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
979 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
980 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
981 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
982 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
983 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
984 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300985 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300986 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
987 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300988 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300989 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
990 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
991 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
992 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300993};
994
Jean-François Moinedae1de62012-03-24 09:20:25 -0300995static const struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300996 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
997 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
998 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
999 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1000 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1001 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1002 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1003 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1004 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1005 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1006 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1007 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1008 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1009 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1010 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1011 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1012};
1013
Jean-François Moinedae1de62012-03-24 09:20:25 -03001014static const struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001015 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001016 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1017 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1018 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1019 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1020 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1021 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001022};
1023
Jean-François Moinedae1de62012-03-24 09:20:25 -03001024static const struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001025 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1026 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1027 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1028 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1029 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1030 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1031 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1032 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1033 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1034 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1035 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1036 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1037 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1038 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1039 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1040 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1041 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1042 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1043 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1044 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1045 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1046 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1047 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1048 {0x06, 0x0029}, {0x05, 0x0009},
1049};
1050
Jean-François Moinedae1de62012-03-24 09:20:25 -03001051static const struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001052 {0x0d, 0x0001},
1053 {0x0d, 0x0000},
1054 {0x04, 0x0500}, /* hres = 1280 */
1055 {0x03, 0x0400}, /* vres = 1024 */
1056 {0x20, 0x1100},
1057 {0x06, 0x0010},
1058 {0x2b, 0x0024},
1059 {0x2e, 0x0024},
1060 {0x35, 0x0024},
1061 {0x2d, 0x0020},
1062 {0x2c, 0x0020},
1063 {0x09, 0x0ad4},
1064 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001065};
1066
Jean-François Moinedae1de62012-03-24 09:20:25 -03001067static const struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001068 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1069 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001070 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1071 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001072};
1073
Jean-François Moinedae1de62012-03-24 09:20:25 -03001074static const struct i2c_reg_u16 mt9m112_init[] = {
Brian Johnsone99ac542010-03-16 13:58:28 -03001075 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1076 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1077 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1078 {0xf0, 0x0000},
1079};
1080
Jean-François Moinedae1de62012-03-24 09:20:25 -03001081static const struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001082 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1083 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1084 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1085 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1086 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1087 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1088 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1089 {0x23, 0x09}, {0x01, 0x08},
1090};
1091
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001092static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001093{
1094 struct usb_device *dev = gspca_dev->dev;
1095 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001096
1097 if (gspca_dev->usb_err < 0)
1098 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001099 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1100 0x00,
1101 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1102 reg,
1103 0x00,
1104 gspca_dev->usb_buf,
1105 length,
1106 500);
1107 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001108 pr_err("Read register %02x failed %d\n", reg, result);
1109 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001110 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001111}
1112
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001113static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
Joe Perches58aa68c2009-09-02 01:12:13 -03001114 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001115{
1116 struct usb_device *dev = gspca_dev->dev;
1117 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001118
1119 if (gspca_dev->usb_err < 0)
1120 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001121 memcpy(gspca_dev->usb_buf, buffer, length);
1122 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1123 0x08,
1124 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1125 reg,
1126 0x00,
1127 gspca_dev->usb_buf,
1128 length,
1129 500);
1130 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001131 pr_err("Write register %02x failed %d\n", reg, result);
1132 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001133 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001134}
1135
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001136static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001137{
Jean-François Moineff38d582012-03-19 04:55:16 -03001138 reg_w(gspca_dev, reg, &value, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001139}
1140
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001141static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001142{
1143 int i;
Jean-François Moineff38d582012-03-19 04:55:16 -03001144
Brian Johnson26e744b2009-07-19 05:52:58 -03001145 reg_w(gspca_dev, 0x10c0, buffer, 8);
1146 for (i = 0; i < 5; i++) {
1147 reg_r(gspca_dev, 0x10c0, 1);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001148 if (gspca_dev->usb_err < 0)
1149 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001150 if (gspca_dev->usb_buf[0] & 0x04) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001151 if (gspca_dev->usb_buf[0] & 0x08) {
1152 pr_err("i2c_w error\n");
1153 gspca_dev->usb_err = -EIO;
1154 }
1155 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001156 }
Jean-François Moinee71389b2012-03-19 04:45:20 -03001157 msleep(10);
Brian Johnson26e744b2009-07-19 05:52:58 -03001158 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001159 pr_err("i2c_w reg %02x no response\n", buffer[2]);
1160/* gspca_dev->usb_err = -EIO; fixme: may occur */
Brian Johnson26e744b2009-07-19 05:52:58 -03001161}
1162
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001163static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001164{
1165 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson26e744b2009-07-19 05:52:58 -03001166 u8 row[8];
1167
1168 /*
1169 * from the point of view of the bridge, the length
1170 * includes the address
1171 */
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001172 row[0] = sd->i2c_intf | (2 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001173 row[1] = sd->i2c_addr;
1174 row[2] = reg;
1175 row[3] = val;
1176 row[4] = 0x00;
1177 row[5] = 0x00;
1178 row[6] = 0x00;
1179 row[7] = 0x10;
1180
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001181 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001182}
1183
Jean-François Moined4689b72012-03-19 04:42:45 -03001184static void i2c_w1_buf(struct gspca_dev *gspca_dev,
Jean-François Moinedae1de62012-03-24 09:20:25 -03001185 const struct i2c_reg_u8 *buf, int sz)
Jean-François Moined4689b72012-03-19 04:42:45 -03001186{
1187 while (--sz >= 0) {
1188 i2c_w1(gspca_dev, buf->reg, buf->val);
1189 buf++;
1190 }
1191}
1192
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001193static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001194{
1195 struct sd *sd = (struct sd *) gspca_dev;
1196 u8 row[8];
1197
1198 /*
1199 * from the point of view of the bridge, the length
1200 * includes the address
1201 */
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001202 row[0] = sd->i2c_intf | (3 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001203 row[1] = sd->i2c_addr;
1204 row[2] = reg;
Jean-François Moineff38d582012-03-19 04:55:16 -03001205 row[3] = val >> 8;
1206 row[4] = val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001207 row[5] = 0x00;
1208 row[6] = 0x00;
1209 row[7] = 0x10;
1210
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001211 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001212}
1213
Jean-François Moined4689b72012-03-19 04:42:45 -03001214static void i2c_w2_buf(struct gspca_dev *gspca_dev,
Jean-François Moinedae1de62012-03-24 09:20:25 -03001215 const struct i2c_reg_u16 *buf, int sz)
Jean-François Moined4689b72012-03-19 04:42:45 -03001216{
1217 while (--sz >= 0) {
1218 i2c_w2(gspca_dev, buf->reg, buf->val);
1219 buf++;
1220 }
1221}
1222
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001223static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001224{
1225 struct sd *sd = (struct sd *) gspca_dev;
1226 u8 row[8];
1227
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001228 row[0] = sd->i2c_intf | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001229 row[1] = sd->i2c_addr;
1230 row[2] = reg;
1231 row[3] = 0;
1232 row[4] = 0;
1233 row[5] = 0;
1234 row[6] = 0;
1235 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001236 i2c_w(gspca_dev, row);
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001237 row[0] = sd->i2c_intf | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001238 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001239 i2c_w(gspca_dev, row);
1240 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001241 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001242}
1243
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001244static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001245{
1246 struct sd *sd = (struct sd *) gspca_dev;
1247 u8 row[8];
1248
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001249 row[0] = sd->i2c_intf | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001250 row[1] = sd->i2c_addr;
1251 row[2] = reg;
1252 row[3] = 0;
1253 row[4] = 0;
1254 row[5] = 0;
1255 row[6] = 0;
1256 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001257 i2c_w(gspca_dev, row);
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001258 row[0] = sd->i2c_intf | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001259 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001260 i2c_w(gspca_dev, row);
1261 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001262 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001263}
1264
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001265static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001266{
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001267 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001268 struct sd *sd = (struct sd *) gspca_dev;
1269
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001270 i2c_r2(gspca_dev, 0x1c, &id);
1271 if (gspca_dev->usb_err < 0)
1272 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001273
1274 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001275 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001276 gspca_dev->usb_err = -ENODEV;
1277 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001278 }
1279
Jean-François Moine92884f82012-03-19 04:33:30 -03001280 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1281 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001282 i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
1283 if (gspca_dev->usb_err < 0)
1284 pr_err("OV9650 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001285 sd->hstart = 1;
1286 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001287}
1288
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001289static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001290{
Brian Johnson26e744b2009-07-19 05:52:58 -03001291 struct sd *sd = (struct sd *) gspca_dev;
1292
Jean-François Moine92884f82012-03-19 04:33:30 -03001293 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1294 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001295 i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
1296 if (gspca_dev->usb_err < 0)
1297 pr_err("OV9655 sensor initialization failed\n");
1298
Brian Johnson26e744b2009-07-19 05:52:58 -03001299 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001300 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001301 sd->hstart = 1;
1302 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001303}
1304
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001305static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001306{
Brian Johnson26e744b2009-07-19 05:52:58 -03001307 struct sd *sd = (struct sd *) gspca_dev;
1308
Jean-François Moine92884f82012-03-19 04:33:30 -03001309 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1310 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001311 i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
1312 if (gspca_dev->usb_err < 0)
1313 pr_err("SOI968 sensor initialization failed\n");
1314
Brian Johnson26e744b2009-07-19 05:52:58 -03001315 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001316 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1317 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001318 sd->hstart = 60;
1319 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001320}
1321
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001322static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001323{
Brian Johnson26e744b2009-07-19 05:52:58 -03001324 struct sd *sd = (struct sd *) gspca_dev;
1325
Jean-François Moine92884f82012-03-19 04:33:30 -03001326 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1327 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001328 i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
1329 if (gspca_dev->usb_err < 0)
1330 pr_err("OV7660 sensor initialization failed\n");
Hans de Goede8bc50f32011-02-16 07:11:14 -03001331 sd->hstart = 3;
1332 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001333}
1334
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001335static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001336{
Brian Johnson26e744b2009-07-19 05:52:58 -03001337 struct sd *sd = (struct sd *) gspca_dev;
1338
Jean-François Moine92884f82012-03-19 04:33:30 -03001339 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1340 msleep(200);
Jean-François Moined4689b72012-03-19 04:42:45 -03001341 i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
1342 if (gspca_dev->usb_err < 0)
1343 pr_err("OV7670 sensor initialization failed\n");
1344
Brian Johnson26e744b2009-07-19 05:52:58 -03001345 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001346 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001347 sd->hstart = 0;
1348 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001349}
1350
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001351static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001352{
1353 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson26e744b2009-07-19 05:52:58 -03001354 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001355
1356 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001357 i2c_r2(gspca_dev, 0xff, &value);
1358 if (gspca_dev->usb_err >= 0
1359 && value == 0x8243) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001360 i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
1361 if (gspca_dev->usb_err < 0) {
1362 pr_err("MT9V011 sensor initialization failed\n");
1363 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001364 }
1365 sd->hstart = 2;
1366 sd->vstart = 2;
1367 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001368 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001369 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001370 }
1371
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001372 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001373 sd->i2c_addr = 0x5c;
1374 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001375 i2c_r2(gspca_dev, 0xff, &value);
1376 if (gspca_dev->usb_err >= 0
1377 && value == 0x823a) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001378 i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
1379 if (gspca_dev->usb_err < 0) {
1380 pr_err("MT9V111 sensor initialization failed\n");
1381 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001382 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001383 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1384 | (1 << AUTOGAIN)
1385 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001386 sd->hstart = 2;
1387 sd->vstart = 2;
1388 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001389 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001390 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001391 }
1392
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001393 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001394 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001395 i2c_w2(gspca_dev, 0xf0, 0x0000);
1396 if (gspca_dev->usb_err < 0) {
1397 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001398 sd->i2c_addr = 0x48;
1399 i2c_w2(gspca_dev, 0xf0, 0x0000);
1400 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001401 i2c_r2(gspca_dev, 0x00, &value);
1402 if (gspca_dev->usb_err >= 0
1403 && value == 0x1229) {
Jean-François Moined4689b72012-03-19 04:42:45 -03001404 i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
1405 if (gspca_dev->usb_err < 0) {
1406 pr_err("MT9V112 sensor initialization failed\n");
1407 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001408 }
1409 sd->hstart = 6;
1410 sd->vstart = 2;
1411 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001412 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001413 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001414 }
1415
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001416 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001417}
1418
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001419static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001420{
1421 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001422
1423 i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
1424 if (gspca_dev->usb_err < 0)
1425 pr_err("MT9M112 sensor initialization failed\n");
1426
Jean-François Moinec5224d82012-03-19 04:30:07 -03001427 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1428 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001429 sd->hstart = 0;
1430 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001431}
1432
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001433static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001434{
1435 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moined4689b72012-03-19 04:42:45 -03001436
1437 i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
1438 if (gspca_dev->usb_err < 0)
1439 pr_err("MT9M111 sensor initialization failed\n");
1440
Jean-François Moinec5224d82012-03-19 04:30:07 -03001441 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1442 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001443 sd->hstart = 0;
1444 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001445}
1446
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001447static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001448{
1449 struct sd *sd = (struct sd *) gspca_dev;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001450 u16 id;
1451
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001452 i2c_r2(gspca_dev, 0x00, &id);
1453 if (gspca_dev->usb_err < 0)
1454 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001455
1456 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1457 switch (id) {
1458 case 0x8411:
1459 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001460 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001461 break;
1462 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001463 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001464 break;
1465 default:
Joe Perches91f58422011-08-21 19:56:55 -03001466 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001467 gspca_dev->usb_err = -ENODEV;
1468 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001469 }
1470
Jean-François Moined4689b72012-03-19 04:42:45 -03001471 i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
1472 if (gspca_dev->usb_err < 0)
1473 pr_err("MT9M001 sensor initialization failed\n");
1474
Brian Johnson26e744b2009-07-19 05:52:58 -03001475 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001476 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001477 sd->hstart = 1;
1478 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001479}
1480
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001481static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001482{
Brian Johnson26e744b2009-07-19 05:52:58 -03001483 struct sd *sd = (struct sd *) gspca_dev;
1484
Jean-François Moined4689b72012-03-19 04:42:45 -03001485 i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
1486 if (gspca_dev->usb_err < 0)
1487 pr_err("HV7131R Sensor initialization failed\n");
1488
Brian Johnson26e744b2009-07-19 05:52:58 -03001489 sd->hstart = 0;
1490 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001491}
1492
Jean-François Moinec5224d82012-03-19 04:30:07 -03001493static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001494{
1495 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001496 int satur;
1497 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001498 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001499
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001500 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001501 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001502 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1503 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001504 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001505
Jean-François Moinec5224d82012-03-19 04:30:07 -03001506 satur = sd->ctrls[SATURATION].val;
1507 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001508 cmatrix[6] = hue_coord;
1509 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001510
Jean-François Moinec5224d82012-03-19 04:30:07 -03001511 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001512 cmatrix[8] = hue_coord;
1513 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001514
Jean-François Moinec5224d82012-03-19 04:30:07 -03001515 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001516 cmatrix[10] = hue_coord;
1517 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001518
Jean-François Moinec5224d82012-03-19 04:30:07 -03001519 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001520 cmatrix[12] = hue_coord;
1521 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001522
Jean-François Moinec5224d82012-03-19 04:30:07 -03001523 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001524 cmatrix[14] = hue_coord;
1525 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001526
Jean-François Moinec5224d82012-03-19 04:30:07 -03001527 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001528 cmatrix[16] = hue_coord;
1529 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001530
Jean-François Moinec5224d82012-03-19 04:30:07 -03001531 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001532}
1533
Jean-François Moinec5224d82012-03-19 04:30:07 -03001534static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001538 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001539
1540 gamma[0] = 0x0a;
1541 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1542 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1543 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1544 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1545 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1546 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1547 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1548 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1549 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1550 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1551 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1552 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1553 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1554 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1555 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1556 gamma[16] = 0xf5;
1557
Jean-François Moinec5224d82012-03-19 04:30:07 -03001558 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001559}
1560
Jean-François Moinec5224d82012-03-19 04:30:07 -03001561static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001562{
1563 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001564
1565 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1566 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001567}
1568
Jean-François Moinec5224d82012-03-19 04:30:07 -03001569static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001570{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001571 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001572 u16 value2;
1573 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001574
1575 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001576 hflip = !sd->ctrls[HFLIP].val;
1577 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001578 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001579 hflip = sd->ctrls[HFLIP].val;
1580 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001581 }
1582
Brian Johnson26e744b2009-07-19 05:52:58 -03001583 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001584 case SENSOR_OV7660:
1585 value = 0x01;
1586 if (hflip)
1587 value |= 0x20;
1588 if (vflip) {
1589 value |= 0x10;
1590 sd->vstart = 2;
Jean-François Moineff38d582012-03-19 04:55:16 -03001591 } else {
Hans de Goede779b51f2011-02-16 08:17:36 -03001592 sd->vstart = 3;
Jean-François Moineff38d582012-03-19 04:55:16 -03001593 }
Hans de Goede779b51f2011-02-16 08:17:36 -03001594 reg_w1(gspca_dev, 0x1182, sd->vstart);
1595 i2c_w1(gspca_dev, 0x1e, value);
1596 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001597 case SENSOR_OV9650:
1598 i2c_r1(gspca_dev, 0x1e, &value);
1599 value &= ~0x30;
1600 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001601 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001602 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001603 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001604 value |= 0x10;
1605 tslb = 0x49;
1606 }
1607 i2c_w1(gspca_dev, 0x1e, value);
1608 i2c_w1(gspca_dev, 0x3a, tslb);
1609 break;
1610 case SENSOR_MT9V111:
1611 case SENSOR_MT9V011:
1612 i2c_r2(gspca_dev, 0x20, &value2);
1613 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001614 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001615 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001616 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001617 value2 |= 0x4020;
1618 i2c_w2(gspca_dev, 0x20, value2);
1619 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001620 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001621 case SENSOR_MT9M111:
1622 case SENSOR_MT9V112:
1623 i2c_r2(gspca_dev, 0x20, &value2);
1624 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001625 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001626 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001627 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001628 value2 |= 0x0001;
1629 i2c_w2(gspca_dev, 0x20, value2);
1630 break;
1631 case SENSOR_HV7131R:
1632 i2c_r1(gspca_dev, 0x01, &value);
1633 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001634 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001635 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001636 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001637 value |= 0x02;
1638 i2c_w1(gspca_dev, 0x01, value);
1639 break;
1640 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001641}
1642
Jean-François Moinec5224d82012-03-19 04:30:07 -03001643static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001644{
1645 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001646 u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
Jean-François Moine4fb81372012-03-24 09:28:39 -03001647 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-François Moinea1ac5dc2012-03-24 09:33:42 -03001648 int expo, expo2;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001649
Jean-François Moine4fb81372012-03-24 09:28:39 -03001650 if (gspca_dev->streaming)
1651 exp[7] = 0x1e;
1652
Jean-François Moinec5224d82012-03-19 04:30:07 -03001653 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001654 switch (sd->sensor) {
1655 case SENSOR_OV7660:
1656 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001657 case SENSOR_OV9655:
1658 case SENSOR_OV9650:
Jean-François Moinea1ac5dc2012-03-24 09:33:42 -03001659 if (expo > 547)
1660 expo2 = 547;
1661 else
1662 expo2 = expo;
1663 exp[0] |= (2 << 4);
1664 exp[2] = 0x10; /* AECH */
1665 exp[3] = expo2 >> 2;
1666 exp[7] = 0x10;
1667 i2c_w(gspca_dev, exp);
1668 exp[2] = 0x04; /* COM1 */
1669 exp[3] = expo2 & 0x0003;
1670 exp[7] = 0x10;
1671 i2c_w(gspca_dev, exp);
1672 expo -= expo2;
1673 exp[7] = 0x1e;
Brian Johnson26e744b2009-07-19 05:52:58 -03001674 exp[0] |= (3 << 4);
Jean-François Moinea1ac5dc2012-03-24 09:33:42 -03001675 exp[2] = 0x2d; /* ADVFL & ADVFH */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001676 exp[3] = expo;
1677 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001678 break;
1679 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001680 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001681 case SENSOR_MT9V011:
1682 exp[0] |= (3 << 4);
1683 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001684 exp[3] = expo >> 8;
1685 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 break;
1687 case SENSOR_HV7131R:
1688 exp[0] |= (4 << 4);
1689 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001690 exp[3] = expo >> 5;
1691 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001692 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001693 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001694 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001695 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001696 }
1697 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001698}
1699
Jean-François Moinec5224d82012-03-19 04:30:07 -03001700static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001701{
1702 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001703 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
Jean-François Moine4fb81372012-03-24 09:28:39 -03001704 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001705 int g;
1706
Jean-François Moine4fb81372012-03-24 09:28:39 -03001707 if (gspca_dev->streaming)
1708 gain[7] = 0x15; /* or 1d ? */
1709
Jean-François Moinec5224d82012-03-19 04:30:07 -03001710 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001711 switch (sd->sensor) {
1712 case SENSOR_OV7660:
1713 case SENSOR_OV7670:
1714 case SENSOR_SOI968:
1715 case SENSOR_OV9655:
1716 case SENSOR_OV9650:
1717 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001718 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001719 break;
1720 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001721 gain[0] |= (3 << 4);
1722 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001723 gain[3] = micron1_gain[g] >> 8;
1724 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001725 break;
1726 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001727 gain[0] |= (3 << 4);
1728 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001729 gain[3] = micron1_gain[g] >> 8;
1730 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001731 break;
1732 case SENSOR_MT9M001:
1733 gain[0] |= (3 << 4);
1734 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001735 gain[3] = micron2_gain[g] >> 8;
1736 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001737 break;
1738 case SENSOR_HV7131R:
1739 gain[0] |= (2 << 4);
1740 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001741 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001742 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001743 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001744 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001745 }
1746 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001747}
1748
Jean-François Moine4c632e42012-03-19 04:35:34 -03001749static void set_quality(struct gspca_dev *gspca_dev)
1750{
1751 struct sd *sd = (struct sd *) gspca_dev;
1752
1753 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
1754 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1755 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1756 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1757 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1758 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1759 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1760 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1761 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1762}
1763
Brian Johnson26e744b2009-07-19 05:52:58 -03001764#ifdef CONFIG_VIDEO_ADV_DEBUG
1765static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1766 struct v4l2_dbg_register *reg)
1767{
1768 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03001769
Brian Johnson26e744b2009-07-19 05:52:58 -03001770 switch (reg->match.type) {
1771 case V4L2_CHIP_MATCH_HOST:
1772 if (reg->match.addr != 0)
1773 return -EINVAL;
1774 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1775 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001776 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001777 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001778 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_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001785 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001786 i2c_r1(gspca_dev, reg->reg, (u8 *) &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
1793static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1794 struct v4l2_dbg_register *reg)
1795{
1796 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03001797
Brian Johnson26e744b2009-07-19 05:52:58 -03001798 switch (reg->match.type) {
1799 case V4L2_CHIP_MATCH_HOST:
1800 if (reg->match.addr != 0)
1801 return -EINVAL;
1802 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1803 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001804 reg_w1(gspca_dev, reg->reg, reg->val);
1805 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001806 case V4L2_CHIP_MATCH_I2C_ADDR:
1807 if (reg->match.addr != sd->i2c_addr)
1808 return -EINVAL;
1809 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001810 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001811 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001812 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001813 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001814 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001815 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001816 }
1817 return -EINVAL;
1818}
1819#endif
1820
1821static int sd_chip_ident(struct gspca_dev *gspca_dev,
1822 struct v4l2_dbg_chip_ident *chip)
1823{
1824 struct sd *sd = (struct sd *) gspca_dev;
1825
1826 switch (chip->match.type) {
1827 case V4L2_CHIP_MATCH_HOST:
1828 if (chip->match.addr != 0)
1829 return -EINVAL;
1830 chip->revision = 0;
1831 chip->ident = V4L2_IDENT_SN9C20X;
1832 return 0;
1833 case V4L2_CHIP_MATCH_I2C_ADDR:
1834 if (chip->match.addr != sd->i2c_addr)
1835 return -EINVAL;
1836 chip->revision = 0;
1837 chip->ident = i2c_ident[sd->sensor];
1838 return 0;
1839 }
1840 return -EINVAL;
1841}
1842
1843static int sd_config(struct gspca_dev *gspca_dev,
1844 const struct usb_device_id *id)
1845{
1846 struct sd *sd = (struct sd *) gspca_dev;
1847 struct cam *cam;
1848
1849 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001850 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001851
Jean-François Moineff38d582012-03-19 04:55:16 -03001852 sd->sensor = id->driver_info >> 8;
1853 sd->i2c_addr = id->driver_info;
1854 sd->flags = id->driver_info >> 16;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001855 sd->i2c_intf = 0x80; /* i2c 100 Kb/s */
Brian Johnson26e744b2009-07-19 05:52:58 -03001856
1857 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001858 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001859 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001860 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001861 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001862 cam->cam_mode = sxga_mode;
1863 cam->nmodes = ARRAY_SIZE(sxga_mode);
1864 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001865 case SENSOR_MT9M001:
1866 cam->cam_mode = mono_mode;
1867 cam->nmodes = ARRAY_SIZE(mono_mode);
1868 break;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001869 case SENSOR_HV7131R:
1870 sd->i2c_intf = 0x81; /* i2c 400 Kb/s */
1871 /* fall thru */
Brian Johnson26e744b2009-07-19 05:52:58 -03001872 default:
1873 cam->cam_mode = vga_mode;
1874 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001875 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001876 }
1877
1878 sd->old_step = 0;
1879 sd->older_step = 0;
1880 sd->exposure_step = 16;
1881
Jean-François Moinec5224d82012-03-19 04:30:07 -03001882 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001883
Jean-François Moine92dcffc2012-03-19 04:47:24 -03001884 INIT_WORK(&sd->work, qual_upd);
Brian Johnson26e744b2009-07-19 05:52:58 -03001885
Brian Johnson26e744b2009-07-19 05:52:58 -03001886 return 0;
1887}
1888
1889static int sd_init(struct gspca_dev *gspca_dev)
1890{
1891 struct sd *sd = (struct sd *) gspca_dev;
1892 int i;
1893 u8 value;
1894 u8 i2c_init[9] =
1895 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1896
1897 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1898 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001899 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1900 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001901 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001902 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001903 }
1904 }
1905
Brian Johnson0c045eb2010-03-16 13:58:27 -03001906 if (sd->flags & LED_REVERSE)
1907 reg_w1(gspca_dev, 0x1006, 0x00);
1908 else
1909 reg_w1(gspca_dev, 0x1006, 0x20);
1910
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001911 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1912 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001913 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001914 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001915 }
1916
1917 switch (sd->sensor) {
1918 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001919 ov9650_init_sensor(gspca_dev);
1920 if (gspca_dev->usb_err < 0)
1921 break;
Joe Perches91f58422011-08-21 19:56:55 -03001922 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001923 break;
1924 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001925 ov9655_init_sensor(gspca_dev);
1926 if (gspca_dev->usb_err < 0)
1927 break;
Joe Perches91f58422011-08-21 19:56:55 -03001928 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001929 break;
1930 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001931 soi968_init_sensor(gspca_dev);
1932 if (gspca_dev->usb_err < 0)
1933 break;
Joe Perches91f58422011-08-21 19:56:55 -03001934 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001935 break;
1936 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001937 ov7660_init_sensor(gspca_dev);
1938 if (gspca_dev->usb_err < 0)
1939 break;
Joe Perches91f58422011-08-21 19:56:55 -03001940 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001941 break;
1942 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001943 ov7670_init_sensor(gspca_dev);
1944 if (gspca_dev->usb_err < 0)
1945 break;
Joe Perches91f58422011-08-21 19:56:55 -03001946 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001947 break;
1948 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001949 mt9v_init_sensor(gspca_dev);
1950 if (gspca_dev->usb_err < 0)
1951 break;
Jean-François Moineff38d582012-03-19 04:55:16 -03001952 pr_info("MT9VPRB sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001953 break;
1954 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001955 mt9m111_init_sensor(gspca_dev);
1956 if (gspca_dev->usb_err < 0)
1957 break;
Joe Perches91f58422011-08-21 19:56:55 -03001958 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001959 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001960 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001961 mt9m112_init_sensor(gspca_dev);
1962 if (gspca_dev->usb_err < 0)
1963 break;
Joe Perches91f58422011-08-21 19:56:55 -03001964 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001965 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001966 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001967 mt9m001_init_sensor(gspca_dev);
1968 if (gspca_dev->usb_err < 0)
1969 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001970 break;
1971 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001972 hv7131r_init_sensor(gspca_dev);
1973 if (gspca_dev->usb_err < 0)
1974 break;
Joe Perches91f58422011-08-21 19:56:55 -03001975 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001976 break;
1977 default:
Jean-François Moineff38d582012-03-19 04:55:16 -03001978 pr_err("Unsupported sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001979 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001980 }
1981
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001982 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001983}
1984
1985static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1986{
1987 struct sd *sd = (struct sd *) gspca_dev;
1988 u8 value;
Jean-François Moineff38d582012-03-19 04:55:16 -03001989
Brian Johnson26e744b2009-07-19 05:52:58 -03001990 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001991 case SENSOR_SOI968:
1992 if (mode & MODE_SXGA) {
1993 i2c_w1(gspca_dev, 0x17, 0x1d);
1994 i2c_w1(gspca_dev, 0x18, 0xbd);
1995 i2c_w1(gspca_dev, 0x19, 0x01);
1996 i2c_w1(gspca_dev, 0x1a, 0x81);
1997 i2c_w1(gspca_dev, 0x12, 0x00);
1998 sd->hstart = 140;
1999 sd->vstart = 19;
2000 } else {
2001 i2c_w1(gspca_dev, 0x17, 0x13);
2002 i2c_w1(gspca_dev, 0x18, 0x63);
2003 i2c_w1(gspca_dev, 0x19, 0x01);
2004 i2c_w1(gspca_dev, 0x1a, 0x79);
2005 i2c_w1(gspca_dev, 0x12, 0x40);
2006 sd->hstart = 60;
2007 sd->vstart = 11;
2008 }
2009 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002010 case SENSOR_OV9650:
2011 if (mode & MODE_SXGA) {
2012 i2c_w1(gspca_dev, 0x17, 0x1b);
2013 i2c_w1(gspca_dev, 0x18, 0xbc);
2014 i2c_w1(gspca_dev, 0x19, 0x01);
2015 i2c_w1(gspca_dev, 0x1a, 0x82);
2016 i2c_r1(gspca_dev, 0x12, &value);
2017 i2c_w1(gspca_dev, 0x12, value & 0x07);
2018 } else {
2019 i2c_w1(gspca_dev, 0x17, 0x24);
2020 i2c_w1(gspca_dev, 0x18, 0xc5);
2021 i2c_w1(gspca_dev, 0x19, 0x00);
2022 i2c_w1(gspca_dev, 0x1a, 0x3c);
2023 i2c_r1(gspca_dev, 0x12, &value);
2024 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2025 }
2026 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002027 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002028 case SENSOR_MT9M111:
2029 if (mode & MODE_SXGA) {
2030 i2c_w2(gspca_dev, 0xf0, 0x0002);
2031 i2c_w2(gspca_dev, 0xc8, 0x970b);
2032 i2c_w2(gspca_dev, 0xf0, 0x0000);
2033 } else {
2034 i2c_w2(gspca_dev, 0xf0, 0x0002);
2035 i2c_w2(gspca_dev, 0xc8, 0x8000);
2036 i2c_w2(gspca_dev, 0xf0, 0x0000);
2037 }
2038 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002039 }
2040}
2041
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002042static int sd_isoc_init(struct gspca_dev *gspca_dev)
2043{
2044 struct usb_interface *intf;
2045 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2046
2047 /*
2048 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2049 * than our regular bandwidth calculations reserve, so we force the
2050 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2051 */
2052 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2053 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2054
2055 if (intf->num_altsetting != 9) {
2056 pr_warn("sn9c20x camera with unknown number of alt "
2057 "settings (%d), please report!\n",
2058 intf->num_altsetting);
2059 gspca_dev->alt = intf->num_altsetting;
2060 return 0;
2061 }
2062
2063 switch (gspca_dev->width) {
2064 case 160: /* 160x120 */
2065 gspca_dev->alt = 2;
2066 break;
2067 case 320: /* 320x240 */
2068 gspca_dev->alt = 6;
2069 break;
2070 default: /* >= 640x480 */
2071 gspca_dev->alt = 9;
Jean-François Moineff38d582012-03-19 04:55:16 -03002072 break;
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002073 }
2074 }
2075
2076 return 0;
2077}
2078
Brian Johnson26e744b2009-07-19 05:52:58 -03002079#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002080((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002081(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2082(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2083
2084#define CLR_WIN(width, height) \
2085((const u8 [])\
2086{0, width >> 2, 0, height >> 1,\
2087((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2088
2089static int sd_start(struct gspca_dev *gspca_dev)
2090{
2091 struct sd *sd = (struct sd *) gspca_dev;
2092 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2093 int width = gspca_dev->width;
2094 int height = gspca_dev->height;
2095 u8 fmt, scale = 0;
2096
Brian Johnson26e744b2009-07-19 05:52:58 -03002097 jpeg_define(sd->jpeg_hdr, height, width,
2098 0x21);
Jean-François Moine4c632e42012-03-19 04:35:34 -03002099 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03002100
2101 if (mode & MODE_RAW)
2102 fmt = 0x2d;
2103 else if (mode & MODE_JPEG)
Jean-François Moine4c632e42012-03-19 04:35:34 -03002104 fmt = 0x24;
Brian Johnson26e744b2009-07-19 05:52:58 -03002105 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002106 fmt = 0x2f; /* YUV 420 */
Jean-François Moine4c632e42012-03-19 04:35:34 -03002107 sd->fmt = fmt;
Brian Johnson26e744b2009-07-19 05:52:58 -03002108
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002109 switch (mode & SCALE_MASK) {
2110 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002111 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002112 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002113 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002114 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002115 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002116 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002117 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002118 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002119 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002120 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002121 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002122 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002123 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002124 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002125 break;
2126 }
2127
2128 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002129 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2130 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002131 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2132 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2133 reg_w1(gspca_dev, 0x1189, scale);
2134 reg_w1(gspca_dev, 0x10e0, fmt);
2135
2136 set_cmatrix(gspca_dev);
2137 set_gamma(gspca_dev);
2138 set_redblue(gspca_dev);
2139 set_gain(gspca_dev);
2140 set_exposure(gspca_dev);
2141 set_hvflip(gspca_dev);
2142
Brian Johnson0c045eb2010-03-16 13:58:27 -03002143 reg_w1(gspca_dev, 0x1007, 0x20);
Jean-François Moineccbaba42012-03-19 04:51:30 -03002144 reg_w1(gspca_dev, 0x1061, 0x03);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002145
2146 /* if JPEG, prepare the compression quality update */
2147 if (mode & MODE_JPEG) {
2148 sd->pktsz = sd->npkt = 0;
2149 sd->nchg = 0;
2150 sd->work_thread =
2151 create_singlethread_workqueue(KBUILD_MODNAME);
2152 }
2153
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002154 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002155}
2156
2157static void sd_stopN(struct gspca_dev *gspca_dev)
2158{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002159 reg_w1(gspca_dev, 0x1007, 0x00);
Jean-François Moineccbaba42012-03-19 04:51:30 -03002160 reg_w1(gspca_dev, 0x1061, 0x01);
Brian Johnson26e744b2009-07-19 05:52:58 -03002161}
2162
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002163/* called on streamoff with alt==0 and on disconnect */
2164/* the usb_lock is held at entry - restore on exit */
2165static void sd_stop0(struct gspca_dev *gspca_dev)
2166{
2167 struct sd *sd = (struct sd *) gspca_dev;
2168
2169 if (sd->work_thread != NULL) {
2170 mutex_unlock(&gspca_dev->usb_lock);
2171 destroy_workqueue(sd->work_thread);
2172 mutex_lock(&gspca_dev->usb_lock);
2173 sd->work_thread = NULL;
2174 }
2175}
2176
Brian Johnsone1430472009-09-02 12:39:41 -03002177static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002178{
2179 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002180 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002181
2182 /*
2183 * some hardcoded values are present
2184 * like those for maximal/minimal exposure
2185 * and exposure steps
2186 */
2187 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002188 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002189 return;
2190
Jean-François Moinec5224d82012-03-19 04:30:07 -03002191 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002192 if (new_exp > 0x1770)
2193 new_exp = 0x1770;
2194 if (new_exp < 0x10)
2195 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002196 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002197 set_exposure(gspca_dev);
2198
2199 sd->older_step = sd->old_step;
2200 sd->old_step = 1;
2201
2202 if (sd->old_step ^ sd->older_step)
2203 sd->exposure_step /= 2;
2204 else
2205 sd->exposure_step += 2;
2206 }
2207 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002208 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002209 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002210 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002211 if (new_exp > 0x1700)
2212 new_exp = 0x1770;
2213 if (new_exp < 0x10)
2214 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002215 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002216 set_exposure(gspca_dev);
2217 sd->older_step = sd->old_step;
2218 sd->old_step = 0;
2219
2220 if (sd->old_step ^ sd->older_step)
2221 sd->exposure_step /= 2;
2222 else
2223 sd->exposure_step += 2;
2224 }
2225}
2226
Brian Johnsone1430472009-09-02 12:39:41 -03002227static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2228{
2229 struct sd *sd = (struct sd *) gspca_dev;
2230
2231 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002232 if (sd->ctrls[GAIN].val + 1 <= 28) {
2233 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002234 set_gain(gspca_dev);
2235 }
2236 }
2237 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002238 if (sd->ctrls[GAIN].val > 0) {
2239 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002240 set_gain(gspca_dev);
2241 }
2242 }
2243}
2244
2245static void sd_dqcallback(struct gspca_dev *gspca_dev)
2246{
2247 struct sd *sd = (struct sd *) gspca_dev;
2248 int avg_lum;
2249
Jean-François Moinec5224d82012-03-19 04:30:07 -03002250 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002251 return;
2252
2253 avg_lum = atomic_read(&sd->avg_lum);
2254 if (sd->sensor == SENSOR_SOI968)
2255 do_autogain(gspca_dev, avg_lum);
2256 else
2257 do_autoexposure(gspca_dev, avg_lum);
2258}
2259
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002260/* JPEG quality update */
2261/* This function is executed from a work queue. */
2262static void qual_upd(struct work_struct *work)
2263{
2264 struct sd *sd = container_of(work, struct sd, work);
2265 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2266
2267 mutex_lock(&gspca_dev->usb_lock);
2268 PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val);
2269 set_quality(gspca_dev);
2270 mutex_unlock(&gspca_dev->usb_lock);
2271}
2272
Jean-François Moine28566432010-10-01 07:33:26 -03002273#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002274static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2275 u8 *data, /* interrupt packet */
2276 int len) /* interrupt packet length */
2277{
2278 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03002279
Brian Johnson33ddc162010-04-18 21:42:40 -03002280 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Jean-François Moineff38d582012-03-19 04:55:16 -03002281 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2282 input_sync(gspca_dev->input_dev);
2283 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2284 input_sync(gspca_dev->input_dev);
2285 return 0;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002286 }
Jean-François Moineff38d582012-03-19 04:55:16 -03002287 return -EINVAL;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002288}
2289#endif
2290
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002291/* check the JPEG compression */
2292static void transfer_check(struct gspca_dev *gspca_dev,
2293 u8 *data)
2294{
2295 struct sd *sd = (struct sd *) gspca_dev;
2296 int new_qual, r;
2297
2298 new_qual = 0;
2299
2300 /* if USB error, discard the frame and decrease the quality */
2301 if (data[6] & 0x08) { /* USB FIFO full */
2302 gspca_dev->last_packet_type = DISCARD_PACKET;
2303 new_qual = -5;
2304 } else {
2305
2306 /* else, compute the filling rate and a new JPEG quality */
2307 r = (sd->pktsz * 100) /
2308 (sd->npkt *
2309 gspca_dev->urb[0]->iso_frame_desc[0].length);
2310 if (r >= 85)
2311 new_qual = -3;
2312 else if (r < 75)
2313 new_qual = 2;
2314 }
2315 if (new_qual != 0) {
2316 sd->nchg += new_qual;
2317 if (sd->nchg < -6 || sd->nchg >= 12) {
2318 sd->nchg = 0;
2319 new_qual += sd->ctrls[QUALITY].val;
2320 if (new_qual < QUALITY_MIN)
2321 new_qual = QUALITY_MIN;
2322 else if (new_qual > QUALITY_MAX)
2323 new_qual = QUALITY_MAX;
2324 if (new_qual != sd->ctrls[QUALITY].val) {
2325 sd->ctrls[QUALITY].val = new_qual;
2326 queue_work(sd->work_thread, &sd->work);
2327 }
2328 }
2329 } else {
2330 sd->nchg = 0;
2331 }
2332 sd->pktsz = sd->npkt = 0;
2333}
2334
Brian Johnson26e744b2009-07-19 05:52:58 -03002335static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002336 u8 *data, /* isoc packet */
2337 int len) /* iso packet length */
2338{
2339 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03002340 int avg_lum, is_jpeg;
Jean-François Moinedae1de62012-03-24 09:20:25 -03002341 static const u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002342 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moineff38d582012-03-19 04:55:16 -03002343
2344 is_jpeg = (sd->fmt & 0x03) == 0;
Jean-François Moine1f42df02012-03-19 04:22:44 -03002345 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002346 avg_lum = ((data[35] >> 2) & 3) |
2347 (data[20] << 2) |
2348 (data[19] << 10);
2349 avg_lum += ((data[35] >> 4) & 3) |
2350 (data[22] << 2) |
2351 (data[21] << 10);
2352 avg_lum += ((data[35] >> 6) & 3) |
2353 (data[24] << 2) |
2354 (data[23] << 10);
2355 avg_lum += (data[36] & 3) |
2356 (data[26] << 2) |
2357 (data[25] << 10);
2358 avg_lum += ((data[36] >> 2) & 3) |
2359 (data[28] << 2) |
2360 (data[27] << 10);
2361 avg_lum += ((data[36] >> 4) & 3) |
2362 (data[30] << 2) |
2363 (data[29] << 10);
2364 avg_lum += ((data[36] >> 6) & 3) |
2365 (data[32] << 2) |
2366 (data[31] << 10);
2367 avg_lum += ((data[44] >> 4) & 3) |
2368 (data[34] << 2) |
2369 (data[33] << 10);
2370 avg_lum >>= 9;
2371 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002372
Jean-François Moineff38d582012-03-19 04:55:16 -03002373 if (is_jpeg)
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002374 transfer_check(gspca_dev, data);
2375
Jean-François Moine04d174e2010-09-13 05:22:37 -03002376 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002377 len -= 64;
2378 if (len == 0)
2379 return;
2380 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002381 }
2382 if (gspca_dev->last_packet_type == LAST_PACKET) {
Jean-François Moineff38d582012-03-19 04:55:16 -03002383 if (is_jpeg) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002384 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002385 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002386 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002387 data, len);
2388 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002389 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002390 data, len);
2391 }
2392 } else {
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002393 /* if JPEG, count the packets and their size */
Jean-François Moineff38d582012-03-19 04:55:16 -03002394 if (is_jpeg) {
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002395 sd->npkt++;
2396 sd->pktsz += len;
2397 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002398 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002399 }
2400}
2401
2402/* sub-driver description */
2403static const struct sd_desc sd_desc = {
Jean-François Moineff38d582012-03-19 04:55:16 -03002404 .name = KBUILD_MODNAME,
Brian Johnson26e744b2009-07-19 05:52:58 -03002405 .ctrls = sd_ctrls,
2406 .nctrls = ARRAY_SIZE(sd_ctrls),
2407 .config = sd_config,
2408 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002409 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002410 .start = sd_start,
2411 .stopN = sd_stopN,
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002412 .stop0 = sd_stop0,
Brian Johnson26e744b2009-07-19 05:52:58 -03002413 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002414#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002415 .int_pkt_scan = sd_int_pkt_scan,
2416#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002417 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002418#ifdef CONFIG_VIDEO_ADV_DEBUG
2419 .set_register = sd_dbg_s_register,
2420 .get_register = sd_dbg_g_register,
2421#endif
2422 .get_chip_ident = sd_chip_ident,
2423};
2424
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002425#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002426 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002427 | (SENSOR_ ## sensor << 8) \
2428 | (i2c_addr)
2429
Jean-François Moine95c967c2011-01-13 05:20:29 -03002430static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002431 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2432 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2433 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002434 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002435 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2436 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2437 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002438 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2439 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2440 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2441 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002442 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002443 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2444 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2445 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2446 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002447 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002448 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002449 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2450 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2451 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2452 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002453 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002454 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002455 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2456 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2457 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2458 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002459 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2460 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002461 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2462 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2463 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2464 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002465 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002466 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2467 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2468 {}
2469};
2470MODULE_DEVICE_TABLE(usb, device_table);
2471
2472/* -- device connect -- */
2473static int sd_probe(struct usb_interface *intf,
2474 const struct usb_device_id *id)
2475{
2476 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2477 THIS_MODULE);
2478}
2479
Brian Johnson26e744b2009-07-19 05:52:58 -03002480static struct usb_driver sd_driver = {
Jean-François Moineff38d582012-03-19 04:55:16 -03002481 .name = KBUILD_MODNAME,
Brian Johnson26e744b2009-07-19 05:52:58 -03002482 .id_table = device_table,
2483 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002484 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002485#ifdef CONFIG_PM
2486 .suspend = gspca_suspend,
2487 .resume = gspca_resume,
2488 .reset_resume = gspca_resume,
2489#endif
2490};
2491
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002492module_usb_driver(sd_driver);