GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / usb / gspca / spca505.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * SPCA505 chip based cameras initialization data
4  *
5  * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
6  */
7
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10 #define MODULE_NAME "spca505"
11
12 #include "gspca.h"
13
14 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
15 MODULE_DESCRIPTION("GSPCA/SPCA505 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 IntelPCCameraPro 0
24 #define Nxultra 1
25 };
26
27 static const struct v4l2_pix_format vga_mode[] = {
28         {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
29                 .bytesperline = 160,
30                 .sizeimage = 160 * 120 * 3 / 2,
31                 .colorspace = V4L2_COLORSPACE_SRGB,
32                 .priv = 4},
33         {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
34                 .bytesperline = 176,
35                 .sizeimage = 176 * 144 * 3 / 2,
36                 .colorspace = V4L2_COLORSPACE_SRGB,
37                 .priv = 3},
38         {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
39                 .bytesperline = 320,
40                 .sizeimage = 320 * 240 * 3 / 2,
41                 .colorspace = V4L2_COLORSPACE_SRGB,
42                 .priv = 2},
43         {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
44                 .bytesperline = 352,
45                 .sizeimage = 352 * 288 * 3 / 2,
46                 .colorspace = V4L2_COLORSPACE_SRGB,
47                 .priv = 1},
48         {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
49                 .bytesperline = 640,
50                 .sizeimage = 640 * 480 * 3 / 2,
51                 .colorspace = V4L2_COLORSPACE_SRGB,
52                 .priv = 0},
53 };
54
55 #define SPCA50X_OFFSET_DATA 10
56
57 #define SPCA50X_REG_USB 0x02    /* spca505 501 */
58
59 #define SPCA50X_USB_CTRL 0x00   /* spca505 */
60 #define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
61
62 #define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
63 #define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
64 #define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
65
66 #define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
67 #define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
68 #define SPCA50X_GMISC3_SAA7113RST 0x20  /* Not sure about this one spca505 */
69
70 /* Image format and compression control */
71 #define SPCA50X_REG_COMPRESS 0x04
72
73 /*
74  * Data to initialize a SPCA505. Common to the CCD and external modes
75  */
76 static const u8 spca505_init_data[][3] = {
77         /* bmRequest,value,index */
78         {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
79         /* Sensor reset */
80         {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
81         {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
82         /* Block USB reset */
83         {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
84
85         {0x05, 0x01, 0x10},
86                                         /* Maybe power down some stuff */
87         {0x05, 0x0f, 0x11},
88
89         /* Setup internal CCD  ? */
90         {0x06, 0x10, 0x08},
91         {0x06, 0x00, 0x09},
92         {0x06, 0x00, 0x0a},
93         {0x06, 0x00, 0x0b},
94         {0x06, 0x10, 0x0c},
95         {0x06, 0x00, 0x0d},
96         {0x06, 0x00, 0x0e},
97         {0x06, 0x00, 0x0f},
98         {0x06, 0x10, 0x10},
99         {0x06, 0x02, 0x11},
100         {0x06, 0x00, 0x12},
101         {0x06, 0x04, 0x13},
102         {0x06, 0x02, 0x14},
103         {0x06, 0x8a, 0x51},
104         {0x06, 0x40, 0x52},
105         {0x06, 0xb6, 0x53},
106         {0x06, 0x3d, 0x54},
107         {}
108 };
109
110 /*
111  * Data to initialize the camera using the internal CCD
112  */
113 static const u8 spca505_open_data_ccd[][3] = {
114         /* bmRequest,value,index */
115         /* Internal CCD data set */
116         {0x03, 0x04, 0x01},
117         /* This could be a reset */
118         {0x03, 0x00, 0x01},
119
120         /* Setup compression and image registers. 0x6 and 0x7 seem to be
121            related to H&V hold, and are resolution mode specific */
122                 {0x04, 0x10, 0x01},
123                 /* DIFF(0x50), was (0x10) */
124         {0x04, 0x00, 0x04},
125         {0x04, 0x00, 0x05},
126         {0x04, 0x20, 0x06},
127         {0x04, 0x20, 0x07},
128
129         {0x08, 0x0a, 0x00},
130         /* DIFF (0x4a), was (0xa) */
131
132         {0x05, 0x00, 0x10},
133         {0x05, 0x00, 0x11},
134         {0x05, 0x00, 0x00},
135         /* DIFF not written */
136         {0x05, 0x00, 0x01},
137         /* DIFF not written */
138         {0x05, 0x00, 0x02},
139         /* DIFF not written */
140         {0x05, 0x00, 0x03},
141         /* DIFF not written */
142         {0x05, 0x00, 0x04},
143         /* DIFF not written */
144                 {0x05, 0x80, 0x05},
145                 /* DIFF not written */
146                 {0x05, 0xe0, 0x06},
147                 /* DIFF not written */
148                 {0x05, 0x20, 0x07},
149                 /* DIFF not written */
150                 {0x05, 0xa0, 0x08},
151                 /* DIFF not written */
152                 {0x05, 0x0, 0x12},
153                 /* DIFF not written */
154         {0x05, 0x02, 0x0f},
155         /* DIFF not written */
156                 {0x05, 0x10, 0x46},
157                 /* DIFF not written */
158                 {0x05, 0x8, 0x4a},
159                 /* DIFF not written */
160
161         {0x03, 0x08, 0x03},
162         /* DIFF (0x3,0x28,0x3) */
163         {0x03, 0x08, 0x01},
164         {0x03, 0x0c, 0x03},
165         /* DIFF not written */
166                 {0x03, 0x21, 0x00},
167                 /* DIFF (0x39) */
168
169 /* Extra block copied from init to hopefully ensure CCD is in a sane state */
170         {0x06, 0x10, 0x08},
171         {0x06, 0x00, 0x09},
172         {0x06, 0x00, 0x0a},
173         {0x06, 0x00, 0x0b},
174         {0x06, 0x10, 0x0c},
175         {0x06, 0x00, 0x0d},
176         {0x06, 0x00, 0x0e},
177         {0x06, 0x00, 0x0f},
178         {0x06, 0x10, 0x10},
179         {0x06, 0x02, 0x11},
180         {0x06, 0x00, 0x12},
181         {0x06, 0x04, 0x13},
182         {0x06, 0x02, 0x14},
183         {0x06, 0x8a, 0x51},
184         {0x06, 0x40, 0x52},
185         {0x06, 0xb6, 0x53},
186         {0x06, 0x3d, 0x54},
187         /* End of extra block */
188
189                 {0x06, 0x3f, 0x1},
190                 /* Block skipped */
191         {0x06, 0x10, 0x02},
192         {0x06, 0x64, 0x07},
193         {0x06, 0x10, 0x08},
194         {0x06, 0x00, 0x09},
195         {0x06, 0x00, 0x0a},
196         {0x06, 0x00, 0x0b},
197         {0x06, 0x10, 0x0c},
198         {0x06, 0x00, 0x0d},
199         {0x06, 0x00, 0x0e},
200         {0x06, 0x00, 0x0f},
201         {0x06, 0x10, 0x10},
202         {0x06, 0x02, 0x11},
203         {0x06, 0x00, 0x12},
204         {0x06, 0x04, 0x13},
205         {0x06, 0x02, 0x14},
206         {0x06, 0x8a, 0x51},
207         {0x06, 0x40, 0x52},
208         {0x06, 0xb6, 0x53},
209         {0x06, 0x3d, 0x54},
210         {0x06, 0x60, 0x57},
211         {0x06, 0x20, 0x58},
212         {0x06, 0x15, 0x59},
213         {0x06, 0x05, 0x5a},
214
215         {0x05, 0x01, 0xc0},
216         {0x05, 0x10, 0xcb},
217                 {0x05, 0x80, 0xc1},
218                 /* */
219                 {0x05, 0x0, 0xc2},
220                 /* 4 was 0 */
221         {0x05, 0x00, 0xca},
222                 {0x05, 0x80, 0xc1},
223                 /*  */
224         {0x05, 0x04, 0xc2},
225         {0x05, 0x00, 0xca},
226                 {0x05, 0x0, 0xc1},
227                 /*  */
228         {0x05, 0x00, 0xc2},
229         {0x05, 0x00, 0xca},
230                 {0x05, 0x40, 0xc1},
231                 /* */
232         {0x05, 0x17, 0xc2},
233         {0x05, 0x00, 0xca},
234                 {0x05, 0x80, 0xc1},
235                 /* */
236         {0x05, 0x06, 0xc2},
237         {0x05, 0x00, 0xca},
238                 {0x05, 0x80, 0xc1},
239                 /* */
240         {0x05, 0x04, 0xc2},
241         {0x05, 0x00, 0xca},
242
243         {0x03, 0x4c, 0x3},
244         {0x03, 0x18, 0x1},
245
246         {0x06, 0x70, 0x51},
247         {0x06, 0xbe, 0x53},
248         {0x06, 0x71, 0x57},
249         {0x06, 0x20, 0x58},
250         {0x06, 0x05, 0x59},
251         {0x06, 0x15, 0x5a},
252
253         {0x04, 0x00, 0x08},
254         /* Compress = OFF (0x1 to turn on) */
255         {0x04, 0x12, 0x09},
256         {0x04, 0x21, 0x0a},
257         {0x04, 0x10, 0x0b},
258         {0x04, 0x21, 0x0c},
259         {0x04, 0x05, 0x00},
260         /* was 5 (Image Type ? ) */
261         {0x04, 0x00, 0x01},
262
263         {0x06, 0x3f, 0x01},
264
265         {0x04, 0x00, 0x04},
266         {0x04, 0x00, 0x05},
267         {0x04, 0x40, 0x06},
268         {0x04, 0x40, 0x07},
269
270         {0x06, 0x1c, 0x17},
271         {0x06, 0xe2, 0x19},
272         {0x06, 0x1c, 0x1b},
273         {0x06, 0xe2, 0x1d},
274         {0x06, 0xaa, 0x1f},
275         {0x06, 0x70, 0x20},
276
277         {0x05, 0x01, 0x10},
278         {0x05, 0x00, 0x11},
279         {0x05, 0x01, 0x00},
280         {0x05, 0x05, 0x01},
281                 {0x05, 0x00, 0xc1},
282                 /* */
283         {0x05, 0x00, 0xc2},
284         {0x05, 0x00, 0xca},
285
286         {0x06, 0x70, 0x51},
287         {0x06, 0xbe, 0x53},
288         {}
289 };
290
291 /*
292  * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
293  * SPCA505b chip based cameras initialization data
294  */
295 /* jfm */
296 #define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
297 /* #define initial_brightness 0x0       //0x0(white)-0xff(black) */
298 /*
299  * Data to initialize a SPCA505. Common to the CCD and external modes
300  */
301 static const u8 spca505b_init_data[][3] = {
302 /* start */
303         {0x02, 0x00, 0x00},             /* init */
304         {0x02, 0x00, 0x01},
305         {0x02, 0x00, 0x02},
306         {0x02, 0x00, 0x03},
307         {0x02, 0x00, 0x04},
308         {0x02, 0x00, 0x05},
309         {0x02, 0x00, 0x06},
310         {0x02, 0x00, 0x07},
311         {0x02, 0x00, 0x08},
312         {0x02, 0x00, 0x09},
313         {0x03, 0x00, 0x00},
314         {0x03, 0x00, 0x01},
315         {0x03, 0x00, 0x02},
316         {0x03, 0x00, 0x03},
317         {0x03, 0x00, 0x04},
318         {0x03, 0x00, 0x05},
319         {0x03, 0x00, 0x06},
320         {0x04, 0x00, 0x00},
321         {0x04, 0x00, 0x02},
322         {0x04, 0x00, 0x04},
323         {0x04, 0x00, 0x05},
324         {0x04, 0x00, 0x06},
325         {0x04, 0x00, 0x07},
326         {0x04, 0x00, 0x08},
327         {0x04, 0x00, 0x09},
328         {0x04, 0x00, 0x0a},
329         {0x04, 0x00, 0x0b},
330         {0x04, 0x00, 0x0c},
331         {0x07, 0x00, 0x00},
332         {0x07, 0x00, 0x03},
333         {0x08, 0x00, 0x00},
334         {0x08, 0x00, 0x01},
335         {0x08, 0x00, 0x02},
336         {0x06, 0x18, 0x08},
337         {0x06, 0xfc, 0x09},
338         {0x06, 0xfc, 0x0a},
339         {0x06, 0xfc, 0x0b},
340         {0x06, 0x18, 0x0c},
341         {0x06, 0xfc, 0x0d},
342         {0x06, 0xfc, 0x0e},
343         {0x06, 0xfc, 0x0f},
344         {0x06, 0x18, 0x10},
345         {0x06, 0xfe, 0x12},
346         {0x06, 0x00, 0x11},
347         {0x06, 0x00, 0x14},
348         {0x06, 0x00, 0x13},
349         {0x06, 0x28, 0x51},
350         {0x06, 0xff, 0x53},
351         {0x02, 0x00, 0x08},
352
353         {0x03, 0x00, 0x03},
354         {0x03, 0x10, 0x03},
355         {}
356 };
357
358 /*
359  * Data to initialize the camera using the internal CCD
360  */
361 static const u8 spca505b_open_data_ccd[][3] = {
362
363 /* {0x02,0x00,0x00}, */
364         {0x03, 0x04, 0x01},             /* rst */
365         {0x03, 0x00, 0x01},
366         {0x03, 0x00, 0x00},
367         {0x03, 0x21, 0x00},
368         {0x03, 0x00, 0x04},
369         {0x03, 0x00, 0x03},
370         {0x03, 0x18, 0x03},
371         {0x03, 0x08, 0x01},
372         {0x03, 0x1c, 0x03},
373         {0x03, 0x5c, 0x03},
374         {0x03, 0x5c, 0x03},
375         {0x03, 0x18, 0x01},
376
377 /* same as 505 */
378         {0x04, 0x10, 0x01},
379         {0x04, 0x00, 0x04},
380         {0x04, 0x00, 0x05},
381         {0x04, 0x20, 0x06},
382         {0x04, 0x20, 0x07},
383
384         {0x08, 0x0a, 0x00},
385
386         {0x05, 0x00, 0x10},
387         {0x05, 0x00, 0x11},
388         {0x05, 0x00, 0x12},
389         {0x05, 0x6f, 0x00},
390         {0x05, initial_brightness >> 6, 0x00},
391         {0x05, (initial_brightness << 2) & 0xff, 0x01},
392         {0x05, 0x00, 0x02},
393         {0x05, 0x01, 0x03},
394         {0x05, 0x00, 0x04},
395         {0x05, 0x03, 0x05},
396         {0x05, 0xe0, 0x06},
397         {0x05, 0x20, 0x07},
398         {0x05, 0xa0, 0x08},
399         {0x05, 0x00, 0x12},
400         {0x05, 0x02, 0x0f},
401         {0x05, 0x80, 0x14},             /* max exposure off (0=on) */
402         {0x05, 0x01, 0xb0},
403         {0x05, 0x01, 0xbf},
404         {0x03, 0x02, 0x06},
405         {0x05, 0x10, 0x46},
406         {0x05, 0x08, 0x4a},
407
408         {0x06, 0x00, 0x01},
409         {0x06, 0x10, 0x02},
410         {0x06, 0x64, 0x07},
411         {0x06, 0x18, 0x08},
412         {0x06, 0xfc, 0x09},
413         {0x06, 0xfc, 0x0a},
414         {0x06, 0xfc, 0x0b},
415         {0x04, 0x00, 0x01},
416         {0x06, 0x18, 0x0c},
417         {0x06, 0xfc, 0x0d},
418         {0x06, 0xfc, 0x0e},
419         {0x06, 0xfc, 0x0f},
420         {0x06, 0x11, 0x10},             /* contrast */
421         {0x06, 0x00, 0x11},
422         {0x06, 0xfe, 0x12},
423         {0x06, 0x00, 0x13},
424         {0x06, 0x00, 0x14},
425         {0x06, 0x9d, 0x51},
426         {0x06, 0x40, 0x52},
427         {0x06, 0x7c, 0x53},
428         {0x06, 0x40, 0x54},
429         {0x06, 0x02, 0x57},
430         {0x06, 0x03, 0x58},
431         {0x06, 0x15, 0x59},
432         {0x06, 0x05, 0x5a},
433         {0x06, 0x03, 0x56},
434         {0x06, 0x02, 0x3f},
435         {0x06, 0x00, 0x40},
436         {0x06, 0x39, 0x41},
437         {0x06, 0x69, 0x42},
438         {0x06, 0x87, 0x43},
439         {0x06, 0x9e, 0x44},
440         {0x06, 0xb1, 0x45},
441         {0x06, 0xbf, 0x46},
442         {0x06, 0xcc, 0x47},
443         {0x06, 0xd5, 0x48},
444         {0x06, 0xdd, 0x49},
445         {0x06, 0xe3, 0x4a},
446         {0x06, 0xe8, 0x4b},
447         {0x06, 0xed, 0x4c},
448         {0x06, 0xf2, 0x4d},
449         {0x06, 0xf7, 0x4e},
450         {0x06, 0xfc, 0x4f},
451         {0x06, 0xff, 0x50},
452
453         {0x05, 0x01, 0xc0},
454         {0x05, 0x10, 0xcb},
455         {0x05, 0x40, 0xc1},
456         {0x05, 0x04, 0xc2},
457         {0x05, 0x00, 0xca},
458         {0x05, 0x40, 0xc1},
459         {0x05, 0x09, 0xc2},
460         {0x05, 0x00, 0xca},
461         {0x05, 0xc0, 0xc1},
462         {0x05, 0x09, 0xc2},
463         {0x05, 0x00, 0xca},
464         {0x05, 0x40, 0xc1},
465         {0x05, 0x59, 0xc2},
466         {0x05, 0x00, 0xca},
467         {0x04, 0x00, 0x01},
468         {0x05, 0x80, 0xc1},
469         {0x05, 0xec, 0xc2},
470         {0x05, 0x0, 0xca},
471
472         {0x06, 0x02, 0x57},
473         {0x06, 0x01, 0x58},
474         {0x06, 0x15, 0x59},
475         {0x06, 0x0a, 0x5a},
476         {0x06, 0x01, 0x57},
477         {0x06, 0x8a, 0x03},
478         {0x06, 0x0a, 0x6c},
479         {0x06, 0x30, 0x01},
480         {0x06, 0x20, 0x02},
481         {0x06, 0x00, 0x03},
482
483         {0x05, 0x8c, 0x25},
484
485         {0x06, 0x4d, 0x51},             /* maybe saturation (4d) */
486         {0x06, 0x84, 0x53},             /* making green (84) */
487         {0x06, 0x00, 0x57},             /* sharpness (1) */
488         {0x06, 0x18, 0x08},
489         {0x06, 0xfc, 0x09},
490         {0x06, 0xfc, 0x0a},
491         {0x06, 0xfc, 0x0b},
492         {0x06, 0x18, 0x0c},             /* maybe hue (18) */
493         {0x06, 0xfc, 0x0d},
494         {0x06, 0xfc, 0x0e},
495         {0x06, 0xfc, 0x0f},
496         {0x06, 0x18, 0x10},             /* maybe contrast (18) */
497
498         {0x05, 0x01, 0x02},
499
500         {0x04, 0x00, 0x08},             /* compression */
501         {0x04, 0x12, 0x09},
502         {0x04, 0x21, 0x0a},
503         {0x04, 0x10, 0x0b},
504         {0x04, 0x21, 0x0c},
505         {0x04, 0x1d, 0x00},             /* imagetype (1d) */
506         {0x04, 0x41, 0x01},             /* hardware snapcontrol */
507
508         {0x04, 0x00, 0x04},
509         {0x04, 0x00, 0x05},
510         {0x04, 0x10, 0x06},
511         {0x04, 0x10, 0x07},
512         {0x04, 0x40, 0x06},
513         {0x04, 0x40, 0x07},
514         {0x04, 0x00, 0x04},
515         {0x04, 0x00, 0x05},
516
517         {0x06, 0x1c, 0x17},
518         {0x06, 0xe2, 0x19},
519         {0x06, 0x1c, 0x1b},
520         {0x06, 0xe2, 0x1d},
521         {0x06, 0x5f, 0x1f},
522         {0x06, 0x32, 0x20},
523
524         {0x05, initial_brightness >> 6, 0x00},
525         {0x05, (initial_brightness << 2) & 0xff, 0x01},
526         {0x05, 0x06, 0xc1},
527         {0x05, 0x58, 0xc2},
528         {0x05, 0x00, 0xca},
529         {0x05, 0x00, 0x11},
530         {}
531 };
532
533 static int reg_write(struct gspca_dev *gspca_dev,
534                      u16 req, u16 index, u16 value)
535 {
536         int ret;
537         struct usb_device *dev = gspca_dev->dev;
538
539         ret = usb_control_msg(dev,
540                         usb_sndctrlpipe(dev, 0),
541                         req,
542                         USB_TYPE_VENDOR | USB_RECIP_DEVICE,
543                         value, index, NULL, 0, 500);
544         gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",
545                   req, index, value, ret);
546         if (ret < 0)
547                 pr_err("reg write: error %d\n", ret);
548         return ret;
549 }
550
551 /* returns: negative is error, pos or zero is data */
552 static int reg_read(struct gspca_dev *gspca_dev,
553                         u16 req,        /* bRequest */
554                         u16 index)      /* wIndex */
555 {
556         int ret;
557
558         ret = usb_control_msg(gspca_dev->dev,
559                         usb_rcvctrlpipe(gspca_dev->dev, 0),
560                         req,
561                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
562                         0,                      /* value */
563                         index,
564                         gspca_dev->usb_buf, 2,
565                         500);                   /* timeout */
566         if (ret < 0)
567                 return ret;
568         return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
569 }
570
571 static int write_vector(struct gspca_dev *gspca_dev,
572                         const u8 data[][3])
573 {
574         int ret, i = 0;
575
576         while (data[i][0] != 0) {
577                 ret = reg_write(gspca_dev, data[i][0], data[i][2],
578                                                                 data[i][1]);
579                 if (ret < 0)
580                         return ret;
581                 i++;
582         }
583         return 0;
584 }
585
586 /* this function is called at probe time */
587 static int sd_config(struct gspca_dev *gspca_dev,
588                         const struct usb_device_id *id)
589 {
590         struct sd *sd = (struct sd *) gspca_dev;
591         struct cam *cam;
592
593         cam = &gspca_dev->cam;
594         cam->cam_mode = vga_mode;
595         sd->subtype = id->driver_info;
596         if (sd->subtype != IntelPCCameraPro)
597                 cam->nmodes = ARRAY_SIZE(vga_mode);
598         else                    /* no 640x480 for IntelPCCameraPro */
599                 cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
600
601         return 0;
602 }
603
604 /* this function is called at probe and resume time */
605 static int sd_init(struct gspca_dev *gspca_dev)
606 {
607         struct sd *sd = (struct sd *) gspca_dev;
608
609         if (write_vector(gspca_dev,
610                          sd->subtype == Nxultra
611                                 ? spca505b_init_data
612                                 : spca505_init_data))
613                 return -EIO;
614         return 0;
615 }
616
617 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
618 {
619         reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
620         reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
621 }
622
623 static int sd_start(struct gspca_dev *gspca_dev)
624 {
625         struct sd *sd = (struct sd *) gspca_dev;
626         int ret, mode;
627         static u8 mode_tb[][3] = {
628         /*        r00   r06   r07       */
629                 {0x00, 0x10, 0x10},     /* 640x480 */
630                 {0x01, 0x1a, 0x1a},     /* 352x288 */
631                 {0x02, 0x1c, 0x1d},     /* 320x240 */
632                 {0x04, 0x34, 0x34},     /* 176x144 */
633                 {0x05, 0x40, 0x40}      /* 160x120 */
634         };
635
636         if (sd->subtype == Nxultra)
637                 write_vector(gspca_dev, spca505b_open_data_ccd);
638         else
639                 write_vector(gspca_dev, spca505_open_data_ccd);
640         ret = reg_read(gspca_dev, 0x06, 0x16);
641
642         if (ret < 0) {
643                 gspca_err(gspca_dev, "register read failed err: %d\n", ret);
644                 return ret;
645         }
646         if (ret != 0x0101) {
647                 pr_err("After vector read returns 0x%04x should be 0x0101\n",
648                        ret);
649         }
650
651         ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
652         if (ret < 0)
653                 return ret;
654         reg_write(gspca_dev, 0x05, 0xc2, 0x12);
655
656         /* necessary because without it we can see stream
657          * only once after loading module */
658         /* stopping usb registers Tomasz change */
659         reg_write(gspca_dev, 0x02, 0x00, 0x00);
660
661         mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
662         reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
663         reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
664         reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
665
666         return reg_write(gspca_dev, SPCA50X_REG_USB,
667                          SPCA50X_USB_CTRL,
668                          SPCA50X_CUSB_ENABLE);
669 }
670
671 static void sd_stopN(struct gspca_dev *gspca_dev)
672 {
673         /* Disable ISO packet machine */
674         reg_write(gspca_dev, 0x02, 0x00, 0x00);
675 }
676
677 /* called on streamoff with alt 0 and on disconnect */
678 static void sd_stop0(struct gspca_dev *gspca_dev)
679 {
680         if (!gspca_dev->present)
681                 return;
682
683         /* This maybe reset or power control */
684         reg_write(gspca_dev, 0x03, 0x03, 0x20);
685         reg_write(gspca_dev, 0x03, 0x01, 0x00);
686         reg_write(gspca_dev, 0x03, 0x00, 0x01);
687         reg_write(gspca_dev, 0x05, 0x10, 0x01);
688         reg_write(gspca_dev, 0x05, 0x11, 0x0f);
689 }
690
691 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
692                         u8 *data,                       /* isoc packet */
693                         int len)                        /* iso packet length */
694 {
695         switch (data[0]) {
696         case 0:                         /* start of frame */
697                 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
698                 data += SPCA50X_OFFSET_DATA;
699                 len -= SPCA50X_OFFSET_DATA;
700                 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
701                 break;
702         case 0xff:                      /* drop */
703                 break;
704         default:
705                 data += 1;
706                 len -= 1;
707                 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
708                 break;
709         }
710 }
711
712 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
713 {
714         struct gspca_dev *gspca_dev =
715                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
716
717         gspca_dev->usb_err = 0;
718
719         if (!gspca_dev->streaming)
720                 return 0;
721
722         switch (ctrl->id) {
723         case V4L2_CID_BRIGHTNESS:
724                 setbrightness(gspca_dev, ctrl->val);
725                 break;
726         }
727         return gspca_dev->usb_err;
728 }
729
730 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
731         .s_ctrl = sd_s_ctrl,
732 };
733
734 static int sd_init_controls(struct gspca_dev *gspca_dev)
735 {
736         struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
737
738         gspca_dev->vdev.ctrl_handler = hdl;
739         v4l2_ctrl_handler_init(hdl, 5);
740         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
741                         V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
742
743         if (hdl->error) {
744                 pr_err("Could not initialize controls\n");
745                 return hdl->error;
746         }
747         return 0;
748 }
749
750 /* sub-driver description */
751 static const struct sd_desc sd_desc = {
752         .name = MODULE_NAME,
753         .config = sd_config,
754         .init_controls = sd_init_controls,
755         .init = sd_init,
756         .start = sd_start,
757         .stopN = sd_stopN,
758         .stop0 = sd_stop0,
759         .pkt_scan = sd_pkt_scan,
760 };
761
762 /* -- module initialisation -- */
763 static const struct usb_device_id device_table[] = {
764         {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
765         {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
766 /*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
767         {}
768 };
769 MODULE_DEVICE_TABLE(usb, device_table);
770
771 /* -- device connect -- */
772 static int sd_probe(struct usb_interface *intf,
773                         const struct usb_device_id *id)
774 {
775         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
776                                 THIS_MODULE);
777 }
778
779 static struct usb_driver sd_driver = {
780         .name = MODULE_NAME,
781         .id_table = device_table,
782         .probe = sd_probe,
783         .disconnect = gspca_disconnect,
784 #ifdef CONFIG_PM
785         .suspend = gspca_suspend,
786         .resume = gspca_resume,
787         .reset_resume = gspca_resume,
788 #endif
789 };
790
791 module_usb_driver(sd_driver);