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