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

source code of linux/drivers/media/usb/gspca/sn9c20x.c