blob: da2904a891aa78ed07faaab4da60bd0cbea59e5c [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},
877 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
878 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
879};
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 Moinec5224d82012-03-19 04:30:07 -03001648 int expo;
1649
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:
1659 exp[0] |= (3 << 4);
1660 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001661 exp[3] = expo;
1662 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001663 break;
1664 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001665 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001666 case SENSOR_MT9V011:
1667 exp[0] |= (3 << 4);
1668 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001669 exp[3] = expo >> 8;
1670 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001671 break;
1672 case SENSOR_HV7131R:
1673 exp[0] |= (4 << 4);
1674 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001675 exp[3] = expo >> 5;
1676 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001677 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001678 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001679 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001680 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001681 }
1682 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001683}
1684
Jean-François Moinec5224d82012-03-19 04:30:07 -03001685static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001686{
1687 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001688 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
Jean-François Moine4fb81372012-03-24 09:28:39 -03001689 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001690 int g;
1691
Jean-François Moine4fb81372012-03-24 09:28:39 -03001692 if (gspca_dev->streaming)
1693 gain[7] = 0x15; /* or 1d ? */
1694
Jean-François Moinec5224d82012-03-19 04:30:07 -03001695 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001696 switch (sd->sensor) {
1697 case SENSOR_OV7660:
1698 case SENSOR_OV7670:
1699 case SENSOR_SOI968:
1700 case SENSOR_OV9655:
1701 case SENSOR_OV9650:
1702 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001703 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001704 break;
1705 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001706 gain[0] |= (3 << 4);
1707 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001708 gain[3] = micron1_gain[g] >> 8;
1709 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001710 break;
1711 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001712 gain[0] |= (3 << 4);
1713 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001714 gain[3] = micron1_gain[g] >> 8;
1715 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001716 break;
1717 case SENSOR_MT9M001:
1718 gain[0] |= (3 << 4);
1719 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001720 gain[3] = micron2_gain[g] >> 8;
1721 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001722 break;
1723 case SENSOR_HV7131R:
1724 gain[0] |= (2 << 4);
1725 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001726 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001727 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001728 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001729 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001730 }
1731 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001732}
1733
Jean-François Moine4c632e42012-03-19 04:35:34 -03001734static void set_quality(struct gspca_dev *gspca_dev)
1735{
1736 struct sd *sd = (struct sd *) gspca_dev;
1737
1738 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
1739 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1740 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1741 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1742 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1743 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1744 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1745 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1746 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1747}
1748
Brian Johnson26e744b2009-07-19 05:52:58 -03001749#ifdef CONFIG_VIDEO_ADV_DEBUG
1750static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1751 struct v4l2_dbg_register *reg)
1752{
1753 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03001754
Brian Johnson26e744b2009-07-19 05:52:58 -03001755 switch (reg->match.type) {
1756 case V4L2_CHIP_MATCH_HOST:
1757 if (reg->match.addr != 0)
1758 return -EINVAL;
1759 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1760 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001761 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001762 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001763 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001764 case V4L2_CHIP_MATCH_I2C_ADDR:
1765 if (reg->match.addr != sd->i2c_addr)
1766 return -EINVAL;
1767 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001768 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001769 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001770 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001771 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001772 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001773 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001774 }
1775 return -EINVAL;
1776}
1777
1778static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1779 struct v4l2_dbg_register *reg)
1780{
1781 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03001782
Brian Johnson26e744b2009-07-19 05:52:58 -03001783 switch (reg->match.type) {
1784 case V4L2_CHIP_MATCH_HOST:
1785 if (reg->match.addr != 0)
1786 return -EINVAL;
1787 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1788 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001789 reg_w1(gspca_dev, reg->reg, reg->val);
1790 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001791 case V4L2_CHIP_MATCH_I2C_ADDR:
1792 if (reg->match.addr != sd->i2c_addr)
1793 return -EINVAL;
1794 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001795 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001796 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001797 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001798 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001799 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001800 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001801 }
1802 return -EINVAL;
1803}
1804#endif
1805
1806static int sd_chip_ident(struct gspca_dev *gspca_dev,
1807 struct v4l2_dbg_chip_ident *chip)
1808{
1809 struct sd *sd = (struct sd *) gspca_dev;
1810
1811 switch (chip->match.type) {
1812 case V4L2_CHIP_MATCH_HOST:
1813 if (chip->match.addr != 0)
1814 return -EINVAL;
1815 chip->revision = 0;
1816 chip->ident = V4L2_IDENT_SN9C20X;
1817 return 0;
1818 case V4L2_CHIP_MATCH_I2C_ADDR:
1819 if (chip->match.addr != sd->i2c_addr)
1820 return -EINVAL;
1821 chip->revision = 0;
1822 chip->ident = i2c_ident[sd->sensor];
1823 return 0;
1824 }
1825 return -EINVAL;
1826}
1827
1828static int sd_config(struct gspca_dev *gspca_dev,
1829 const struct usb_device_id *id)
1830{
1831 struct sd *sd = (struct sd *) gspca_dev;
1832 struct cam *cam;
1833
1834 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001835 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001836
Jean-François Moineff38d582012-03-19 04:55:16 -03001837 sd->sensor = id->driver_info >> 8;
1838 sd->i2c_addr = id->driver_info;
1839 sd->flags = id->driver_info >> 16;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001840 sd->i2c_intf = 0x80; /* i2c 100 Kb/s */
Brian Johnson26e744b2009-07-19 05:52:58 -03001841
1842 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001843 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001844 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001845 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001846 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001847 cam->cam_mode = sxga_mode;
1848 cam->nmodes = ARRAY_SIZE(sxga_mode);
1849 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001850 case SENSOR_MT9M001:
1851 cam->cam_mode = mono_mode;
1852 cam->nmodes = ARRAY_SIZE(mono_mode);
1853 break;
Jean-François Moinec4407fe2012-03-24 09:23:56 -03001854 case SENSOR_HV7131R:
1855 sd->i2c_intf = 0x81; /* i2c 400 Kb/s */
1856 /* fall thru */
Brian Johnson26e744b2009-07-19 05:52:58 -03001857 default:
1858 cam->cam_mode = vga_mode;
1859 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001860 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001861 }
1862
1863 sd->old_step = 0;
1864 sd->older_step = 0;
1865 sd->exposure_step = 16;
1866
Jean-François Moinec5224d82012-03-19 04:30:07 -03001867 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001868
Jean-François Moine92dcffc2012-03-19 04:47:24 -03001869 INIT_WORK(&sd->work, qual_upd);
Brian Johnson26e744b2009-07-19 05:52:58 -03001870
Brian Johnson26e744b2009-07-19 05:52:58 -03001871 return 0;
1872}
1873
1874static int sd_init(struct gspca_dev *gspca_dev)
1875{
1876 struct sd *sd = (struct sd *) gspca_dev;
1877 int i;
1878 u8 value;
1879 u8 i2c_init[9] =
1880 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1881
1882 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1883 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001884 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1885 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001886 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001887 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001888 }
1889 }
1890
Brian Johnson0c045eb2010-03-16 13:58:27 -03001891 if (sd->flags & LED_REVERSE)
1892 reg_w1(gspca_dev, 0x1006, 0x00);
1893 else
1894 reg_w1(gspca_dev, 0x1006, 0x20);
1895
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001896 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1897 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001898 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001899 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001900 }
1901
1902 switch (sd->sensor) {
1903 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001904 ov9650_init_sensor(gspca_dev);
1905 if (gspca_dev->usb_err < 0)
1906 break;
Joe Perches91f58422011-08-21 19:56:55 -03001907 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001908 break;
1909 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001910 ov9655_init_sensor(gspca_dev);
1911 if (gspca_dev->usb_err < 0)
1912 break;
Joe Perches91f58422011-08-21 19:56:55 -03001913 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001914 break;
1915 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001916 soi968_init_sensor(gspca_dev);
1917 if (gspca_dev->usb_err < 0)
1918 break;
Joe Perches91f58422011-08-21 19:56:55 -03001919 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001920 break;
1921 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001922 ov7660_init_sensor(gspca_dev);
1923 if (gspca_dev->usb_err < 0)
1924 break;
Joe Perches91f58422011-08-21 19:56:55 -03001925 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001926 break;
1927 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001928 ov7670_init_sensor(gspca_dev);
1929 if (gspca_dev->usb_err < 0)
1930 break;
Joe Perches91f58422011-08-21 19:56:55 -03001931 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001932 break;
1933 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001934 mt9v_init_sensor(gspca_dev);
1935 if (gspca_dev->usb_err < 0)
1936 break;
Jean-François Moineff38d582012-03-19 04:55:16 -03001937 pr_info("MT9VPRB sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001938 break;
1939 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001940 mt9m111_init_sensor(gspca_dev);
1941 if (gspca_dev->usb_err < 0)
1942 break;
Joe Perches91f58422011-08-21 19:56:55 -03001943 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001944 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001945 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001946 mt9m112_init_sensor(gspca_dev);
1947 if (gspca_dev->usb_err < 0)
1948 break;
Joe Perches91f58422011-08-21 19:56:55 -03001949 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001950 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001951 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001952 mt9m001_init_sensor(gspca_dev);
1953 if (gspca_dev->usb_err < 0)
1954 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001955 break;
1956 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001957 hv7131r_init_sensor(gspca_dev);
1958 if (gspca_dev->usb_err < 0)
1959 break;
Joe Perches91f58422011-08-21 19:56:55 -03001960 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001961 break;
1962 default:
Jean-François Moineff38d582012-03-19 04:55:16 -03001963 pr_err("Unsupported sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001964 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001965 }
1966
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001967 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001968}
1969
1970static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1971{
1972 struct sd *sd = (struct sd *) gspca_dev;
1973 u8 value;
Jean-François Moineff38d582012-03-19 04:55:16 -03001974
Brian Johnson26e744b2009-07-19 05:52:58 -03001975 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001976 case SENSOR_SOI968:
1977 if (mode & MODE_SXGA) {
1978 i2c_w1(gspca_dev, 0x17, 0x1d);
1979 i2c_w1(gspca_dev, 0x18, 0xbd);
1980 i2c_w1(gspca_dev, 0x19, 0x01);
1981 i2c_w1(gspca_dev, 0x1a, 0x81);
1982 i2c_w1(gspca_dev, 0x12, 0x00);
1983 sd->hstart = 140;
1984 sd->vstart = 19;
1985 } else {
1986 i2c_w1(gspca_dev, 0x17, 0x13);
1987 i2c_w1(gspca_dev, 0x18, 0x63);
1988 i2c_w1(gspca_dev, 0x19, 0x01);
1989 i2c_w1(gspca_dev, 0x1a, 0x79);
1990 i2c_w1(gspca_dev, 0x12, 0x40);
1991 sd->hstart = 60;
1992 sd->vstart = 11;
1993 }
1994 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001995 case SENSOR_OV9650:
1996 if (mode & MODE_SXGA) {
1997 i2c_w1(gspca_dev, 0x17, 0x1b);
1998 i2c_w1(gspca_dev, 0x18, 0xbc);
1999 i2c_w1(gspca_dev, 0x19, 0x01);
2000 i2c_w1(gspca_dev, 0x1a, 0x82);
2001 i2c_r1(gspca_dev, 0x12, &value);
2002 i2c_w1(gspca_dev, 0x12, value & 0x07);
2003 } else {
2004 i2c_w1(gspca_dev, 0x17, 0x24);
2005 i2c_w1(gspca_dev, 0x18, 0xc5);
2006 i2c_w1(gspca_dev, 0x19, 0x00);
2007 i2c_w1(gspca_dev, 0x1a, 0x3c);
2008 i2c_r1(gspca_dev, 0x12, &value);
2009 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2010 }
2011 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002012 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002013 case SENSOR_MT9M111:
2014 if (mode & MODE_SXGA) {
2015 i2c_w2(gspca_dev, 0xf0, 0x0002);
2016 i2c_w2(gspca_dev, 0xc8, 0x970b);
2017 i2c_w2(gspca_dev, 0xf0, 0x0000);
2018 } else {
2019 i2c_w2(gspca_dev, 0xf0, 0x0002);
2020 i2c_w2(gspca_dev, 0xc8, 0x8000);
2021 i2c_w2(gspca_dev, 0xf0, 0x0000);
2022 }
2023 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002024 }
2025}
2026
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002027static int sd_isoc_init(struct gspca_dev *gspca_dev)
2028{
2029 struct usb_interface *intf;
2030 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2031
2032 /*
2033 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2034 * than our regular bandwidth calculations reserve, so we force the
2035 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2036 */
2037 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2038 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2039
2040 if (intf->num_altsetting != 9) {
2041 pr_warn("sn9c20x camera with unknown number of alt "
2042 "settings (%d), please report!\n",
2043 intf->num_altsetting);
2044 gspca_dev->alt = intf->num_altsetting;
2045 return 0;
2046 }
2047
2048 switch (gspca_dev->width) {
2049 case 160: /* 160x120 */
2050 gspca_dev->alt = 2;
2051 break;
2052 case 320: /* 320x240 */
2053 gspca_dev->alt = 6;
2054 break;
2055 default: /* >= 640x480 */
2056 gspca_dev->alt = 9;
Jean-François Moineff38d582012-03-19 04:55:16 -03002057 break;
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002058 }
2059 }
2060
2061 return 0;
2062}
2063
Brian Johnson26e744b2009-07-19 05:52:58 -03002064#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002065((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002066(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2067(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2068
2069#define CLR_WIN(width, height) \
2070((const u8 [])\
2071{0, width >> 2, 0, height >> 1,\
2072((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2073
2074static int sd_start(struct gspca_dev *gspca_dev)
2075{
2076 struct sd *sd = (struct sd *) gspca_dev;
2077 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2078 int width = gspca_dev->width;
2079 int height = gspca_dev->height;
2080 u8 fmt, scale = 0;
2081
Brian Johnson26e744b2009-07-19 05:52:58 -03002082 jpeg_define(sd->jpeg_hdr, height, width,
2083 0x21);
Jean-François Moine4c632e42012-03-19 04:35:34 -03002084 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03002085
2086 if (mode & MODE_RAW)
2087 fmt = 0x2d;
2088 else if (mode & MODE_JPEG)
Jean-François Moine4c632e42012-03-19 04:35:34 -03002089 fmt = 0x24;
Brian Johnson26e744b2009-07-19 05:52:58 -03002090 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002091 fmt = 0x2f; /* YUV 420 */
Jean-François Moine4c632e42012-03-19 04:35:34 -03002092 sd->fmt = fmt;
Brian Johnson26e744b2009-07-19 05:52:58 -03002093
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002094 switch (mode & SCALE_MASK) {
2095 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002096 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002097 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002098 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002099 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002100 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002101 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002102 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002103 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002104 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002105 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002106 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002107 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002108 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002109 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002110 break;
2111 }
2112
2113 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002114 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2115 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002116 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2117 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2118 reg_w1(gspca_dev, 0x1189, scale);
2119 reg_w1(gspca_dev, 0x10e0, fmt);
2120
2121 set_cmatrix(gspca_dev);
2122 set_gamma(gspca_dev);
2123 set_redblue(gspca_dev);
2124 set_gain(gspca_dev);
2125 set_exposure(gspca_dev);
2126 set_hvflip(gspca_dev);
2127
Brian Johnson0c045eb2010-03-16 13:58:27 -03002128 reg_w1(gspca_dev, 0x1007, 0x20);
Jean-François Moineccbaba42012-03-19 04:51:30 -03002129 reg_w1(gspca_dev, 0x1061, 0x03);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002130
2131 /* if JPEG, prepare the compression quality update */
2132 if (mode & MODE_JPEG) {
2133 sd->pktsz = sd->npkt = 0;
2134 sd->nchg = 0;
2135 sd->work_thread =
2136 create_singlethread_workqueue(KBUILD_MODNAME);
2137 }
2138
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002139 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002140}
2141
2142static void sd_stopN(struct gspca_dev *gspca_dev)
2143{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002144 reg_w1(gspca_dev, 0x1007, 0x00);
Jean-François Moineccbaba42012-03-19 04:51:30 -03002145 reg_w1(gspca_dev, 0x1061, 0x01);
Brian Johnson26e744b2009-07-19 05:52:58 -03002146}
2147
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002148/* called on streamoff with alt==0 and on disconnect */
2149/* the usb_lock is held at entry - restore on exit */
2150static void sd_stop0(struct gspca_dev *gspca_dev)
2151{
2152 struct sd *sd = (struct sd *) gspca_dev;
2153
2154 if (sd->work_thread != NULL) {
2155 mutex_unlock(&gspca_dev->usb_lock);
2156 destroy_workqueue(sd->work_thread);
2157 mutex_lock(&gspca_dev->usb_lock);
2158 sd->work_thread = NULL;
2159 }
2160}
2161
Brian Johnsone1430472009-09-02 12:39:41 -03002162static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002163{
2164 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002165 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002166
2167 /*
2168 * some hardcoded values are present
2169 * like those for maximal/minimal exposure
2170 * and exposure steps
2171 */
2172 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002173 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002174 return;
2175
Jean-François Moinec5224d82012-03-19 04:30:07 -03002176 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002177 if (new_exp > 0x1770)
2178 new_exp = 0x1770;
2179 if (new_exp < 0x10)
2180 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002181 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002182 set_exposure(gspca_dev);
2183
2184 sd->older_step = sd->old_step;
2185 sd->old_step = 1;
2186
2187 if (sd->old_step ^ sd->older_step)
2188 sd->exposure_step /= 2;
2189 else
2190 sd->exposure_step += 2;
2191 }
2192 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002193 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002194 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002195 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002196 if (new_exp > 0x1700)
2197 new_exp = 0x1770;
2198 if (new_exp < 0x10)
2199 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002200 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002201 set_exposure(gspca_dev);
2202 sd->older_step = sd->old_step;
2203 sd->old_step = 0;
2204
2205 if (sd->old_step ^ sd->older_step)
2206 sd->exposure_step /= 2;
2207 else
2208 sd->exposure_step += 2;
2209 }
2210}
2211
Brian Johnsone1430472009-09-02 12:39:41 -03002212static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2213{
2214 struct sd *sd = (struct sd *) gspca_dev;
2215
2216 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002217 if (sd->ctrls[GAIN].val + 1 <= 28) {
2218 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002219 set_gain(gspca_dev);
2220 }
2221 }
2222 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002223 if (sd->ctrls[GAIN].val > 0) {
2224 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002225 set_gain(gspca_dev);
2226 }
2227 }
2228}
2229
2230static void sd_dqcallback(struct gspca_dev *gspca_dev)
2231{
2232 struct sd *sd = (struct sd *) gspca_dev;
2233 int avg_lum;
2234
Jean-François Moinec5224d82012-03-19 04:30:07 -03002235 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002236 return;
2237
2238 avg_lum = atomic_read(&sd->avg_lum);
2239 if (sd->sensor == SENSOR_SOI968)
2240 do_autogain(gspca_dev, avg_lum);
2241 else
2242 do_autoexposure(gspca_dev, avg_lum);
2243}
2244
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002245/* JPEG quality update */
2246/* This function is executed from a work queue. */
2247static void qual_upd(struct work_struct *work)
2248{
2249 struct sd *sd = container_of(work, struct sd, work);
2250 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2251
2252 mutex_lock(&gspca_dev->usb_lock);
2253 PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val);
2254 set_quality(gspca_dev);
2255 mutex_unlock(&gspca_dev->usb_lock);
2256}
2257
Jean-François Moine28566432010-10-01 07:33:26 -03002258#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002259static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2260 u8 *data, /* interrupt packet */
2261 int len) /* interrupt packet length */
2262{
2263 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03002264
Brian Johnson33ddc162010-04-18 21:42:40 -03002265 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Jean-François Moineff38d582012-03-19 04:55:16 -03002266 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2267 input_sync(gspca_dev->input_dev);
2268 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2269 input_sync(gspca_dev->input_dev);
2270 return 0;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002271 }
Jean-François Moineff38d582012-03-19 04:55:16 -03002272 return -EINVAL;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002273}
2274#endif
2275
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002276/* check the JPEG compression */
2277static void transfer_check(struct gspca_dev *gspca_dev,
2278 u8 *data)
2279{
2280 struct sd *sd = (struct sd *) gspca_dev;
2281 int new_qual, r;
2282
2283 new_qual = 0;
2284
2285 /* if USB error, discard the frame and decrease the quality */
2286 if (data[6] & 0x08) { /* USB FIFO full */
2287 gspca_dev->last_packet_type = DISCARD_PACKET;
2288 new_qual = -5;
2289 } else {
2290
2291 /* else, compute the filling rate and a new JPEG quality */
2292 r = (sd->pktsz * 100) /
2293 (sd->npkt *
2294 gspca_dev->urb[0]->iso_frame_desc[0].length);
2295 if (r >= 85)
2296 new_qual = -3;
2297 else if (r < 75)
2298 new_qual = 2;
2299 }
2300 if (new_qual != 0) {
2301 sd->nchg += new_qual;
2302 if (sd->nchg < -6 || sd->nchg >= 12) {
2303 sd->nchg = 0;
2304 new_qual += sd->ctrls[QUALITY].val;
2305 if (new_qual < QUALITY_MIN)
2306 new_qual = QUALITY_MIN;
2307 else if (new_qual > QUALITY_MAX)
2308 new_qual = QUALITY_MAX;
2309 if (new_qual != sd->ctrls[QUALITY].val) {
2310 sd->ctrls[QUALITY].val = new_qual;
2311 queue_work(sd->work_thread, &sd->work);
2312 }
2313 }
2314 } else {
2315 sd->nchg = 0;
2316 }
2317 sd->pktsz = sd->npkt = 0;
2318}
2319
Brian Johnson26e744b2009-07-19 05:52:58 -03002320static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002321 u8 *data, /* isoc packet */
2322 int len) /* iso packet length */
2323{
2324 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineff38d582012-03-19 04:55:16 -03002325 int avg_lum, is_jpeg;
Jean-François Moinedae1de62012-03-24 09:20:25 -03002326 static const u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002327 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moineff38d582012-03-19 04:55:16 -03002328
2329 is_jpeg = (sd->fmt & 0x03) == 0;
Jean-François Moine1f42df02012-03-19 04:22:44 -03002330 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002331 avg_lum = ((data[35] >> 2) & 3) |
2332 (data[20] << 2) |
2333 (data[19] << 10);
2334 avg_lum += ((data[35] >> 4) & 3) |
2335 (data[22] << 2) |
2336 (data[21] << 10);
2337 avg_lum += ((data[35] >> 6) & 3) |
2338 (data[24] << 2) |
2339 (data[23] << 10);
2340 avg_lum += (data[36] & 3) |
2341 (data[26] << 2) |
2342 (data[25] << 10);
2343 avg_lum += ((data[36] >> 2) & 3) |
2344 (data[28] << 2) |
2345 (data[27] << 10);
2346 avg_lum += ((data[36] >> 4) & 3) |
2347 (data[30] << 2) |
2348 (data[29] << 10);
2349 avg_lum += ((data[36] >> 6) & 3) |
2350 (data[32] << 2) |
2351 (data[31] << 10);
2352 avg_lum += ((data[44] >> 4) & 3) |
2353 (data[34] << 2) |
2354 (data[33] << 10);
2355 avg_lum >>= 9;
2356 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002357
Jean-François Moineff38d582012-03-19 04:55:16 -03002358 if (is_jpeg)
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002359 transfer_check(gspca_dev, data);
2360
Jean-François Moine04d174e2010-09-13 05:22:37 -03002361 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002362 len -= 64;
2363 if (len == 0)
2364 return;
2365 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002366 }
2367 if (gspca_dev->last_packet_type == LAST_PACKET) {
Jean-François Moineff38d582012-03-19 04:55:16 -03002368 if (is_jpeg) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002369 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002370 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002371 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002372 data, len);
2373 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002374 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002375 data, len);
2376 }
2377 } else {
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002378 /* if JPEG, count the packets and their size */
Jean-François Moineff38d582012-03-19 04:55:16 -03002379 if (is_jpeg) {
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002380 sd->npkt++;
2381 sd->pktsz += len;
2382 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002383 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002384 }
2385}
2386
2387/* sub-driver description */
2388static const struct sd_desc sd_desc = {
Jean-François Moineff38d582012-03-19 04:55:16 -03002389 .name = KBUILD_MODNAME,
Brian Johnson26e744b2009-07-19 05:52:58 -03002390 .ctrls = sd_ctrls,
2391 .nctrls = ARRAY_SIZE(sd_ctrls),
2392 .config = sd_config,
2393 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002394 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002395 .start = sd_start,
2396 .stopN = sd_stopN,
Jean-François Moine92dcffc2012-03-19 04:47:24 -03002397 .stop0 = sd_stop0,
Brian Johnson26e744b2009-07-19 05:52:58 -03002398 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002399#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002400 .int_pkt_scan = sd_int_pkt_scan,
2401#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002402 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002403#ifdef CONFIG_VIDEO_ADV_DEBUG
2404 .set_register = sd_dbg_s_register,
2405 .get_register = sd_dbg_g_register,
2406#endif
2407 .get_chip_ident = sd_chip_ident,
2408};
2409
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002410#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002411 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002412 | (SENSOR_ ## sensor << 8) \
2413 | (i2c_addr)
2414
Jean-François Moine95c967c2011-01-13 05:20:29 -03002415static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002416 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2417 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2418 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002419 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002420 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2421 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2422 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002423 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2424 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2425 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2426 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002427 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002428 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2429 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2430 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2431 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002432 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002433 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002434 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2435 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2436 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2437 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002438 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002439 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002440 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2441 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2442 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2443 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002444 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2445 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002446 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2447 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2448 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2449 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002450 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002451 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2452 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2453 {}
2454};
2455MODULE_DEVICE_TABLE(usb, device_table);
2456
2457/* -- device connect -- */
2458static int sd_probe(struct usb_interface *intf,
2459 const struct usb_device_id *id)
2460{
2461 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2462 THIS_MODULE);
2463}
2464
Brian Johnson26e744b2009-07-19 05:52:58 -03002465static struct usb_driver sd_driver = {
Jean-François Moineff38d582012-03-19 04:55:16 -03002466 .name = KBUILD_MODNAME,
Brian Johnson26e744b2009-07-19 05:52:58 -03002467 .id_table = device_table,
2468 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002469 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002470#ifdef CONFIG_PM
2471 .suspend = gspca_suspend,
2472 .resume = gspca_resume,
2473 .reset_resume = gspca_resume,
2474#endif
2475};
2476
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002477module_usb_driver(sd_driver);