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