2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
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.
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #define MODULE_NAME "sunplus"
25 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
27 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev
; /* !! must be the first item */
38 #define BRIDGE_SPCA504 0
39 #define BRIDGE_SPCA504B 1
40 #define BRIDGE_SPCA504C 2
41 #define BRIDGE_SPCA533 3
42 #define BRIDGE_SPCA536 4
44 #define AiptekMiniPenCam13 1
45 #define LogitechClickSmart420 2
46 #define LogitechClickSmart820 3
50 u8 jpeg_hdr
[JPEG_HDR_SZ
];
53 static const struct v4l2_pix_format vga_mode
[] = {
54 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
56 .sizeimage
= 320 * 240 * 3 / 8 + 590,
57 .colorspace
= V4L2_COLORSPACE_JPEG
,
59 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
61 .sizeimage
= 640 * 480 * 3 / 8 + 590,
62 .colorspace
= V4L2_COLORSPACE_JPEG
,
66 static const struct v4l2_pix_format custom_mode
[] = {
67 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
69 .sizeimage
= 320 * 240 * 3 / 8 + 590,
70 .colorspace
= V4L2_COLORSPACE_JPEG
,
72 {464, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
74 .sizeimage
= 464 * 480 * 3 / 8 + 590,
75 .colorspace
= V4L2_COLORSPACE_JPEG
,
79 static const struct v4l2_pix_format vga_mode2
[] = {
80 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
82 .sizeimage
= 176 * 144 * 3 / 8 + 590,
83 .colorspace
= V4L2_COLORSPACE_JPEG
,
85 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
87 .sizeimage
= 320 * 240 * 3 / 8 + 590,
88 .colorspace
= V4L2_COLORSPACE_JPEG
,
90 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
92 .sizeimage
= 352 * 288 * 3 / 8 + 590,
93 .colorspace
= V4L2_COLORSPACE_JPEG
,
95 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
97 .sizeimage
= 640 * 480 * 3 / 8 + 590,
98 .colorspace
= V4L2_COLORSPACE_JPEG
,
102 #define SPCA50X_OFFSET_DATA 10
103 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
104 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
105 #define SPCA504_PCCAM600_OFFSET_MODE 5
106 #define SPCA504_PCCAM600_OFFSET_DATA 14
107 /* Frame packet header offsets for the spca533 */
108 #define SPCA533_OFFSET_DATA 16
109 #define SPCA533_OFFSET_FRAMSEQ 15
110 /* Frame packet header offsets for the spca536 */
111 #define SPCA536_OFFSET_DATA 4
112 #define SPCA536_OFFSET_FRAMSEQ 1
120 /* Initialisation data for the Creative PC-CAM 600 */
121 static const struct cmd spca504_pccam600_init_data
[] = {
122 /* {0xa0, 0x0000, 0x0503}, * capture mode */
123 {0x00, 0x0000, 0x2000},
124 {0x00, 0x0013, 0x2301},
125 {0x00, 0x0003, 0x2000},
126 {0x00, 0x0001, 0x21ac},
127 {0x00, 0x0001, 0x21a6},
128 {0x00, 0x0000, 0x21a7}, /* brightness */
129 {0x00, 0x0020, 0x21a8}, /* contrast */
130 {0x00, 0x0001, 0x21ac}, /* sat/hue */
131 {0x00, 0x0000, 0x21ad}, /* hue */
132 {0x00, 0x001a, 0x21ae}, /* saturation */
133 {0x00, 0x0002, 0x21a3}, /* gamma */
134 {0x30, 0x0154, 0x0008},
135 {0x30, 0x0004, 0x0006},
136 {0x30, 0x0258, 0x0009},
137 {0x30, 0x0004, 0x0000},
138 {0x30, 0x0093, 0x0004},
139 {0x30, 0x0066, 0x0005},
140 {0x00, 0x0000, 0x2000},
141 {0x00, 0x0013, 0x2301},
142 {0x00, 0x0003, 0x2000},
143 {0x00, 0x0013, 0x2301},
144 {0x00, 0x0003, 0x2000},
147 /* Creative PC-CAM 600 specific open data, sent before using the
148 * generic initialisation data from spca504_open_data.
150 static const struct cmd spca504_pccam600_open_data
[] = {
151 {0x00, 0x0001, 0x2501},
152 {0x20, 0x0500, 0x0001}, /* snapshot mode */
153 {0x00, 0x0003, 0x2880},
154 {0x00, 0x0001, 0x2881},
157 /* Initialisation data for the logitech clicksmart 420 */
158 static const struct cmd spca504A_clicksmart420_init_data
[] = {
159 /* {0xa0, 0x0000, 0x0503}, * capture mode */
160 {0x00, 0x0000, 0x2000},
161 {0x00, 0x0013, 0x2301},
162 {0x00, 0x0003, 0x2000},
163 {0x00, 0x0001, 0x21ac},
164 {0x00, 0x0001, 0x21a6},
165 {0x00, 0x0000, 0x21a7}, /* brightness */
166 {0x00, 0x0020, 0x21a8}, /* contrast */
167 {0x00, 0x0001, 0x21ac}, /* sat/hue */
168 {0x00, 0x0000, 0x21ad}, /* hue */
169 {0x00, 0x001a, 0x21ae}, /* saturation */
170 {0x00, 0x0002, 0x21a3}, /* gamma */
171 {0x30, 0x0004, 0x000a},
172 {0xb0, 0x0001, 0x0000},
174 {0xa1, 0x0080, 0x0001},
175 {0x30, 0x0049, 0x0000},
176 {0x30, 0x0060, 0x0005},
177 {0x0c, 0x0004, 0x0000},
178 {0x00, 0x0000, 0x0000},
179 {0x00, 0x0000, 0x2000},
180 {0x00, 0x0013, 0x2301},
181 {0x00, 0x0003, 0x2000},
184 /* clicksmart 420 open data ? */
185 static const struct cmd spca504A_clicksmart420_open_data
[] = {
186 {0x00, 0x0001, 0x2501},
187 {0x20, 0x0502, 0x0000},
188 {0x06, 0x0000, 0x0000},
189 {0x00, 0x0004, 0x2880},
190 {0x00, 0x0001, 0x2881},
192 {0xa0, 0x0000, 0x0503},
195 static const u8 qtable_creative_pccam
[2][64] = {
196 { /* Q-table Y-components */
197 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
198 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
199 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
200 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
201 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
202 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
203 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
204 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
205 { /* Q-table C-components */
206 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
207 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
208 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
209 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
210 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
211 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
212 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
216 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
217 * except for one byte. Possibly a typo?
220 static const u8 qtable_spca504_default
[2][64] = {
221 { /* Q-table Y-components */
222 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
223 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
224 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
225 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
226 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
227 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
228 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
229 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
231 { /* Q-table C-components */
232 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
233 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
234 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
235 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
236 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
237 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
238 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
242 /* read <len> bytes to gspca_dev->usb_buf */
243 static void reg_r(struct gspca_dev
*gspca_dev
,
250 if (len
> USB_BUF_SZ
) {
251 gspca_err(gspca_dev
, "reg_r: buffer overflow\n");
254 if (gspca_dev
->usb_err
< 0)
256 ret
= usb_control_msg(gspca_dev
->dev
,
257 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
259 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
262 len
? gspca_dev
->usb_buf
: NULL
, len
,
265 pr_err("reg_r err %d\n", ret
);
266 gspca_dev
->usb_err
= ret
;
268 * Make sure the buffer is zeroed to avoid uninitialized
271 memset(gspca_dev
->usb_buf
, 0, USB_BUF_SZ
);
276 static void reg_w_1(struct gspca_dev
*gspca_dev
,
284 if (gspca_dev
->usb_err
< 0)
286 gspca_dev
->usb_buf
[0] = byte
;
287 ret
= usb_control_msg(gspca_dev
->dev
,
288 usb_sndctrlpipe(gspca_dev
->dev
, 0),
290 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
292 gspca_dev
->usb_buf
, 1,
295 pr_err("reg_w_1 err %d\n", ret
);
296 gspca_dev
->usb_err
= ret
;
300 /* write req / index / value */
301 static void reg_w_riv(struct gspca_dev
*gspca_dev
,
302 u8 req
, u16 index
, u16 value
)
304 struct usb_device
*dev
= gspca_dev
->dev
;
307 if (gspca_dev
->usb_err
< 0)
309 ret
= usb_control_msg(dev
,
310 usb_sndctrlpipe(dev
, 0),
312 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
313 value
, index
, NULL
, 0, 500);
315 pr_err("reg_w_riv err %d\n", ret
);
316 gspca_dev
->usb_err
= ret
;
319 gspca_dbg(gspca_dev
, D_USBO
, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
323 static void write_vector(struct gspca_dev
*gspca_dev
,
324 const struct cmd
*data
, int ncmds
)
326 while (--ncmds
>= 0) {
327 reg_w_riv(gspca_dev
, data
->req
, data
->idx
, data
->val
);
332 static void setup_qtable(struct gspca_dev
*gspca_dev
,
333 const u8 qtable
[2][64])
337 /* loop over y components */
338 for (i
= 0; i
< 64; i
++)
339 reg_w_riv(gspca_dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
341 /* loop over c components */
342 for (i
= 0; i
< 64; i
++)
343 reg_w_riv(gspca_dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
346 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
347 u8 req
, u16 idx
, u16 val
)
349 reg_w_riv(gspca_dev
, req
, idx
, val
);
350 reg_r(gspca_dev
, 0x01, 0x0001, 1);
351 gspca_dbg(gspca_dev
, D_FRAM
, "before wait 0x%04x\n",
352 gspca_dev
->usb_buf
[0]);
353 reg_w_riv(gspca_dev
, req
, idx
, val
);
356 reg_r(gspca_dev
, 0x01, 0x0001, 1);
357 gspca_dbg(gspca_dev
, D_FRAM
, "after wait 0x%04x\n",
358 gspca_dev
->usb_buf
[0]);
361 static void spca504_read_info(struct gspca_dev
*gspca_dev
)
366 if (gspca_debug
< D_STREAM
)
369 for (i
= 0; i
< 6; i
++) {
370 reg_r(gspca_dev
, 0, i
, 1);
371 info
[i
] = gspca_dev
->usb_buf
[0];
373 gspca_dbg(gspca_dev
, D_STREAM
,
374 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
375 info
[0], info
[1], info
[2],
376 info
[3], info
[4], info
[5]);
379 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
381 u16 idx
, u16 val
, u8 endcode
, u8 count
)
385 reg_w_riv(gspca_dev
, req
, idx
, val
);
386 reg_r(gspca_dev
, 0x01, 0x0001, 1);
387 if (gspca_dev
->usb_err
< 0)
389 gspca_dbg(gspca_dev
, D_FRAM
, "Status 0x%02x Need 0x%02x\n",
390 gspca_dev
->usb_buf
[0], endcode
);
394 while (--count
> 0) {
396 /* gsmart mini2 write a each wait setting 1 ms is enough */
397 /* reg_w_riv(gspca_dev, req, idx, val); */
398 reg_r(gspca_dev
, 0x01, 0x0001, 1);
399 status
= gspca_dev
->usb_buf
[0];
400 if (status
== endcode
) {
401 gspca_dbg(gspca_dev
, D_FRAM
, "status 0x%04x after wait %d\n",
402 status
, 200 - count
);
408 static void spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
412 while (--count
> 0) {
413 reg_r(gspca_dev
, 0x21, 0, 1);
414 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
420 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
424 while (--count
> 0) {
425 reg_r(gspca_dev
, 0x21, 1, 1);
426 if (gspca_dev
->usb_buf
[0] != 0) {
427 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
428 reg_r(gspca_dev
, 0x21, 1, 1);
429 spca504B_PollingDataReady(gspca_dev
);
436 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
440 if (gspca_debug
< D_STREAM
)
443 data
= gspca_dev
->usb_buf
;
444 reg_r(gspca_dev
, 0x20, 0, 5);
445 gspca_dbg(gspca_dev
, D_STREAM
, "FirmWare: %d %d %d %d %d\n",
446 data
[0], data
[1], data
[2], data
[3], data
[4]);
447 reg_r(gspca_dev
, 0x23, 0, 64);
448 reg_r(gspca_dev
, 0x23, 1, 64);
451 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
453 struct sd
*sd
= (struct sd
*) gspca_dev
;
456 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
457 switch (sd
->bridge
) {
459 reg_w_riv(gspca_dev
, 0x31, 0, 0);
460 spca504B_WaitCmdStatus(gspca_dev
);
461 spca504B_PollingDataReady(gspca_dev
);
462 spca50x_GetFirmware(gspca_dev
);
464 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
465 reg_r(gspca_dev
, 0x24, 8, 1);
467 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
468 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
469 spca504B_PollingDataReady(gspca_dev
);
471 /* Init the cam width height with some values get on init ? */
472 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
473 spca504B_WaitCmdStatus(gspca_dev
);
474 spca504B_PollingDataReady(gspca_dev
);
477 /* case BRIDGE_SPCA504B: */
478 /* case BRIDGE_SPCA536: */
479 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
480 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
481 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
482 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
483 spca504B_PollingDataReady(gspca_dev
);
487 if (sd
->subtype
== AiptekMiniPenCam13
) {
488 /* spca504a aiptek */
489 spca504A_acknowledged_command(gspca_dev
,
491 0x80 | (Size
& 0x0f), 1);
492 spca504A_acknowledged_command(gspca_dev
,
495 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
498 case BRIDGE_SPCA504C
:
500 reg_w_riv(gspca_dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
501 reg_w_riv(gspca_dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
506 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
512 /* With this we get the status, when return 0 it's all ok */
513 reg_r(gspca_dev
, 0x06, 0x00, 1);
514 if (gspca_dev
->usb_buf
[0] == 0)
520 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
522 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
523 reg_r(gspca_dev
, 0x26, 0, 1);
524 spca504B_PollingDataReady(gspca_dev
);
527 static void setbrightness(struct gspca_dev
*gspca_dev
, s32 val
)
529 struct sd
*sd
= (struct sd
*) gspca_dev
;
532 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
533 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
536 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
538 struct sd
*sd
= (struct sd
*) gspca_dev
;
541 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
542 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
545 static void setcolors(struct gspca_dev
*gspca_dev
, s32 val
)
547 struct sd
*sd
= (struct sd
*) gspca_dev
;
550 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
551 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
554 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
556 struct sd
*sd
= (struct sd
*) gspca_dev
;
559 switch (sd
->bridge
) {
561 case BRIDGE_SPCA504C
:
565 /* case BRIDGE_SPCA533: */
566 /* case BRIDGE_SPCA504B: */
567 reg_w_riv(gspca_dev
, 0, 0x21ad, 0x00); /* hue */
568 reg_w_riv(gspca_dev
, 0, 0x21ac, 0x01); /* sat/hue */
569 reg_w_riv(gspca_dev
, 0, 0x21a3, 0x00); /* gamma */
572 reg_w_riv(gspca_dev
, 0, 0x20f5, 0x40);
573 reg_w_riv(gspca_dev
, 0, 0x20f4, 0x01);
574 reg_w_riv(gspca_dev
, 0, 0x2089, 0x00);
578 spca504B_PollingDataReady(gspca_dev
);
581 /* this function is called at probe time */
582 static int sd_config(struct gspca_dev
*gspca_dev
,
583 const struct usb_device_id
*id
)
585 struct sd
*sd
= (struct sd
*) gspca_dev
;
588 cam
= &gspca_dev
->cam
;
590 sd
->bridge
= id
->driver_info
>> 8;
591 sd
->subtype
= id
->driver_info
;
593 if (sd
->subtype
== AiptekMiniPenCam13
) {
595 /* try to get the firmware as some cam answer 2.0.1.2.2
596 * and should be a spca504b then overwrite that setting */
597 reg_r(gspca_dev
, 0x20, 0, 1);
598 switch (gspca_dev
->usb_buf
[0]) {
600 break; /* (right bridge/subtype) */
602 sd
->bridge
= BRIDGE_SPCA504B
;
610 switch (sd
->bridge
) {
612 /* case BRIDGE_SPCA504B: */
613 /* case BRIDGE_SPCA504: */
614 /* case BRIDGE_SPCA536: */
615 cam
->cam_mode
= vga_mode
;
616 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
619 cam
->cam_mode
= custom_mode
;
620 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
621 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
623 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
625 case BRIDGE_SPCA504C
:
626 cam
->cam_mode
= vga_mode2
;
627 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
633 /* this function is called at probe and resume time */
634 static int sd_init(struct gspca_dev
*gspca_dev
)
636 struct sd
*sd
= (struct sd
*) gspca_dev
;
638 switch (sd
->bridge
) {
639 case BRIDGE_SPCA504B
:
640 reg_w_riv(gspca_dev
, 0x1d, 0x00, 0);
641 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x01);
642 reg_w_riv(gspca_dev
, 0x00, 0x0d04, 0x00);
643 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x00);
644 reg_w_riv(gspca_dev
, 0x00, 0x2301, 0x13);
645 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x00);
648 spca504B_PollingDataReady(gspca_dev
);
649 spca50x_GetFirmware(gspca_dev
);
652 spca50x_GetFirmware(gspca_dev
);
653 reg_r(gspca_dev
, 0x00, 0x5002, 1);
654 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
655 reg_r(gspca_dev
, 0x24, 0, 1);
656 spca504B_PollingDataReady(gspca_dev
);
657 reg_w_riv(gspca_dev
, 0x34, 0, 0);
658 spca504B_WaitCmdStatus(gspca_dev
);
660 case BRIDGE_SPCA504C
: /* pccam600 */
661 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504 (PC-CAM 600)\n");
662 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0000);
663 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0001); /* reset */
664 spca504_wait_status(gspca_dev
);
665 if (sd
->subtype
== LogitechClickSmart420
)
666 write_vector(gspca_dev
,
667 spca504A_clicksmart420_open_data
,
668 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
670 write_vector(gspca_dev
, spca504_pccam600_open_data
,
671 ARRAY_SIZE(spca504_pccam600_open_data
));
672 setup_qtable(gspca_dev
, qtable_creative_pccam
);
675 /* case BRIDGE_SPCA504: */
676 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504\n");
677 if (sd
->subtype
== AiptekMiniPenCam13
) {
678 spca504_read_info(gspca_dev
);
680 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
681 spca504A_acknowledged_command(gspca_dev
, 0x24,
683 /* Twice sequential need status 0xff->0x9e->0x9d */
684 spca504A_acknowledged_command(gspca_dev
, 0x24,
687 spca504A_acknowledged_command(gspca_dev
, 0x24,
689 /******************************/
690 /* spca504a aiptek */
691 spca504A_acknowledged_command(gspca_dev
, 0x08,
693 /* reg_write (dev, 0, 0x2000, 0); */
694 /* reg_write (dev, 0, 0x2883, 1); */
695 /* spca504A_acknowledged_command (gspca_dev, 0x08,
697 /* spca504A_acknowledged_command (gspca_dev, 0x24,
699 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
701 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
702 spca504A_acknowledged_command(gspca_dev
, 0x01,
706 reg_w_riv(gspca_dev
, 0, 0x2000, 0);
707 reg_w_riv(gspca_dev
, 0, 0x2883, 1);
708 setup_qtable(gspca_dev
, qtable_spca504_default
);
711 return gspca_dev
->usb_err
;
714 static int sd_start(struct gspca_dev
*gspca_dev
)
716 struct sd
*sd
= (struct sd
*) gspca_dev
;
719 /* create the JPEG header */
720 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->pixfmt
.height
,
721 gspca_dev
->pixfmt
.width
,
722 0x22); /* JPEG 411 */
723 jpeg_set_qual(sd
->jpeg_hdr
, QUALITY
);
725 if (sd
->bridge
== BRIDGE_SPCA504B
)
726 spca504B_setQtable(gspca_dev
);
727 spca504B_SetSizeType(gspca_dev
);
728 switch (sd
->bridge
) {
730 /* case BRIDGE_SPCA504B: */
731 /* case BRIDGE_SPCA533: */
732 /* case BRIDGE_SPCA536: */
733 switch (sd
->subtype
) {
735 case LogitechClickSmart820
:
737 reg_w_riv(gspca_dev
, 0xf0, 0, 0);
738 spca504B_WaitCmdStatus(gspca_dev
);
739 reg_r(gspca_dev
, 0xf0, 4, 0);
740 spca504B_WaitCmdStatus(gspca_dev
);
743 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
744 spca504B_WaitCmdStatus(gspca_dev
);
745 spca504B_PollingDataReady(gspca_dev
);
750 if (sd
->subtype
== AiptekMiniPenCam13
) {
751 spca504_read_info(gspca_dev
);
753 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
754 spca504A_acknowledged_command(gspca_dev
, 0x24,
756 /* Twice sequential need status 0xff->0x9e->0x9d */
757 spca504A_acknowledged_command(gspca_dev
, 0x24,
759 spca504A_acknowledged_command(gspca_dev
, 0x24,
762 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
763 spca504_read_info(gspca_dev
);
764 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
765 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
767 spca504B_SetSizeType(gspca_dev
);
768 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
770 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
772 case BRIDGE_SPCA504C
:
773 if (sd
->subtype
== LogitechClickSmart420
) {
774 write_vector(gspca_dev
,
775 spca504A_clicksmart420_init_data
,
776 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
778 write_vector(gspca_dev
, spca504_pccam600_init_data
,
779 ARRAY_SIZE(spca504_pccam600_init_data
));
781 enable
= (sd
->autogain
? 0x04 : 0x01);
782 reg_w_riv(gspca_dev
, 0x0c, 0x0000, enable
);
784 reg_w_riv(gspca_dev
, 0xb0, 0x0000, enable
);
787 /* set default exposure compensation and whiteness balance */
788 reg_w_riv(gspca_dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
789 reg_w_riv(gspca_dev
, 0x30, 0x0002, 1600);
790 spca504B_SetSizeType(gspca_dev
);
793 init_ctl_reg(gspca_dev
);
794 return gspca_dev
->usb_err
;
797 static void sd_stopN(struct gspca_dev
*gspca_dev
)
799 struct sd
*sd
= (struct sd
*) gspca_dev
;
801 switch (sd
->bridge
) {
803 /* case BRIDGE_SPCA533: */
804 /* case BRIDGE_SPCA536: */
805 /* case BRIDGE_SPCA504B: */
806 reg_w_riv(gspca_dev
, 0x31, 0, 0);
807 spca504B_WaitCmdStatus(gspca_dev
);
808 spca504B_PollingDataReady(gspca_dev
);
811 case BRIDGE_SPCA504C
:
812 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x0000);
814 if (sd
->subtype
== AiptekMiniPenCam13
) {
815 /* spca504a aiptek */
816 /* spca504A_acknowledged_command(gspca_dev, 0x08,
818 spca504A_acknowledged_command(gspca_dev
, 0x24,
819 0x00, 0x00, 0x9d, 1);
820 spca504A_acknowledged_command(gspca_dev
, 0x01,
821 0x0f, 0x00, 0xff, 1);
823 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
824 reg_w_riv(gspca_dev
, 0x01, 0x000f, 0x0000);
830 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
831 u8
*data
, /* isoc packet */
832 int len
) /* iso packet length */
834 struct sd
*sd
= (struct sd
*) gspca_dev
;
836 static u8 ffd9
[] = {0xff, 0xd9};
838 /* frames are jpeg 4.1.1 without 0xff escape */
839 switch (sd
->bridge
) {
841 if (data
[0] == 0xff) {
842 if (data
[1] != 0x01) { /* drop packet */
843 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
847 data
+= SPCA533_OFFSET_DATA
;
848 len
-= SPCA533_OFFSET_DATA
;
855 if (data
[0] == 0xff) {
857 data
+= SPCA536_OFFSET_DATA
;
858 len
-= SPCA536_OFFSET_DATA
;
865 /* case BRIDGE_SPCA504: */
866 /* case BRIDGE_SPCA504B: */
868 case 0xfe: /* start of frame */
870 data
+= SPCA50X_OFFSET_DATA
;
871 len
-= SPCA50X_OFFSET_DATA
;
873 case 0xff: /* drop packet */
874 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
882 case BRIDGE_SPCA504C
:
884 case 0xfe: /* start of frame */
886 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
887 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
889 case 0xff: /* drop packet */
890 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
899 if (sof
) { /* start of frame */
900 gspca_frame_add(gspca_dev
, LAST_PACKET
,
903 /* put the JPEG header in the new frame */
904 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
905 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
908 /* add 0x00 after 0xff */
911 if (data
[i
] == 0xff) {
912 gspca_frame_add(gspca_dev
, INTER_PACKET
,
921 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
924 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
926 struct gspca_dev
*gspca_dev
=
927 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
928 struct sd
*sd
= (struct sd
*)gspca_dev
;
930 gspca_dev
->usb_err
= 0;
932 if (!gspca_dev
->streaming
)
936 case V4L2_CID_BRIGHTNESS
:
937 setbrightness(gspca_dev
, ctrl
->val
);
939 case V4L2_CID_CONTRAST
:
940 setcontrast(gspca_dev
, ctrl
->val
);
942 case V4L2_CID_SATURATION
:
943 setcolors(gspca_dev
, ctrl
->val
);
945 case V4L2_CID_AUTOGAIN
:
946 sd
->autogain
= ctrl
->val
;
949 return gspca_dev
->usb_err
;
952 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
956 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
958 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
960 gspca_dev
->vdev
.ctrl_handler
= hdl
;
961 v4l2_ctrl_handler_init(hdl
, 4);
962 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
963 V4L2_CID_BRIGHTNESS
, -128, 127, 1, 0);
964 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
965 V4L2_CID_CONTRAST
, 0, 255, 1, 0x20);
966 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
967 V4L2_CID_SATURATION
, 0, 255, 1, 0x1a);
968 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
969 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
972 pr_err("Could not initialize controls\n");
978 /* sub-driver description */
979 static const struct sd_desc sd_desc
= {
983 .init_controls
= sd_init_controls
,
986 .pkt_scan
= sd_pkt_scan
,
989 /* -- module initialisation -- */
990 #define BS(bridge, subtype) \
991 .driver_info = (BRIDGE_ ## bridge << 8) \
993 static const struct usb_device_id device_table
[] = {
994 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
995 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
996 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
997 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
998 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
999 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
1000 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
1001 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
1002 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
1003 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
1004 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
1005 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
1006 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
1007 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
1008 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1009 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1010 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1011 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1012 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533
, MegapixV4
)},
1013 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1014 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1015 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1016 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1017 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1018 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1019 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1020 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1021 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1022 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1023 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1024 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1025 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1026 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1027 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1028 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1029 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1030 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1031 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1032 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B
, 0)},
1033 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1034 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1035 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1036 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1037 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1038 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1039 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1040 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1041 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1042 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1043 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1044 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1045 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1046 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1047 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1048 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1049 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1050 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1051 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1052 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1053 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1056 MODULE_DEVICE_TABLE(usb
, device_table
);
1058 /* -- device connect -- */
1059 static int sd_probe(struct usb_interface
*intf
,
1060 const struct usb_device_id
*id
)
1062 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1066 static struct usb_driver sd_driver
= {
1067 .name
= MODULE_NAME
,
1068 .id_table
= device_table
,
1070 .disconnect
= gspca_disconnect
,
1072 .suspend
= gspca_suspend
,
1073 .resume
= gspca_resume
,
1074 .reset_resume
= gspca_resume
,
1078 module_usb_driver(sd_driver
);