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