xref: /linux/drivers/media/usb/gspca/spca508.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
1 /*
2  * SPCA508 chip based cameras subdriver
3  *
4  * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  */
16 
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 
19 #define MODULE_NAME "spca508"
20 
21 #include "gspca.h"
22 
23 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
24 MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
25 MODULE_LICENSE("GPL");
26 
27 /* specific webcam descriptor */
28 struct sd {
29 	struct gspca_dev gspca_dev;		/* !! must be the first item */
30 
31 	u8 subtype;
32 #define CreativeVista 0
33 #define HamaUSBSightcam 1
34 #define HamaUSBSightcam2 2
35 #define IntelEasyPCCamera 3
36 #define MicroInnovationIC200 4
37 #define ViewQuestVQ110 5
38 };
39 
40 static const struct v4l2_pix_format sif_mode[] = {
41 	{160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
42 		.bytesperline = 160,
43 		.sizeimage = 160 * 120 * 3 / 2,
44 		.colorspace = V4L2_COLORSPACE_SRGB,
45 		.priv = 3},
46 	{176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
47 		.bytesperline = 176,
48 		.sizeimage = 176 * 144 * 3 / 2,
49 		.colorspace = V4L2_COLORSPACE_SRGB,
50 		.priv = 2},
51 	{320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
52 		.bytesperline = 320,
53 		.sizeimage = 320 * 240 * 3 / 2,
54 		.colorspace = V4L2_COLORSPACE_SRGB,
55 		.priv = 1},
56 	{352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
57 		.bytesperline = 352,
58 		.sizeimage = 352 * 288 * 3 / 2,
59 		.colorspace = V4L2_COLORSPACE_SRGB,
60 		.priv = 0},
61 };
62 
63 /* Frame packet header offsets for the spca508 */
64 #define SPCA508_OFFSET_DATA 37
65 
66 /*
67  * Initialization data: this is the first set-up data written to the
68  * device (before the open data).
69  */
70 static const u16 spca508_init_data[][2] = {
71 	{0x0000, 0x870b},
72 
73 	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
74 	{0x0003, 0x8111},	/* Reset compression & memory */
75 	{0x0000, 0x8110},	/* Disable all outputs */
76 	/* READ {0x0000, 0x8114} -> 0000: 00  */
77 	{0x0000, 0x8114},	/* SW GPIO data */
78 	{0x0008, 0x8110},	/* Enable charge pump output */
79 	{0x0002, 0x8116},	/* 200 kHz pump clock */
80 	/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
81 	{0x0003, 0x8111},	/* Reset compression & memory */
82 	{0x0000, 0x8111},	/* Normal mode (not reset) */
83 	{0x0098, 0x8110},
84 		/* Enable charge pump output, sync.serial,external 2x clock */
85 	{0x000d, 0x8114},	/* SW GPIO data */
86 	{0x0002, 0x8116},	/* 200 kHz pump clock */
87 	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
88 /* --------------------------------------- */
89 	{0x000f, 0x8402},	/* memory bank */
90 	{0x0000, 0x8403},	/* ... address */
91 /* --------------------------------------- */
92 /* 0x88__ is Synchronous Serial Interface. */
93 /* TBD: This table could be expressed more compactly */
94 /* using spca508_write_i2c_vector(). */
95 /* TBD: Should see if the values in spca50x_i2c_data */
96 /* would work with the VQ110 instead of the values */
97 /* below. */
98 	{0x00c0, 0x8804},	/* SSI slave addr */
99 	{0x0008, 0x8802},	/* 375 Khz SSI clock */
100 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
101 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
102 	{0x0008, 0x8802},	/* 375 Khz SSI clock */
103 	{0x0012, 0x8801},	/* SSI reg addr */
104 	{0x0080, 0x8800},	/* SSI data to write */
105 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
106 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
107 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
108 	{0x0008, 0x8802},	/* 375 Khz SSI clock */
109 	{0x0012, 0x8801},	/* SSI reg addr */
110 	{0x0000, 0x8800},	/* SSI data to write */
111 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
112 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
113 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
114 	{0x0008, 0x8802},	/* 375 Khz SSI clock */
115 	{0x0011, 0x8801},	/* SSI reg addr */
116 	{0x0040, 0x8800},	/* SSI data to write */
117 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
118 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
119 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
120 	{0x0008, 0x8802},
121 	{0x0013, 0x8801},
122 	{0x0000, 0x8800},
123 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
124 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
125 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
126 	{0x0008, 0x8802},
127 	{0x0014, 0x8801},
128 	{0x0000, 0x8800},
129 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
130 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
131 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
132 	{0x0008, 0x8802},
133 	{0x0015, 0x8801},
134 	{0x0001, 0x8800},
135 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
136 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
137 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
138 	{0x0008, 0x8802},
139 	{0x0016, 0x8801},
140 	{0x0003, 0x8800},
141 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
142 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
143 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
144 	{0x0008, 0x8802},
145 	{0x0017, 0x8801},
146 	{0x0036, 0x8800},
147 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
148 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
149 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
150 	{0x0008, 0x8802},
151 	{0x0018, 0x8801},
152 	{0x00ec, 0x8800},
153 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
154 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
155 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
156 	{0x0008, 0x8802},
157 	{0x001a, 0x8801},
158 	{0x0094, 0x8800},
159 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
160 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
161 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
162 	{0x0008, 0x8802},
163 	{0x001b, 0x8801},
164 	{0x0000, 0x8800},
165 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
166 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
167 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
168 	{0x0008, 0x8802},
169 	{0x0027, 0x8801},
170 	{0x00a2, 0x8800},
171 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
172 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
173 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
174 	{0x0008, 0x8802},
175 	{0x0028, 0x8801},
176 	{0x0040, 0x8800},
177 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
178 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
179 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
180 	{0x0008, 0x8802},
181 	{0x002a, 0x8801},
182 	{0x0084, 0x8800},
183 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
184 	/* READ { 0x0001, 0x8803 } -> 0000: 00 */
185 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
186 	{0x0008, 0x8802},
187 	{0x002b, 0x8801},
188 	{0x00a8, 0x8800},
189 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
190 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
191 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
192 	{0x0008, 0x8802},
193 	{0x002c, 0x8801},
194 	{0x00fe, 0x8800},
195 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
196 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
197 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
198 	{0x0008, 0x8802},
199 	{0x002d, 0x8801},
200 	{0x0003, 0x8800},
201 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
202 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
203 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
204 	{0x0008, 0x8802},
205 	{0x0038, 0x8801},
206 	{0x0083, 0x8800},
207 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
208 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
209 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
210 	{0x0008, 0x8802},
211 	{0x0033, 0x8801},
212 	{0x0081, 0x8800},
213 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
214 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
215 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
216 	{0x0008, 0x8802},
217 	{0x0034, 0x8801},
218 	{0x004a, 0x8800},
219 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
220 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
221 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
222 	{0x0008, 0x8802},
223 	{0x0039, 0x8801},
224 	{0x0000, 0x8800},
225 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
226 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
227 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
228 	{0x0008, 0x8802},
229 	{0x0010, 0x8801},
230 	{0x00a8, 0x8800},
231 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
232 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
233 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
234 	{0x0008, 0x8802},
235 	{0x0006, 0x8801},
236 	{0x0058, 0x8800},
237 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
238 	/* READ { 0x0001, 0x8803 } -> 0000: 00 */
239 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
240 	{0x0008, 0x8802},
241 	{0x0000, 0x8801},
242 	{0x0004, 0x8800},
243 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
244 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
245 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
246 	{0x0008, 0x8802},
247 	{0x0040, 0x8801},
248 	{0x0080, 0x8800},
249 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
250 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
251 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
252 	{0x0008, 0x8802},
253 	{0x0041, 0x8801},
254 	{0x000c, 0x8800},
255 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
256 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
257 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
258 	{0x0008, 0x8802},
259 	{0x0042, 0x8801},
260 	{0x000c, 0x8800},
261 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
262 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
263 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
264 	{0x0008, 0x8802},
265 	{0x0043, 0x8801},
266 	{0x0028, 0x8800},
267 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
268 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
269 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
270 	{0x0008, 0x8802},
271 	{0x0044, 0x8801},
272 	{0x0080, 0x8800},
273 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
274 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
275 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
276 	{0x0008, 0x8802},
277 	{0x0045, 0x8801},
278 	{0x0020, 0x8800},
279 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
280 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
281 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
282 	{0x0008, 0x8802},
283 	{0x0046, 0x8801},
284 	{0x0020, 0x8800},
285 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
286 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
287 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
288 	{0x0008, 0x8802},
289 	{0x0047, 0x8801},
290 	{0x0080, 0x8800},
291 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
292 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
293 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
294 	{0x0008, 0x8802},
295 	{0x0048, 0x8801},
296 	{0x004c, 0x8800},
297 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
298 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
299 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
300 	{0x0008, 0x8802},
301 	{0x0049, 0x8801},
302 	{0x0084, 0x8800},
303 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
304 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
305 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
306 	{0x0008, 0x8802},
307 	{0x004a, 0x8801},
308 	{0x0084, 0x8800},
309 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
310 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
311 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
312 	{0x0008, 0x8802},
313 	{0x004b, 0x8801},
314 	{0x0084, 0x8800},
315 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
316 	/* --------------------------------------- */
317 	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
318 	{0x0000, 0x8701},	/* CKx1 clock delay adj */
319 	{0x0000, 0x8701},	/* CKx1 clock delay adj */
320 	{0x0001, 0x870c},	/* CKOx2 output */
321 	/* --------------------------------------- */
322 	{0x0080, 0x8600},	/* Line memory read counter (L) */
323 	{0x0001, 0x8606},	/* reserved */
324 	{0x0064, 0x8607},	/* Line memory read counter (H) 0x6480=25,728 */
325 	{0x002a, 0x8601},	/* CDSP sharp interpolation mode,
326 	 *			line sel for color sep, edge enhance enab */
327 	{0x0000, 0x8602},	/* optical black level for user settng = 0 */
328 	{0x0080, 0x8600},	/* Line memory read counter (L) */
329 	{0x000a, 0x8603},	/* optical black level calc mode:
330 				 * auto; optical black offset = 10 */
331 	{0x00df, 0x865b},	/* Horiz offset for valid pixels (L)=0xdf */
332 	{0x0012, 0x865c},	/* Vert offset for valid lines (L)=0x12 */
333 
334 /* The following two lines seem to be the "wrong" resolution. */
335 /* But perhaps these indicate the actual size of the sensor */
336 /* rather than the size of the current video mode. */
337 	{0x0058, 0x865d},	/* Horiz valid pixels (*4) (L) = 352 */
338 	{0x0048, 0x865e},	/* Vert valid lines (*4) (L) = 288 */
339 
340 	{0x0015, 0x8608},	/* A11 Coef ... */
341 	{0x0030, 0x8609},
342 	{0x00fb, 0x860a},
343 	{0x003e, 0x860b},
344 	{0x00ce, 0x860c},
345 	{0x00f4, 0x860d},
346 	{0x00eb, 0x860e},
347 	{0x00dc, 0x860f},
348 	{0x0039, 0x8610},
349 	{0x0001, 0x8611},	/* R offset for white balance ... */
350 	{0x0000, 0x8612},
351 	{0x0001, 0x8613},
352 	{0x0000, 0x8614},
353 	{0x005b, 0x8651},	/* R gain for white balance ... */
354 	{0x0040, 0x8652},
355 	{0x0060, 0x8653},
356 	{0x0040, 0x8654},
357 	{0x0000, 0x8655},
358 	{0x0001, 0x863f},	/* Fixed gamma correction enable, USB control,
359 				 * lum filter disable, lum noise clip disable */
360 	{0x00a1, 0x8656},	/* Window1 size 256x256, Windows2 size 64x64,
361 				 * gamma look-up disable,
362 				 * new edge enhancement enable */
363 	{0x0018, 0x8657},	/* Edge gain high thresh */
364 	{0x0020, 0x8658},	/* Edge gain low thresh */
365 	{0x000a, 0x8659},	/* Edge bandwidth high threshold */
366 	{0x0005, 0x865a},	/* Edge bandwidth low threshold */
367 	/* -------------------------------- */
368 	{0x0030, 0x8112},	/* Video drop enable, ISO streaming enable */
369 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
370 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
371 	{0xa908, 0x8802},
372 	{0x0034, 0x8801},	/* SSI reg addr */
373 	{0x00ca, 0x8800},
374 	/* SSI data to write */
375 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
376 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
377 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
378 	{0x1f08, 0x8802},
379 	{0x0006, 0x8801},
380 	{0x0080, 0x8800},
381 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
382 
383 /* ----- Read back coefs we wrote earlier. */
384 	/* READ { 0x0000, 0x8608 } -> 0000: 15  */
385 	/* READ { 0x0000, 0x8609 } -> 0000: 30  */
386 	/* READ { 0x0000, 0x860a } -> 0000: fb  */
387 	/* READ { 0x0000, 0x860b } -> 0000: 3e  */
388 	/* READ { 0x0000, 0x860c } -> 0000: ce  */
389 	/* READ { 0x0000, 0x860d } -> 0000: f4  */
390 	/* READ { 0x0000, 0x860e } -> 0000: eb  */
391 	/* READ { 0x0000, 0x860f } -> 0000: dc  */
392 	/* READ { 0x0000, 0x8610 } -> 0000: 39  */
393 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
394 	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
395 	{0xb008, 0x8802},
396 	{0x0006, 0x8801},
397 	{0x007d, 0x8800},
398 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
399 
400 
401 	/* This chunk is seemingly redundant with */
402 	/* earlier commands (A11 Coef...), but if I disable it, */
403 	/* the image appears too dark.  Maybe there was some kind of */
404 	/* reset since the earlier commands, so this is necessary again. */
405 	{0x0015, 0x8608},
406 	{0x0030, 0x8609},
407 	{0xfffb, 0x860a},
408 	{0x003e, 0x860b},
409 	{0xffce, 0x860c},
410 	{0xfff4, 0x860d},
411 	{0xffeb, 0x860e},
412 	{0xffdc, 0x860f},
413 	{0x0039, 0x8610},
414 	{0x0018, 0x8657},
415 
416 	{0x0000, 0x8508},	/* Disable compression. */
417 	/* Previous line was:
418 	{0x0021, 0x8508},	 * Enable compression. */
419 	{0x0032, 0x850b},	/* compression stuff */
420 	{0x0003, 0x8509},	/* compression stuff */
421 	{0x0011, 0x850a},	/* compression stuff */
422 	{0x0021, 0x850d},	/* compression stuff */
423 	{0x0010, 0x850c},	/* compression stuff */
424 	{0x0003, 0x8500},	/* *** Video mode: 160x120 */
425 	{0x0001, 0x8501},	/* Hardware-dominated snap control */
426 	{0x0061, 0x8656},	/* Window1 size 128x128, Windows2 size 128x128,
427 				 * gamma look-up disable,
428 				 * new edge enhancement enable */
429 	{0x0018, 0x8617},	/* Window1 start X (*2) */
430 	{0x0008, 0x8618},	/* Window1 start Y (*2) */
431 	{0x0061, 0x8656},	/* Window1 size 128x128, Windows2 size 128x128,
432 				 * gamma look-up disable,
433 				 * new edge enhancement enable */
434 	{0x0058, 0x8619},	/* Window2 start X (*2) */
435 	{0x0008, 0x861a},	/* Window2 start Y (*2) */
436 	{0x00ff, 0x8615},	/* High lum thresh for white balance */
437 	{0x0000, 0x8616},	/* Low lum thresh for white balance */
438 	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
439 	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
440 	/* READ { 0x0000, 0x8656 } -> 0000: 61  */
441 	{0x0028, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
442 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
443 	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
444 	{0x1f28, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
445 	{0x0010, 0x8801},	/* SSI reg addr */
446 	{0x003e, 0x8800},	/* SSI data to write */
447 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
448 	{0x0028, 0x8802},
449 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
450 	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
451 	{0x1f28, 0x8802},
452 	{0x0000, 0x8801},
453 	{0x001f, 0x8800},
454 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
455 	{0x0001, 0x8602},    /* optical black level for user settning = 1 */
456 
457 	/* Original: */
458 	{0x0023, 0x8700},	/* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
459 	{0x000f, 0x8602},    /* optical black level for user settning = 15 */
460 
461 	{0x0028, 0x8802},
462 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
463 	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
464 	{0x1f28, 0x8802},
465 	{0x0010, 0x8801},
466 	{0x007b, 0x8800},
467 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
468 	{0x002f, 0x8651},	/* R gain for white balance ... */
469 	{0x0080, 0x8653},
470 	/* READ { 0x0000, 0x8655 } -> 0000: 00  */
471 	{0x0000, 0x8655},
472 
473 	{0x0030, 0x8112},	/* Video drop enable, ISO streaming enable */
474 	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
475 	/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
476 	{}
477 };
478 
479 /*
480  * Initialization data for Intel EasyPC Camera CS110
481  */
482 static const u16 spca508cs110_init_data[][2] = {
483 	{0x0000, 0x870b},	/* Reset CTL3 */
484 	{0x0003, 0x8111},	/* Soft Reset compression, memory, TG & CDSP */
485 	{0x0000, 0x8111},	/* Normal operation on reset */
486 	{0x0090, 0x8110},
487 		 /* External Clock 2x & Synchronous Serial Interface Output */
488 	{0x0020, 0x8112},	/* Video Drop packet enable */
489 	{0x0000, 0x8114},	/* Software GPIO output data */
490 	{0x0001, 0x8114},
491 	{0x0001, 0x8114},
492 	{0x0001, 0x8114},
493 	{0x0003, 0x8114},
494 
495 	/* Initial sequence Synchronous Serial Interface */
496 	{0x000f, 0x8402},	/* Memory bank Address */
497 	{0x0000, 0x8403},	/* Memory bank Address */
498 	{0x00ba, 0x8804},	/* SSI Slave address */
499 	{0x0010, 0x8802},	/* 93.75kHz SSI Clock Two DataByte */
500 	{0x0010, 0x8802},	/* 93.75kHz SSI Clock two DataByte */
501 
502 	{0x0001, 0x8801},
503 	{0x000a, 0x8805},	/* a - NWG: Dunno what this is about */
504 	{0x0000, 0x8800},
505 	{0x0010, 0x8802},
506 
507 	{0x0002, 0x8801},
508 	{0x0000, 0x8805},
509 	{0x0000, 0x8800},
510 	{0x0010, 0x8802},
511 
512 	{0x0003, 0x8801},
513 	{0x0027, 0x8805},
514 	{0x0001, 0x8800},
515 	{0x0010, 0x8802},
516 
517 	{0x0004, 0x8801},
518 	{0x0065, 0x8805},
519 	{0x0001, 0x8800},
520 	{0x0010, 0x8802},
521 
522 	{0x0005, 0x8801},
523 	{0x0003, 0x8805},
524 	{0x0000, 0x8800},
525 	{0x0010, 0x8802},
526 
527 	{0x0006, 0x8801},
528 	{0x001c, 0x8805},
529 	{0x0000, 0x8800},
530 	{0x0010, 0x8802},
531 
532 	{0x0007, 0x8801},
533 	{0x002a, 0x8805},
534 	{0x0000, 0x8800},
535 	{0x0010, 0x8802},
536 
537 	{0x0002, 0x8704},	/* External input CKIx1 */
538 	{0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
539 	{0x009a, 0x8600},	/* Line memory Read Counter (L) */
540 	{0x0001, 0x865b},	/* 1 Horizontal Offset for Valid Pixel(L) */
541 	{0x0003, 0x865c},	/* 3 Vertical Offset for Valid Lines(L) */
542 	{0x0058, 0x865d},	/* 58 Horizontal Valid Pixel Window(L) */
543 
544 	{0x0006, 0x8660},	/* Nibble data + input order */
545 
546 	{0x000a, 0x8602},	/* Optical black level set to 0x0a */
547 	{0x0000, 0x8603},	/* Optical black level Offset */
548 
549 /*	{0x0000, 0x8611},	 * 0 R  Offset for white Balance */
550 /*	{0x0000, 0x8612},	 * 1 Gr Offset for white Balance */
551 /*	{0x0000, 0x8613},	 * 1f B  Offset for white Balance */
552 /*	{0x0000, 0x8614},	 * f0 Gb Offset for white Balance */
553 
554 	{0x0040, 0x8651},   /* 2b BLUE gain for white balance  good at all 60 */
555 	{0x0030, 0x8652},	/* 41 Gr Gain for white Balance (L) */
556 	{0x0035, 0x8653},	/* 26 RED gain for white balance */
557 	{0x0035, 0x8654},	/* 40Gb Gain for white Balance (L) */
558 	{0x0041, 0x863f},
559 	      /* Fixed Gamma correction enabled (makes colours look better) */
560 
561 	{0x0000, 0x8655},
562 		/* High bits for white balance*****brightness control*** */
563 	{}
564 };
565 
566 static const u16 spca508_sightcam_init_data[][2] = {
567 /* This line seems to setup the frame/canvas */
568 	{0x000f, 0x8402},
569 
570 /* These 6 lines are needed to startup the webcam */
571 	{0x0090, 0x8110},
572 	{0x0001, 0x8114},
573 	{0x0001, 0x8114},
574 	{0x0001, 0x8114},
575 	{0x0003, 0x8114},
576 	{0x0080, 0x8804},
577 
578 /* This part seems to make the pictures darker? (autobrightness?) */
579 	{0x0001, 0x8801},
580 	{0x0004, 0x8800},
581 	{0x0003, 0x8801},
582 	{0x00e0, 0x8800},
583 	{0x0004, 0x8801},
584 	{0x00b4, 0x8800},
585 	{0x0005, 0x8801},
586 	{0x0000, 0x8800},
587 
588 	{0x0006, 0x8801},
589 	{0x00e0, 0x8800},
590 	{0x0007, 0x8801},
591 	{0x000c, 0x8800},
592 
593 /* This section is just needed, it probably
594  * does something like the previous section,
595  * but the cam won't start if it's not included.
596  */
597 	{0x0014, 0x8801},
598 	{0x0008, 0x8800},
599 	{0x0015, 0x8801},
600 	{0x0067, 0x8800},
601 	{0x0016, 0x8801},
602 	{0x0000, 0x8800},
603 	{0x0017, 0x8801},
604 	{0x0020, 0x8800},
605 	{0x0018, 0x8801},
606 	{0x0044, 0x8800},
607 
608 /* Makes the picture darker - and the
609  * cam won't start if not included
610  */
611 	{0x001e, 0x8801},
612 	{0x00ea, 0x8800},
613 	{0x001f, 0x8801},
614 	{0x0001, 0x8800},
615 	{0x0003, 0x8801},
616 	{0x00e0, 0x8800},
617 
618 /* seems to place the colors ontop of each other #1 */
619 	{0x0006, 0x8704},
620 	{0x0001, 0x870c},
621 	{0x0016, 0x8600},
622 	{0x0002, 0x8606},
623 
624 /* if not included the pictures becomes _very_ dark */
625 	{0x0064, 0x8607},
626 	{0x003a, 0x8601},
627 	{0x0000, 0x8602},
628 
629 /* seems to place the colors ontop of each other #2 */
630 	{0x0016, 0x8600},
631 	{0x0018, 0x8617},
632 	{0x0008, 0x8618},
633 	{0x00a1, 0x8656},
634 
635 /* webcam won't start if not included */
636 	{0x0007, 0x865b},
637 	{0x0001, 0x865c},
638 	{0x0058, 0x865d},
639 	{0x0048, 0x865e},
640 
641 /* adjusts the colors */
642 	{0x0049, 0x8651},
643 	{0x0040, 0x8652},
644 	{0x004c, 0x8653},
645 	{0x0040, 0x8654},
646 	{}
647 };
648 
649 static const u16 spca508_sightcam2_init_data[][2] = {
650 	{0x0020, 0x8112},
651 
652 	{0x000f, 0x8402},
653 	{0x0000, 0x8403},
654 
655 	{0x0008, 0x8201},
656 	{0x0008, 0x8200},
657 	{0x0001, 0x8200},
658 	{0x0009, 0x8201},
659 	{0x0008, 0x8200},
660 	{0x0001, 0x8200},
661 	{0x000a, 0x8201},
662 	{0x0008, 0x8200},
663 	{0x0001, 0x8200},
664 	{0x000b, 0x8201},
665 	{0x0008, 0x8200},
666 	{0x0001, 0x8200},
667 	{0x000c, 0x8201},
668 	{0x0008, 0x8200},
669 	{0x0001, 0x8200},
670 	{0x000d, 0x8201},
671 	{0x0008, 0x8200},
672 	{0x0001, 0x8200},
673 	{0x000e, 0x8201},
674 	{0x0008, 0x8200},
675 	{0x0001, 0x8200},
676 	{0x0007, 0x8201},
677 	{0x0008, 0x8200},
678 	{0x0001, 0x8200},
679 	{0x000f, 0x8201},
680 	{0x0008, 0x8200},
681 	{0x0001, 0x8200},
682 
683 	{0x0018, 0x8660},
684 	{0x0010, 0x8201},
685 
686 	{0x0008, 0x8200},
687 	{0x0001, 0x8200},
688 	{0x0011, 0x8201},
689 	{0x0008, 0x8200},
690 	{0x0001, 0x8200},
691 
692 	{0x0000, 0x86b0},
693 	{0x0034, 0x86b1},
694 	{0x0000, 0x86b2},
695 	{0x0049, 0x86b3},
696 	{0x0000, 0x86b4},
697 	{0x0000, 0x86b4},
698 
699 	{0x0012, 0x8201},
700 	{0x0008, 0x8200},
701 	{0x0001, 0x8200},
702 	{0x0013, 0x8201},
703 	{0x0008, 0x8200},
704 	{0x0001, 0x8200},
705 
706 	{0x0001, 0x86b0},
707 	{0x00aa, 0x86b1},
708 	{0x0000, 0x86b2},
709 	{0x00e4, 0x86b3},
710 	{0x0000, 0x86b4},
711 	{0x0000, 0x86b4},
712 
713 	{0x0018, 0x8660},
714 
715 	{0x0090, 0x8110},
716 	{0x0001, 0x8114},
717 	{0x0001, 0x8114},
718 	{0x0001, 0x8114},
719 	{0x0003, 0x8114},
720 
721 	{0x0080, 0x8804},
722 	{0x0003, 0x8801},
723 	{0x0012, 0x8800},
724 	{0x0004, 0x8801},
725 	{0x0005, 0x8800},
726 	{0x0005, 0x8801},
727 	{0x0000, 0x8800},
728 	{0x0006, 0x8801},
729 	{0x0000, 0x8800},
730 	{0x0007, 0x8801},
731 	{0x0000, 0x8800},
732 	{0x0008, 0x8801},
733 	{0x0005, 0x8800},
734 	{0x000a, 0x8700},
735 	{0x000e, 0x8801},
736 	{0x0004, 0x8800},
737 	{0x0005, 0x8801},
738 	{0x0047, 0x8800},
739 	{0x0006, 0x8801},
740 	{0x0000, 0x8800},
741 	{0x0007, 0x8801},
742 	{0x00c0, 0x8800},
743 	{0x0008, 0x8801},
744 	{0x0003, 0x8800},
745 	{0x0013, 0x8801},
746 	{0x0001, 0x8800},
747 	{0x0009, 0x8801},
748 	{0x0000, 0x8800},
749 	{0x000a, 0x8801},
750 	{0x0000, 0x8800},
751 	{0x000b, 0x8801},
752 	{0x0000, 0x8800},
753 	{0x000c, 0x8801},
754 	{0x0000, 0x8800},
755 	{0x000e, 0x8801},
756 	{0x0004, 0x8800},
757 	{0x000f, 0x8801},
758 	{0x0000, 0x8800},
759 	{0x0010, 0x8801},
760 	{0x0006, 0x8800},
761 	{0x0011, 0x8801},
762 	{0x0006, 0x8800},
763 	{0x0012, 0x8801},
764 	{0x0000, 0x8800},
765 	{0x0013, 0x8801},
766 	{0x0001, 0x8800},
767 
768 	{0x000a, 0x8700},
769 	{0x0000, 0x8702},
770 	{0x0000, 0x8703},
771 	{0x00c2, 0x8704},
772 	{0x0001, 0x870c},
773 
774 	{0x0044, 0x8600},
775 	{0x0002, 0x8606},
776 	{0x0064, 0x8607},
777 	{0x003a, 0x8601},
778 	{0x0008, 0x8602},
779 	{0x0044, 0x8600},
780 	{0x0018, 0x8617},
781 	{0x0008, 0x8618},
782 	{0x00a1, 0x8656},
783 	{0x0004, 0x865b},
784 	{0x0002, 0x865c},
785 	{0x0058, 0x865d},
786 	{0x0048, 0x865e},
787 	{0x0012, 0x8608},
788 	{0x002c, 0x8609},
789 	{0x0002, 0x860a},
790 	{0x002c, 0x860b},
791 	{0x00db, 0x860c},
792 	{0x00f9, 0x860d},
793 	{0x00f1, 0x860e},
794 	{0x00e3, 0x860f},
795 	{0x002c, 0x8610},
796 	{0x006c, 0x8651},
797 	{0x0041, 0x8652},
798 	{0x0059, 0x8653},
799 	{0x0040, 0x8654},
800 	{0x00fa, 0x8611},
801 	{0x00ff, 0x8612},
802 	{0x00f8, 0x8613},
803 	{0x0000, 0x8614},
804 	{0x0001, 0x863f},
805 	{0x0000, 0x8640},
806 	{0x0026, 0x8641},
807 	{0x0045, 0x8642},
808 	{0x0060, 0x8643},
809 	{0x0075, 0x8644},
810 	{0x0088, 0x8645},
811 	{0x009b, 0x8646},
812 	{0x00b0, 0x8647},
813 	{0x00c5, 0x8648},
814 	{0x00d2, 0x8649},
815 	{0x00dc, 0x864a},
816 	{0x00e5, 0x864b},
817 	{0x00eb, 0x864c},
818 	{0x00f0, 0x864d},
819 	{0x00f6, 0x864e},
820 	{0x00fa, 0x864f},
821 	{0x00ff, 0x8650},
822 	{0x0060, 0x8657},
823 	{0x0010, 0x8658},
824 	{0x0018, 0x8659},
825 	{0x0005, 0x865a},
826 	{0x0018, 0x8660},
827 	{0x0003, 0x8509},
828 	{0x0011, 0x850a},
829 	{0x0032, 0x850b},
830 	{0x0010, 0x850c},
831 	{0x0021, 0x850d},
832 	{0x0001, 0x8500},
833 	{0x0000, 0x8508},
834 	{0x0012, 0x8608},
835 	{0x002c, 0x8609},
836 	{0x0002, 0x860a},
837 	{0x0039, 0x860b},
838 	{0x00d0, 0x860c},
839 	{0x00f7, 0x860d},
840 	{0x00ed, 0x860e},
841 	{0x00db, 0x860f},
842 	{0x0039, 0x8610},
843 	{0x0012, 0x8657},
844 	{0x000c, 0x8619},
845 	{0x0004, 0x861a},
846 	{0x00a1, 0x8656},
847 	{0x00c8, 0x8615},
848 	{0x0032, 0x8616},
849 
850 	{0x0030, 0x8112},
851 	{0x0020, 0x8112},
852 	{0x0020, 0x8112},
853 	{0x000f, 0x8402},
854 	{0x0000, 0x8403},
855 
856 	{0x0090, 0x8110},
857 	{0x0001, 0x8114},
858 	{0x0001, 0x8114},
859 	{0x0001, 0x8114},
860 	{0x0003, 0x8114},
861 	{0x0080, 0x8804},
862 
863 	{0x0003, 0x8801},
864 	{0x0012, 0x8800},
865 	{0x0004, 0x8801},
866 	{0x0005, 0x8800},
867 	{0x0005, 0x8801},
868 	{0x0047, 0x8800},
869 	{0x0006, 0x8801},
870 	{0x0000, 0x8800},
871 	{0x0007, 0x8801},
872 	{0x00c0, 0x8800},
873 	{0x0008, 0x8801},
874 	{0x0003, 0x8800},
875 	{0x000a, 0x8700},
876 	{0x000e, 0x8801},
877 	{0x0004, 0x8800},
878 	{0x0005, 0x8801},
879 	{0x0047, 0x8800},
880 	{0x0006, 0x8801},
881 	{0x0000, 0x8800},
882 	{0x0007, 0x8801},
883 	{0x00c0, 0x8800},
884 	{0x0008, 0x8801},
885 	{0x0003, 0x8800},
886 	{0x0013, 0x8801},
887 	{0x0001, 0x8800},
888 	{0x0009, 0x8801},
889 	{0x0000, 0x8800},
890 	{0x000a, 0x8801},
891 	{0x0000, 0x8800},
892 	{0x000b, 0x8801},
893 	{0x0000, 0x8800},
894 	{0x000c, 0x8801},
895 	{0x0000, 0x8800},
896 	{0x000e, 0x8801},
897 	{0x0004, 0x8800},
898 	{0x000f, 0x8801},
899 	{0x0000, 0x8800},
900 	{0x0010, 0x8801},
901 	{0x0006, 0x8800},
902 	{0x0011, 0x8801},
903 	{0x0006, 0x8800},
904 	{0x0012, 0x8801},
905 	{0x0000, 0x8800},
906 	{0x0013, 0x8801},
907 	{0x0001, 0x8800},
908 	{0x000a, 0x8700},
909 	{0x0000, 0x8702},
910 	{0x0000, 0x8703},
911 	{0x00c2, 0x8704},
912 	{0x0001, 0x870c},
913 	{0x0044, 0x8600},
914 	{0x0002, 0x8606},
915 	{0x0064, 0x8607},
916 	{0x003a, 0x8601},
917 	{0x0008, 0x8602},
918 	{0x0044, 0x8600},
919 	{0x0018, 0x8617},
920 	{0x0008, 0x8618},
921 	{0x00a1, 0x8656},
922 	{0x0004, 0x865b},
923 	{0x0002, 0x865c},
924 	{0x0058, 0x865d},
925 	{0x0048, 0x865e},
926 	{0x0012, 0x8608},
927 	{0x002c, 0x8609},
928 	{0x0002, 0x860a},
929 	{0x002c, 0x860b},
930 	{0x00db, 0x860c},
931 	{0x00f9, 0x860d},
932 	{0x00f1, 0x860e},
933 	{0x00e3, 0x860f},
934 	{0x002c, 0x8610},
935 	{0x006c, 0x8651},
936 	{0x0041, 0x8652},
937 	{0x0059, 0x8653},
938 	{0x0040, 0x8654},
939 	{0x00fa, 0x8611},
940 	{0x00ff, 0x8612},
941 	{0x00f8, 0x8613},
942 	{0x0000, 0x8614},
943 	{0x0001, 0x863f},
944 	{0x0000, 0x8640},
945 	{0x0026, 0x8641},
946 	{0x0045, 0x8642},
947 	{0x0060, 0x8643},
948 	{0x0075, 0x8644},
949 	{0x0088, 0x8645},
950 	{0x009b, 0x8646},
951 	{0x00b0, 0x8647},
952 	{0x00c5, 0x8648},
953 	{0x00d2, 0x8649},
954 	{0x00dc, 0x864a},
955 	{0x00e5, 0x864b},
956 	{0x00eb, 0x864c},
957 	{0x00f0, 0x864d},
958 	{0x00f6, 0x864e},
959 	{0x00fa, 0x864f},
960 	{0x00ff, 0x8650},
961 	{0x0060, 0x8657},
962 	{0x0010, 0x8658},
963 	{0x0018, 0x8659},
964 	{0x0005, 0x865a},
965 	{0x0018, 0x8660},
966 	{0x0003, 0x8509},
967 	{0x0011, 0x850a},
968 	{0x0032, 0x850b},
969 	{0x0010, 0x850c},
970 	{0x0021, 0x850d},
971 	{0x0001, 0x8500},
972 	{0x0000, 0x8508},
973 
974 	{0x0012, 0x8608},
975 	{0x002c, 0x8609},
976 	{0x0002, 0x860a},
977 	{0x0039, 0x860b},
978 	{0x00d0, 0x860c},
979 	{0x00f7, 0x860d},
980 	{0x00ed, 0x860e},
981 	{0x00db, 0x860f},
982 	{0x0039, 0x8610},
983 	{0x0012, 0x8657},
984 	{0x0064, 0x8619},
985 
986 /* This line starts it all, it is not needed here */
987 /* since it has been build into the driver */
988 /* jfm: don't start now */
989 /*	{0x0030, 0x8112}, */
990 	{}
991 };
992 
993 /*
994  * Initialization data for Creative Webcam Vista
995  */
996 static const u16 spca508_vista_init_data[][2] = {
997 	{0x0008, 0x8200},	/* Clear register */
998 	{0x0000, 0x870b},	/* Reset CTL3 */
999 	{0x0020, 0x8112},	/* Video Drop packet enable */
1000 	{0x0003, 0x8111},	/* Soft Reset compression, memory, TG & CDSP */
1001 	{0x0000, 0x8110},	/* Disable everything */
1002 	{0x0000, 0x8114},	/* Software GPIO output data */
1003 	{0x0000, 0x8114},
1004 
1005 	{0x0003, 0x8111},
1006 	{0x0000, 0x8111},
1007 	{0x0090, 0x8110},    /* Enable: SSI output, External 2X clock output */
1008 	{0x0020, 0x8112},
1009 	{0x0000, 0x8114},
1010 	{0x0001, 0x8114},
1011 	{0x0001, 0x8114},
1012 	{0x0001, 0x8114},
1013 	{0x0003, 0x8114},
1014 
1015 	{0x000f, 0x8402},	/* Memory bank Address */
1016 	{0x0000, 0x8403},	/* Memory bank Address */
1017 	{0x00ba, 0x8804},	/* SSI Slave address */
1018 	{0x0010, 0x8802},	/* 93.75kHz SSI Clock Two DataByte */
1019 
1020 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1021 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1022 	{0x0010, 0x8802},	/* Will write 2 bytes (DATA1+DATA2) */
1023 	{0x0020, 0x8801},	/* Register address for SSI read/write */
1024 	{0x0044, 0x8805},	/* DATA2 */
1025 	{0x0004, 0x8800},	/* DATA1 -> write triggered */
1026 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1027 
1028 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1029 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1030 	{0x0010, 0x8802},
1031 	{0x0009, 0x8801},
1032 	{0x0042, 0x8805},
1033 	{0x0001, 0x8800},
1034 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1035 
1036 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1037 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1038 	{0x0010, 0x8802},
1039 	{0x003c, 0x8801},
1040 	{0x0001, 0x8805},
1041 	{0x0000, 0x8800},
1042 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1043 
1044 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1045 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1046 	{0x0010, 0x8802},
1047 	{0x0001, 0x8801},
1048 	{0x000a, 0x8805},
1049 	{0x0000, 0x8800},
1050 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1051 
1052 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1053 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1054 	{0x0010, 0x8802},
1055 	{0x0002, 0x8801},
1056 	{0x0000, 0x8805},
1057 	{0x0000, 0x8800},
1058 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1059 
1060 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1061 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1062 	{0x0010, 0x8802},
1063 	{0x0003, 0x8801},
1064 	{0x0027, 0x8805},
1065 	{0x0001, 0x8800},
1066 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1067 
1068 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1069 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1070 	{0x0010, 0x8802},
1071 	{0x0004, 0x8801},
1072 	{0x0065, 0x8805},
1073 	{0x0001, 0x8800},
1074 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1075 
1076 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1077 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1078 	{0x0010, 0x8802},
1079 	{0x0005, 0x8801},
1080 	{0x0003, 0x8805},
1081 	{0x0000, 0x8800},
1082 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1083 
1084 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1085 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1086 	{0x0010, 0x8802},
1087 	{0x0006, 0x8801},
1088 	{0x001c, 0x8805},
1089 	{0x0000, 0x8800},
1090 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1091 
1092 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1093 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1094 	{0x0010, 0x8802},
1095 	{0x0007, 0x8801},
1096 	{0x002a, 0x8805},
1097 	{0x0000, 0x8800},
1098 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1099 
1100 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1101 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1102 	{0x0010, 0x8802},
1103 	{0x000e, 0x8801},
1104 	{0x0000, 0x8805},
1105 	{0x0000, 0x8800},
1106 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1107 
1108 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1109 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1110 	{0x0010, 0x8802},
1111 	{0x0028, 0x8801},
1112 	{0x002e, 0x8805},
1113 	{0x0000, 0x8800},
1114 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1115 
1116 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1117 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1118 	{0x0010, 0x8802},
1119 	{0x0039, 0x8801},
1120 	{0x0013, 0x8805},
1121 	{0x0000, 0x8800},
1122 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1123 
1124 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1125 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1126 	{0x0010, 0x8802},
1127 	{0x003b, 0x8801},
1128 	{0x000c, 0x8805},
1129 	{0x0000, 0x8800},
1130 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1131 
1132 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1133 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1134 	{0x0010, 0x8802},
1135 	{0x0035, 0x8801},
1136 	{0x0028, 0x8805},
1137 	{0x0000, 0x8800},
1138 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1139 
1140 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1141 	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
1142 	{0x0010, 0x8802},
1143 	{0x0009, 0x8801},
1144 	{0x0042, 0x8805},
1145 	{0x0001, 0x8800},
1146 	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
1147 
1148 	{0x0050, 0x8703},
1149 	{0x0002, 0x8704},	/* External input CKIx1 */
1150 	{0x0001, 0x870c},	/* Select CKOx2 output */
1151 	{0x009a, 0x8600},	/* Line memory Read Counter (L) */
1152 	{0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
1153 	{0x0023, 0x8601},
1154 	{0x0010, 0x8602},
1155 	{0x000a, 0x8603},
1156 	{0x009a, 0x8600},
1157 	{0x0001, 0x865b},	/* 1 Horizontal Offset for Valid Pixel(L) */
1158 	{0x0003, 0x865c},	/* Vertical offset for valid lines (L) */
1159 	{0x0058, 0x865d},	/* Horizontal valid pixels window (L) */
1160 	{0x0048, 0x865e},	/* Vertical valid lines window (L) */
1161 	{0x0000, 0x865f},
1162 
1163 	{0x0006, 0x8660},
1164 		    /* Enable nibble data input, select nibble input order */
1165 
1166 	{0x0013, 0x8608},	/* A11 Coeficients for color correction */
1167 	{0x0028, 0x8609},
1168 		    /* Note: these values are confirmed at the end of array */
1169 	{0x0005, 0x860a},	/* ... */
1170 	{0x0025, 0x860b},
1171 	{0x00e1, 0x860c},
1172 	{0x00fa, 0x860d},
1173 	{0x00f4, 0x860e},
1174 	{0x00e8, 0x860f},
1175 	{0x0025, 0x8610},	/* A33 Coef. */
1176 	{0x00fc, 0x8611},	/* White balance offset: R */
1177 	{0x0001, 0x8612},	/* White balance offset: Gr */
1178 	{0x00fe, 0x8613},	/* White balance offset: B */
1179 	{0x0000, 0x8614},	/* White balance offset: Gb */
1180 
1181 	{0x0064, 0x8651},	/* R gain for white balance (L) */
1182 	{0x0040, 0x8652},	/* Gr gain for white balance (L) */
1183 	{0x0066, 0x8653},	/* B gain for white balance (L) */
1184 	{0x0040, 0x8654},	/* Gb gain for white balance (L) */
1185 	{0x0001, 0x863f},	/* Enable fixed gamma correction */
1186 
1187 	{0x00a1, 0x8656},	/* Size - Window1: 256x256, Window2: 128x128,
1188 				 * UV division: UV no change,
1189 				 * Enable New edge enhancement */
1190 	{0x0018, 0x8657},	/* Edge gain high threshold */
1191 	{0x0020, 0x8658},	/* Edge gain low threshold */
1192 	{0x000a, 0x8659},	/* Edge bandwidth high threshold */
1193 	{0x0005, 0x865a},	/* Edge bandwidth low threshold */
1194 	{0x0064, 0x8607},	/* UV filter enable */
1195 
1196 	{0x0016, 0x8660},
1197 	{0x0000, 0x86b0},	/* Bad pixels compensation address */
1198 	{0x00dc, 0x86b1},	/* X coord for bad pixels compensation (L) */
1199 	{0x0000, 0x86b2},
1200 	{0x0009, 0x86b3},	/* Y coord for bad pixels compensation (L) */
1201 	{0x0000, 0x86b4},
1202 
1203 	{0x0001, 0x86b0},
1204 	{0x00f5, 0x86b1},
1205 	{0x0000, 0x86b2},
1206 	{0x00c6, 0x86b3},
1207 	{0x0000, 0x86b4},
1208 
1209 	{0x0002, 0x86b0},
1210 	{0x001c, 0x86b1},
1211 	{0x0001, 0x86b2},
1212 	{0x00d7, 0x86b3},
1213 	{0x0000, 0x86b4},
1214 
1215 	{0x0003, 0x86b0},
1216 	{0x001c, 0x86b1},
1217 	{0x0001, 0x86b2},
1218 	{0x00d8, 0x86b3},
1219 	{0x0000, 0x86b4},
1220 
1221 	{0x0004, 0x86b0},
1222 	{0x001d, 0x86b1},
1223 	{0x0001, 0x86b2},
1224 	{0x00d8, 0x86b3},
1225 	{0x0000, 0x86b4},
1226 	{0x001e, 0x8660},
1227 
1228 	/* READ { 0x0000, 0x8608 } -> 0000: 13  */
1229 	/* READ { 0x0000, 0x8609 } -> 0000: 28  */
1230 	/* READ { 0x0000, 0x8610 } -> 0000: 05  */
1231 	/* READ { 0x0000, 0x8611 } -> 0000: 25  */
1232 	/* READ { 0x0000, 0x8612 } -> 0000: e1  */
1233 	/* READ { 0x0000, 0x8613 } -> 0000: fa  */
1234 	/* READ { 0x0000, 0x8614 } -> 0000: f4  */
1235 	/* READ { 0x0000, 0x8615 } -> 0000: e8  */
1236 	/* READ { 0x0000, 0x8616 } -> 0000: 25  */
1237 	{}
1238 };
1239 
1240 static int reg_write(struct gspca_dev *gspca_dev, u16 index, u16 value)
1241 {
1242 	int ret;
1243 	struct usb_device *dev = gspca_dev->dev;
1244 
1245 	ret = usb_control_msg(dev,
1246 			usb_sndctrlpipe(dev, 0),
1247 			0,		/* request */
1248 			USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1249 			value, index, NULL, 0, 500);
1250 	PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1251 		index, value);
1252 	if (ret < 0)
1253 		pr_err("reg write: error %d\n", ret);
1254 	return ret;
1255 }
1256 
1257 /* read 1 byte */
1258 /* returns: negative is error, pos or zero is data */
1259 static int reg_read(struct gspca_dev *gspca_dev,
1260 			u16 index)	/* wIndex */
1261 {
1262 	int ret;
1263 
1264 	ret = usb_control_msg(gspca_dev->dev,
1265 			usb_rcvctrlpipe(gspca_dev->dev, 0),
1266 			0,			/* register */
1267 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1268 			0,		/* value */
1269 			index,
1270 			gspca_dev->usb_buf, 1,
1271 			500);			/* timeout */
1272 	PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1273 		index, gspca_dev->usb_buf[0]);
1274 	if (ret < 0) {
1275 		pr_err("reg_read err %d\n", ret);
1276 		return ret;
1277 	}
1278 	return gspca_dev->usb_buf[0];
1279 }
1280 
1281 /* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
1282 static int ssi_w(struct gspca_dev *gspca_dev,
1283 		u16 reg, u16 val)
1284 {
1285 	int ret, retry;
1286 
1287 	ret = reg_write(gspca_dev, 0x8802, reg >> 8);
1288 	if (ret < 0)
1289 		goto out;
1290 	ret = reg_write(gspca_dev, 0x8801, reg & 0x00ff);
1291 	if (ret < 0)
1292 		goto out;
1293 	if ((reg & 0xff00) == 0x1000) {		/* if 2 bytes */
1294 		ret = reg_write(gspca_dev, 0x8805, val & 0x00ff);
1295 		if (ret < 0)
1296 			goto out;
1297 		val >>= 8;
1298 	}
1299 	ret = reg_write(gspca_dev, 0x8800, val);
1300 	if (ret < 0)
1301 		goto out;
1302 
1303 	/* poll until not busy */
1304 	retry = 10;
1305 	for (;;) {
1306 		ret = reg_read(gspca_dev, 0x8803);
1307 		if (ret < 0)
1308 			break;
1309 		if (gspca_dev->usb_buf[0] == 0)
1310 			break;
1311 		if (--retry <= 0) {
1312 			PERR("ssi_w busy %02x", gspca_dev->usb_buf[0]);
1313 			ret = -1;
1314 			break;
1315 		}
1316 		msleep(8);
1317 	}
1318 
1319 out:
1320 	return ret;
1321 }
1322 
1323 static int write_vector(struct gspca_dev *gspca_dev,
1324 			const u16 (*data)[2])
1325 {
1326 	int ret = 0;
1327 
1328 	while ((*data)[1] != 0) {
1329 		if ((*data)[1] & 0x8000) {
1330 			if ((*data)[1] == 0xdd00)	/* delay */
1331 				msleep((*data)[0]);
1332 			else
1333 				ret = reg_write(gspca_dev, (*data)[1],
1334 								(*data)[0]);
1335 		} else {
1336 			ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
1337 		}
1338 		if (ret < 0)
1339 			break;
1340 		data++;
1341 	}
1342 	return ret;
1343 }
1344 
1345 /* this function is called at probe time */
1346 static int sd_config(struct gspca_dev *gspca_dev,
1347 			const struct usb_device_id *id)
1348 {
1349 	struct sd *sd = (struct sd *) gspca_dev;
1350 	struct cam *cam;
1351 	const u16 (*init_data)[2];
1352 	static const u16 (*(init_data_tb[]))[2] = {
1353 		spca508_vista_init_data,	/* CreativeVista 0 */
1354 		spca508_sightcam_init_data,	/* HamaUSBSightcam 1 */
1355 		spca508_sightcam2_init_data,	/* HamaUSBSightcam2 2 */
1356 		spca508cs110_init_data,		/* IntelEasyPCCamera 3 */
1357 		spca508cs110_init_data,		/* MicroInnovationIC200 4 */
1358 		spca508_init_data,		/* ViewQuestVQ110 5 */
1359 	};
1360 	int data1, data2;
1361 
1362 	/* Read from global register the USB product and vendor IDs, just to
1363 	 * prove that we can communicate with the device.  This works, which
1364 	 * confirms at we are communicating properly and that the device
1365 	 * is a 508. */
1366 	data1 = reg_read(gspca_dev, 0x8104);
1367 	data2 = reg_read(gspca_dev, 0x8105);
1368 	PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1369 
1370 	data1 = reg_read(gspca_dev, 0x8106);
1371 	data2 = reg_read(gspca_dev, 0x8107);
1372 	PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1373 
1374 	data1 = reg_read(gspca_dev, 0x8621);
1375 	PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1376 
1377 	cam = &gspca_dev->cam;
1378 	cam->cam_mode = sif_mode;
1379 	cam->nmodes = ARRAY_SIZE(sif_mode);
1380 
1381 	sd->subtype = id->driver_info;
1382 
1383 	init_data = init_data_tb[sd->subtype];
1384 	return write_vector(gspca_dev, init_data);
1385 }
1386 
1387 /* this function is called at probe and resume time */
1388 static int sd_init(struct gspca_dev *gspca_dev)
1389 {
1390 	return 0;
1391 }
1392 
1393 static int sd_start(struct gspca_dev *gspca_dev)
1394 {
1395 	int mode;
1396 
1397 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1398 	reg_write(gspca_dev, 0x8500, mode);
1399 	switch (mode) {
1400 	case 0:
1401 	case 1:
1402 		reg_write(gspca_dev, 0x8700, 0x28); /* clock */
1403 		break;
1404 	default:
1405 /*	case 2: */
1406 /*	case 3: */
1407 		reg_write(gspca_dev, 0x8700, 0x23); /* clock */
1408 		break;
1409 	}
1410 	reg_write(gspca_dev, 0x8112, 0x10 | 0x20);
1411 	return 0;
1412 }
1413 
1414 static void sd_stopN(struct gspca_dev *gspca_dev)
1415 {
1416 	/* Video ISO disable, Video Drop Packet enable: */
1417 	reg_write(gspca_dev, 0x8112, 0x20);
1418 }
1419 
1420 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1421 			u8 *data,			/* isoc packet */
1422 			int len)			/* iso packet length */
1423 {
1424 	switch (data[0]) {
1425 	case 0:				/* start of frame */
1426 		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1427 		data += SPCA508_OFFSET_DATA;
1428 		len -= SPCA508_OFFSET_DATA;
1429 		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1430 		break;
1431 	case 0xff:			/* drop */
1432 		break;
1433 	default:
1434 		data += 1;
1435 		len -= 1;
1436 		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1437 		break;
1438 	}
1439 }
1440 
1441 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
1442 {
1443 	/* MX seem contrast */
1444 	reg_write(gspca_dev, 0x8651, brightness);
1445 	reg_write(gspca_dev, 0x8652, brightness);
1446 	reg_write(gspca_dev, 0x8653, brightness);
1447 	reg_write(gspca_dev, 0x8654, brightness);
1448 }
1449 
1450 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1451 {
1452 	struct gspca_dev *gspca_dev =
1453 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1454 
1455 	gspca_dev->usb_err = 0;
1456 
1457 	if (!gspca_dev->streaming)
1458 		return 0;
1459 
1460 	switch (ctrl->id) {
1461 	case V4L2_CID_BRIGHTNESS:
1462 		setbrightness(gspca_dev, ctrl->val);
1463 		break;
1464 	}
1465 	return gspca_dev->usb_err;
1466 }
1467 
1468 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1469 	.s_ctrl = sd_s_ctrl,
1470 };
1471 
1472 static int sd_init_controls(struct gspca_dev *gspca_dev)
1473 {
1474 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1475 
1476 	gspca_dev->vdev.ctrl_handler = hdl;
1477 	v4l2_ctrl_handler_init(hdl, 5);
1478 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1479 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1480 
1481 	if (hdl->error) {
1482 		pr_err("Could not initialize controls\n");
1483 		return hdl->error;
1484 	}
1485 	return 0;
1486 }
1487 
1488 /* sub-driver description */
1489 static const struct sd_desc sd_desc = {
1490 	.name = MODULE_NAME,
1491 	.config = sd_config,
1492 	.init = sd_init,
1493 	.init_controls = sd_init_controls,
1494 	.start = sd_start,
1495 	.stopN = sd_stopN,
1496 	.pkt_scan = sd_pkt_scan,
1497 };
1498 
1499 /* -- module initialisation -- */
1500 static const struct usb_device_id device_table[] = {
1501 	{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
1502 	{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
1503 	{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
1504 	{USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
1505 	{USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
1506 	{USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
1507 	{}
1508 };
1509 MODULE_DEVICE_TABLE(usb, device_table);
1510 
1511 /* -- device connect -- */
1512 static int sd_probe(struct usb_interface *intf,
1513 			const struct usb_device_id *id)
1514 {
1515 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1516 				THIS_MODULE);
1517 }
1518 
1519 static struct usb_driver sd_driver = {
1520 	.name = MODULE_NAME,
1521 	.id_table = device_table,
1522 	.probe = sd_probe,
1523 	.disconnect = gspca_disconnect,
1524 #ifdef CONFIG_PM
1525 	.suspend = gspca_suspend,
1526 	.resume = gspca_resume,
1527 	.reset_resume = gspca_resume,
1528 #endif
1529 };
1530 
1531 module_usb_driver(sd_driver);
1532