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