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
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct 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
44static const struct v4l2_pix_format sif_mode[] = {
45	{160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
46		.bytesperline = 160,
47		.sizeimage = 160 * 120 * 3 / 2,
48		.colorspace = V4L2_COLORSPACE_SRGB,
49		.priv = 3},
50	{176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
51		.bytesperline = 176,
52		.sizeimage = 176 * 144 * 3 / 2,
53		.colorspace = V4L2_COLORSPACE_SRGB,
54		.priv = 2},
55	{320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
56		.bytesperline = 320,
57		.sizeimage = 320 * 240 * 3 / 2,
58		.colorspace = V4L2_COLORSPACE_SRGB,
59		.priv = 1},
60	{352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
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 */
74static 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 */
486static 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
570static 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
653static 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 */
1000static 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
1244static int reg_write(struct gspca_dev *gspca_dev, u16 index, u16 value)
1245{
1246	int ret;
1247	struct usb_device *dev = gspca_dev->dev;
1248
1249	ret = usb_control_msg(dev,
1250			usb_sndctrlpipe(dev, 0),
1251			0,		/* request */
1252			USB_TYPE_VENDOR | USB_RECIP_DEVICE,
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 */
1263static 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 */
1271			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
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 */
1286static int ssi_w(struct gspca_dev *gspca_dev,
1287		u16 reg, u16 val)
1288{
1289	int ret, retry;
1290
1291	ret = reg_write(gspca_dev, 0x8802, reg >> 8);
1292	if (ret < 0)
1293		goto out;
1294	ret = reg_write(gspca_dev, 0x8801, reg & 0x00ff);
1295	if (ret < 0)
1296		goto out;
1297	if ((reg & 0xff00) == 0x1000) {		/* if 2 bytes */
1298		ret = reg_write(gspca_dev, 0x8805, val & 0x00ff);
1299		if (ret < 0)
1300			goto out;
1301		val >>= 8;
1302	}
1303	ret = reg_write(gspca_dev, 0x8800, val);
1304	if (ret < 0)
1305		goto out;
1306
1307	/* poll until not busy */
1308	retry = 10;
1309	for (;;) {
1310		ret = reg_read(gspca_dev, 0x8803);
1311		if (ret < 0)
1312			break;
1313		if (gspca_dev->usb_buf[0] == 0)
1314			break;
1315		if (--retry <= 0) {
1316			PERR("ssi_w busy %02x", gspca_dev->usb_buf[0]);
1317			ret = -1;
1318			break;
1319		}
1320		msleep(8);
1321	}
1322
1323out:
1324	return ret;
1325}
1326
1327static int write_vector(struct gspca_dev *gspca_dev,
1328			const u16 (*data)[2])
1329{
1330	int ret = 0;
1331
1332	while ((*data)[1] != 0) {
1333		if ((*data)[1] & 0x8000) {
1334			if ((*data)[1] == 0xdd00)	/* delay */
1335				msleep((*data)[0]);
1336			else
1337				ret = reg_write(gspca_dev, (*data)[1],
1338								(*data)[0]);
1339		} else {
1340			ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
1341		}
1342		if (ret < 0)
1343			break;
1344		data++;
1345	}
1346	return ret;
1347}
1348
1349/* this function is called at probe time */
1350static int sd_config(struct gspca_dev *gspca_dev,
1351			const struct usb_device_id *id)
1352{
1353	struct sd *sd = (struct sd *) gspca_dev;
1354	struct cam *cam;
1355	const u16 (*init_data)[2];
1356	static const u16 (*(init_data_tb[]))[2] = {
1357		spca508_vista_init_data,	/* CreativeVista 0 */
1358		spca508_sightcam_init_data,	/* HamaUSBSightcam 1 */
1359		spca508_sightcam2_init_data,	/* HamaUSBSightcam2 2 */
1360		spca508cs110_init_data,		/* IntelEasyPCCamera 3 */
1361		spca508cs110_init_data,		/* MicroInnovationIC200 4 */
1362		spca508_init_data,		/* ViewQuestVQ110 5 */
1363	};
1364	int data1, data2;
1365
1366	/* Read from global register the USB product and vendor IDs, just to
1367	 * prove that we can communicate with the device.  This works, which
1368	 * confirms at we are communicating properly and that the device
1369	 * is a 508. */
1370	data1 = reg_read(gspca_dev, 0x8104);
1371	data2 = reg_read(gspca_dev, 0x8105);
1372	PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1373
1374	data1 = reg_read(gspca_dev, 0x8106);
1375	data2 = reg_read(gspca_dev, 0x8107);
1376	PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1377
1378	data1 = reg_read(gspca_dev, 0x8621);
1379	PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1380
1381	cam = &gspca_dev->cam;
1382	cam->cam_mode = sif_mode;
1383	cam->nmodes = ARRAY_SIZE(sif_mode);
1384
1385	sd->subtype = id->driver_info;
1386
1387	init_data = init_data_tb[sd->subtype];
1388	return write_vector(gspca_dev, init_data);
1389}
1390
1391/* this function is called at probe and resume time */
1392static int sd_init(struct gspca_dev *gspca_dev)
1393{
1394	return 0;
1395}
1396
1397static int sd_start(struct gspca_dev *gspca_dev)
1398{
1399	int mode;
1400
1401	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1402	reg_write(gspca_dev, 0x8500, mode);
1403	switch (mode) {
1404	case 0:
1405	case 1:
1406		reg_write(gspca_dev, 0x8700, 0x28); /* clock */
1407		break;
1408	default:
1409/*	case 2: */
1410/*	case 3: */
1411		reg_write(gspca_dev, 0x8700, 0x23); /* clock */
1412		break;
1413	}
1414	reg_write(gspca_dev, 0x8112, 0x10 | 0x20);
1415	return 0;
1416}
1417
1418static void sd_stopN(struct gspca_dev *gspca_dev)
1419{
1420	/* Video ISO disable, Video Drop Packet enable: */
1421	reg_write(gspca_dev, 0x8112, 0x20);
1422}
1423
1424static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1425			u8 *data,			/* isoc packet */
1426			int len)			/* iso packet length */
1427{
1428	switch (data[0]) {
1429	case 0:				/* start of frame */
1430		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1431		data += SPCA508_OFFSET_DATA;
1432		len -= SPCA508_OFFSET_DATA;
1433		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1434		break;
1435	case 0xff:			/* drop */
1436		break;
1437	default:
1438		data += 1;
1439		len -= 1;
1440		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1441		break;
1442	}
1443}
1444
1445static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
1446{
1447	/* MX seem contrast */
1448	reg_write(gspca_dev, 0x8651, brightness);
1449	reg_write(gspca_dev, 0x8652, brightness);
1450	reg_write(gspca_dev, 0x8653, brightness);
1451	reg_write(gspca_dev, 0x8654, brightness);
1452}
1453
1454static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1455{
1456	struct gspca_dev *gspca_dev =
1457		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1458
1459	gspca_dev->usb_err = 0;
1460
1461	if (!gspca_dev->streaming)
1462		return 0;
1463
1464	switch (ctrl->id) {
1465	case V4L2_CID_BRIGHTNESS:
1466		setbrightness(gspca_dev, ctrl->val);
1467		break;
1468	}
1469	return gspca_dev->usb_err;
1470}
1471
1472static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1473	.s_ctrl = sd_s_ctrl,
1474};
1475
1476static int sd_init_controls(struct gspca_dev *gspca_dev)
1477{
1478	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1479
1480	gspca_dev->vdev.ctrl_handler = hdl;
1481	v4l2_ctrl_handler_init(hdl, 5);
1482	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1483			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1484
1485	if (hdl->error) {
1486		pr_err("Could not initialize controls\n");
1487		return hdl->error;
1488	}
1489	return 0;
1490}
1491
1492/* sub-driver description */
1493static const struct sd_desc sd_desc = {
1494	.name = MODULE_NAME,
1495	.config = sd_config,
1496	.init = sd_init,
1497	.init_controls = sd_init_controls,
1498	.start = sd_start,
1499	.stopN = sd_stopN,
1500	.pkt_scan = sd_pkt_scan,
1501};
1502
1503/* -- module initialisation -- */
1504static const struct usb_device_id device_table[] = {
1505	{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
1506	{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
1507	{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
1508	{USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
1509	{USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
1510	{USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
1511	{}
1512};
1513MODULE_DEVICE_TABLE(usb, device_table);
1514
1515/* -- device connect -- */
1516static int sd_probe(struct usb_interface *intf,
1517			const struct usb_device_id *id)
1518{
1519	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1520				THIS_MODULE);
1521}
1522
1523static struct usb_driver sd_driver = {
1524	.name = MODULE_NAME,
1525	.id_table = device_table,
1526	.probe = sd_probe,
1527	.disconnect = gspca_disconnect,
1528#ifdef CONFIG_PM
1529	.suspend = gspca_suspend,
1530	.resume = gspca_resume,
1531	.reset_resume = gspca_resume,
1532#endif
1533};
1534
1535module_usb_driver(sd_driver);
1536