aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sunplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sunplus.c')
-rw-r--r--drivers/media/video/gspca/sunplus.c1677
1 files changed, 1677 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
new file mode 100644
index 000000000000..abd7bef9b3d1
--- /dev/null
+++ b/drivers/media/video/gspca/sunplus.c
@@ -0,0 +1,1677 @@
1/*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 char qindex;
47 char bridge;
48#define BRIDGE_SPCA504 0
49#define BRIDGE_SPCA504B 1
50#define BRIDGE_SPCA504C 2
51#define BRIDGE_SPCA533 3
52#define BRIDGE_SPCA536 4
53 char subtype;
54#define AiptekMiniPenCam13 1
55#define LogitechClickSmart420 2
56#define LogitechClickSmart820 3
57#define MegapixV4 4
58};
59
60/* V4L2 controls supported by the driver */
61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70static struct ctrl sd_ctrls[] = {
71#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 0xff,
79 .step = 1,
80 .default_value = 0,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85#define SD_CONTRAST 1
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 0xff,
93 .step = 1,
94 .default_value = 0x20,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99#define SD_COLOR 2
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 0xff,
107 .step = 1,
108 .default_value = 0x1a,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113#define SD_AUTOGAIN 3
114 {
115 {
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Auto Gain",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 1,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
129static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
140};
141
142static struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
153};
154
155static struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
176};
177
178#define SPCA50X_OFFSET_DATA 10
179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181#define SPCA504_PCCAM600_OFFSET_MODE 5
182#define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186/* Frame packet header offsets for the spca536 */
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190/* Initialisation data for the Creative PC-CAM 600 */
191static const __u16 spca504_pccam600_init_data[][3] = {
192/* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {}
216};
217
218/* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
220 */
221static const __u16 spca504_pccam600_open_data[][3] = {
222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
226 {}
227};
228
229/* Initialisation data for the logitech clicksmart 420 */
230static const __u16 spca504A_clicksmart420_init_data[][3] = {
231/* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
245
246
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
256
257 {}
258};
259
260/* clicksmart 420 open data ? */
261static const __u16 spca504A_clicksmart420_open_data[][3] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267/* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
284
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
301
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
318
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
335
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
352
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
369
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
386
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
403
404 {0xa0, 0x0000, 0x0503},
405 {}
406};
407
408static const __u8 qtable_creative_pccam[2][64] = {
409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
427};
428
429/* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
431 * NWG: 18/05/2003.
432 */
433static const __u8 qtable_spca504_default[2][64] = {
434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 },
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
453};
454
455static void reg_r(struct usb_device *dev,
456 __u16 req,
457 __u16 index,
458 __u8 *buffer, __u16 length)
459{
460 usb_control_msg(dev,
461 usb_rcvctrlpipe(dev, 0),
462 req,
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
464 0, /* value */
465 index, buffer, length,
466 500);
467}
468
469static void reg_w(struct usb_device *dev,
470 __u16 req,
471 __u16 value,
472 __u16 index,
473 __u8 *buffer, __u16 length)
474{
475 usb_control_msg(dev,
476 usb_sndctrlpipe(dev, 0),
477 req,
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
480 500);
481}
482
483/* write req / index / value */
484static int reg_w_riv(struct usb_device *dev,
485 __u16 req, __u16 index, __u16 value)
486{
487 int ret;
488
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
491 req,
492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
493 value, index, NULL, 0, 500);
494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
495 req, index, value, ret);
496 if (ret < 0)
497 PDEBUG(D_ERR, "reg write: error %d", ret);
498 return ret;
499}
500
501/* read 1 byte */
502static int reg_r_1(struct gspca_dev *gspca_dev,
503 __u16 value) /* wValue */
504{
505 int ret;
506
507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
509 0x20, /* request */
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value,
512 0, /* index */
513 gspca_dev->usb_buf, 1,
514 500); /* timeout */
515 if (ret < 0) {
516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
517 return 0;
518 }
519 return gspca_dev->usb_buf[0];
520}
521
522/* read 1 or 2 bytes - returns < 0 if error */
523static int reg_r_12(struct gspca_dev *gspca_dev,
524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
527{
528 int ret;
529
530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
533 req,
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
535 0, /* value */
536 index,
537 gspca_dev->usb_buf, length,
538 500);
539 if (ret < 0) {
540 PDEBUG(D_ERR, "reg_read err %d", ret);
541 return -1;
542 }
543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
544}
545
546static int write_vector(struct gspca_dev *gspca_dev,
547 const __u16 data[][3])
548{
549 struct usb_device *dev = gspca_dev->dev;
550 int ret, i = 0;
551
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
553 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
554 if (ret < 0) {
555 PDEBUG(D_ERR,
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
558 return ret;
559 }
560 i++;
561 }
562 return 0;
563}
564
565static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
567 unsigned int ybase,
568 unsigned int cbase,
569 const __u8 qtable[2][64])
570{
571 struct usb_device *dev = gspca_dev->dev;
572 int i, err;
573
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
576 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
577 if (err < 0)
578 return err;
579 }
580
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
583 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
584 if (err < 0)
585 return err;
586 }
587 return 0;
588}
589
590static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
592{
593 struct usb_device *dev = gspca_dev->dev;
594 __u8 notdone;
595
596 reg_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
599
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
601
602 msleep(200);
603 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
605}
606
607static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
608 __u16 req,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
610{
611 struct usb_device *dev = gspca_dev->dev;
612 __u8 status;
613 __u8 endcode;
614
615 reg_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
617 endcode = stat;
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 if (!count)
620 return;
621 count = 200;
622 while (--count > 0) {
623 msleep(10);
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
625/* reg_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
630 break;
631 }
632 }
633}
634
635static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
636{
637 int count = 10;
638
639 while (--count > 0) {
640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
642 break;
643 msleep(10);
644 }
645 return gspca_dev->usb_buf[0];
646}
647
648static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
649{
650 struct usb_device *dev = gspca_dev->dev;
651 int count = 50;
652
653 while (--count > 0) {
654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
660 break;
661 }
662 msleep(10);
663 }
664}
665
666static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
667{
668 struct usb_device *dev = gspca_dev->dev;
669 __u8 *data;
670
671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
677 kfree(data);
678}
679
680static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
684 __u8 Size;
685 __u8 Type;
686 int rc;
687
688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
689 Type = 0;
690 switch (sd->bridge) {
691 case BRIDGE_SPCA533:
692 reg_w(dev, 0x31, 0, 0, NULL, 0);
693 spca504B_WaitCmdStatus(gspca_dev);
694 rc = spca504B_PollingDataReady(gspca_dev);
695 spca50x_GetFirmware(gspca_dev);
696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
699
700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
704
705 /* Init the cam width height with some values get on init ? */
706 reg_w(dev, 0x31, 0, 4, NULL, 0);
707 spca504B_WaitCmdStatus(gspca_dev);
708 rc = spca504B_PollingDataReady(gspca_dev);
709 break;
710 default:
711/* case BRIDGE_SPCA504B: */
712/* case BRIDGE_SPCA536: */
713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
716 Type = 6;
717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
721 break;
722 case BRIDGE_SPCA504:
723 Size += 3;
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
727 0x08, Size, 0,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
730 1, 3, 0, 0x9f, 0);
731 } else {
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
733 }
734 break;
735 case BRIDGE_SPCA504C:
736 /* capture mode */
737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
739 break;
740 }
741}
742
743static void spca504_wait_status(struct gspca_dev *gspca_dev)
744{
745 int cnt;
746
747 cnt = 256;
748 while (--cnt > 0) {
749 /* With this we get the status, when return 0 it's all ok */
750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
751 return;
752 msleep(10);
753 }
754}
755
756static void spca504B_setQtable(struct gspca_dev *gspca_dev)
757{
758 struct usb_device *dev = gspca_dev->dev;
759
760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_dev);
764}
765
766static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
770 int pollreg = 1;
771
772 switch (sd->bridge) {
773 case BRIDGE_SPCA504:
774 case BRIDGE_SPCA504C:
775 pollreg = 0;
776 /* fall thru */
777 default:
778/* case BRIDGE_SPCA533: */
779/* case BRIDGE_SPCA504B: */
780 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
786 break;
787 case BRIDGE_SPCA536:
788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
794 break;
795 }
796 if (pollreg)
797 spca504B_PollingDataReady(gspca_dev);
798}
799
800/* this function is called at probe time */
801static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
806 struct cam *cam;
807 __u16 vendor;
808 __u16 product;
809 __u8 fw;
810
811 vendor = id->idVendor;
812 product = id->idProduct;
813 switch (vendor) {
814 case 0x041e: /* Creative cameras */
815/* switch (product) { */
816/* case 0x400b: */
817/* case 0x4012: */
818/* case 0x4013: */
819/* sd->bridge = BRIDGE_SPCA504C; */
820/* break; */
821/* } */
822 break;
823 case 0x0458: /* Genius KYE cameras */
824/* switch (product) { */
825/* case 0x7006: */
826 sd->bridge = BRIDGE_SPCA504B;
827/* break; */
828/* } */
829 break;
830 case 0x0461: /* MicroInnovation */
831/* switch (product) { */
832/* case 0x0821: */
833 sd->bridge = BRIDGE_SPCA533;
834/* break; */
835/* } */
836 break;
837 case 0x046d: /* Logitech Labtec */
838 switch (product) {
839 case 0x0905:
840 sd->subtype = LogitechClickSmart820;
841 sd->bridge = BRIDGE_SPCA533;
842 break;
843 case 0x0960:
844 sd->subtype = LogitechClickSmart420;
845 sd->bridge = BRIDGE_SPCA504C;
846 break;
847 }
848 break;
849 case 0x0471: /* Philips */
850/* switch (product) { */
851/* case 0x0322: */
852 sd->bridge = BRIDGE_SPCA504B;
853/* break; */
854/* } */
855 break;
856 case 0x04a5: /* Benq */
857 switch (product) {
858 case 0x3003:
859 sd->bridge = BRIDGE_SPCA504B;
860 break;
861 case 0x3008:
862 case 0x300a:
863 sd->bridge = BRIDGE_SPCA533;
864 break;
865 }
866 break;
867 case 0x04f1: /* JVC */
868/* switch (product) { */
869/* case 0x1001: */
870 sd->bridge = BRIDGE_SPCA504B;
871/* break; */
872/* } */
873 break;
874 case 0x04fc: /* SunPlus */
875 switch (product) {
876 case 0x500c:
877 sd->bridge = BRIDGE_SPCA504B;
878 break;
879 case 0x504a:
880/* try to get the firmware as some cam answer 2.0.1.2.2
881 * and should be a spca504b then overwrite that setting */
882 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
883 fw = gspca_dev->usb_buf[0];
884 if (fw == 1) {
885 sd->subtype = AiptekMiniPenCam13;
886 sd->bridge = BRIDGE_SPCA504;
887 } else if (fw == 2) {
888 sd->bridge = BRIDGE_SPCA504B;
889 } else
890 return -ENODEV;
891 break;
892 case 0x504b:
893 sd->bridge = BRIDGE_SPCA504B;
894 break;
895 case 0x5330:
896 sd->bridge = BRIDGE_SPCA533;
897 break;
898 case 0x5360:
899 sd->bridge = BRIDGE_SPCA536;
900 break;
901 case 0xffff:
902 sd->bridge = BRIDGE_SPCA504B;
903 break;
904 }
905 break;
906 case 0x052b: /* ?? Megapix */
907/* switch (product) { */
908/* case 0x1513: */
909 sd->subtype = MegapixV4;
910 sd->bridge = BRIDGE_SPCA533;
911/* break; */
912/* } */
913 break;
914 case 0x0546: /* Polaroid */
915 switch (product) {
916 case 0x3155:
917 sd->bridge = BRIDGE_SPCA533;
918 break;
919 case 0x3191:
920 case 0x3273:
921 sd->bridge = BRIDGE_SPCA504B;
922 break;
923 }
924 break;
925 case 0x055f: /* Mustek cameras */
926 switch (product) {
927 case 0xc211:
928 sd->bridge = BRIDGE_SPCA536;
929 break;
930 case 0xc230:
931 case 0xc232:
932 sd->bridge = BRIDGE_SPCA533;
933 break;
934 case 0xc360:
935 sd->bridge = BRIDGE_SPCA536;
936 break;
937 case 0xc420:
938 sd->bridge = BRIDGE_SPCA504;
939 break;
940 case 0xc430:
941 case 0xc440:
942 sd->bridge = BRIDGE_SPCA533;
943 break;
944 case 0xc520:
945 sd->bridge = BRIDGE_SPCA504;
946 break;
947 case 0xc530:
948 case 0xc540:
949 case 0xc630:
950 case 0xc650:
951 sd->bridge = BRIDGE_SPCA533;
952 break;
953 }
954 break;
955 case 0x05da: /* Digital Dream cameras */
956/* switch (product) { */
957/* case 0x1018: */
958 sd->bridge = BRIDGE_SPCA504B;
959/* break; */
960/* } */
961 break;
962 case 0x06d6: /* Trust */
963/* switch (product) { */
964/* case 0x0031: */
965 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
966/* break; */
967/* } */
968 break;
969 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
970 switch (product) {
971 case 0x1311:
972 case 0x1314:
973 case 0x2211:
974 case 0x2221:
975 sd->bridge = BRIDGE_SPCA533;
976 break;
977 case 0x3261:
978 case 0x3281:
979 sd->bridge = BRIDGE_SPCA536;
980 break;
981 }
982 break;
983 case 0x08ca: /* Aiptek */
984 switch (product) {
985 case 0x0104:
986 case 0x0106:
987 sd->bridge = BRIDGE_SPCA533;
988 break;
989 case 0x2008:
990 sd->bridge = BRIDGE_SPCA504B;
991 break;
992 case 0x2010:
993 sd->bridge = BRIDGE_SPCA533;
994 break;
995 case 0x2016:
996 case 0x2018:
997 sd->bridge = BRIDGE_SPCA504B;
998 break;
999 case 0x2020:
1000 case 0x2022:
1001 sd->bridge = BRIDGE_SPCA533;
1002 break;
1003 case 0x2024:
1004 sd->bridge = BRIDGE_SPCA536;
1005 break;
1006 case 0x2028:
1007 sd->bridge = BRIDGE_SPCA533;
1008 break;
1009 case 0x2040:
1010 case 0x2042:
1011 case 0x2050:
1012 case 0x2060:
1013 sd->bridge = BRIDGE_SPCA536;
1014 break;
1015 }
1016 break;
1017 case 0x0d64: /* SunPlus */
1018/* switch (product) { */
1019/* case 0x0303: */
1020 sd->bridge = BRIDGE_SPCA536;
1021/* break; */
1022/* } */
1023 break;
1024 }
1025
1026 cam = &gspca_dev->cam;
1027 cam->dev_name = (char *) id->driver_info;
1028 cam->epaddr = 0x01;
1029
1030 switch (sd->bridge) {
1031 default:
1032/* case BRIDGE_SPCA504B: */
1033/* case BRIDGE_SPCA504: */
1034/* case BRIDGE_SPCA536: */
1035 cam->cam_mode = vga_mode;
1036 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1037 break;
1038 case BRIDGE_SPCA533:
1039 cam->cam_mode = custom_mode;
1040 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1041 break;
1042 case BRIDGE_SPCA504C:
1043 cam->cam_mode = vga_mode2;
1044 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1045 break;
1046 }
1047 sd->qindex = 5; /* set the quantization table */
1048 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1049 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1050 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1051 return 0;
1052}
1053
1054/* this function is called at open time */
1055static int sd_open(struct gspca_dev *gspca_dev)
1056{
1057 struct sd *sd = (struct sd *) gspca_dev;
1058 struct usb_device *dev = gspca_dev->dev;
1059 int rc;
1060 __u8 i;
1061 __u8 info[6];
1062 int err_code;
1063
1064 switch (sd->bridge) {
1065 case BRIDGE_SPCA504B:
1066 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1067 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1068 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1069 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1070 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1071 reg_w(dev, 0, 0, 0x2306, NULL, 0);
1072 /* fall thru */
1073 case BRIDGE_SPCA533:
1074 rc = spca504B_PollingDataReady(gspca_dev);
1075 spca50x_GetFirmware(gspca_dev);
1076 break;
1077 case BRIDGE_SPCA536:
1078 spca50x_GetFirmware(gspca_dev);
1079 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1080 gspca_dev->usb_buf[0] = 0;
1081 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1082 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1083 rc = spca504B_PollingDataReady(gspca_dev);
1084 reg_w(dev, 0x34, 0, 0, NULL, 0);
1085 spca504B_WaitCmdStatus(gspca_dev);
1086 break;
1087 case BRIDGE_SPCA504C: /* pccam600 */
1088 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1089 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1090 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
1091 spca504_wait_status(gspca_dev);
1092 if (sd->subtype == LogitechClickSmart420)
1093 write_vector(gspca_dev,
1094 spca504A_clicksmart420_open_data);
1095 else
1096 write_vector(gspca_dev, spca504_pccam600_open_data);
1097 err_code = spca50x_setup_qtable(gspca_dev,
1098 0x00, 0x2800,
1099 0x2840, qtable_creative_pccam);
1100 if (err_code < 0) {
1101 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1102 return err_code;
1103 }
1104 break;
1105 default:
1106/* case BRIDGE_SPCA504: */
1107 PDEBUG(D_STREAM, "Opening SPCA504");
1108 if (sd->subtype == AiptekMiniPenCam13) {
1109 /*****************************/
1110 for (i = 0; i < 6; i++)
1111 info[i] = reg_r_1(gspca_dev, i);
1112 PDEBUG(D_STREAM,
1113 "Read info: %d %d %d %d %d %d."
1114 " Should be 1,0,2,2,0,0",
1115 info[0], info[1], info[2],
1116 info[3], info[4], info[5]);
1117 /* spca504a aiptek */
1118 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1119 spca504A_acknowledged_command(gspca_dev, 0x24,
1120 8, 3, 0x9e, 1);
1121 /* Twice sequencial need status 0xff->0x9e->0x9d */
1122 spca504A_acknowledged_command(gspca_dev, 0x24,
1123 8, 3, 0x9e, 0);
1124
1125 spca504A_acknowledged_command(gspca_dev, 0x24,
1126 0, 0, 0x9d, 1);
1127 /******************************/
1128 /* spca504a aiptek */
1129 spca504A_acknowledged_command(gspca_dev, 0x08,
1130 6, 0, 0x86, 1);
1131/* reg_write (dev, 0, 0x2000, 0); */
1132/* reg_write (dev, 0, 0x2883, 1); */
1133/* spca504A_acknowledged_command (gspca_dev, 0x08,
1134 6, 0, 0x86, 1); */
1135/* spca504A_acknowledged_command (gspca_dev, 0x24,
1136 0, 0, 0x9D, 1); */
1137 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1138 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1139 spca504A_acknowledged_command(gspca_dev, 0x01,
1140 0x0f, 0, 0xff, 0);
1141 }
1142 /* setup qtable */
1143 reg_w_riv(dev, 0, 0x2000, 0);
1144 reg_w_riv(dev, 0, 0x2883, 1);
1145 err_code = spca50x_setup_qtable(gspca_dev,
1146 0x00, 0x2800,
1147 0x2840,
1148 qtable_spca504_default);
1149 if (err_code < 0) {
1150 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1151 return err_code;
1152 }
1153 break;
1154 }
1155 return 0;
1156}
1157
1158static void sd_start(struct gspca_dev *gspca_dev)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 struct usb_device *dev = gspca_dev->dev;
1162 int rc;
1163 int enable;
1164 __u8 i;
1165 __u8 info[6];
1166
1167 if (sd->bridge == BRIDGE_SPCA504B)
1168 spca504B_setQtable(gspca_dev);
1169 spca504B_SetSizeType(gspca_dev);
1170 switch (sd->bridge) {
1171 default:
1172/* case BRIDGE_SPCA504B: */
1173/* case BRIDGE_SPCA533: */
1174/* case BRIDGE_SPCA536: */
1175 if (sd->subtype == MegapixV4 ||
1176 sd->subtype == LogitechClickSmart820) {
1177 reg_w(dev, 0xf0, 0, 0, NULL, 0);
1178 spca504B_WaitCmdStatus(gspca_dev);
1179 reg_r(dev, 0xf0, 4, NULL, 0);
1180 spca504B_WaitCmdStatus(gspca_dev);
1181 } else {
1182 reg_w(dev, 0x31, 0, 4, NULL, 0);
1183 spca504B_WaitCmdStatus(gspca_dev);
1184 rc = spca504B_PollingDataReady(gspca_dev);
1185 }
1186 break;
1187 case BRIDGE_SPCA504:
1188 if (sd->subtype == AiptekMiniPenCam13) {
1189 for (i = 0; i < 6; i++)
1190 info[i] = reg_r_1(gspca_dev, i);
1191 PDEBUG(D_STREAM,
1192 "Read info: %d %d %d %d %d %d."
1193 " Should be 1,0,2,2,0,0",
1194 info[0], info[1], info[2],
1195 info[3], info[4], info[5]);
1196 /* spca504a aiptek */
1197 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1198 spca504A_acknowledged_command(gspca_dev, 0x24,
1199 8, 3, 0x9e, 1);
1200 /* Twice sequencial need status 0xff->0x9e->0x9d */
1201 spca504A_acknowledged_command(gspca_dev, 0x24,
1202 8, 3, 0x9e, 0);
1203 spca504A_acknowledged_command(gspca_dev, 0x24,
1204 0, 0, 0x9d, 1);
1205 } else {
1206 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1207 for (i = 0; i < 6; i++)
1208 info[i] = reg_r_1(gspca_dev, i);
1209 PDEBUG(D_STREAM,
1210 "Read info: %d %d %d %d %d %d."
1211 " Should be 1,0,2,2,0,0",
1212 info[0], info[1], info[2],
1213 info[3], info[4], info[5]);
1214 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1215 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1216 }
1217 spca504B_SetSizeType(gspca_dev);
1218 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1219 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1220 break;
1221 case BRIDGE_SPCA504C:
1222 if (sd->subtype == LogitechClickSmart420) {
1223 write_vector(gspca_dev,
1224 spca504A_clicksmart420_init_data);
1225 } else {
1226 write_vector(gspca_dev, spca504_pccam600_init_data);
1227 }
1228 enable = (sd->autogain ? 0x04 : 0x01);
1229 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1230 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1231
1232 /* set default exposure compensation and whiteness balance */
1233 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1234 reg_w_riv(dev, 0x30, 0x0002, 1600);
1235 spca504B_SetSizeType(gspca_dev);
1236 break;
1237 }
1238 sp5xx_initContBrigHueRegisters(gspca_dev);
1239}
1240
1241static void sd_stopN(struct gspca_dev *gspca_dev)
1242{
1243 struct sd *sd = (struct sd *) gspca_dev;
1244 struct usb_device *dev = gspca_dev->dev;
1245
1246 switch (sd->bridge) {
1247 default:
1248/* case BRIDGE_SPCA533: */
1249/* case BRIDGE_SPCA536: */
1250/* case BRIDGE_SPCA504B: */
1251 reg_w(dev, 0x31, 0, 0, NULL, 0);
1252 spca504B_WaitCmdStatus(gspca_dev);
1253 spca504B_PollingDataReady(gspca_dev);
1254 break;
1255 case BRIDGE_SPCA504:
1256 case BRIDGE_SPCA504C:
1257 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1258
1259 if (sd->subtype == AiptekMiniPenCam13) {
1260 /* spca504a aiptek */
1261/* spca504A_acknowledged_command(gspca_dev, 0x08,
1262 6, 0, 0x86, 1); */
1263 spca504A_acknowledged_command(gspca_dev, 0x24,
1264 0x00, 0x00, 0x9d, 1);
1265 spca504A_acknowledged_command(gspca_dev, 0x01,
1266 0x0f, 0x00, 0xff, 1);
1267 } else {
1268 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1269 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1270 }
1271 break;
1272 }
1273}
1274
1275static void sd_stop0(struct gspca_dev *gspca_dev)
1276{
1277}
1278
1279static void sd_close(struct gspca_dev *gspca_dev)
1280{
1281}
1282
1283static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1284 struct gspca_frame *frame, /* target */
1285 __u8 *data, /* isoc packet */
1286 int len) /* iso packet length */
1287{
1288 struct sd *sd = (struct sd *) gspca_dev;
1289 int i, sof = 0;
1290 unsigned char *s, *d;
1291 static unsigned char ffd9[] = {0xff, 0xd9};
1292
1293/* frames are jpeg 4.1.1 without 0xff escape */
1294 switch (sd->bridge) {
1295 case BRIDGE_SPCA533:
1296 if (data[0] == 0xff) {
1297 if (data[1] != 0x01) { /* drop packet */
1298/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1299 return;
1300 }
1301 sof = 1;
1302 data += SPCA533_OFFSET_DATA;
1303 len -= SPCA533_OFFSET_DATA;
1304 } else {
1305 data += 1;
1306 len -= 1;
1307 }
1308 break;
1309 case BRIDGE_SPCA536:
1310 if (data[0] == 0xff) {
1311 sof = 1;
1312 data += SPCA536_OFFSET_DATA;
1313 len -= SPCA536_OFFSET_DATA;
1314 } else {
1315 data += 2;
1316 len -= 2;
1317 }
1318 break;
1319 default:
1320/* case BRIDGE_SPCA504: */
1321/* case BRIDGE_SPCA504B: */
1322 switch (data[0]) {
1323 case 0xfe: /* start of frame */
1324 sof = 1;
1325 data += SPCA50X_OFFSET_DATA;
1326 len -= SPCA50X_OFFSET_DATA;
1327 break;
1328 case 0xff: /* drop packet */
1329/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1330 return;
1331 default:
1332 data += 1;
1333 len -= 1;
1334 break;
1335 }
1336 break;
1337 case BRIDGE_SPCA504C:
1338 switch (data[0]) {
1339 case 0xfe: /* start of frame */
1340 sof = 1;
1341 data += SPCA504_PCCAM600_OFFSET_DATA;
1342 len -= SPCA504_PCCAM600_OFFSET_DATA;
1343 break;
1344 case 0xff: /* drop packet */
1345/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1346 return;
1347 default:
1348 data += 1;
1349 len -= 1;
1350 break;
1351 }
1352 break;
1353 }
1354 if (sof) { /* start of frame */
1355 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1356 ffd9, 2);
1357
1358 /* put the JPEG header in the new frame */
1359 jpeg_put_header(gspca_dev, frame,
1360 ((struct sd *) gspca_dev)->qindex,
1361 0x22);
1362 }
1363
1364 /* add 0x00 after 0xff */
1365 for (i = len; --i >= 0; )
1366 if (data[i] == 0xff)
1367 break;
1368 if (i < 0) { /* no 0xff */
1369 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1370 return;
1371 }
1372 s = data;
1373 d = sd->packet;
1374 for (i = 0; i < len; i++) {
1375 *d++ = *s++;
1376 if (s[-1] == 0xff)
1377 *d++ = 0x00;
1378 }
1379 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1380 sd->packet, d - sd->packet);
1381}
1382
1383static void setbrightness(struct gspca_dev *gspca_dev)
1384{
1385 struct sd *sd = (struct sd *) gspca_dev;
1386 struct usb_device *dev = gspca_dev->dev;
1387
1388 switch (sd->bridge) {
1389 default:
1390/* case BRIDGE_SPCA533: */
1391/* case BRIDGE_SPCA504B: */
1392/* case BRIDGE_SPCA504: */
1393/* case BRIDGE_SPCA504C: */
1394 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1395 break;
1396 case BRIDGE_SPCA536:
1397 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1398 break;
1399 }
1400}
1401
1402static void getbrightness(struct gspca_dev *gspca_dev)
1403{
1404 struct sd *sd = (struct sd *) gspca_dev;
1405 __u16 brightness = 0;
1406
1407 switch (sd->bridge) {
1408 default:
1409/* case BRIDGE_SPCA533: */
1410/* case BRIDGE_SPCA504B: */
1411/* case BRIDGE_SPCA504: */
1412/* case BRIDGE_SPCA504C: */
1413 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1414 break;
1415 case BRIDGE_SPCA536:
1416 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1417 break;
1418 }
1419 sd->brightness = ((brightness & 0xff) - 128) % 255;
1420}
1421
1422static void setcontrast(struct gspca_dev *gspca_dev)
1423{
1424 struct sd *sd = (struct sd *) gspca_dev;
1425 struct usb_device *dev = gspca_dev->dev;
1426
1427 switch (sd->bridge) {
1428 default:
1429/* case BRIDGE_SPCA533: */
1430/* case BRIDGE_SPCA504B: */
1431/* case BRIDGE_SPCA504: */
1432/* case BRIDGE_SPCA504C: */
1433 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1434 break;
1435 case BRIDGE_SPCA536:
1436 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1437 break;
1438 }
1439}
1440
1441static void getcontrast(struct gspca_dev *gspca_dev)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444
1445 switch (sd->bridge) {
1446 default:
1447/* case BRIDGE_SPCA533: */
1448/* case BRIDGE_SPCA504B: */
1449/* case BRIDGE_SPCA504: */
1450/* case BRIDGE_SPCA504C: */
1451 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1452 break;
1453 case BRIDGE_SPCA536:
1454 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1455 break;
1456 }
1457}
1458
1459static void setcolors(struct gspca_dev *gspca_dev)
1460{
1461 struct sd *sd = (struct sd *) gspca_dev;
1462 struct usb_device *dev = gspca_dev->dev;
1463
1464 switch (sd->bridge) {
1465 default:
1466/* case BRIDGE_SPCA533: */
1467/* case BRIDGE_SPCA504B: */
1468/* case BRIDGE_SPCA504: */
1469/* case BRIDGE_SPCA504C: */
1470 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1471 break;
1472 case BRIDGE_SPCA536:
1473 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1474 break;
1475 }
1476}
1477
1478static void getcolors(struct gspca_dev *gspca_dev)
1479{
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 switch (sd->bridge) {
1483 default:
1484/* case BRIDGE_SPCA533: */
1485/* case BRIDGE_SPCA504B: */
1486/* case BRIDGE_SPCA504: */
1487/* case BRIDGE_SPCA504C: */
1488 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1489 break;
1490 case BRIDGE_SPCA536:
1491 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1492 break;
1493 }
1494}
1495
1496static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1497{
1498 struct sd *sd = (struct sd *) gspca_dev;
1499
1500 sd->brightness = val;
1501 if (gspca_dev->streaming)
1502 setbrightness(gspca_dev);
1503 return 0;
1504}
1505
1506static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1507{
1508 struct sd *sd = (struct sd *) gspca_dev;
1509
1510 getbrightness(gspca_dev);
1511 *val = sd->brightness;
1512 return 0;
1513}
1514
1515static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 sd->contrast = val;
1520 if (gspca_dev->streaming)
1521 setcontrast(gspca_dev);
1522 return 0;
1523}
1524
1525static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528
1529 getcontrast(gspca_dev);
1530 *val = sd->contrast;
1531 return 0;
1532}
1533
1534static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537
1538 sd->colors = val;
1539 if (gspca_dev->streaming)
1540 setcolors(gspca_dev);
1541 return 0;
1542}
1543
1544static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1545{
1546 struct sd *sd = (struct sd *) gspca_dev;
1547
1548 getcolors(gspca_dev);
1549 *val = sd->colors;
1550 return 0;
1551}
1552
1553static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 sd->autogain = val;
1558 return 0;
1559}
1560
1561static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1562{
1563 struct sd *sd = (struct sd *) gspca_dev;
1564
1565 *val = sd->autogain;
1566 return 0;
1567}
1568
1569/* sub-driver description */
1570static const struct sd_desc sd_desc = {
1571 .name = MODULE_NAME,
1572 .ctrls = sd_ctrls,
1573 .nctrls = ARRAY_SIZE(sd_ctrls),
1574 .config = sd_config,
1575 .open = sd_open,
1576 .start = sd_start,
1577 .stopN = sd_stopN,
1578 .stop0 = sd_stop0,
1579 .close = sd_close,
1580 .pkt_scan = sd_pkt_scan,
1581};
1582
1583/* -- module initialisation -- */
1584#define DVNM(name) .driver_info = (kernel_ulong_t) name
1585static const __devinitdata struct usb_device_id device_table[] = {
1586 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1587 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1588 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1589 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1590 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
1591 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1592 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1593 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1594 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1595 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1596 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1597 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1598 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1599 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1600 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1601 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1602 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1603 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1604 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1605 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1606 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1607 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1608 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1609 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1610 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1611 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1612 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1613 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1614 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1615 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1616 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1617 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1618 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1619 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1620 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1621 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1622 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1623 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1624 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1625 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1626 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1627 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1628 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1629 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1630 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1631 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1632 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1633 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1634 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1635 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1636 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1637 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1638 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1639 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1640 {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
1641 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1642 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1643 {}
1644};
1645MODULE_DEVICE_TABLE(usb, device_table);
1646
1647/* -- device connect -- */
1648static int sd_probe(struct usb_interface *intf,
1649 const struct usb_device_id *id)
1650{
1651 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1652 THIS_MODULE);
1653}
1654
1655static struct usb_driver sd_driver = {
1656 .name = MODULE_NAME,
1657 .id_table = device_table,
1658 .probe = sd_probe,
1659 .disconnect = gspca_disconnect,
1660};
1661
1662/* -- module insert / remove -- */
1663static int __init sd_mod_init(void)
1664{
1665 if (usb_register(&sd_driver) < 0)
1666 return -1;
1667 PDEBUG(D_PROBE, "v%s registered", version);
1668 return 0;
1669}
1670static void __exit sd_mod_exit(void)
1671{
1672 usb_deregister(&sd_driver);
1673 PDEBUG(D_PROBE, "deregistered");
1674}
1675
1676module_init(sd_mod_init);
1677module_exit(sd_mod_exit);