Merge tag 'v3.5-rc6' into irqdomain/next
[deliverable/linux.git] / drivers / media / video / gspca / sn9c20x.c
CommitLineData
26e744b6
BJ
1/*
2 * Sonix sn9c201 sn9c202 library
ff38d58e
JFM
3 *
4 * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
26e744b6
BJ
5 * 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
91f5842b
JP
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
26e744b6 25#include <linux/input.h>
26e744b6 26
c15b95ed
MCC
27#include "gspca.h"
28#include "jpeg.h"
29
30#include <media/v4l2-chip-ident.h>
7ddaac7f 31#include <linux/dmi.h>
c15b95ed 32
26e744b6
BJ
33MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
34 "microdia project <microdia@googlegroups.com>");
35MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
36MODULE_LICENSE("GPL");
37
86701c1d
MCC
38/*
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
26e744b6
BJ
46#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
e99ac54d
BJ
60#define SENSOR_MT9M112 10
61#define SENSOR_HV7131R 11
9637c652 62#define SENSOR_MT9VPRB 12
26e744b6 63
a39db27a 64/* camera flags */
33ddc16f 65#define HAS_NO_BUTTON 0x1
0c045eb7 66#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
7ddaac7f 67#define FLIP_DETECT 0x4
a39db27a 68
26e744b6
BJ
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev;
72
63069da1
HV
73 struct { /* color control cluster */
74 struct v4l2_ctrl *brightness;
75 struct v4l2_ctrl *contrast;
76 struct v4l2_ctrl *saturation;
77 struct v4l2_ctrl *hue;
78 };
79 struct { /* blue/red balance control cluster */
80 struct v4l2_ctrl *blue;
81 struct v4l2_ctrl *red;
82 };
83 struct { /* h/vflip control cluster */
84 struct v4l2_ctrl *hflip;
85 struct v4l2_ctrl *vflip;
86 };
87 struct v4l2_ctrl *gamma;
88 struct { /* autogain and exposure or gain control cluster */
89 struct v4l2_ctrl *autogain;
90 struct v4l2_ctrl *exposure;
91 struct v4l2_ctrl *gain;
92 };
93 struct v4l2_ctrl *jpegqual;
c5224d81 94
92dcffcf
JFM
95 struct work_struct work;
96 struct workqueue_struct *work_thread;
97
98 u32 pktsz; /* (used by pkt_scan) */
99 u16 npkt;
100 s8 nchg;
4c632e4e
JFM
101 u8 fmt; /* (used for JPEG QTAB update */
102
26e744b6
BJ
103#define MIN_AVG_LUM 80
104#define MAX_AVG_LUM 130
105 atomic_t avg_lum;
106 u8 old_step;
107 u8 older_step;
108 u8 exposure_step;
109
26e744b6 110 u8 i2c_addr;
c4407fe8 111 u8 i2c_intf;
26e744b6
BJ
112 u8 sensor;
113 u8 hstart;
114 u8 vstart;
115
9a731a32 116 u8 jpeg_hdr[JPEG_HDR_SZ];
26e744b6 117
a39db27a 118 u8 flags;
26e744b6
BJ
119};
120
92dcffcf
JFM
121static void qual_upd(struct work_struct *work);
122
58aa68c2
JP
123struct i2c_reg_u8 {
124 u8 reg;
125 u8 val;
126};
127
128struct i2c_reg_u16 {
129 u8 reg;
130 u16 val;
131};
132
7ddaac7f
BJ
133static const struct dmi_system_id flip_dmi_table[] = {
134 {
135 .ident = "MSI MS-1034",
136 .matches = {
137 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
138 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
139 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
140 }
141 },
142 {
143 .ident = "MSI MS-1632",
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
146 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
147 }
148 },
bcc6f669
HG
149 {
150 .ident = "MSI MS-1633X",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
153 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
154 }
155 },
5d26ed91
BJ
156 {
157 .ident = "MSI MS-1635X",
158 .matches = {
159 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
160 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
161 }
162 },
e077f86b
BJ
163 {
164 .ident = "ASUSTeK W7J",
165 .matches = {
166 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
167 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
168 }
169 },
7ddaac7f
BJ
170 {}
171};
172
26e744b6
BJ
173static const struct v4l2_pix_format vga_mode[] = {
174 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 175 .bytesperline = 160,
9b1d3cae 176 .sizeimage = 160 * 120 * 4 / 8 + 590,
26e744b6 177 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 178 .priv = SCALE_160x120 | MODE_JPEG},
26e744b6
BJ
179 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
180 .bytesperline = 160,
181 .sizeimage = 160 * 120,
182 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 183 .priv = SCALE_160x120 | MODE_RAW},
26e744b6 184 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 185 .bytesperline = 160,
26e744b6
BJ
186 .sizeimage = 240 * 120,
187 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 188 .priv = SCALE_160x120},
26e744b6 189 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 190 .bytesperline = 320,
6899a9c7 191 .sizeimage = 320 * 240 * 4 / 8 + 590,
26e744b6 192 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 193 .priv = SCALE_320x240 | MODE_JPEG},
26e744b6
BJ
194 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
195 .bytesperline = 320,
196 .sizeimage = 320 * 240 ,
197 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 198 .priv = SCALE_320x240 | MODE_RAW},
26e744b6 199 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 200 .bytesperline = 320,
26e744b6
BJ
201 .sizeimage = 480 * 240 ,
202 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 203 .priv = SCALE_320x240},
26e744b6 204 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 205 .bytesperline = 640,
6899a9c7 206 .sizeimage = 640 * 480 * 4 / 8 + 590,
26e744b6 207 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 208 .priv = SCALE_640x480 | MODE_JPEG},
26e744b6
BJ
209 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
210 .bytesperline = 640,
211 .sizeimage = 640 * 480,
212 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 213 .priv = SCALE_640x480 | MODE_RAW},
26e744b6 214 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 215 .bytesperline = 640,
26e744b6
BJ
216 .sizeimage = 960 * 480,
217 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 218 .priv = SCALE_640x480},
26e744b6
BJ
219};
220
221static const struct v4l2_pix_format sxga_mode[] = {
222 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 223 .bytesperline = 160,
9b1d3cae 224 .sizeimage = 160 * 120 * 4 / 8 + 590,
26e744b6 225 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 226 .priv = SCALE_160x120 | MODE_JPEG},
26e744b6
BJ
227 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
228 .bytesperline = 160,
229 .sizeimage = 160 * 120,
230 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 231 .priv = SCALE_160x120 | MODE_RAW},
26e744b6 232 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 233 .bytesperline = 160,
26e744b6
BJ
234 .sizeimage = 240 * 120,
235 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 236 .priv = SCALE_160x120},
26e744b6 237 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 238 .bytesperline = 320,
6899a9c7 239 .sizeimage = 320 * 240 * 4 / 8 + 590,
26e744b6 240 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 241 .priv = SCALE_320x240 | MODE_JPEG},
26e744b6
BJ
242 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
243 .bytesperline = 320,
244 .sizeimage = 320 * 240 ,
245 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 246 .priv = SCALE_320x240 | MODE_RAW},
26e744b6 247 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 248 .bytesperline = 320,
26e744b6
BJ
249 .sizeimage = 480 * 240 ,
250 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 251 .priv = SCALE_320x240},
26e744b6 252 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
b1e4665b 253 .bytesperline = 640,
6899a9c7 254 .sizeimage = 640 * 480 * 4 / 8 + 590,
26e744b6 255 .colorspace = V4L2_COLORSPACE_JPEG,
86701c1d 256 .priv = SCALE_640x480 | MODE_JPEG},
26e744b6
BJ
257 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
258 .bytesperline = 640,
259 .sizeimage = 640 * 480,
260 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 261 .priv = SCALE_640x480 | MODE_RAW},
26e744b6 262 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
b1e4665b 263 .bytesperline = 640,
26e744b6
BJ
264 .sizeimage = 960 * 480,
265 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 266 .priv = SCALE_640x480},
26e744b6
BJ
267 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
268 .bytesperline = 1280,
9b1d3cae 269 .sizeimage = 1280 * 1024,
26e744b6 270 .colorspace = V4L2_COLORSPACE_SRGB,
86701c1d 271 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
26e744b6
BJ
272};
273
d162e7aa
MCC
274static const struct v4l2_pix_format mono_mode[] = {
275 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
276 .bytesperline = 160,
277 .sizeimage = 160 * 120,
278 .colorspace = V4L2_COLORSPACE_SRGB,
279 .priv = SCALE_160x120 | MODE_RAW},
280 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
281 .bytesperline = 320,
282 .sizeimage = 320 * 240 ,
283 .colorspace = V4L2_COLORSPACE_SRGB,
284 .priv = SCALE_320x240 | MODE_RAW},
285 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
286 .bytesperline = 640,
287 .sizeimage = 640 * 480,
288 .colorspace = V4L2_COLORSPACE_SRGB,
289 .priv = SCALE_640x480 | MODE_RAW},
290 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
291 .bytesperline = 1280,
292 .sizeimage = 1280 * 1024,
293 .colorspace = V4L2_COLORSPACE_SRGB,
294 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
295};
296
58aa68c2 297static const s16 hsv_red_x[] = {
26e744b6
BJ
298 41, 44, 46, 48, 50, 52, 54, 56,
299 58, 60, 62, 64, 66, 68, 70, 72,
300 74, 76, 78, 80, 81, 83, 85, 87,
301 88, 90, 92, 93, 95, 97, 98, 100,
302 101, 102, 104, 105, 107, 108, 109, 110,
303 112, 113, 114, 115, 116, 117, 118, 119,
304 120, 121, 122, 123, 123, 124, 125, 125,
305 126, 127, 127, 128, 128, 129, 129, 129,
306 130, 130, 130, 130, 131, 131, 131, 131,
307 131, 131, 131, 131, 130, 130, 130, 130,
308 129, 129, 129, 128, 128, 127, 127, 126,
309 125, 125, 124, 123, 122, 122, 121, 120,
310 119, 118, 117, 116, 115, 114, 112, 111,
311 110, 109, 107, 106, 105, 103, 102, 101,
312 99, 98, 96, 94, 93, 91, 90, 88,
313 86, 84, 83, 81, 79, 77, 75, 74,
314 72, 70, 68, 66, 64, 62, 60, 58,
315 56, 54, 52, 49, 47, 45, 43, 41,
316 39, 36, 34, 32, 30, 28, 25, 23,
317 21, 19, 16, 14, 12, 9, 7, 5,
318 3, 0, -1, -3, -6, -8, -10, -12,
319 -15, -17, -19, -22, -24, -26, -28, -30,
320 -33, -35, -37, -39, -41, -44, -46, -48,
321 -50, -52, -54, -56, -58, -60, -62, -64,
322 -66, -68, -70, -72, -74, -76, -78, -80,
323 -81, -83, -85, -87, -88, -90, -92, -93,
324 -95, -97, -98, -100, -101, -102, -104, -105,
325 -107, -108, -109, -110, -112, -113, -114, -115,
326 -116, -117, -118, -119, -120, -121, -122, -123,
327 -123, -124, -125, -125, -126, -127, -127, -128,
328 -128, -128, -128, -128, -128, -128, -128, -128,
329 -128, -128, -128, -128, -128, -128, -128, -128,
330 -128, -128, -128, -128, -128, -128, -128, -128,
331 -128, -127, -127, -126, -125, -125, -124, -123,
332 -122, -122, -121, -120, -119, -118, -117, -116,
333 -115, -114, -112, -111, -110, -109, -107, -106,
334 -105, -103, -102, -101, -99, -98, -96, -94,
335 -93, -91, -90, -88, -86, -84, -83, -81,
336 -79, -77, -75, -74, -72, -70, -68, -66,
337 -64, -62, -60, -58, -56, -54, -52, -49,
338 -47, -45, -43, -41, -39, -36, -34, -32,
339 -30, -28, -25, -23, -21, -19, -16, -14,
340 -12, -9, -7, -5, -3, 0, 1, 3,
341 6, 8, 10, 12, 15, 17, 19, 22,
342 24, 26, 28, 30, 33, 35, 37, 39, 41
343};
344
58aa68c2 345static const s16 hsv_red_y[] = {
26e744b6
BJ
346 82, 80, 78, 76, 74, 73, 71, 69,
347 67, 65, 63, 61, 58, 56, 54, 52,
348 50, 48, 46, 44, 41, 39, 37, 35,
349 32, 30, 28, 26, 23, 21, 19, 16,
350 14, 12, 10, 7, 5, 3, 0, -1,
351 -3, -6, -8, -10, -13, -15, -17, -19,
352 -22, -24, -26, -29, -31, -33, -35, -38,
353 -40, -42, -44, -46, -48, -51, -53, -55,
354 -57, -59, -61, -63, -65, -67, -69, -71,
355 -73, -75, -77, -79, -81, -82, -84, -86,
356 -88, -89, -91, -93, -94, -96, -98, -99,
357 -101, -102, -104, -105, -106, -108, -109, -110,
358 -112, -113, -114, -115, -116, -117, -119, -120,
359 -120, -121, -122, -123, -124, -125, -126, -126,
360 -127, -128, -128, -128, -128, -128, -128, -128,
361 -128, -128, -128, -128, -128, -128, -128, -128,
362 -128, -128, -128, -128, -128, -128, -128, -128,
363 -128, -128, -128, -128, -128, -128, -128, -128,
364 -127, -127, -126, -125, -125, -124, -123, -122,
365 -121, -120, -119, -118, -117, -116, -115, -114,
366 -113, -111, -110, -109, -107, -106, -105, -103,
367 -102, -100, -99, -97, -96, -94, -92, -91,
368 -89, -87, -85, -84, -82, -80, -78, -76,
369 -74, -73, -71, -69, -67, -65, -63, -61,
370 -58, -56, -54, -52, -50, -48, -46, -44,
371 -41, -39, -37, -35, -32, -30, -28, -26,
372 -23, -21, -19, -16, -14, -12, -10, -7,
373 -5, -3, 0, 1, 3, 6, 8, 10,
374 13, 15, 17, 19, 22, 24, 26, 29,
375 31, 33, 35, 38, 40, 42, 44, 46,
376 48, 51, 53, 55, 57, 59, 61, 63,
377 65, 67, 69, 71, 73, 75, 77, 79,
378 81, 82, 84, 86, 88, 89, 91, 93,
379 94, 96, 98, 99, 101, 102, 104, 105,
380 106, 108, 109, 110, 112, 113, 114, 115,
381 116, 117, 119, 120, 120, 121, 122, 123,
382 124, 125, 126, 126, 127, 128, 128, 129,
383 129, 130, 130, 131, 131, 131, 131, 132,
384 132, 132, 132, 132, 132, 132, 132, 132,
385 132, 132, 132, 131, 131, 131, 130, 130,
386 130, 129, 129, 128, 127, 127, 126, 125,
387 125, 124, 123, 122, 121, 120, 119, 118,
388 117, 116, 115, 114, 113, 111, 110, 109,
389 107, 106, 105, 103, 102, 100, 99, 97,
390 96, 94, 92, 91, 89, 87, 85, 84, 82
391};
392
58aa68c2 393static const s16 hsv_green_x[] = {
26e744b6
BJ
394 -124, -124, -125, -125, -125, -125, -125, -125,
395 -125, -126, -126, -125, -125, -125, -125, -125,
396 -125, -124, -124, -124, -123, -123, -122, -122,
397 -121, -121, -120, -120, -119, -118, -117, -117,
398 -116, -115, -114, -113, -112, -111, -110, -109,
399 -108, -107, -105, -104, -103, -102, -100, -99,
400 -98, -96, -95, -93, -92, -91, -89, -87,
401 -86, -84, -83, -81, -79, -77, -76, -74,
402 -72, -70, -69, -67, -65, -63, -61, -59,
403 -57, -55, -53, -51, -49, -47, -45, -43,
404 -41, -39, -37, -35, -33, -30, -28, -26,
405 -24, -22, -20, -18, -15, -13, -11, -9,
406 -7, -4, -2, 0, 1, 3, 6, 8,
407 10, 12, 14, 17, 19, 21, 23, 25,
408 27, 29, 32, 34, 36, 38, 40, 42,
409 44, 46, 48, 50, 52, 54, 56, 58,
410 60, 62, 64, 66, 68, 70, 71, 73,
411 75, 77, 78, 80, 82, 83, 85, 87,
412 88, 90, 91, 93, 94, 96, 97, 98,
413 100, 101, 102, 104, 105, 106, 107, 108,
414 109, 111, 112, 113, 113, 114, 115, 116,
415 117, 118, 118, 119, 120, 120, 121, 122,
416 122, 123, 123, 124, 124, 124, 125, 125,
417 125, 125, 125, 125, 125, 126, 126, 125,
418 125, 125, 125, 125, 125, 124, 124, 124,
419 123, 123, 122, 122, 121, 121, 120, 120,
420 119, 118, 117, 117, 116, 115, 114, 113,
421 112, 111, 110, 109, 108, 107, 105, 104,
422 103, 102, 100, 99, 98, 96, 95, 93,
423 92, 91, 89, 87, 86, 84, 83, 81,
424 79, 77, 76, 74, 72, 70, 69, 67,
425 65, 63, 61, 59, 57, 55, 53, 51,
426 49, 47, 45, 43, 41, 39, 37, 35,
427 33, 30, 28, 26, 24, 22, 20, 18,
428 15, 13, 11, 9, 7, 4, 2, 0,
429 -1, -3, -6, -8, -10, -12, -14, -17,
430 -19, -21, -23, -25, -27, -29, -32, -34,
431 -36, -38, -40, -42, -44, -46, -48, -50,
432 -52, -54, -56, -58, -60, -62, -64, -66,
433 -68, -70, -71, -73, -75, -77, -78, -80,
434 -82, -83, -85, -87, -88, -90, -91, -93,
435 -94, -96, -97, -98, -100, -101, -102, -104,
436 -105, -106, -107, -108, -109, -111, -112, -113,
437 -113, -114, -115, -116, -117, -118, -118, -119,
438 -120, -120, -121, -122, -122, -123, -123, -124, -124
439};
440
58aa68c2 441static const s16 hsv_green_y[] = {
26e744b6
BJ
442 -100, -99, -98, -97, -95, -94, -93, -91,
443 -90, -89, -87, -86, -84, -83, -81, -80,
444 -78, -76, -75, -73, -71, -70, -68, -66,
445 -64, -63, -61, -59, -57, -55, -53, -51,
446 -49, -48, -46, -44, -42, -40, -38, -36,
447 -34, -32, -30, -27, -25, -23, -21, -19,
448 -17, -15, -13, -11, -9, -7, -4, -2,
449 0, 1, 3, 5, 7, 9, 11, 14,
450 16, 18, 20, 22, 24, 26, 28, 30,
451 32, 34, 36, 38, 40, 42, 44, 46,
452 48, 50, 52, 54, 56, 58, 59, 61,
453 63, 65, 67, 68, 70, 72, 74, 75,
454 77, 78, 80, 82, 83, 85, 86, 88,
455 89, 90, 92, 93, 95, 96, 97, 98,
456 100, 101, 102, 103, 104, 105, 106, 107,
457 108, 109, 110, 111, 112, 112, 113, 114,
458 115, 115, 116, 116, 117, 117, 118, 118,
459 119, 119, 119, 120, 120, 120, 120, 120,
460 121, 121, 121, 121, 121, 121, 120, 120,
461 120, 120, 120, 119, 119, 119, 118, 118,
462 117, 117, 116, 116, 115, 114, 114, 113,
463 112, 111, 111, 110, 109, 108, 107, 106,
464 105, 104, 103, 102, 100, 99, 98, 97,
465 95, 94, 93, 91, 90, 89, 87, 86,
466 84, 83, 81, 80, 78, 76, 75, 73,
467 71, 70, 68, 66, 64, 63, 61, 59,
468 57, 55, 53, 51, 49, 48, 46, 44,
469 42, 40, 38, 36, 34, 32, 30, 27,
470 25, 23, 21, 19, 17, 15, 13, 11,
471 9, 7, 4, 2, 0, -1, -3, -5,
472 -7, -9, -11, -14, -16, -18, -20, -22,
473 -24, -26, -28, -30, -32, -34, -36, -38,
474 -40, -42, -44, -46, -48, -50, -52, -54,
475 -56, -58, -59, -61, -63, -65, -67, -68,
476 -70, -72, -74, -75, -77, -78, -80, -82,
477 -83, -85, -86, -88, -89, -90, -92, -93,
478 -95, -96, -97, -98, -100, -101, -102, -103,
479 -104, -105, -106, -107, -108, -109, -110, -111,
480 -112, -112, -113, -114, -115, -115, -116, -116,
481 -117, -117, -118, -118, -119, -119, -119, -120,
482 -120, -120, -120, -120, -121, -121, -121, -121,
483 -121, -121, -120, -120, -120, -120, -120, -119,
484 -119, -119, -118, -118, -117, -117, -116, -116,
485 -115, -114, -114, -113, -112, -111, -111, -110,
486 -109, -108, -107, -106, -105, -104, -103, -102, -100
487};
488
58aa68c2 489static const s16 hsv_blue_x[] = {
26e744b6
BJ
490 112, 113, 114, 114, 115, 116, 117, 117,
491 118, 118, 119, 119, 120, 120, 120, 121,
492 121, 121, 122, 122, 122, 122, 122, 122,
493 122, 122, 122, 122, 122, 122, 121, 121,
494 121, 120, 120, 120, 119, 119, 118, 118,
495 117, 116, 116, 115, 114, 113, 113, 112,
496 111, 110, 109, 108, 107, 106, 105, 104,
497 103, 102, 100, 99, 98, 97, 95, 94,
498 93, 91, 90, 88, 87, 85, 84, 82,
499 80, 79, 77, 76, 74, 72, 70, 69,
500 67, 65, 63, 61, 60, 58, 56, 54,
501 52, 50, 48, 46, 44, 42, 40, 38,
502 36, 34, 32, 30, 28, 26, 24, 22,
503 19, 17, 15, 13, 11, 9, 7, 5,
504 2, 0, -1, -3, -5, -7, -9, -12,
505 -14, -16, -18, -20, -22, -24, -26, -28,
506 -31, -33, -35, -37, -39, -41, -43, -45,
507 -47, -49, -51, -53, -54, -56, -58, -60,
508 -62, -64, -66, -67, -69, -71, -73, -74,
509 -76, -78, -79, -81, -83, -84, -86, -87,
510 -89, -90, -92, -93, -94, -96, -97, -98,
511 -99, -101, -102, -103, -104, -105, -106, -107,
512 -108, -109, -110, -111, -112, -113, -114, -114,
513 -115, -116, -117, -117, -118, -118, -119, -119,
514 -120, -120, -120, -121, -121, -121, -122, -122,
515 -122, -122, -122, -122, -122, -122, -122, -122,
516 -122, -122, -121, -121, -121, -120, -120, -120,
517 -119, -119, -118, -118, -117, -116, -116, -115,
518 -114, -113, -113, -112, -111, -110, -109, -108,
519 -107, -106, -105, -104, -103, -102, -100, -99,
520 -98, -97, -95, -94, -93, -91, -90, -88,
521 -87, -85, -84, -82, -80, -79, -77, -76,
522 -74, -72, -70, -69, -67, -65, -63, -61,
523 -60, -58, -56, -54, -52, -50, -48, -46,
524 -44, -42, -40, -38, -36, -34, -32, -30,
525 -28, -26, -24, -22, -19, -17, -15, -13,
526 -11, -9, -7, -5, -2, 0, 1, 3,
527 5, 7, 9, 12, 14, 16, 18, 20,
528 22, 24, 26, 28, 31, 33, 35, 37,
529 39, 41, 43, 45, 47, 49, 51, 53,
530 54, 56, 58, 60, 62, 64, 66, 67,
531 69, 71, 73, 74, 76, 78, 79, 81,
532 83, 84, 86, 87, 89, 90, 92, 93,
533 94, 96, 97, 98, 99, 101, 102, 103,
534 104, 105, 106, 107, 108, 109, 110, 111, 112
535};
536
58aa68c2 537static const s16 hsv_blue_y[] = {
26e744b6
BJ
538 -11, -13, -15, -17, -19, -21, -23, -25,
539 -27, -29, -31, -33, -35, -37, -39, -41,
540 -43, -45, -46, -48, -50, -52, -54, -55,
541 -57, -59, -61, -62, -64, -66, -67, -69,
542 -71, -72, -74, -75, -77, -78, -80, -81,
543 -83, -84, -86, -87, -88, -90, -91, -92,
544 -93, -95, -96, -97, -98, -99, -100, -101,
545 -102, -103, -104, -105, -106, -106, -107, -108,
546 -109, -109, -110, -111, -111, -112, -112, -113,
547 -113, -114, -114, -114, -115, -115, -115, -115,
548 -116, -116, -116, -116, -116, -116, -116, -116,
549 -116, -115, -115, -115, -115, -114, -114, -114,
550 -113, -113, -112, -112, -111, -111, -110, -110,
551 -109, -108, -108, -107, -106, -105, -104, -103,
552 -102, -101, -100, -99, -98, -97, -96, -95,
553 -94, -93, -91, -90, -89, -88, -86, -85,
554 -84, -82, -81, -79, -78, -76, -75, -73,
555 -71, -70, -68, -67, -65, -63, -62, -60,
556 -58, -56, -55, -53, -51, -49, -47, -45,
557 -44, -42, -40, -38, -36, -34, -32, -30,
558 -28, -26, -24, -22, -20, -18, -16, -14,
559 -12, -10, -8, -6, -4, -2, 0, 1,
560 3, 5, 7, 9, 11, 13, 15, 17,
561 19, 21, 23, 25, 27, 29, 31, 33,
562 35, 37, 39, 41, 43, 45, 46, 48,
563 50, 52, 54, 55, 57, 59, 61, 62,
564 64, 66, 67, 69, 71, 72, 74, 75,
565 77, 78, 80, 81, 83, 84, 86, 87,
566 88, 90, 91, 92, 93, 95, 96, 97,
567 98, 99, 100, 101, 102, 103, 104, 105,
568 106, 106, 107, 108, 109, 109, 110, 111,
569 111, 112, 112, 113, 113, 114, 114, 114,
570 115, 115, 115, 115, 116, 116, 116, 116,
571 116, 116, 116, 116, 116, 115, 115, 115,
572 115, 114, 114, 114, 113, 113, 112, 112,
573 111, 111, 110, 110, 109, 108, 108, 107,
574 106, 105, 104, 103, 102, 101, 100, 99,
575 98, 97, 96, 95, 94, 93, 91, 90,
576 89, 88, 86, 85, 84, 82, 81, 79,
577 78, 76, 75, 73, 71, 70, 68, 67,
578 65, 63, 62, 60, 58, 56, 55, 53,
579 51, 49, 47, 45, 44, 42, 40, 38,
580 36, 34, 32, 30, 28, 26, 24, 22,
581 20, 18, 16, 14, 12, 10, 8, 6,
582 4, 2, 0, -1, -3, -5, -7, -9, -11
583};
584
dae1de64 585static const u16 i2c_ident[] = {
26e744b6
BJ
586 V4L2_IDENT_OV9650,
587 V4L2_IDENT_OV9655,
588 V4L2_IDENT_SOI968,
589 V4L2_IDENT_OV7660,
590 V4L2_IDENT_OV7670,
591 V4L2_IDENT_MT9V011,
592 V4L2_IDENT_MT9V111,
593 V4L2_IDENT_MT9V112,
594 V4L2_IDENT_MT9M001C12ST,
595 V4L2_IDENT_MT9M111,
e99ac54d 596 V4L2_IDENT_MT9M112,
26e744b6 597 V4L2_IDENT_HV7131R,
bed37388 598[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN,
26e744b6
BJ
599};
600
dae1de64 601static const u16 bridge_init[][2] = {
26e744b6
BJ
602 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
603 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
604 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
605 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
606 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
607 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
608 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
609 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
610 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
611 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
612 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
613 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
614 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
615 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
616 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
617 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
618 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
619 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
0c045eb7
BJ
620 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
621 {0x1007, 0x00}
26e744b6
BJ
622};
623
624/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
dae1de64 625static const u8 ov_gain[] = {
26e744b6
BJ
626 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
627 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
628 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
629 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
630 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
631 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
632 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
633 0x70 /* 8x */
634};
635
636/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
dae1de64 637static const u16 micron1_gain[] = {
26e744b6
BJ
638 /* 1x 1.25x 1.5x 1.75x */
639 0x0020, 0x0028, 0x0030, 0x0038,
640 /* 2x 2.25x 2.5x 2.75x */
641 0x00a0, 0x00a4, 0x00a8, 0x00ac,
642 /* 3x 3.25x 3.5x 3.75x */
643 0x00b0, 0x00b4, 0x00b8, 0x00bc,
644 /* 4x 4.25x 4.5x 4.75x */
645 0x00c0, 0x00c4, 0x00c8, 0x00cc,
646 /* 5x 5.25x 5.5x 5.75x */
647 0x00d0, 0x00d4, 0x00d8, 0x00dc,
648 /* 6x 6.25x 6.5x 6.75x */
649 0x00e0, 0x00e4, 0x00e8, 0x00ec,
650 /* 7x 7.25x 7.5x 7.75x */
651 0x00f0, 0x00f4, 0x00f8, 0x00fc,
652 /* 8x */
653 0x01c0
654};
655
656/* mt9m001 sensor uses a different gain formula then other micron sensors */
657/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
dae1de64 658static const u16 micron2_gain[] = {
26e744b6
BJ
659 /* 1x 1.25x 1.5x 1.75x */
660 0x0008, 0x000a, 0x000c, 0x000e,
661 /* 2x 2.25x 2.5x 2.75x */
662 0x0010, 0x0012, 0x0014, 0x0016,
663 /* 3x 3.25x 3.5x 3.75x */
664 0x0018, 0x001a, 0x001c, 0x001e,
665 /* 4x 4.25x 4.5x 4.75x */
666 0x0020, 0x0051, 0x0052, 0x0053,
667 /* 5x 5.25x 5.5x 5.75x */
668 0x0054, 0x0055, 0x0056, 0x0057,
669 /* 6x 6.25x 6.5x 6.75x */
670 0x0058, 0x0059, 0x005a, 0x005b,
671 /* 7x 7.25x 7.5x 7.75x */
672 0x005c, 0x005d, 0x005e, 0x005f,
673 /* 8x */
674 0x0060
675};
676
677/* Gain = .5 + bit[7:0] / 16 */
dae1de64 678static const u8 hv7131r_gain[] = {
26e744b6
BJ
679 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
680 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
681 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
682 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
683 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
684 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
685 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
686 0x78 /* 8x */
687};
688
dae1de64 689static const struct i2c_reg_u8 soi968_init[] = {
92884f80 690 {0x0c, 0x00}, {0x0f, 0x1f},
26e744b6
BJ
691 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
692 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
693 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
694 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
695 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
e1430471 696 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
26e744b6
BJ
697 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
698 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
699 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
700 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
701};
702
dae1de64 703static const struct i2c_reg_u8 ov7660_init[] = {
26e744b6
BJ
704 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
705 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
706 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
8bc50f35
HG
707 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
708 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
709 {0x17, 0x10}, {0x18, 0x61},
26e744b6 710 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
a1ac5dc2
JFM
711 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
712 {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
26e744b6
BJ
713};
714
dae1de64 715static const struct i2c_reg_u8 ov7670_init[] = {
92884f80 716 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
26e744b6
BJ
717 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
718 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
719 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
720 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
721 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
722 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
723 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
724 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
725 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
726 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
727 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
728 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
729 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
730 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
731 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
732 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
733 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
734 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
735 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
736 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
737 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
738 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
739 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
740 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
741 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
742 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
743 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
744 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
745 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
746 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
747 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
748 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
749 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
750 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
751 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
752 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
753 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
754 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
755 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
756 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
757 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
758 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
759 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
760 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
761 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
762 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
763 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
764 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
765 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
766 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
767 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
768 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
769 {0x93, 0x00},
770};
771
dae1de64 772static const struct i2c_reg_u8 ov9650_init[] = {
92884f80 773 {0x00, 0x00}, {0x01, 0x78},
26e744b6
BJ
774 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
775 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
776 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
777 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
778 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
779 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
780 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
781 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
782 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
783 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
784 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
785 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
786 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
787 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
788 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
789 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
790 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
791 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
792 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
793 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
794 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
795 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
796 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
797 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
798 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
799 {0xaa, 0x92}, {0xab, 0x0a},
800};
801
dae1de64 802static const struct i2c_reg_u8 ov9655_init[] = {
92884f80 803 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
cc2a8335
BJ
804 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
805 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
806 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
807 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
808 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
809 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
810 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
811 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
812 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
813 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
814 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
815 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
816 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
817 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
818 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
26e744b6 819 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
cc2a8335
BJ
820 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
821 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
26e744b6 822 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
cc2a8335
BJ
823 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
824 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
825 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
826 {0x04, 0x03}, {0x00, 0x13},
26e744b6
BJ
827};
828
dae1de64 829static const struct i2c_reg_u16 mt9v112_init[] = {
26e744b6
BJ
830 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
831 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
832 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
833 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
834 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
835 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
836 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
837 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
838 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
839 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
840 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
841 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
842 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
843 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
844 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
845 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
846};
847
dae1de64 848static const struct i2c_reg_u16 mt9v111_init[] = {
26e744b6 849 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
6ea23bd0
BJ
850 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
851 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
852 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
853 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
854 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
855 {0x0e, 0x0008}, {0x20, 0x0000}
26e744b6
BJ
856};
857
dae1de64 858static const struct i2c_reg_u16 mt9v011_init[] = {
26e744b6
BJ
859 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
860 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
861 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
862 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
863 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
864 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
865 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
866 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
867 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
868 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
869 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
870 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
871 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
872 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
873 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
874 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
875 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
876 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
877 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
878 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
879 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
880 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
881 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
882 {0x06, 0x0029}, {0x05, 0x0009},
883};
884
dae1de64 885static const struct i2c_reg_u16 mt9m001_init[] = {
d162e7aa
MCC
886 {0x0d, 0x0001},
887 {0x0d, 0x0000},
888 {0x04, 0x0500}, /* hres = 1280 */
889 {0x03, 0x0400}, /* vres = 1024 */
890 {0x20, 0x1100},
891 {0x06, 0x0010},
892 {0x2b, 0x0024},
893 {0x2e, 0x0024},
894 {0x35, 0x0024},
895 {0x2d, 0x0020},
896 {0x2c, 0x0020},
897 {0x09, 0x0ad4},
898 {0x35, 0x0057},
26e744b6
BJ
899};
900
dae1de64 901static const struct i2c_reg_u16 mt9m111_init[] = {
13a84fa4
BJ
902 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
903 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
4d708a5e
BJ
904 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
905 {0xf0, 0x0000},
26e744b6
BJ
906};
907
dae1de64 908static const struct i2c_reg_u16 mt9m112_init[] = {
e99ac54d
BJ
909 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
910 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
911 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
912 {0xf0, 0x0000},
913};
914
dae1de64 915static const struct i2c_reg_u8 hv7131r_init[] = {
26e744b6
BJ
916 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
917 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
918 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
919 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
920 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
921 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
922 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
923 {0x23, 0x09}, {0x01, 0x08},
924};
925
fe86ec75 926static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
26e744b6
BJ
927{
928 struct usb_device *dev = gspca_dev->dev;
929 int result;
fe86ec75
JFM
930
931 if (gspca_dev->usb_err < 0)
932 return;
26e744b6
BJ
933 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
934 0x00,
935 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
936 reg,
937 0x00,
938 gspca_dev->usb_buf,
939 length,
940 500);
941 if (unlikely(result < 0 || result != length)) {
fe86ec75
JFM
942 pr_err("Read register %02x failed %d\n", reg, result);
943 gspca_dev->usb_err = result;
26e744b6 944 }
26e744b6
BJ
945}
946
fe86ec75 947static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
58aa68c2 948 const u8 *buffer, int length)
26e744b6
BJ
949{
950 struct usb_device *dev = gspca_dev->dev;
951 int result;
fe86ec75
JFM
952
953 if (gspca_dev->usb_err < 0)
954 return;
26e744b6
BJ
955 memcpy(gspca_dev->usb_buf, buffer, length);
956 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
957 0x08,
958 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
959 reg,
960 0x00,
961 gspca_dev->usb_buf,
962 length,
963 500);
964 if (unlikely(result < 0 || result != length)) {
fe86ec75
JFM
965 pr_err("Write register %02x failed %d\n", reg, result);
966 gspca_dev->usb_err = result;
26e744b6 967 }
26e744b6
BJ
968}
969
fe86ec75 970static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
26e744b6 971{
ff38d58e 972 reg_w(gspca_dev, reg, &value, 1);
26e744b6
BJ
973}
974
fe86ec75 975static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
26e744b6
BJ
976{
977 int i;
ff38d58e 978
26e744b6
BJ
979 reg_w(gspca_dev, 0x10c0, buffer, 8);
980 for (i = 0; i < 5; i++) {
981 reg_r(gspca_dev, 0x10c0, 1);
fe86ec75
JFM
982 if (gspca_dev->usb_err < 0)
983 return;
26e744b6 984 if (gspca_dev->usb_buf[0] & 0x04) {
fe86ec75
JFM
985 if (gspca_dev->usb_buf[0] & 0x08) {
986 pr_err("i2c_w error\n");
987 gspca_dev->usb_err = -EIO;
988 }
989 return;
26e744b6 990 }
e71389be 991 msleep(10);
26e744b6 992 }
fe86ec75
JFM
993 pr_err("i2c_w reg %02x no response\n", buffer[2]);
994/* gspca_dev->usb_err = -EIO; fixme: may occur */
26e744b6
BJ
995}
996
fe86ec75 997static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
26e744b6
BJ
998{
999 struct sd *sd = (struct sd *) gspca_dev;
26e744b6
BJ
1000 u8 row[8];
1001
1002 /*
1003 * from the point of view of the bridge, the length
1004 * includes the address
1005 */
c4407fe8 1006 row[0] = sd->i2c_intf | (2 << 4);
26e744b6
BJ
1007 row[1] = sd->i2c_addr;
1008 row[2] = reg;
1009 row[3] = val;
1010 row[4] = 0x00;
1011 row[5] = 0x00;
1012 row[6] = 0x00;
1013 row[7] = 0x10;
1014
fe86ec75 1015 i2c_w(gspca_dev, row);
26e744b6
BJ
1016}
1017
d4689b74 1018static void i2c_w1_buf(struct gspca_dev *gspca_dev,
dae1de64 1019 const struct i2c_reg_u8 *buf, int sz)
d4689b74
JFM
1020{
1021 while (--sz >= 0) {
1022 i2c_w1(gspca_dev, buf->reg, buf->val);
1023 buf++;
1024 }
1025}
1026
fe86ec75 1027static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
26e744b6
BJ
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
1030 u8 row[8];
1031
1032 /*
1033 * from the point of view of the bridge, the length
1034 * includes the address
1035 */
c4407fe8 1036 row[0] = sd->i2c_intf | (3 << 4);
26e744b6
BJ
1037 row[1] = sd->i2c_addr;
1038 row[2] = reg;
ff38d58e
JFM
1039 row[3] = val >> 8;
1040 row[4] = val;
26e744b6
BJ
1041 row[5] = 0x00;
1042 row[6] = 0x00;
1043 row[7] = 0x10;
1044
fe86ec75 1045 i2c_w(gspca_dev, row);
26e744b6
BJ
1046}
1047
d4689b74 1048static void i2c_w2_buf(struct gspca_dev *gspca_dev,
dae1de64 1049 const struct i2c_reg_u16 *buf, int sz)
d4689b74
JFM
1050{
1051 while (--sz >= 0) {
1052 i2c_w2(gspca_dev, buf->reg, buf->val);
1053 buf++;
1054 }
1055}
1056
fe86ec75 1057static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
26e744b6
BJ
1058{
1059 struct sd *sd = (struct sd *) gspca_dev;
1060 u8 row[8];
1061
c4407fe8 1062 row[0] = sd->i2c_intf | (1 << 4);
26e744b6
BJ
1063 row[1] = sd->i2c_addr;
1064 row[2] = reg;
1065 row[3] = 0;
1066 row[4] = 0;
1067 row[5] = 0;
1068 row[6] = 0;
1069 row[7] = 0x10;
fe86ec75 1070 i2c_w(gspca_dev, row);
c4407fe8 1071 row[0] = sd->i2c_intf | (1 << 4) | 0x02;
26e744b6 1072 row[2] = 0;
fe86ec75
JFM
1073 i2c_w(gspca_dev, row);
1074 reg_r(gspca_dev, 0x10c2, 5);
00b581ef 1075 *val = gspca_dev->usb_buf[4];
26e744b6
BJ
1076}
1077
fe86ec75 1078static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
26e744b6
BJ
1079{
1080 struct sd *sd = (struct sd *) gspca_dev;
1081 u8 row[8];
1082
c4407fe8 1083 row[0] = sd->i2c_intf | (1 << 4);
26e744b6
BJ
1084 row[1] = sd->i2c_addr;
1085 row[2] = reg;
1086 row[3] = 0;
1087 row[4] = 0;
1088 row[5] = 0;
1089 row[6] = 0;
1090 row[7] = 0x10;
fe86ec75 1091 i2c_w(gspca_dev, row);
c4407fe8 1092 row[0] = sd->i2c_intf | (2 << 4) | 0x02;
26e744b6 1093 row[2] = 0;
fe86ec75
JFM
1094 i2c_w(gspca_dev, row);
1095 reg_r(gspca_dev, 0x10c2, 5);
00b581ef 1096 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
26e744b6
BJ
1097}
1098
fe86ec75 1099static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1100{
e78567d2 1101 u16 id;
26e744b6
BJ
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
fe86ec75
JFM
1104 i2c_r2(gspca_dev, 0x1c, &id);
1105 if (gspca_dev->usb_err < 0)
1106 return;
e78567d2
MCC
1107
1108 if (id != 0x7fa2) {
91f5842b 1109 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
fe86ec75
JFM
1110 gspca_dev->usb_err = -ENODEV;
1111 return;
e78567d2
MCC
1112 }
1113
92884f80
JFM
1114 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1115 msleep(200);
d4689b74
JFM
1116 i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
1117 if (gspca_dev->usb_err < 0)
1118 pr_err("OV9650 sensor initialization failed\n");
26e744b6
BJ
1119 sd->hstart = 1;
1120 sd->vstart = 7;
26e744b6
BJ
1121}
1122
fe86ec75 1123static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1124{
26e744b6
BJ
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
92884f80
JFM
1127 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1128 msleep(200);
d4689b74
JFM
1129 i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
1130 if (gspca_dev->usb_err < 0)
1131 pr_err("OV9655 sensor initialization failed\n");
1132
cc2a8335
BJ
1133 sd->hstart = 1;
1134 sd->vstart = 2;
26e744b6
BJ
1135}
1136
fe86ec75 1137static void soi968_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1138{
26e744b6
BJ
1139 struct sd *sd = (struct sd *) gspca_dev;
1140
92884f80
JFM
1141 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1142 msleep(200);
d4689b74
JFM
1143 i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
1144 if (gspca_dev->usb_err < 0)
1145 pr_err("SOI968 sensor initialization failed\n");
1146
26e744b6
BJ
1147 sd->hstart = 60;
1148 sd->vstart = 11;
26e744b6
BJ
1149}
1150
fe86ec75 1151static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1152{
26e744b6
BJ
1153 struct sd *sd = (struct sd *) gspca_dev;
1154
92884f80
JFM
1155 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1156 msleep(200);
d4689b74
JFM
1157 i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
1158 if (gspca_dev->usb_err < 0)
1159 pr_err("OV7660 sensor initialization failed\n");
8bc50f35
HG
1160 sd->hstart = 3;
1161 sd->vstart = 3;
26e744b6
BJ
1162}
1163
fe86ec75 1164static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1165{
26e744b6
BJ
1166 struct sd *sd = (struct sd *) gspca_dev;
1167
92884f80
JFM
1168 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1169 msleep(200);
d4689b74
JFM
1170 i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
1171 if (gspca_dev->usb_err < 0)
1172 pr_err("OV7670 sensor initialization failed\n");
1173
26e744b6
BJ
1174 sd->hstart = 0;
1175 sd->vstart = 1;
26e744b6
BJ
1176}
1177
fe86ec75 1178static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
26e744b6
BJ
1179{
1180 struct sd *sd = (struct sd *) gspca_dev;
26e744b6 1181 u16 value;
26e744b6
BJ
1182
1183 sd->i2c_addr = 0x5d;
fe86ec75
JFM
1184 i2c_r2(gspca_dev, 0xff, &value);
1185 if (gspca_dev->usb_err >= 0
1186 && value == 0x8243) {
d4689b74
JFM
1187 i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
1188 if (gspca_dev->usb_err < 0) {
1189 pr_err("MT9V011 sensor initialization failed\n");
1190 return;
26e744b6
BJ
1191 }
1192 sd->hstart = 2;
1193 sd->vstart = 2;
1194 sd->sensor = SENSOR_MT9V011;
91f5842b 1195 pr_info("MT9V011 sensor detected\n");
fe86ec75 1196 return;
26e744b6
BJ
1197 }
1198
fe86ec75 1199 gspca_dev->usb_err = 0;
26e744b6
BJ
1200 sd->i2c_addr = 0x5c;
1201 i2c_w2(gspca_dev, 0x01, 0x0004);
fe86ec75
JFM
1202 i2c_r2(gspca_dev, 0xff, &value);
1203 if (gspca_dev->usb_err >= 0
1204 && value == 0x823a) {
d4689b74
JFM
1205 i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
1206 if (gspca_dev->usb_err < 0) {
1207 pr_err("MT9V111 sensor initialization failed\n");
1208 return;
26e744b6
BJ
1209 }
1210 sd->hstart = 2;
1211 sd->vstart = 2;
1212 sd->sensor = SENSOR_MT9V111;
91f5842b 1213 pr_info("MT9V111 sensor detected\n");
fe86ec75 1214 return;
26e744b6
BJ
1215 }
1216
fe86ec75 1217 gspca_dev->usb_err = 0;
26e744b6 1218 sd->i2c_addr = 0x5d;
fe86ec75
JFM
1219 i2c_w2(gspca_dev, 0xf0, 0x0000);
1220 if (gspca_dev->usb_err < 0) {
1221 gspca_dev->usb_err = 0;
26e744b6
BJ
1222 sd->i2c_addr = 0x48;
1223 i2c_w2(gspca_dev, 0xf0, 0x0000);
1224 }
fe86ec75
JFM
1225 i2c_r2(gspca_dev, 0x00, &value);
1226 if (gspca_dev->usb_err >= 0
1227 && value == 0x1229) {
d4689b74
JFM
1228 i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
1229 if (gspca_dev->usb_err < 0) {
1230 pr_err("MT9V112 sensor initialization failed\n");
1231 return;
26e744b6
BJ
1232 }
1233 sd->hstart = 6;
1234 sd->vstart = 2;
1235 sd->sensor = SENSOR_MT9V112;
91f5842b 1236 pr_info("MT9V112 sensor detected\n");
fe86ec75 1237 return;
26e744b6
BJ
1238 }
1239
fe86ec75 1240 gspca_dev->usb_err = -ENODEV;
26e744b6
BJ
1241}
1242
fe86ec75 1243static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
e99ac54d
BJ
1244{
1245 struct sd *sd = (struct sd *) gspca_dev;
d4689b74
JFM
1246
1247 i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
1248 if (gspca_dev->usb_err < 0)
1249 pr_err("MT9M112 sensor initialization failed\n");
1250
e99ac54d
BJ
1251 sd->hstart = 0;
1252 sd->vstart = 2;
e99ac54d
BJ
1253}
1254
fe86ec75 1255static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
26e744b6
BJ
1256{
1257 struct sd *sd = (struct sd *) gspca_dev;
d4689b74
JFM
1258
1259 i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
1260 if (gspca_dev->usb_err < 0)
1261 pr_err("MT9M111 sensor initialization failed\n");
1262
26e744b6
BJ
1263 sd->hstart = 0;
1264 sd->vstart = 2;
26e744b6
BJ
1265}
1266
fe86ec75 1267static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
26e744b6
BJ
1268{
1269 struct sd *sd = (struct sd *) gspca_dev;
d162e7aa
MCC
1270 u16 id;
1271
fe86ec75
JFM
1272 i2c_r2(gspca_dev, 0x00, &id);
1273 if (gspca_dev->usb_err < 0)
1274 return;
d162e7aa
MCC
1275
1276 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1277 switch (id) {
1278 case 0x8411:
1279 case 0x8421:
91f5842b 1280 pr_info("MT9M001 color sensor detected\n");
d162e7aa
MCC
1281 break;
1282 case 0x8431:
91f5842b 1283 pr_info("MT9M001 mono sensor detected\n");
d162e7aa
MCC
1284 break;
1285 default:
91f5842b 1286 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
fe86ec75
JFM
1287 gspca_dev->usb_err = -ENODEV;
1288 return;
d162e7aa
MCC
1289 }
1290
d4689b74
JFM
1291 i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
1292 if (gspca_dev->usb_err < 0)
1293 pr_err("MT9M001 sensor initialization failed\n");
1294
d162e7aa
MCC
1295 sd->hstart = 1;
1296 sd->vstart = 1;
26e744b6
BJ
1297}
1298
fe86ec75 1299static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
26e744b6 1300{
26e744b6
BJ
1301 struct sd *sd = (struct sd *) gspca_dev;
1302
d4689b74
JFM
1303 i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
1304 if (gspca_dev->usb_err < 0)
1305 pr_err("HV7131R Sensor initialization failed\n");
1306
26e744b6
BJ
1307 sd->hstart = 0;
1308 sd->vstart = 1;
26e744b6
BJ
1309}
1310
63069da1
HV
1311static void set_cmatrix(struct gspca_dev *gspca_dev,
1312 s32 brightness, s32 contrast, s32 satur, s32 hue)
26e744b6 1313{
63069da1 1314 s32 hue_coord, hue_index = 180 + hue;
26e744b6 1315 u8 cmatrix[21];
26e744b6 1316
de2d1549 1317 memset(cmatrix, 0, sizeof cmatrix);
63069da1 1318 cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
26e744b6
BJ
1319 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1320 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
63069da1 1321 cmatrix[18] = brightness - 0x80;
26e744b6 1322
c5224d81 1323 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
de2d1549
JFM
1324 cmatrix[6] = hue_coord;
1325 cmatrix[7] = (hue_coord >> 8) & 0x0f;
26e744b6 1326
c5224d81 1327 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
de2d1549
JFM
1328 cmatrix[8] = hue_coord;
1329 cmatrix[9] = (hue_coord >> 8) & 0x0f;
26e744b6 1330
c5224d81 1331 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
de2d1549
JFM
1332 cmatrix[10] = hue_coord;
1333 cmatrix[11] = (hue_coord >> 8) & 0x0f;
26e744b6 1334
c5224d81 1335 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
de2d1549
JFM
1336 cmatrix[12] = hue_coord;
1337 cmatrix[13] = (hue_coord >> 8) & 0x0f;
26e744b6 1338
c5224d81 1339 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
de2d1549
JFM
1340 cmatrix[14] = hue_coord;
1341 cmatrix[15] = (hue_coord >> 8) & 0x0f;
26e744b6 1342
c5224d81 1343 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
de2d1549
JFM
1344 cmatrix[16] = hue_coord;
1345 cmatrix[17] = (hue_coord >> 8) & 0x0f;
26e744b6 1346
c5224d81 1347 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
26e744b6
BJ
1348}
1349
63069da1 1350static void set_gamma(struct gspca_dev *gspca_dev, s32 val)
26e744b6 1351{
26e744b6 1352 u8 gamma[17];
63069da1 1353 u8 gval = val * 0xb8 / 0x100;
26e744b6
BJ
1354
1355 gamma[0] = 0x0a;
1356 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1357 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1358 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1359 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1360 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1361 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1362 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1363 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1364 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1365 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1366 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1367 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1368 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1369 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1370 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1371 gamma[16] = 0xf5;
1372
c5224d81 1373 reg_w(gspca_dev, 0x1190, gamma, 17);
26e744b6
BJ
1374}
1375
63069da1 1376static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
26e744b6 1377{
63069da1
HV
1378 reg_w1(gspca_dev, 0x118c, red);
1379 reg_w1(gspca_dev, 0x118f, blue);
26e744b6
BJ
1380}
1381
63069da1 1382static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
26e744b6 1383{
63069da1 1384 u8 value, tslb;
26e744b6
BJ
1385 u16 value2;
1386 struct sd *sd = (struct sd *) gspca_dev;
7ddaac7f
BJ
1387
1388 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
63069da1
HV
1389 hflip = !hflip;
1390 vflip = !vflip;
7ddaac7f
BJ
1391 }
1392
26e744b6 1393 switch (sd->sensor) {
779b51f7
HG
1394 case SENSOR_OV7660:
1395 value = 0x01;
1396 if (hflip)
1397 value |= 0x20;
1398 if (vflip) {
1399 value |= 0x10;
1400 sd->vstart = 2;
ff38d58e 1401 } else {
779b51f7 1402 sd->vstart = 3;
ff38d58e 1403 }
779b51f7
HG
1404 reg_w1(gspca_dev, 0x1182, sd->vstart);
1405 i2c_w1(gspca_dev, 0x1e, value);
1406 break;
26e744b6
BJ
1407 case SENSOR_OV9650:
1408 i2c_r1(gspca_dev, 0x1e, &value);
1409 value &= ~0x30;
1410 tslb = 0x01;
7ddaac7f 1411 if (hflip)
26e744b6 1412 value |= 0x20;
7ddaac7f 1413 if (vflip) {
26e744b6
BJ
1414 value |= 0x10;
1415 tslb = 0x49;
1416 }
1417 i2c_w1(gspca_dev, 0x1e, value);
1418 i2c_w1(gspca_dev, 0x3a, tslb);
1419 break;
1420 case SENSOR_MT9V111:
1421 case SENSOR_MT9V011:
1422 i2c_r2(gspca_dev, 0x20, &value2);
1423 value2 &= ~0xc0a0;
7ddaac7f 1424 if (hflip)
26e744b6 1425 value2 |= 0x8080;
7ddaac7f 1426 if (vflip)
26e744b6
BJ
1427 value2 |= 0x4020;
1428 i2c_w2(gspca_dev, 0x20, value2);
1429 break;
e99ac54d 1430 case SENSOR_MT9M112:
26e744b6
BJ
1431 case SENSOR_MT9M111:
1432 case SENSOR_MT9V112:
1433 i2c_r2(gspca_dev, 0x20, &value2);
1434 value2 &= ~0x0003;
7ddaac7f 1435 if (hflip)
26e744b6 1436 value2 |= 0x0002;
7ddaac7f 1437 if (vflip)
26e744b6
BJ
1438 value2 |= 0x0001;
1439 i2c_w2(gspca_dev, 0x20, value2);
1440 break;
1441 case SENSOR_HV7131R:
1442 i2c_r1(gspca_dev, 0x01, &value);
1443 value &= ~0x03;
7ddaac7f 1444 if (vflip)
26e744b6 1445 value |= 0x01;
7ddaac7f 1446 if (hflip)
26e744b6
BJ
1447 value |= 0x02;
1448 i2c_w1(gspca_dev, 0x01, value);
1449 break;
1450 }
26e744b6
BJ
1451}
1452
63069da1 1453static void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
26e744b6
BJ
1454{
1455 struct sd *sd = (struct sd *) gspca_dev;
c4407fe8 1456 u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
4fb8137c 1457 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
63069da1 1458 int expo2;
c5224d81 1459
4fb8137c
JFM
1460 if (gspca_dev->streaming)
1461 exp[7] = 0x1e;
1462
26e744b6
BJ
1463 switch (sd->sensor) {
1464 case SENSOR_OV7660:
1465 case SENSOR_OV7670:
26e744b6
BJ
1466 case SENSOR_OV9655:
1467 case SENSOR_OV9650:
a1ac5dc2
JFM
1468 if (expo > 547)
1469 expo2 = 547;
1470 else
1471 expo2 = expo;
1472 exp[0] |= (2 << 4);
1473 exp[2] = 0x10; /* AECH */
1474 exp[3] = expo2 >> 2;
1475 exp[7] = 0x10;
1476 i2c_w(gspca_dev, exp);
1477 exp[2] = 0x04; /* COM1 */
1478 exp[3] = expo2 & 0x0003;
1479 exp[7] = 0x10;
1480 i2c_w(gspca_dev, exp);
1481 expo -= expo2;
1482 exp[7] = 0x1e;
26e744b6 1483 exp[0] |= (3 << 4);
a1ac5dc2 1484 exp[2] = 0x2d; /* ADVFL & ADVFH */
c5224d81
JFM
1485 exp[3] = expo;
1486 exp[4] = expo >> 8;
26e744b6
BJ
1487 break;
1488 case SENSOR_MT9M001:
26e744b6 1489 case SENSOR_MT9V112:
26e744b6
BJ
1490 case SENSOR_MT9V011:
1491 exp[0] |= (3 << 4);
1492 exp[2] = 0x09;
c5224d81
JFM
1493 exp[3] = expo >> 8;
1494 exp[4] = expo;
26e744b6
BJ
1495 break;
1496 case SENSOR_HV7131R:
1497 exp[0] |= (4 << 4);
1498 exp[2] = 0x25;
c5224d81
JFM
1499 exp[3] = expo >> 5;
1500 exp[4] = expo << 3;
e10f7319 1501 exp[5] = 0;
26e744b6 1502 break;
e1430471 1503 default:
c5224d81 1504 return;
26e744b6
BJ
1505 }
1506 i2c_w(gspca_dev, exp);
26e744b6
BJ
1507}
1508
63069da1 1509static void set_gain(struct gspca_dev *gspca_dev, s32 g)
26e744b6
BJ
1510{
1511 struct sd *sd = (struct sd *) gspca_dev;
c4407fe8 1512 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
4fb8137c 1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
c5224d81 1514
4fb8137c
JFM
1515 if (gspca_dev->streaming)
1516 gain[7] = 0x15; /* or 1d ? */
1517
26e744b6
BJ
1518 switch (sd->sensor) {
1519 case SENSOR_OV7660:
1520 case SENSOR_OV7670:
1521 case SENSOR_SOI968:
1522 case SENSOR_OV9655:
1523 case SENSOR_OV9650:
1524 gain[0] |= (2 << 4);
c5224d81 1525 gain[3] = ov_gain[g];
26e744b6
BJ
1526 break;
1527 case SENSOR_MT9V011:
26e744b6
BJ
1528 gain[0] |= (3 << 4);
1529 gain[2] = 0x35;
c5224d81
JFM
1530 gain[3] = micron1_gain[g] >> 8;
1531 gain[4] = micron1_gain[g];
26e744b6
BJ
1532 break;
1533 case SENSOR_MT9V112:
26e744b6
BJ
1534 gain[0] |= (3 << 4);
1535 gain[2] = 0x2f;
c5224d81
JFM
1536 gain[3] = micron1_gain[g] >> 8;
1537 gain[4] = micron1_gain[g];
26e744b6
BJ
1538 break;
1539 case SENSOR_MT9M001:
1540 gain[0] |= (3 << 4);
1541 gain[2] = 0x2f;
c5224d81
JFM
1542 gain[3] = micron2_gain[g] >> 8;
1543 gain[4] = micron2_gain[g];
26e744b6
BJ
1544 break;
1545 case SENSOR_HV7131R:
1546 gain[0] |= (2 << 4);
1547 gain[2] = 0x30;
c5224d81 1548 gain[3] = hv7131r_gain[g];
26e744b6 1549 break;
e1430471 1550 default:
c5224d81 1551 return;
26e744b6
BJ
1552 }
1553 i2c_w(gspca_dev, gain);
26e744b6
BJ
1554}
1555
63069da1 1556static void set_quality(struct gspca_dev *gspca_dev, s32 val)
4c632e4e
JFM
1557{
1558 struct sd *sd = (struct sd *) gspca_dev;
1559
63069da1 1560 jpeg_set_qual(sd->jpeg_hdr, val);
4c632e4e
JFM
1561 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1562 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1563 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1564 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1565 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1566 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1567 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1568 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1569}
1570
26e744b6
BJ
1571#ifdef CONFIG_VIDEO_ADV_DEBUG
1572static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1573 struct v4l2_dbg_register *reg)
1574{
1575 struct sd *sd = (struct sd *) gspca_dev;
ff38d58e 1576
26e744b6
BJ
1577 switch (reg->match.type) {
1578 case V4L2_CHIP_MATCH_HOST:
1579 if (reg->match.addr != 0)
1580 return -EINVAL;
1581 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1582 return -EINVAL;
fe86ec75 1583 reg_r(gspca_dev, reg->reg, 1);
26e744b6 1584 reg->val = gspca_dev->usb_buf[0];
fe86ec75 1585 return gspca_dev->usb_err;
26e744b6
BJ
1586 case V4L2_CHIP_MATCH_I2C_ADDR:
1587 if (reg->match.addr != sd->i2c_addr)
1588 return -EINVAL;
1589 if (sd->sensor >= SENSOR_MT9V011 &&
e99ac54d 1590 sd->sensor <= SENSOR_MT9M112) {
fe86ec75 1591 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
26e744b6 1592 } else {
fe86ec75 1593 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
26e744b6 1594 }
fe86ec75 1595 return gspca_dev->usb_err;
26e744b6
BJ
1596 }
1597 return -EINVAL;
1598}
1599
1600static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1601 struct v4l2_dbg_register *reg)
1602{
1603 struct sd *sd = (struct sd *) gspca_dev;
ff38d58e 1604
26e744b6
BJ
1605 switch (reg->match.type) {
1606 case V4L2_CHIP_MATCH_HOST:
1607 if (reg->match.addr != 0)
1608 return -EINVAL;
1609 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1610 return -EINVAL;
fe86ec75
JFM
1611 reg_w1(gspca_dev, reg->reg, reg->val);
1612 return gspca_dev->usb_err;
26e744b6
BJ
1613 case V4L2_CHIP_MATCH_I2C_ADDR:
1614 if (reg->match.addr != sd->i2c_addr)
1615 return -EINVAL;
1616 if (sd->sensor >= SENSOR_MT9V011 &&
e99ac54d 1617 sd->sensor <= SENSOR_MT9M112) {
fe86ec75 1618 i2c_w2(gspca_dev, reg->reg, reg->val);
26e744b6 1619 } else {
fe86ec75 1620 i2c_w1(gspca_dev, reg->reg, reg->val);
26e744b6 1621 }
fe86ec75 1622 return gspca_dev->usb_err;
26e744b6
BJ
1623 }
1624 return -EINVAL;
1625}
1626#endif
1627
1628static int sd_chip_ident(struct gspca_dev *gspca_dev,
1629 struct v4l2_dbg_chip_ident *chip)
1630{
1631 struct sd *sd = (struct sd *) gspca_dev;
1632
1633 switch (chip->match.type) {
1634 case V4L2_CHIP_MATCH_HOST:
1635 if (chip->match.addr != 0)
1636 return -EINVAL;
1637 chip->revision = 0;
1638 chip->ident = V4L2_IDENT_SN9C20X;
1639 return 0;
1640 case V4L2_CHIP_MATCH_I2C_ADDR:
1641 if (chip->match.addr != sd->i2c_addr)
1642 return -EINVAL;
1643 chip->revision = 0;
1644 chip->ident = i2c_ident[sd->sensor];
1645 return 0;
1646 }
1647 return -EINVAL;
1648}
1649
1650static int sd_config(struct gspca_dev *gspca_dev,
1651 const struct usb_device_id *id)
1652{
1653 struct sd *sd = (struct sd *) gspca_dev;
1654 struct cam *cam;
1655
1656 cam = &gspca_dev->cam;
eb3fb7c9 1657 cam->needs_full_bandwidth = 1;
26e744b6 1658
ff38d58e
JFM
1659 sd->sensor = id->driver_info >> 8;
1660 sd->i2c_addr = id->driver_info;
1661 sd->flags = id->driver_info >> 16;
c4407fe8 1662 sd->i2c_intf = 0x80; /* i2c 100 Kb/s */
26e744b6
BJ
1663
1664 switch (sd->sensor) {
e99ac54d 1665 case SENSOR_MT9M112:
4d708a5e 1666 case SENSOR_MT9M111:
26e744b6 1667 case SENSOR_OV9650:
e8b7acc1 1668 case SENSOR_SOI968:
26e744b6
BJ
1669 cam->cam_mode = sxga_mode;
1670 cam->nmodes = ARRAY_SIZE(sxga_mode);
1671 break;
d162e7aa
MCC
1672 case SENSOR_MT9M001:
1673 cam->cam_mode = mono_mode;
1674 cam->nmodes = ARRAY_SIZE(mono_mode);
1675 break;
c4407fe8
JFM
1676 case SENSOR_HV7131R:
1677 sd->i2c_intf = 0x81; /* i2c 400 Kb/s */
1678 /* fall thru */
26e744b6
BJ
1679 default:
1680 cam->cam_mode = vga_mode;
1681 cam->nmodes = ARRAY_SIZE(vga_mode);
de2d1549 1682 break;
26e744b6
BJ
1683 }
1684
1685 sd->old_step = 0;
1686 sd->older_step = 0;
1687 sd->exposure_step = 16;
1688
92dcffcf 1689 INIT_WORK(&sd->work, qual_upd);
26e744b6 1690
26e744b6
BJ
1691 return 0;
1692}
1693
63069da1
HV
1694static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1695{
a8a47860
HG
1696 struct gspca_dev *gspca_dev =
1697 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1698 struct sd *sd = (struct sd *)gspca_dev;
63069da1
HV
1699
1700 gspca_dev->usb_err = 0;
1701
1702 if (!gspca_dev->streaming)
1703 return 0;
1704
1705 switch (ctrl->id) {
1706 /* color control cluster */
1707 case V4L2_CID_BRIGHTNESS:
a8a47860 1708 set_cmatrix(gspca_dev, sd->brightness->val,
63069da1
HV
1709 sd->contrast->val, sd->saturation->val, sd->hue->val);
1710 break;
1711 case V4L2_CID_GAMMA:
a8a47860 1712 set_gamma(gspca_dev, ctrl->val);
63069da1
HV
1713 break;
1714 /* blue/red balance cluster */
1715 case V4L2_CID_BLUE_BALANCE:
a8a47860 1716 set_redblue(gspca_dev, sd->blue->val, sd->red->val);
63069da1
HV
1717 break;
1718 /* h/vflip cluster */
1719 case V4L2_CID_HFLIP:
a8a47860 1720 set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
63069da1
HV
1721 break;
1722 /* standalone exposure control */
1723 case V4L2_CID_EXPOSURE:
a8a47860 1724 set_exposure(gspca_dev, ctrl->val);
63069da1
HV
1725 break;
1726 /* standalone gain control */
1727 case V4L2_CID_GAIN:
a8a47860 1728 set_gain(gspca_dev, ctrl->val);
63069da1
HV
1729 break;
1730 /* autogain + exposure or gain control cluster */
1731 case V4L2_CID_AUTOGAIN:
1732 if (sd->sensor == SENSOR_SOI968)
a8a47860 1733 set_gain(gspca_dev, sd->gain->val);
63069da1 1734 else
a8a47860 1735 set_exposure(gspca_dev, sd->exposure->val);
63069da1
HV
1736 break;
1737 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
a8a47860 1738 set_quality(gspca_dev, ctrl->val);
63069da1
HV
1739 break;
1740 }
1741 return gspca_dev->usb_err;
1742}
1743
1744static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1745 .s_ctrl = sd_s_ctrl,
1746};
1747
1748static int sd_init_controls(struct gspca_dev *gspca_dev)
1749{
1750 struct sd *sd = (struct sd *) gspca_dev;
a8a47860 1751 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
63069da1
HV
1752
1753 gspca_dev->vdev.ctrl_handler = hdl;
1754 v4l2_ctrl_handler_init(hdl, 13);
1755
1756 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1757 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1758 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1759 V4L2_CID_CONTRAST, 0, 255, 1, 127);
1760 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1761 V4L2_CID_SATURATION, 0, 255, 1, 127);
1762 sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1763 V4L2_CID_HUE, -180, 180, 1, 0);
63069da1
HV
1764
1765 sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1766 V4L2_CID_GAMMA, 0, 255, 1, 0x10);
1767
1768 sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1769 V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
1770 sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1771 V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
63069da1
HV
1772
1773 if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
1774 sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
1775 sd->sensor != SENSOR_MT9VPRB) {
1776 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1777 V4L2_CID_HFLIP, 0, 1, 1, 0);
1778 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1779 V4L2_CID_VFLIP, 0, 1, 1, 0);
63069da1
HV
1780 }
1781
1782 if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
1783 sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
1784 sd->sensor != SENSOR_MT9V111)
1785 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1786 V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
1787
1788 if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
1789 sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
1790 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1791 V4L2_CID_GAIN, 0, 28, 1, 0);
1792 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1793 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
bc378fee
HG
1794 }
1795
1796 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1797 V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
1798 if (hdl->error) {
1799 pr_err("Could not initialize controls\n");
1800 return hdl->error;
1801 }
1802
1803 v4l2_ctrl_cluster(4, &sd->brightness);
1804 v4l2_ctrl_cluster(2, &sd->blue);
1805 if (sd->hflip)
1806 v4l2_ctrl_cluster(2, &sd->hflip);
1807 if (sd->autogain) {
63069da1
HV
1808 if (sd->sensor == SENSOR_SOI968)
1809 /* this sensor doesn't have the exposure control and
1810 autogain is clustered with gain instead. This works
1811 because sd->exposure == NULL. */
1812 v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
1813 else
1814 /* Otherwise autogain is clustered with exposure. */
1815 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
1816 }
63069da1
HV
1817 return 0;
1818}
1819
26e744b6
BJ
1820static int sd_init(struct gspca_dev *gspca_dev)
1821{
1822 struct sd *sd = (struct sd *) gspca_dev;
1823 int i;
1824 u8 value;
1825 u8 i2c_init[9] =
1826 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1827
1828 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1829 value = bridge_init[i][1];
fe86ec75
JFM
1830 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1831 if (gspca_dev->usb_err < 0) {
91f5842b 1832 pr_err("Device initialization failed\n");
fe86ec75 1833 return gspca_dev->usb_err;
26e744b6
BJ
1834 }
1835 }
1836
0c045eb7
BJ
1837 if (sd->flags & LED_REVERSE)
1838 reg_w1(gspca_dev, 0x1006, 0x00);
1839 else
1840 reg_w1(gspca_dev, 0x1006, 0x20);
1841
fe86ec75
JFM
1842 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1843 if (gspca_dev->usb_err < 0) {
91f5842b 1844 pr_err("Device initialization failed\n");
fe86ec75 1845 return gspca_dev->usb_err;
26e744b6
BJ
1846 }
1847
1848 switch (sd->sensor) {
1849 case SENSOR_OV9650:
fe86ec75
JFM
1850 ov9650_init_sensor(gspca_dev);
1851 if (gspca_dev->usb_err < 0)
1852 break;
91f5842b 1853 pr_info("OV9650 sensor detected\n");
26e744b6
BJ
1854 break;
1855 case SENSOR_OV9655:
fe86ec75
JFM
1856 ov9655_init_sensor(gspca_dev);
1857 if (gspca_dev->usb_err < 0)
1858 break;
91f5842b 1859 pr_info("OV9655 sensor detected\n");
26e744b6
BJ
1860 break;
1861 case SENSOR_SOI968:
fe86ec75
JFM
1862 soi968_init_sensor(gspca_dev);
1863 if (gspca_dev->usb_err < 0)
1864 break;
91f5842b 1865 pr_info("SOI968 sensor detected\n");
26e744b6
BJ
1866 break;
1867 case SENSOR_OV7660:
fe86ec75
JFM
1868 ov7660_init_sensor(gspca_dev);
1869 if (gspca_dev->usb_err < 0)
1870 break;
91f5842b 1871 pr_info("OV7660 sensor detected\n");
26e744b6
BJ
1872 break;
1873 case SENSOR_OV7670:
fe86ec75
JFM
1874 ov7670_init_sensor(gspca_dev);
1875 if (gspca_dev->usb_err < 0)
1876 break;
91f5842b 1877 pr_info("OV7670 sensor detected\n");
26e744b6
BJ
1878 break;
1879 case SENSOR_MT9VPRB:
fe86ec75
JFM
1880 mt9v_init_sensor(gspca_dev);
1881 if (gspca_dev->usb_err < 0)
1882 break;
ff38d58e 1883 pr_info("MT9VPRB sensor detected\n");
26e744b6
BJ
1884 break;
1885 case SENSOR_MT9M111:
fe86ec75
JFM
1886 mt9m111_init_sensor(gspca_dev);
1887 if (gspca_dev->usb_err < 0)
1888 break;
91f5842b 1889 pr_info("MT9M111 sensor detected\n");
26e744b6 1890 break;
e99ac54d 1891 case SENSOR_MT9M112:
fe86ec75
JFM
1892 mt9m112_init_sensor(gspca_dev);
1893 if (gspca_dev->usb_err < 0)
1894 break;
91f5842b 1895 pr_info("MT9M112 sensor detected\n");
e99ac54d 1896 break;
26e744b6 1897 case SENSOR_MT9M001:
fe86ec75
JFM
1898 mt9m001_init_sensor(gspca_dev);
1899 if (gspca_dev->usb_err < 0)
1900 break;
26e744b6
BJ
1901 break;
1902 case SENSOR_HV7131R:
fe86ec75
JFM
1903 hv7131r_init_sensor(gspca_dev);
1904 if (gspca_dev->usb_err < 0)
1905 break;
91f5842b 1906 pr_info("HV7131R sensor detected\n");
26e744b6
BJ
1907 break;
1908 default:
ff38d58e 1909 pr_err("Unsupported sensor\n");
fe86ec75 1910 gspca_dev->usb_err = -ENODEV;
26e744b6 1911 }
fe86ec75 1912 return gspca_dev->usb_err;
26e744b6
BJ
1913}
1914
1915static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1916{
1917 struct sd *sd = (struct sd *) gspca_dev;
1918 u8 value;
ff38d58e 1919
26e744b6 1920 switch (sd->sensor) {
e8b7acc1
BJ
1921 case SENSOR_SOI968:
1922 if (mode & MODE_SXGA) {
1923 i2c_w1(gspca_dev, 0x17, 0x1d);
1924 i2c_w1(gspca_dev, 0x18, 0xbd);
1925 i2c_w1(gspca_dev, 0x19, 0x01);
1926 i2c_w1(gspca_dev, 0x1a, 0x81);
1927 i2c_w1(gspca_dev, 0x12, 0x00);
1928 sd->hstart = 140;
1929 sd->vstart = 19;
1930 } else {
1931 i2c_w1(gspca_dev, 0x17, 0x13);
1932 i2c_w1(gspca_dev, 0x18, 0x63);
1933 i2c_w1(gspca_dev, 0x19, 0x01);
1934 i2c_w1(gspca_dev, 0x1a, 0x79);
1935 i2c_w1(gspca_dev, 0x12, 0x40);
1936 sd->hstart = 60;
1937 sd->vstart = 11;
1938 }
1939 break;
26e744b6
BJ
1940 case SENSOR_OV9650:
1941 if (mode & MODE_SXGA) {
1942 i2c_w1(gspca_dev, 0x17, 0x1b);
1943 i2c_w1(gspca_dev, 0x18, 0xbc);
1944 i2c_w1(gspca_dev, 0x19, 0x01);
1945 i2c_w1(gspca_dev, 0x1a, 0x82);
1946 i2c_r1(gspca_dev, 0x12, &value);
1947 i2c_w1(gspca_dev, 0x12, value & 0x07);
1948 } else {
1949 i2c_w1(gspca_dev, 0x17, 0x24);
1950 i2c_w1(gspca_dev, 0x18, 0xc5);
1951 i2c_w1(gspca_dev, 0x19, 0x00);
1952 i2c_w1(gspca_dev, 0x1a, 0x3c);
1953 i2c_r1(gspca_dev, 0x12, &value);
1954 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1955 }
1956 break;
e99ac54d 1957 case SENSOR_MT9M112:
4d708a5e
BJ
1958 case SENSOR_MT9M111:
1959 if (mode & MODE_SXGA) {
1960 i2c_w2(gspca_dev, 0xf0, 0x0002);
1961 i2c_w2(gspca_dev, 0xc8, 0x970b);
1962 i2c_w2(gspca_dev, 0xf0, 0x0000);
1963 } else {
1964 i2c_w2(gspca_dev, 0xf0, 0x0002);
1965 i2c_w2(gspca_dev, 0xc8, 0x8000);
1966 i2c_w2(gspca_dev, 0xf0, 0x0000);
1967 }
1968 break;
26e744b6
BJ
1969 }
1970}
1971
d80dd5d0
HG
1972static int sd_isoc_init(struct gspca_dev *gspca_dev)
1973{
1974 struct usb_interface *intf;
1975 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
1976
1977 /*
1978 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
1979 * than our regular bandwidth calculations reserve, so we force the
1980 * use of a specific altsetting when using the SN9C20X_I420 fmt.
1981 */
1982 if (!(flags & (MODE_RAW | MODE_JPEG))) {
1983 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
1984
1985 if (intf->num_altsetting != 9) {
1986 pr_warn("sn9c20x camera with unknown number of alt "
7135d884
HG
1987 "settings (%d), please report!\n",
1988 intf->num_altsetting);
d80dd5d0
HG
1989 gspca_dev->alt = intf->num_altsetting;
1990 return 0;
1991 }
1992
1993 switch (gspca_dev->width) {
1994 case 160: /* 160x120 */
1995 gspca_dev->alt = 2;
1996 break;
1997 case 320: /* 320x240 */
1998 gspca_dev->alt = 6;
1999 break;
2000 default: /* >= 640x480 */
2001 gspca_dev->alt = 9;
ff38d58e 2002 break;
d80dd5d0
HG
2003 }
2004 }
2005
2006 return 0;
2007}
2008
26e744b6 2009#define HW_WIN(mode, hstart, vstart) \
83955556 2010((const u8 []){hstart, 0, vstart, 0, \
26e744b6
BJ
2011(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2012(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2013
2014#define CLR_WIN(width, height) \
2015((const u8 [])\
2016{0, width >> 2, 0, height >> 1,\
2017((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2018
2019static int sd_start(struct gspca_dev *gspca_dev)
2020{
2021 struct sd *sd = (struct sd *) gspca_dev;
2022 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2023 int width = gspca_dev->width;
2024 int height = gspca_dev->height;
2025 u8 fmt, scale = 0;
2026
26e744b6
BJ
2027 jpeg_define(sd->jpeg_hdr, height, width,
2028 0x21);
63069da1 2029 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
26e744b6
BJ
2030
2031 if (mode & MODE_RAW)
2032 fmt = 0x2d;
2033 else if (mode & MODE_JPEG)
4c632e4e 2034 fmt = 0x24;
26e744b6 2035 else
86701c1d 2036 fmt = 0x2f; /* YUV 420 */
4c632e4e 2037 sd->fmt = fmt;
26e744b6 2038
86701c1d
MCC
2039 switch (mode & SCALE_MASK) {
2040 case SCALE_1280x1024:
26e744b6 2041 scale = 0xc0;
91f5842b 2042 pr_info("Set 1280x1024\n");
26e744b6 2043 break;
86701c1d 2044 case SCALE_640x480:
26e744b6 2045 scale = 0x80;
91f5842b 2046 pr_info("Set 640x480\n");
26e744b6 2047 break;
86701c1d 2048 case SCALE_320x240:
26e744b6 2049 scale = 0x90;
91f5842b 2050 pr_info("Set 320x240\n");
26e744b6 2051 break;
86701c1d 2052 case SCALE_160x120:
26e744b6 2053 scale = 0xa0;
91f5842b 2054 pr_info("Set 160x120\n");
26e744b6
BJ
2055 break;
2056 }
2057
2058 configure_sensor_output(gspca_dev, mode);
9a731a32
JFM
2059 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2060 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
26e744b6
BJ
2061 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2062 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2063 reg_w1(gspca_dev, 0x1189, scale);
2064 reg_w1(gspca_dev, 0x10e0, fmt);
2065
63069da1
HV
2066 set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
2067 v4l2_ctrl_g_ctrl(sd->contrast),
2068 v4l2_ctrl_g_ctrl(sd->saturation),
2069 v4l2_ctrl_g_ctrl(sd->hue));
2070 set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
2071 set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
2072 v4l2_ctrl_g_ctrl(sd->red));
2073 set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
2074 set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
2075 set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
2076 v4l2_ctrl_g_ctrl(sd->vflip));
26e744b6 2077
0c045eb7 2078 reg_w1(gspca_dev, 0x1007, 0x20);
ccbaba43 2079 reg_w1(gspca_dev, 0x1061, 0x03);
92dcffcf
JFM
2080
2081 /* if JPEG, prepare the compression quality update */
2082 if (mode & MODE_JPEG) {
2083 sd->pktsz = sd->npkt = 0;
2084 sd->nchg = 0;
2085 sd->work_thread =
2086 create_singlethread_workqueue(KBUILD_MODNAME);
2087 }
2088
fe86ec75 2089 return gspca_dev->usb_err;
26e744b6
BJ
2090}
2091
2092static void sd_stopN(struct gspca_dev *gspca_dev)
2093{
0c045eb7 2094 reg_w1(gspca_dev, 0x1007, 0x00);
ccbaba43 2095 reg_w1(gspca_dev, 0x1061, 0x01);
26e744b6
BJ
2096}
2097
92dcffcf
JFM
2098/* called on streamoff with alt==0 and on disconnect */
2099/* the usb_lock is held at entry - restore on exit */
2100static void sd_stop0(struct gspca_dev *gspca_dev)
2101{
2102 struct sd *sd = (struct sd *) gspca_dev;
2103
2104 if (sd->work_thread != NULL) {
2105 mutex_unlock(&gspca_dev->usb_lock);
2106 destroy_workqueue(sd->work_thread);
2107 mutex_lock(&gspca_dev->usb_lock);
2108 sd->work_thread = NULL;
2109 }
2110}
2111
e1430471 2112static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
26e744b6
BJ
2113{
2114 struct sd *sd = (struct sd *) gspca_dev;
63069da1
HV
2115 s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
2116 s32 max = sd->exposure->maximum - sd->exposure_step;
2117 s32 min = sd->exposure->minimum + sd->exposure_step;
e1430471 2118 s16 new_exp;
26e744b6
BJ
2119
2120 /*
2121 * some hardcoded values are present
2122 * like those for maximal/minimal exposure
2123 * and exposure steps
2124 */
2125 if (avg_lum < MIN_AVG_LUM) {
63069da1 2126 if (cur_exp > max)
26e744b6
BJ
2127 return;
2128
63069da1
HV
2129 new_exp = cur_exp + sd->exposure_step;
2130 if (new_exp > max)
2131 new_exp = max;
2132 if (new_exp < min)
2133 new_exp = min;
2134 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
26e744b6
BJ
2135
2136 sd->older_step = sd->old_step;
2137 sd->old_step = 1;
2138
2139 if (sd->old_step ^ sd->older_step)
2140 sd->exposure_step /= 2;
2141 else
2142 sd->exposure_step += 2;
2143 }
2144 if (avg_lum > MAX_AVG_LUM) {
63069da1 2145 if (cur_exp < min)
26e744b6 2146 return;
63069da1
HV
2147 new_exp = cur_exp - sd->exposure_step;
2148 if (new_exp > max)
2149 new_exp = max;
2150 if (new_exp < min)
2151 new_exp = min;
2152 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
26e744b6
BJ
2153 sd->older_step = sd->old_step;
2154 sd->old_step = 0;
2155
2156 if (sd->old_step ^ sd->older_step)
2157 sd->exposure_step /= 2;
2158 else
2159 sd->exposure_step += 2;
2160 }
2161}
2162
e1430471
BJ
2163static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2164{
2165 struct sd *sd = (struct sd *) gspca_dev;
63069da1 2166 s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
e1430471 2167
63069da1
HV
2168 if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
2169 v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
2170 if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
2171 v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
e1430471
BJ
2172}
2173
2174static void sd_dqcallback(struct gspca_dev *gspca_dev)
2175{
2176 struct sd *sd = (struct sd *) gspca_dev;
2177 int avg_lum;
2178
63069da1 2179 if (!v4l2_ctrl_g_ctrl(sd->autogain))
e1430471
BJ
2180 return;
2181
2182 avg_lum = atomic_read(&sd->avg_lum);
2183 if (sd->sensor == SENSOR_SOI968)
2184 do_autogain(gspca_dev, avg_lum);
2185 else
2186 do_autoexposure(gspca_dev, avg_lum);
2187}
2188
92dcffcf
JFM
2189/* JPEG quality update */
2190/* This function is executed from a work queue. */
2191static void qual_upd(struct work_struct *work)
2192{
2193 struct sd *sd = container_of(work, struct sd, work);
2194 struct gspca_dev *gspca_dev = &sd->gspca_dev;
63069da1 2195 s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
92dcffcf
JFM
2196
2197 mutex_lock(&gspca_dev->usb_lock);
63069da1
HV
2198 PDEBUG(D_STREAM, "qual_upd %d%%", qual);
2199 set_quality(gspca_dev, qual);
92dcffcf
JFM
2200 mutex_unlock(&gspca_dev->usb_lock);
2201}
2202
2856643e 2203#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
a39db27a
MCC
2204static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2205 u8 *data, /* interrupt packet */
2206 int len) /* interrupt packet length */
2207{
2208 struct sd *sd = (struct sd *) gspca_dev;
ff38d58e 2209
33ddc16f 2210 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
ff38d58e
JFM
2211 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2212 input_sync(gspca_dev->input_dev);
2213 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2214 input_sync(gspca_dev->input_dev);
2215 return 0;
a39db27a 2216 }
ff38d58e 2217 return -EINVAL;
a39db27a
MCC
2218}
2219#endif
2220
92dcffcf
JFM
2221/* check the JPEG compression */
2222static void transfer_check(struct gspca_dev *gspca_dev,
2223 u8 *data)
2224{
2225 struct sd *sd = (struct sd *) gspca_dev;
2226 int new_qual, r;
2227
2228 new_qual = 0;
2229
2230 /* if USB error, discard the frame and decrease the quality */
2231 if (data[6] & 0x08) { /* USB FIFO full */
2232 gspca_dev->last_packet_type = DISCARD_PACKET;
2233 new_qual = -5;
2234 } else {
2235
2236 /* else, compute the filling rate and a new JPEG quality */
2237 r = (sd->pktsz * 100) /
2238 (sd->npkt *
2239 gspca_dev->urb[0]->iso_frame_desc[0].length);
2240 if (r >= 85)
2241 new_qual = -3;
2242 else if (r < 75)
2243 new_qual = 2;
2244 }
2245 if (new_qual != 0) {
2246 sd->nchg += new_qual;
2247 if (sd->nchg < -6 || sd->nchg >= 12) {
63069da1
HV
2248 /* Note: we are in interrupt context, so we can't
2249 use v4l2_ctrl_g/s_ctrl here. Access the value
2250 directly instead. */
2251 s32 curqual = sd->jpegqual->cur.val;
92dcffcf 2252 sd->nchg = 0;
63069da1
HV
2253 new_qual += curqual;
2254 if (new_qual < sd->jpegqual->minimum)
2255 new_qual = sd->jpegqual->minimum;
2256 else if (new_qual > sd->jpegqual->maximum)
2257 new_qual = sd->jpegqual->maximum;
2258 if (new_qual != curqual) {
2259 sd->jpegqual->cur.val = new_qual;
92dcffcf
JFM
2260 queue_work(sd->work_thread, &sd->work);
2261 }
2262 }
2263 } else {
2264 sd->nchg = 0;
2265 }
2266 sd->pktsz = sd->npkt = 0;
2267}
2268
26e744b6 2269static void sd_pkt_scan(struct gspca_dev *gspca_dev,
26e744b6
BJ
2270 u8 *data, /* isoc packet */
2271 int len) /* iso packet length */
2272{
2273 struct sd *sd = (struct sd *) gspca_dev;
ff38d58e 2274 int avg_lum, is_jpeg;
dae1de64 2275 static const u8 frame_header[] =
26e744b6 2276 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
ff38d58e
JFM
2277
2278 is_jpeg = (sd->fmt & 0x03) == 0;
1f42df0d 2279 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
26e744b6
BJ
2280 avg_lum = ((data[35] >> 2) & 3) |
2281 (data[20] << 2) |
2282 (data[19] << 10);
2283 avg_lum += ((data[35] >> 4) & 3) |
2284 (data[22] << 2) |
2285 (data[21] << 10);
2286 avg_lum += ((data[35] >> 6) & 3) |
2287 (data[24] << 2) |
2288 (data[23] << 10);
2289 avg_lum += (data[36] & 3) |
2290 (data[26] << 2) |
2291 (data[25] << 10);
2292 avg_lum += ((data[36] >> 2) & 3) |
2293 (data[28] << 2) |
2294 (data[27] << 10);
2295 avg_lum += ((data[36] >> 4) & 3) |
2296 (data[30] << 2) |
2297 (data[29] << 10);
2298 avg_lum += ((data[36] >> 6) & 3) |
2299 (data[32] << 2) |
2300 (data[31] << 10);
2301 avg_lum += ((data[44] >> 4) & 3) |
2302 (data[34] << 2) |
2303 (data[33] << 10);
2304 avg_lum >>= 9;
2305 atomic_set(&sd->avg_lum, avg_lum);
92dcffcf 2306
ff38d58e 2307 if (is_jpeg)
92dcffcf
JFM
2308 transfer_check(gspca_dev, data);
2309
04d174e9 2310 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1f42df0d
JFM
2311 len -= 64;
2312 if (len == 0)
2313 return;
2314 data += 64;
26e744b6
BJ
2315 }
2316 if (gspca_dev->last_packet_type == LAST_PACKET) {
ff38d58e 2317 if (is_jpeg) {
76dd272b 2318 gspca_frame_add(gspca_dev, FIRST_PACKET,
26e744b6 2319 sd->jpeg_hdr, JPEG_HDR_SZ);
76dd272b 2320 gspca_frame_add(gspca_dev, INTER_PACKET,
26e744b6
BJ
2321 data, len);
2322 } else {
76dd272b 2323 gspca_frame_add(gspca_dev, FIRST_PACKET,
26e744b6
BJ
2324 data, len);
2325 }
2326 } else {
92dcffcf 2327 /* if JPEG, count the packets and their size */
ff38d58e 2328 if (is_jpeg) {
92dcffcf
JFM
2329 sd->npkt++;
2330 sd->pktsz += len;
2331 }
76dd272b 2332 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
26e744b6
BJ
2333 }
2334}
2335
2336/* sub-driver description */
2337static const struct sd_desc sd_desc = {
ff38d58e 2338 .name = KBUILD_MODNAME,
26e744b6
BJ
2339 .config = sd_config,
2340 .init = sd_init,
63069da1 2341 .init_controls = sd_init_controls,
d80dd5d0 2342 .isoc_init = sd_isoc_init,
26e744b6
BJ
2343 .start = sd_start,
2344 .stopN = sd_stopN,
92dcffcf 2345 .stop0 = sd_stop0,
26e744b6 2346 .pkt_scan = sd_pkt_scan,
2856643e 2347#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
a39db27a
MCC
2348 .int_pkt_scan = sd_int_pkt_scan,
2349#endif
e1430471 2350 .dq_callback = sd_dqcallback,
26e744b6
BJ
2351#ifdef CONFIG_VIDEO_ADV_DEBUG
2352 .set_register = sd_dbg_s_register,
2353 .get_register = sd_dbg_g_register,
2354#endif
2355 .get_chip_ident = sd_chip_ident,
2356};
2357
a39db27a 2358#define SN9C20X(sensor, i2c_addr, flags) \
0c045eb7 2359 .driver_info = ((flags & 0xff) << 16) \
26e744b6
BJ
2360 | (SENSOR_ ## sensor << 8) \
2361 | (i2c_addr)
2362
95c967c1 2363static const struct usb_device_id device_table[] = {
26e744b6
BJ
2364 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2365 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2366 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
e99ac54d 2367 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
33ddc16f
BJ
2368 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2369 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2370 (FLIP_DETECT | HAS_NO_BUTTON))},
26e744b6
BJ
2371 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2372 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2373 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2374 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
779b51f7 2375 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
26e744b6
BJ
2376 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2377 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2378 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2379 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
33ddc16f 2380 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
e99ac54d 2381 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
26e744b6
BJ
2382 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2383 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2384 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2385 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
114cfbdf 2386 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
b39e0cb9 2387 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
26e744b6
BJ
2388 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2389 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2390 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2391 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
e99ac54d
BJ
2392 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2393 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
26e744b6
BJ
2394 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2395 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2396 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2397 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
33ddc16f 2398 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
26e744b6
BJ
2399 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2400 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2401 {}
2402};
2403MODULE_DEVICE_TABLE(usb, device_table);
2404
2405/* -- device connect -- */
2406static int sd_probe(struct usb_interface *intf,
2407 const struct usb_device_id *id)
2408{
2409 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2410 THIS_MODULE);
2411}
2412
26e744b6 2413static struct usb_driver sd_driver = {
ff38d58e 2414 .name = KBUILD_MODNAME,
26e744b6
BJ
2415 .id_table = device_table,
2416 .probe = sd_probe,
a39db27a 2417 .disconnect = gspca_disconnect,
26e744b6
BJ
2418#ifdef CONFIG_PM
2419 .suspend = gspca_suspend,
2420 .resume = gspca_resume,
2421 .reset_resume = gspca_resume,
2422#endif
2423};
2424
ecb3b2b3 2425module_usb_driver(sd_driver);
This page took 0.383767 seconds and 5 git commands to generate.