Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/sunplus.c
17531 views
1
/*
2
* Sunplus spca504(abc) spca533 spca536 library
3
* Copyright (C) 2005 Michel Xhaard [email protected]
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
MODULE_AUTHOR("Michel Xhaard <[email protected]>");
28
MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29
MODULE_LICENSE("GPL");
30
31
/* specific webcam descriptor */
32
struct sd {
33
struct gspca_dev gspca_dev; /* !! must be the first item */
34
35
s8 brightness;
36
u8 contrast;
37
u8 colors;
38
u8 autogain;
39
u8 quality;
40
#define QUALITY_MIN 70
41
#define QUALITY_MAX 95
42
#define QUALITY_DEF 85
43
44
u8 bridge;
45
#define BRIDGE_SPCA504 0
46
#define BRIDGE_SPCA504B 1
47
#define BRIDGE_SPCA504C 2
48
#define BRIDGE_SPCA533 3
49
#define BRIDGE_SPCA536 4
50
u8 subtype;
51
#define AiptekMiniPenCam13 1
52
#define LogitechClickSmart420 2
53
#define LogitechClickSmart820 3
54
#define MegapixV4 4
55
#define MegaImageVI 5
56
57
u8 jpeg_hdr[JPEG_HDR_SZ];
58
};
59
60
/* V4L2 controls supported by the driver */
61
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70
static const struct ctrl sd_ctrls[] = {
71
{
72
{
73
.id = V4L2_CID_BRIGHTNESS,
74
.type = V4L2_CTRL_TYPE_INTEGER,
75
.name = "Brightness",
76
.minimum = -128,
77
.maximum = 127,
78
.step = 1,
79
#define BRIGHTNESS_DEF 0
80
.default_value = BRIGHTNESS_DEF,
81
},
82
.set = sd_setbrightness,
83
.get = sd_getbrightness,
84
},
85
{
86
{
87
.id = V4L2_CID_CONTRAST,
88
.type = V4L2_CTRL_TYPE_INTEGER,
89
.name = "Contrast",
90
.minimum = 0,
91
.maximum = 0xff,
92
.step = 1,
93
#define CONTRAST_DEF 0x20
94
.default_value = CONTRAST_DEF,
95
},
96
.set = sd_setcontrast,
97
.get = sd_getcontrast,
98
},
99
{
100
{
101
.id = V4L2_CID_SATURATION,
102
.type = V4L2_CTRL_TYPE_INTEGER,
103
.name = "Color",
104
.minimum = 0,
105
.maximum = 0xff,
106
.step = 1,
107
#define COLOR_DEF 0x1a
108
.default_value = COLOR_DEF,
109
},
110
.set = sd_setcolors,
111
.get = sd_getcolors,
112
},
113
{
114
{
115
.id = V4L2_CID_AUTOGAIN,
116
.type = V4L2_CTRL_TYPE_BOOLEAN,
117
.name = "Auto Gain",
118
.minimum = 0,
119
.maximum = 1,
120
.step = 1,
121
#define AUTOGAIN_DEF 1
122
.default_value = AUTOGAIN_DEF,
123
},
124
.set = sd_setautogain,
125
.get = sd_getautogain,
126
},
127
};
128
129
static const 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
142
static const 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
155
static const 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
struct cmd {
191
u8 req;
192
u16 val;
193
u16 idx;
194
};
195
196
/* Initialisation data for the Creative PC-CAM 600 */
197
static const struct cmd spca504_pccam600_init_data[] = {
198
/* {0xa0, 0x0000, 0x0503}, * capture mode */
199
{0x00, 0x0000, 0x2000},
200
{0x00, 0x0013, 0x2301},
201
{0x00, 0x0003, 0x2000},
202
{0x00, 0x0001, 0x21ac},
203
{0x00, 0x0001, 0x21a6},
204
{0x00, 0x0000, 0x21a7}, /* brightness */
205
{0x00, 0x0020, 0x21a8}, /* contrast */
206
{0x00, 0x0001, 0x21ac}, /* sat/hue */
207
{0x00, 0x0000, 0x21ad}, /* hue */
208
{0x00, 0x001a, 0x21ae}, /* saturation */
209
{0x00, 0x0002, 0x21a3}, /* gamma */
210
{0x30, 0x0154, 0x0008},
211
{0x30, 0x0004, 0x0006},
212
{0x30, 0x0258, 0x0009},
213
{0x30, 0x0004, 0x0000},
214
{0x30, 0x0093, 0x0004},
215
{0x30, 0x0066, 0x0005},
216
{0x00, 0x0000, 0x2000},
217
{0x00, 0x0013, 0x2301},
218
{0x00, 0x0003, 0x2000},
219
{0x00, 0x0013, 0x2301},
220
{0x00, 0x0003, 0x2000},
221
};
222
223
/* Creative PC-CAM 600 specific open data, sent before using the
224
* generic initialisation data from spca504_open_data.
225
*/
226
static const struct cmd spca504_pccam600_open_data[] = {
227
{0x00, 0x0001, 0x2501},
228
{0x20, 0x0500, 0x0001}, /* snapshot mode */
229
{0x00, 0x0003, 0x2880},
230
{0x00, 0x0001, 0x2881},
231
};
232
233
/* Initialisation data for the logitech clicksmart 420 */
234
static const struct cmd spca504A_clicksmart420_init_data[] = {
235
/* {0xa0, 0x0000, 0x0503}, * capture mode */
236
{0x00, 0x0000, 0x2000},
237
{0x00, 0x0013, 0x2301},
238
{0x00, 0x0003, 0x2000},
239
{0x00, 0x0001, 0x21ac},
240
{0x00, 0x0001, 0x21a6},
241
{0x00, 0x0000, 0x21a7}, /* brightness */
242
{0x00, 0x0020, 0x21a8}, /* contrast */
243
{0x00, 0x0001, 0x21ac}, /* sat/hue */
244
{0x00, 0x0000, 0x21ad}, /* hue */
245
{0x00, 0x001a, 0x21ae}, /* saturation */
246
{0x00, 0x0002, 0x21a3}, /* gamma */
247
{0x30, 0x0004, 0x000a},
248
{0xb0, 0x0001, 0x0000},
249
250
251
{0xa1, 0x0080, 0x0001},
252
{0x30, 0x0049, 0x0000},
253
{0x30, 0x0060, 0x0005},
254
{0x0c, 0x0004, 0x0000},
255
{0x00, 0x0000, 0x0000},
256
{0x00, 0x0000, 0x2000},
257
{0x00, 0x0013, 0x2301},
258
{0x00, 0x0003, 0x2000},
259
{0x00, 0x0000, 0x2000},
260
261
};
262
263
/* clicksmart 420 open data ? */
264
static const struct cmd spca504A_clicksmart420_open_data[] = {
265
{0x00, 0x0001, 0x2501},
266
{0x20, 0x0502, 0x0000},
267
{0x06, 0x0000, 0x0000},
268
{0x00, 0x0004, 0x2880},
269
{0x00, 0x0001, 0x2881},
270
271
{0xa0, 0x0000, 0x0503},
272
};
273
274
static const u8 qtable_creative_pccam[2][64] = {
275
{ /* Q-table Y-components */
276
0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
277
0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
278
0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
279
0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
280
0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
281
0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
282
0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
283
0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
284
{ /* Q-table C-components */
285
0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
286
0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
287
0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288
0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
290
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
291
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
292
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
293
};
294
295
/* FIXME: This Q-table is identical to the Creative PC-CAM one,
296
* except for one byte. Possibly a typo?
297
* NWG: 18/05/2003.
298
*/
299
static const u8 qtable_spca504_default[2][64] = {
300
{ /* Q-table Y-components */
301
0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
302
0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
303
0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
304
0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
305
0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
306
0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
307
0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
308
0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
309
},
310
{ /* Q-table C-components */
311
0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
312
0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
313
0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314
0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
316
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
317
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
318
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
319
};
320
321
/* read <len> bytes to gspca_dev->usb_buf */
322
static void reg_r(struct gspca_dev *gspca_dev,
323
u8 req,
324
u16 index,
325
u16 len)
326
{
327
int ret;
328
329
#ifdef GSPCA_DEBUG
330
if (len > USB_BUF_SZ) {
331
err("reg_r: buffer overflow");
332
return;
333
}
334
#endif
335
if (gspca_dev->usb_err < 0)
336
return;
337
ret = usb_control_msg(gspca_dev->dev,
338
usb_rcvctrlpipe(gspca_dev->dev, 0),
339
req,
340
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
341
0, /* value */
342
index,
343
len ? gspca_dev->usb_buf : NULL, len,
344
500);
345
if (ret < 0) {
346
err("reg_r err %d", ret);
347
gspca_dev->usb_err = ret;
348
}
349
}
350
351
/* write one byte */
352
static void reg_w_1(struct gspca_dev *gspca_dev,
353
u8 req,
354
u16 value,
355
u16 index,
356
u16 byte)
357
{
358
int ret;
359
360
if (gspca_dev->usb_err < 0)
361
return;
362
gspca_dev->usb_buf[0] = byte;
363
ret = usb_control_msg(gspca_dev->dev,
364
usb_sndctrlpipe(gspca_dev->dev, 0),
365
req,
366
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
367
value, index,
368
gspca_dev->usb_buf, 1,
369
500);
370
if (ret < 0) {
371
err("reg_w_1 err %d", ret);
372
gspca_dev->usb_err = ret;
373
}
374
}
375
376
/* write req / index / value */
377
static void reg_w_riv(struct gspca_dev *gspca_dev,
378
u8 req, u16 index, u16 value)
379
{
380
struct usb_device *dev = gspca_dev->dev;
381
int ret;
382
383
if (gspca_dev->usb_err < 0)
384
return;
385
ret = usb_control_msg(dev,
386
usb_sndctrlpipe(dev, 0),
387
req,
388
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
389
value, index, NULL, 0, 500);
390
if (ret < 0) {
391
err("reg_w_riv err %d", ret);
392
gspca_dev->usb_err = ret;
393
return;
394
}
395
PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
396
req, index, value);
397
}
398
399
static void write_vector(struct gspca_dev *gspca_dev,
400
const struct cmd *data, int ncmds)
401
{
402
while (--ncmds >= 0) {
403
reg_w_riv(gspca_dev, data->req, data->idx, data->val);
404
data++;
405
}
406
}
407
408
static void setup_qtable(struct gspca_dev *gspca_dev,
409
const u8 qtable[2][64])
410
{
411
int i;
412
413
/* loop over y components */
414
for (i = 0; i < 64; i++)
415
reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
416
417
/* loop over c components */
418
for (i = 0; i < 64; i++)
419
reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
420
}
421
422
static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
423
u8 req, u16 idx, u16 val)
424
{
425
reg_w_riv(gspca_dev, req, idx, val);
426
reg_r(gspca_dev, 0x01, 0x0001, 1);
427
PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
428
reg_w_riv(gspca_dev, req, idx, val);
429
430
msleep(200);
431
reg_r(gspca_dev, 0x01, 0x0001, 1);
432
PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
433
}
434
435
#ifdef GSPCA_DEBUG
436
static void spca504_read_info(struct gspca_dev *gspca_dev)
437
{
438
int i;
439
u8 info[6];
440
441
for (i = 0; i < 6; i++) {
442
reg_r(gspca_dev, 0, i, 1);
443
info[i] = gspca_dev->usb_buf[0];
444
}
445
PDEBUG(D_STREAM,
446
"Read info: %d %d %d %d %d %d."
447
" Should be 1,0,2,2,0,0",
448
info[0], info[1], info[2],
449
info[3], info[4], info[5]);
450
}
451
#endif
452
453
static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
454
u8 req,
455
u16 idx, u16 val, u8 endcode, u8 count)
456
{
457
u16 status;
458
459
reg_w_riv(gspca_dev, req, idx, val);
460
reg_r(gspca_dev, 0x01, 0x0001, 1);
461
if (gspca_dev->usb_err < 0)
462
return;
463
PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
464
gspca_dev->usb_buf[0], endcode);
465
if (!count)
466
return;
467
count = 200;
468
while (--count > 0) {
469
msleep(10);
470
/* gsmart mini2 write a each wait setting 1 ms is enough */
471
/* reg_w_riv(gspca_dev, req, idx, val); */
472
reg_r(gspca_dev, 0x01, 0x0001, 1);
473
status = gspca_dev->usb_buf[0];
474
if (status == endcode) {
475
PDEBUG(D_FRAM, "status 0x%04x after wait %d",
476
status, 200 - count);
477
break;
478
}
479
}
480
}
481
482
static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
483
{
484
int count = 10;
485
486
while (--count > 0) {
487
reg_r(gspca_dev, 0x21, 0, 1);
488
if ((gspca_dev->usb_buf[0] & 0x01) == 0)
489
break;
490
msleep(10);
491
}
492
}
493
494
static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
495
{
496
int count = 50;
497
498
while (--count > 0) {
499
reg_r(gspca_dev, 0x21, 1, 1);
500
if (gspca_dev->usb_buf[0] != 0) {
501
reg_w_1(gspca_dev, 0x21, 0, 1, 0);
502
reg_r(gspca_dev, 0x21, 1, 1);
503
spca504B_PollingDataReady(gspca_dev);
504
break;
505
}
506
msleep(10);
507
}
508
}
509
510
#ifdef GSPCA_DEBUG
511
static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
512
{
513
u8 *data;
514
515
data = gspca_dev->usb_buf;
516
reg_r(gspca_dev, 0x20, 0, 5);
517
PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
518
data[0], data[1], data[2], data[3], data[4]);
519
reg_r(gspca_dev, 0x23, 0, 64);
520
reg_r(gspca_dev, 0x23, 1, 64);
521
}
522
#endif
523
524
static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
525
{
526
struct sd *sd = (struct sd *) gspca_dev;
527
u8 Size;
528
529
Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
530
switch (sd->bridge) {
531
case BRIDGE_SPCA533:
532
reg_w_riv(gspca_dev, 0x31, 0, 0);
533
spca504B_WaitCmdStatus(gspca_dev);
534
spca504B_PollingDataReady(gspca_dev);
535
#ifdef GSPCA_DEBUG
536
spca50x_GetFirmware(gspca_dev);
537
#endif
538
reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
539
reg_r(gspca_dev, 0x24, 8, 1);
540
541
reg_w_1(gspca_dev, 0x25, 0, 4, Size);
542
reg_r(gspca_dev, 0x25, 4, 1); /* size */
543
spca504B_PollingDataReady(gspca_dev);
544
545
/* Init the cam width height with some values get on init ? */
546
reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
547
spca504B_WaitCmdStatus(gspca_dev);
548
spca504B_PollingDataReady(gspca_dev);
549
break;
550
default:
551
/* case BRIDGE_SPCA504B: */
552
/* case BRIDGE_SPCA536: */
553
reg_w_1(gspca_dev, 0x25, 0, 4, Size);
554
reg_r(gspca_dev, 0x25, 4, 1); /* size */
555
reg_w_1(gspca_dev, 0x27, 0, 0, 6);
556
reg_r(gspca_dev, 0x27, 0, 1); /* type */
557
spca504B_PollingDataReady(gspca_dev);
558
break;
559
case BRIDGE_SPCA504:
560
Size += 3;
561
if (sd->subtype == AiptekMiniPenCam13) {
562
/* spca504a aiptek */
563
spca504A_acknowledged_command(gspca_dev,
564
0x08, Size, 0,
565
0x80 | (Size & 0x0f), 1);
566
spca504A_acknowledged_command(gspca_dev,
567
1, 3, 0, 0x9f, 0);
568
} else {
569
spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
570
}
571
break;
572
case BRIDGE_SPCA504C:
573
/* capture mode */
574
reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
575
reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
576
break;
577
}
578
}
579
580
static void spca504_wait_status(struct gspca_dev *gspca_dev)
581
{
582
int cnt;
583
584
cnt = 256;
585
while (--cnt > 0) {
586
/* With this we get the status, when return 0 it's all ok */
587
reg_r(gspca_dev, 0x06, 0x00, 1);
588
if (gspca_dev->usb_buf[0] == 0)
589
return;
590
msleep(10);
591
}
592
}
593
594
static void spca504B_setQtable(struct gspca_dev *gspca_dev)
595
{
596
reg_w_1(gspca_dev, 0x26, 0, 0, 3);
597
reg_r(gspca_dev, 0x26, 0, 1);
598
spca504B_PollingDataReady(gspca_dev);
599
}
600
601
static void setbrightness(struct gspca_dev *gspca_dev)
602
{
603
struct sd *sd = (struct sd *) gspca_dev;
604
u16 reg;
605
606
reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
607
reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
608
}
609
610
static void setcontrast(struct gspca_dev *gspca_dev)
611
{
612
struct sd *sd = (struct sd *) gspca_dev;
613
u16 reg;
614
615
reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
616
reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
617
}
618
619
static void setcolors(struct gspca_dev *gspca_dev)
620
{
621
struct sd *sd = (struct sd *) gspca_dev;
622
u16 reg;
623
624
reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
625
reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
626
}
627
628
static void init_ctl_reg(struct gspca_dev *gspca_dev)
629
{
630
struct sd *sd = (struct sd *) gspca_dev;
631
int pollreg = 1;
632
633
setbrightness(gspca_dev);
634
setcontrast(gspca_dev);
635
setcolors(gspca_dev);
636
637
switch (sd->bridge) {
638
case BRIDGE_SPCA504:
639
case BRIDGE_SPCA504C:
640
pollreg = 0;
641
/* fall thru */
642
default:
643
/* case BRIDGE_SPCA533: */
644
/* case BRIDGE_SPCA504B: */
645
reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
646
reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
647
reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
648
break;
649
case BRIDGE_SPCA536:
650
reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
651
reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
652
reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
653
break;
654
}
655
if (pollreg)
656
spca504B_PollingDataReady(gspca_dev);
657
}
658
659
/* this function is called at probe time */
660
static int sd_config(struct gspca_dev *gspca_dev,
661
const struct usb_device_id *id)
662
{
663
struct sd *sd = (struct sd *) gspca_dev;
664
struct cam *cam;
665
666
cam = &gspca_dev->cam;
667
668
sd->bridge = id->driver_info >> 8;
669
sd->subtype = id->driver_info;
670
671
if (sd->subtype == AiptekMiniPenCam13) {
672
673
/* try to get the firmware as some cam answer 2.0.1.2.2
674
* and should be a spca504b then overwrite that setting */
675
reg_r(gspca_dev, 0x20, 0, 1);
676
switch (gspca_dev->usb_buf[0]) {
677
case 1:
678
break; /* (right bridge/subtype) */
679
case 2:
680
sd->bridge = BRIDGE_SPCA504B;
681
sd->subtype = 0;
682
break;
683
default:
684
return -ENODEV;
685
}
686
}
687
688
switch (sd->bridge) {
689
default:
690
/* case BRIDGE_SPCA504B: */
691
/* case BRIDGE_SPCA504: */
692
/* case BRIDGE_SPCA536: */
693
cam->cam_mode = vga_mode;
694
cam->nmodes = ARRAY_SIZE(vga_mode);
695
break;
696
case BRIDGE_SPCA533:
697
cam->cam_mode = custom_mode;
698
if (sd->subtype == MegaImageVI) /* 320x240 only */
699
cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
700
else
701
cam->nmodes = ARRAY_SIZE(custom_mode);
702
break;
703
case BRIDGE_SPCA504C:
704
cam->cam_mode = vga_mode2;
705
cam->nmodes = ARRAY_SIZE(vga_mode2);
706
break;
707
}
708
sd->brightness = BRIGHTNESS_DEF;
709
sd->contrast = CONTRAST_DEF;
710
sd->colors = COLOR_DEF;
711
sd->autogain = AUTOGAIN_DEF;
712
sd->quality = QUALITY_DEF;
713
return 0;
714
}
715
716
/* this function is called at probe and resume time */
717
static int sd_init(struct gspca_dev *gspca_dev)
718
{
719
struct sd *sd = (struct sd *) gspca_dev;
720
721
switch (sd->bridge) {
722
case BRIDGE_SPCA504B:
723
reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
724
reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
725
reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
726
reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
727
reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
728
reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
729
/* fall thru */
730
case BRIDGE_SPCA533:
731
spca504B_PollingDataReady(gspca_dev);
732
#ifdef GSPCA_DEBUG
733
spca50x_GetFirmware(gspca_dev);
734
#endif
735
break;
736
case BRIDGE_SPCA536:
737
#ifdef GSPCA_DEBUG
738
spca50x_GetFirmware(gspca_dev);
739
#endif
740
reg_r(gspca_dev, 0x00, 0x5002, 1);
741
reg_w_1(gspca_dev, 0x24, 0, 0, 0);
742
reg_r(gspca_dev, 0x24, 0, 1);
743
spca504B_PollingDataReady(gspca_dev);
744
reg_w_riv(gspca_dev, 0x34, 0, 0);
745
spca504B_WaitCmdStatus(gspca_dev);
746
break;
747
case BRIDGE_SPCA504C: /* pccam600 */
748
PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
749
reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
750
reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
751
spca504_wait_status(gspca_dev);
752
if (sd->subtype == LogitechClickSmart420)
753
write_vector(gspca_dev,
754
spca504A_clicksmart420_open_data,
755
ARRAY_SIZE(spca504A_clicksmart420_open_data));
756
else
757
write_vector(gspca_dev, spca504_pccam600_open_data,
758
ARRAY_SIZE(spca504_pccam600_open_data));
759
setup_qtable(gspca_dev, qtable_creative_pccam);
760
break;
761
default:
762
/* case BRIDGE_SPCA504: */
763
PDEBUG(D_STREAM, "Opening SPCA504");
764
if (sd->subtype == AiptekMiniPenCam13) {
765
#ifdef GSPCA_DEBUG
766
spca504_read_info(gspca_dev);
767
#endif
768
769
/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
770
spca504A_acknowledged_command(gspca_dev, 0x24,
771
8, 3, 0x9e, 1);
772
/* Twice sequential need status 0xff->0x9e->0x9d */
773
spca504A_acknowledged_command(gspca_dev, 0x24,
774
8, 3, 0x9e, 0);
775
776
spca504A_acknowledged_command(gspca_dev, 0x24,
777
0, 0, 0x9d, 1);
778
/******************************/
779
/* spca504a aiptek */
780
spca504A_acknowledged_command(gspca_dev, 0x08,
781
6, 0, 0x86, 1);
782
/* reg_write (dev, 0, 0x2000, 0); */
783
/* reg_write (dev, 0, 0x2883, 1); */
784
/* spca504A_acknowledged_command (gspca_dev, 0x08,
785
6, 0, 0x86, 1); */
786
/* spca504A_acknowledged_command (gspca_dev, 0x24,
787
0, 0, 0x9D, 1); */
788
reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
789
/* L92 sno1t.txt */
790
reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
791
spca504A_acknowledged_command(gspca_dev, 0x01,
792
0x0f, 0, 0xff, 0);
793
}
794
/* setup qtable */
795
reg_w_riv(gspca_dev, 0, 0x2000, 0);
796
reg_w_riv(gspca_dev, 0, 0x2883, 1);
797
setup_qtable(gspca_dev, qtable_spca504_default);
798
break;
799
}
800
return gspca_dev->usb_err;
801
}
802
803
static int sd_start(struct gspca_dev *gspca_dev)
804
{
805
struct sd *sd = (struct sd *) gspca_dev;
806
int enable;
807
808
/* create the JPEG header */
809
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
810
0x22); /* JPEG 411 */
811
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
812
813
if (sd->bridge == BRIDGE_SPCA504B)
814
spca504B_setQtable(gspca_dev);
815
spca504B_SetSizeType(gspca_dev);
816
switch (sd->bridge) {
817
default:
818
/* case BRIDGE_SPCA504B: */
819
/* case BRIDGE_SPCA533: */
820
/* case BRIDGE_SPCA536: */
821
switch (sd->subtype) {
822
case MegapixV4:
823
case LogitechClickSmart820:
824
case MegaImageVI:
825
reg_w_riv(gspca_dev, 0xf0, 0, 0);
826
spca504B_WaitCmdStatus(gspca_dev);
827
reg_r(gspca_dev, 0xf0, 4, 0);
828
spca504B_WaitCmdStatus(gspca_dev);
829
break;
830
default:
831
reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
832
spca504B_WaitCmdStatus(gspca_dev);
833
spca504B_PollingDataReady(gspca_dev);
834
break;
835
}
836
break;
837
case BRIDGE_SPCA504:
838
if (sd->subtype == AiptekMiniPenCam13) {
839
#ifdef GSPCA_DEBUG
840
spca504_read_info(gspca_dev);
841
#endif
842
843
/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
844
spca504A_acknowledged_command(gspca_dev, 0x24,
845
8, 3, 0x9e, 1);
846
/* Twice sequential need status 0xff->0x9e->0x9d */
847
spca504A_acknowledged_command(gspca_dev, 0x24,
848
8, 3, 0x9e, 0);
849
spca504A_acknowledged_command(gspca_dev, 0x24,
850
0, 0, 0x9d, 1);
851
} else {
852
spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
853
#ifdef GSPCA_DEBUG
854
spca504_read_info(gspca_dev);
855
#endif
856
spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
857
spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
858
}
859
spca504B_SetSizeType(gspca_dev);
860
reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
861
/* L92 sno1t.txt */
862
reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
863
break;
864
case BRIDGE_SPCA504C:
865
if (sd->subtype == LogitechClickSmart420) {
866
write_vector(gspca_dev,
867
spca504A_clicksmart420_init_data,
868
ARRAY_SIZE(spca504A_clicksmart420_init_data));
869
} else {
870
write_vector(gspca_dev, spca504_pccam600_init_data,
871
ARRAY_SIZE(spca504_pccam600_init_data));
872
}
873
enable = (sd->autogain ? 0x04 : 0x01);
874
reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
875
/* auto exposure */
876
reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
877
/* auto whiteness */
878
879
/* set default exposure compensation and whiteness balance */
880
reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
881
reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
882
spca504B_SetSizeType(gspca_dev);
883
break;
884
}
885
init_ctl_reg(gspca_dev);
886
return gspca_dev->usb_err;
887
}
888
889
static void sd_stopN(struct gspca_dev *gspca_dev)
890
{
891
struct sd *sd = (struct sd *) gspca_dev;
892
893
switch (sd->bridge) {
894
default:
895
/* case BRIDGE_SPCA533: */
896
/* case BRIDGE_SPCA536: */
897
/* case BRIDGE_SPCA504B: */
898
reg_w_riv(gspca_dev, 0x31, 0, 0);
899
spca504B_WaitCmdStatus(gspca_dev);
900
spca504B_PollingDataReady(gspca_dev);
901
break;
902
case BRIDGE_SPCA504:
903
case BRIDGE_SPCA504C:
904
reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
905
906
if (sd->subtype == AiptekMiniPenCam13) {
907
/* spca504a aiptek */
908
/* spca504A_acknowledged_command(gspca_dev, 0x08,
909
6, 0, 0x86, 1); */
910
spca504A_acknowledged_command(gspca_dev, 0x24,
911
0x00, 0x00, 0x9d, 1);
912
spca504A_acknowledged_command(gspca_dev, 0x01,
913
0x0f, 0x00, 0xff, 1);
914
} else {
915
spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
916
reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
917
}
918
break;
919
}
920
}
921
922
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
923
u8 *data, /* isoc packet */
924
int len) /* iso packet length */
925
{
926
struct sd *sd = (struct sd *) gspca_dev;
927
int i, sof = 0;
928
static u8 ffd9[] = {0xff, 0xd9};
929
930
/* frames are jpeg 4.1.1 without 0xff escape */
931
switch (sd->bridge) {
932
case BRIDGE_SPCA533:
933
if (data[0] == 0xff) {
934
if (data[1] != 0x01) { /* drop packet */
935
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
936
return;
937
}
938
sof = 1;
939
data += SPCA533_OFFSET_DATA;
940
len -= SPCA533_OFFSET_DATA;
941
} else {
942
data += 1;
943
len -= 1;
944
}
945
break;
946
case BRIDGE_SPCA536:
947
if (data[0] == 0xff) {
948
sof = 1;
949
data += SPCA536_OFFSET_DATA;
950
len -= SPCA536_OFFSET_DATA;
951
} else {
952
data += 2;
953
len -= 2;
954
}
955
break;
956
default:
957
/* case BRIDGE_SPCA504: */
958
/* case BRIDGE_SPCA504B: */
959
switch (data[0]) {
960
case 0xfe: /* start of frame */
961
sof = 1;
962
data += SPCA50X_OFFSET_DATA;
963
len -= SPCA50X_OFFSET_DATA;
964
break;
965
case 0xff: /* drop packet */
966
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
967
return;
968
default:
969
data += 1;
970
len -= 1;
971
break;
972
}
973
break;
974
case BRIDGE_SPCA504C:
975
switch (data[0]) {
976
case 0xfe: /* start of frame */
977
sof = 1;
978
data += SPCA504_PCCAM600_OFFSET_DATA;
979
len -= SPCA504_PCCAM600_OFFSET_DATA;
980
break;
981
case 0xff: /* drop packet */
982
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
983
return;
984
default:
985
data += 1;
986
len -= 1;
987
break;
988
}
989
break;
990
}
991
if (sof) { /* start of frame */
992
gspca_frame_add(gspca_dev, LAST_PACKET,
993
ffd9, 2);
994
995
/* put the JPEG header in the new frame */
996
gspca_frame_add(gspca_dev, FIRST_PACKET,
997
sd->jpeg_hdr, JPEG_HDR_SZ);
998
}
999
1000
/* add 0x00 after 0xff */
1001
i = 0;
1002
do {
1003
if (data[i] == 0xff) {
1004
gspca_frame_add(gspca_dev, INTER_PACKET,
1005
data, i + 1);
1006
len -= i;
1007
data += i;
1008
*data = 0x00;
1009
i = 0;
1010
}
1011
i++;
1012
} while (i < len);
1013
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1014
}
1015
1016
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1017
{
1018
struct sd *sd = (struct sd *) gspca_dev;
1019
1020
sd->brightness = val;
1021
if (gspca_dev->streaming)
1022
setbrightness(gspca_dev);
1023
return gspca_dev->usb_err;
1024
}
1025
1026
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1027
{
1028
struct sd *sd = (struct sd *) gspca_dev;
1029
1030
*val = sd->brightness;
1031
return 0;
1032
}
1033
1034
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1035
{
1036
struct sd *sd = (struct sd *) gspca_dev;
1037
1038
sd->contrast = val;
1039
if (gspca_dev->streaming)
1040
setcontrast(gspca_dev);
1041
return gspca_dev->usb_err;
1042
}
1043
1044
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1045
{
1046
struct sd *sd = (struct sd *) gspca_dev;
1047
1048
*val = sd->contrast;
1049
return 0;
1050
}
1051
1052
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1053
{
1054
struct sd *sd = (struct sd *) gspca_dev;
1055
1056
sd->colors = val;
1057
if (gspca_dev->streaming)
1058
setcolors(gspca_dev);
1059
return gspca_dev->usb_err;
1060
}
1061
1062
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1063
{
1064
struct sd *sd = (struct sd *) gspca_dev;
1065
1066
*val = sd->colors;
1067
return 0;
1068
}
1069
1070
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1071
{
1072
struct sd *sd = (struct sd *) gspca_dev;
1073
1074
sd->autogain = val;
1075
return 0;
1076
}
1077
1078
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1079
{
1080
struct sd *sd = (struct sd *) gspca_dev;
1081
1082
*val = sd->autogain;
1083
return 0;
1084
}
1085
1086
static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1087
struct v4l2_jpegcompression *jcomp)
1088
{
1089
struct sd *sd = (struct sd *) gspca_dev;
1090
1091
if (jcomp->quality < QUALITY_MIN)
1092
sd->quality = QUALITY_MIN;
1093
else if (jcomp->quality > QUALITY_MAX)
1094
sd->quality = QUALITY_MAX;
1095
else
1096
sd->quality = jcomp->quality;
1097
if (gspca_dev->streaming)
1098
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1099
return gspca_dev->usb_err;
1100
}
1101
1102
static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1103
struct v4l2_jpegcompression *jcomp)
1104
{
1105
struct sd *sd = (struct sd *) gspca_dev;
1106
1107
memset(jcomp, 0, sizeof *jcomp);
1108
jcomp->quality = sd->quality;
1109
jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1110
| V4L2_JPEG_MARKER_DQT;
1111
return 0;
1112
}
1113
1114
/* sub-driver description */
1115
static const struct sd_desc sd_desc = {
1116
.name = MODULE_NAME,
1117
.ctrls = sd_ctrls,
1118
.nctrls = ARRAY_SIZE(sd_ctrls),
1119
.config = sd_config,
1120
.init = sd_init,
1121
.start = sd_start,
1122
.stopN = sd_stopN,
1123
.pkt_scan = sd_pkt_scan,
1124
.get_jcomp = sd_get_jcomp,
1125
.set_jcomp = sd_set_jcomp,
1126
};
1127
1128
/* -- module initialisation -- */
1129
#define BS(bridge, subtype) \
1130
.driver_info = (BRIDGE_ ## bridge << 8) \
1131
| (subtype)
1132
static const struct usb_device_id device_table[] = {
1133
{USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1134
{USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1135
{USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1136
{USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1137
{USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1138
{USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1139
{USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1140
{USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1141
{USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1142
{USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1143
{USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1144
{USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1145
{USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1146
{USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1147
{USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1148
{USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1149
{USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1150
{USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1151
{USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1152
{USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1153
{USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1154
{USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1155
{USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1156
{USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1157
{USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1158
{USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1159
{USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1160
{USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1161
{USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1162
{USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1163
{USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1164
{USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1165
{USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1166
{USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1167
{USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1168
{USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1169
{USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1170
{USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1171
{USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1172
{USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1173
{USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1174
{USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1175
{USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1176
{USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1177
{USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1178
{USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1179
{USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1180
{USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1181
{USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1182
{USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1183
{USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1184
{USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1185
{USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1186
{USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1187
{USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1188
{USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1189
{USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1190
{USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1191
{USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1192
{}
1193
};
1194
MODULE_DEVICE_TABLE(usb, device_table);
1195
1196
/* -- device connect -- */
1197
static int sd_probe(struct usb_interface *intf,
1198
const struct usb_device_id *id)
1199
{
1200
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1201
THIS_MODULE);
1202
}
1203
1204
static struct usb_driver sd_driver = {
1205
.name = MODULE_NAME,
1206
.id_table = device_table,
1207
.probe = sd_probe,
1208
.disconnect = gspca_disconnect,
1209
#ifdef CONFIG_PM
1210
.suspend = gspca_suspend,
1211
.resume = gspca_resume,
1212
#endif
1213
};
1214
1215
/* -- module insert / remove -- */
1216
static int __init sd_mod_init(void)
1217
{
1218
return usb_register(&sd_driver);
1219
}
1220
static void __exit sd_mod_exit(void)
1221
{
1222
usb_deregister(&sd_driver);
1223
}
1224
1225
module_init(sd_mod_init);
1226
module_exit(sd_mod_exit);
1227
1228