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.
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
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24 #define MODULE_NAME "sunplus"
29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
31 MODULE_LICENSE("GPL");
33 /* specific webcam descriptor */
35 struct gspca_dev gspca_dev
; /* !! must be the first item */
42 #define QUALITY_MIN 70
43 #define QUALITY_MAX 95
44 #define QUALITY_DEF 85
47 #define BRIDGE_SPCA504 0
48 #define BRIDGE_SPCA504B 1
49 #define BRIDGE_SPCA504C 2
50 #define BRIDGE_SPCA533 3
51 #define BRIDGE_SPCA536 4
53 #define AiptekMiniPenCam13 1
54 #define LogitechClickSmart420 2
55 #define LogitechClickSmart820 3
59 u8 jpeg_hdr
[JPEG_HDR_SZ
];
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
);
64 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
);
65 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
);
66 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
);
67 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
);
68 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
);
69 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
);
70 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
);
72 static const struct ctrl sd_ctrls
[] = {
75 .id
= V4L2_CID_BRIGHTNESS
,
76 .type
= V4L2_CTRL_TYPE_INTEGER
,
81 #define BRIGHTNESS_DEF 0
82 .default_value
= BRIGHTNESS_DEF
,
84 .set
= sd_setbrightness
,
85 .get
= sd_getbrightness
,
89 .id
= V4L2_CID_CONTRAST
,
90 .type
= V4L2_CTRL_TYPE_INTEGER
,
95 #define CONTRAST_DEF 0x20
96 .default_value
= CONTRAST_DEF
,
98 .set
= sd_setcontrast
,
99 .get
= sd_getcontrast
,
103 .id
= V4L2_CID_SATURATION
,
104 .type
= V4L2_CTRL_TYPE_INTEGER
,
109 #define COLOR_DEF 0x1a
110 .default_value
= COLOR_DEF
,
117 .id
= V4L2_CID_AUTOGAIN
,
118 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
123 #define AUTOGAIN_DEF 1
124 .default_value
= AUTOGAIN_DEF
,
126 .set
= sd_setautogain
,
127 .get
= sd_getautogain
,
131 static const struct v4l2_pix_format vga_mode
[] = {
132 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
134 .sizeimage
= 320 * 240 * 3 / 8 + 590,
135 .colorspace
= V4L2_COLORSPACE_JPEG
,
137 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
139 .sizeimage
= 640 * 480 * 3 / 8 + 590,
140 .colorspace
= V4L2_COLORSPACE_JPEG
,
144 static const struct v4l2_pix_format custom_mode
[] = {
145 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
147 .sizeimage
= 320 * 240 * 3 / 8 + 590,
148 .colorspace
= V4L2_COLORSPACE_JPEG
,
150 {464, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
152 .sizeimage
= 464 * 480 * 3 / 8 + 590,
153 .colorspace
= V4L2_COLORSPACE_JPEG
,
157 static const struct v4l2_pix_format vga_mode2
[] = {
158 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
160 .sizeimage
= 176 * 144 * 3 / 8 + 590,
161 .colorspace
= V4L2_COLORSPACE_JPEG
,
163 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
165 .sizeimage
= 320 * 240 * 3 / 8 + 590,
166 .colorspace
= V4L2_COLORSPACE_JPEG
,
168 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
170 .sizeimage
= 352 * 288 * 3 / 8 + 590,
171 .colorspace
= V4L2_COLORSPACE_JPEG
,
173 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
175 .sizeimage
= 640 * 480 * 3 / 8 + 590,
176 .colorspace
= V4L2_COLORSPACE_JPEG
,
180 #define SPCA50X_OFFSET_DATA 10
181 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
182 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
183 #define SPCA504_PCCAM600_OFFSET_MODE 5
184 #define SPCA504_PCCAM600_OFFSET_DATA 14
185 /* Frame packet header offsets for the spca533 */
186 #define SPCA533_OFFSET_DATA 16
187 #define SPCA533_OFFSET_FRAMSEQ 15
188 /* Frame packet header offsets for the spca536 */
189 #define SPCA536_OFFSET_DATA 4
190 #define SPCA536_OFFSET_FRAMSEQ 1
198 /* Initialisation data for the Creative PC-CAM 600 */
199 static const struct cmd spca504_pccam600_init_data
[] = {
200 /* {0xa0, 0x0000, 0x0503}, * capture mode */
201 {0x00, 0x0000, 0x2000},
202 {0x00, 0x0013, 0x2301},
203 {0x00, 0x0003, 0x2000},
204 {0x00, 0x0001, 0x21ac},
205 {0x00, 0x0001, 0x21a6},
206 {0x00, 0x0000, 0x21a7}, /* brightness */
207 {0x00, 0x0020, 0x21a8}, /* contrast */
208 {0x00, 0x0001, 0x21ac}, /* sat/hue */
209 {0x00, 0x0000, 0x21ad}, /* hue */
210 {0x00, 0x001a, 0x21ae}, /* saturation */
211 {0x00, 0x0002, 0x21a3}, /* gamma */
212 {0x30, 0x0154, 0x0008},
213 {0x30, 0x0004, 0x0006},
214 {0x30, 0x0258, 0x0009},
215 {0x30, 0x0004, 0x0000},
216 {0x30, 0x0093, 0x0004},
217 {0x30, 0x0066, 0x0005},
218 {0x00, 0x0000, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
221 {0x00, 0x0013, 0x2301},
222 {0x00, 0x0003, 0x2000},
225 /* Creative PC-CAM 600 specific open data, sent before using the
226 * generic initialisation data from spca504_open_data.
228 static const struct cmd spca504_pccam600_open_data
[] = {
229 {0x00, 0x0001, 0x2501},
230 {0x20, 0x0500, 0x0001}, /* snapshot mode */
231 {0x00, 0x0003, 0x2880},
232 {0x00, 0x0001, 0x2881},
235 /* Initialisation data for the logitech clicksmart 420 */
236 static const struct cmd spca504A_clicksmart420_init_data
[] = {
237 /* {0xa0, 0x0000, 0x0503}, * capture mode */
238 {0x00, 0x0000, 0x2000},
239 {0x00, 0x0013, 0x2301},
240 {0x00, 0x0003, 0x2000},
241 {0x00, 0x0001, 0x21ac},
242 {0x00, 0x0001, 0x21a6},
243 {0x00, 0x0000, 0x21a7}, /* brightness */
244 {0x00, 0x0020, 0x21a8}, /* contrast */
245 {0x00, 0x0001, 0x21ac}, /* sat/hue */
246 {0x00, 0x0000, 0x21ad}, /* hue */
247 {0x00, 0x001a, 0x21ae}, /* saturation */
248 {0x00, 0x0002, 0x21a3}, /* gamma */
249 {0x30, 0x0004, 0x000a},
250 {0xb0, 0x0001, 0x0000},
252 {0xa1, 0x0080, 0x0001},
253 {0x30, 0x0049, 0x0000},
254 {0x30, 0x0060, 0x0005},
255 {0x0c, 0x0004, 0x0000},
256 {0x00, 0x0000, 0x0000},
257 {0x00, 0x0000, 0x2000},
258 {0x00, 0x0013, 0x2301},
259 {0x00, 0x0003, 0x2000},
262 /* clicksmart 420 open data ? */
263 static const struct cmd spca504A_clicksmart420_open_data
[] = {
264 {0x00, 0x0001, 0x2501},
265 {0x20, 0x0502, 0x0000},
266 {0x06, 0x0000, 0x0000},
267 {0x00, 0x0004, 0x2880},
268 {0x00, 0x0001, 0x2881},
270 {0xa0, 0x0000, 0x0503},
273 static const u8 qtable_creative_pccam
[2][64] = {
274 { /* Q-table Y-components */
275 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
276 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
277 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
278 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
279 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
280 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
281 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
282 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
283 { /* Q-table C-components */
284 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 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}
294 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
295 * except for one byte. Possibly a typo?
298 static const u8 qtable_spca504_default
[2][64] = {
299 { /* Q-table Y-components */
300 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
301 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
302 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
303 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
304 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
305 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
306 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
307 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
309 { /* Q-table C-components */
310 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 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}
320 /* read <len> bytes to gspca_dev->usb_buf */
321 static void reg_r(struct gspca_dev
*gspca_dev
,
329 if (len
> USB_BUF_SZ
) {
330 pr_err("reg_r: buffer overflow\n");
334 if (gspca_dev
->usb_err
< 0)
336 ret
= usb_control_msg(gspca_dev
->dev
,
337 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
339 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
342 len
? gspca_dev
->usb_buf
: NULL
, len
,
345 pr_err("reg_r err %d\n", ret
);
346 gspca_dev
->usb_err
= ret
;
351 static void reg_w_1(struct gspca_dev
*gspca_dev
,
359 if (gspca_dev
->usb_err
< 0)
361 gspca_dev
->usb_buf
[0] = byte
;
362 ret
= usb_control_msg(gspca_dev
->dev
,
363 usb_sndctrlpipe(gspca_dev
->dev
, 0),
365 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
367 gspca_dev
->usb_buf
, 1,
370 pr_err("reg_w_1 err %d\n", ret
);
371 gspca_dev
->usb_err
= ret
;
375 /* write req / index / value */
376 static void reg_w_riv(struct gspca_dev
*gspca_dev
,
377 u8 req
, u16 index
, u16 value
)
379 struct usb_device
*dev
= gspca_dev
->dev
;
382 if (gspca_dev
->usb_err
< 0)
384 ret
= usb_control_msg(dev
,
385 usb_sndctrlpipe(dev
, 0),
387 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
388 value
, index
, NULL
, 0, 500);
390 pr_err("reg_w_riv err %d\n", ret
);
391 gspca_dev
->usb_err
= ret
;
394 PDEBUG(D_USBO
, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
398 static void write_vector(struct gspca_dev
*gspca_dev
,
399 const struct cmd
*data
, int ncmds
)
401 while (--ncmds
>= 0) {
402 reg_w_riv(gspca_dev
, data
->req
, data
->idx
, data
->val
);
407 static void setup_qtable(struct gspca_dev
*gspca_dev
,
408 const u8 qtable
[2][64])
412 /* loop over y components */
413 for (i
= 0; i
< 64; i
++)
414 reg_w_riv(gspca_dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
416 /* loop over c components */
417 for (i
= 0; i
< 64; i
++)
418 reg_w_riv(gspca_dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
421 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
422 u8 req
, u16 idx
, u16 val
)
424 reg_w_riv(gspca_dev
, req
, idx
, val
);
425 reg_r(gspca_dev
, 0x01, 0x0001, 1);
426 PDEBUG(D_FRAM
, "before wait 0x%04x", gspca_dev
->usb_buf
[0]);
427 reg_w_riv(gspca_dev
, req
, idx
, val
);
430 reg_r(gspca_dev
, 0x01, 0x0001, 1);
431 PDEBUG(D_FRAM
, "after wait 0x%04x", gspca_dev
->usb_buf
[0]);
435 static void spca504_read_info(struct gspca_dev
*gspca_dev
)
440 for (i
= 0; i
< 6; i
++) {
441 reg_r(gspca_dev
, 0, i
, 1);
442 info
[i
] = gspca_dev
->usb_buf
[0];
445 "Read info: %d %d %d %d %d %d."
446 " Should be 1,0,2,2,0,0",
447 info
[0], info
[1], info
[2],
448 info
[3], info
[4], info
[5]);
452 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
454 u16 idx
, u16 val
, u8 endcode
, u8 count
)
458 reg_w_riv(gspca_dev
, req
, idx
, val
);
459 reg_r(gspca_dev
, 0x01, 0x0001, 1);
460 if (gspca_dev
->usb_err
< 0)
462 PDEBUG(D_FRAM
, "Status 0x%02x Need 0x%02x",
463 gspca_dev
->usb_buf
[0], endcode
);
467 while (--count
> 0) {
469 /* gsmart mini2 write a each wait setting 1 ms is enough */
470 /* reg_w_riv(gspca_dev, req, idx, val); */
471 reg_r(gspca_dev
, 0x01, 0x0001, 1);
472 status
= gspca_dev
->usb_buf
[0];
473 if (status
== endcode
) {
474 PDEBUG(D_FRAM
, "status 0x%04x after wait %d",
475 status
, 200 - count
);
481 static void spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
485 while (--count
> 0) {
486 reg_r(gspca_dev
, 0x21, 0, 1);
487 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
493 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
497 while (--count
> 0) {
498 reg_r(gspca_dev
, 0x21, 1, 1);
499 if (gspca_dev
->usb_buf
[0] != 0) {
500 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
501 reg_r(gspca_dev
, 0x21, 1, 1);
502 spca504B_PollingDataReady(gspca_dev
);
510 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
514 data
= gspca_dev
->usb_buf
;
515 reg_r(gspca_dev
, 0x20, 0, 5);
516 PDEBUG(D_STREAM
, "FirmWare: %d %d %d %d %d",
517 data
[0], data
[1], data
[2], data
[3], data
[4]);
518 reg_r(gspca_dev
, 0x23, 0, 64);
519 reg_r(gspca_dev
, 0x23, 1, 64);
523 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
525 struct sd
*sd
= (struct sd
*) gspca_dev
;
528 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
529 switch (sd
->bridge
) {
531 reg_w_riv(gspca_dev
, 0x31, 0, 0);
532 spca504B_WaitCmdStatus(gspca_dev
);
533 spca504B_PollingDataReady(gspca_dev
);
535 spca50x_GetFirmware(gspca_dev
);
537 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
538 reg_r(gspca_dev
, 0x24, 8, 1);
540 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
541 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
542 spca504B_PollingDataReady(gspca_dev
);
544 /* Init the cam width height with some values get on init ? */
545 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
546 spca504B_WaitCmdStatus(gspca_dev
);
547 spca504B_PollingDataReady(gspca_dev
);
550 /* case BRIDGE_SPCA504B: */
551 /* case BRIDGE_SPCA536: */
552 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
553 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
554 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
555 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
556 spca504B_PollingDataReady(gspca_dev
);
560 if (sd
->subtype
== AiptekMiniPenCam13
) {
561 /* spca504a aiptek */
562 spca504A_acknowledged_command(gspca_dev
,
564 0x80 | (Size
& 0x0f), 1);
565 spca504A_acknowledged_command(gspca_dev
,
568 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
571 case BRIDGE_SPCA504C
:
573 reg_w_riv(gspca_dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
574 reg_w_riv(gspca_dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
579 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
585 /* With this we get the status, when return 0 it's all ok */
586 reg_r(gspca_dev
, 0x06, 0x00, 1);
587 if (gspca_dev
->usb_buf
[0] == 0)
593 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
595 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
596 reg_r(gspca_dev
, 0x26, 0, 1);
597 spca504B_PollingDataReady(gspca_dev
);
600 static void setbrightness(struct gspca_dev
*gspca_dev
)
602 struct sd
*sd
= (struct sd
*) gspca_dev
;
605 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
606 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->brightness
);
609 static void setcontrast(struct gspca_dev
*gspca_dev
)
611 struct sd
*sd
= (struct sd
*) gspca_dev
;
614 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
615 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->contrast
);
618 static void setcolors(struct gspca_dev
*gspca_dev
)
620 struct sd
*sd
= (struct sd
*) gspca_dev
;
623 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
624 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->colors
);
627 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
629 struct sd
*sd
= (struct sd
*) gspca_dev
;
632 setbrightness(gspca_dev
);
633 setcontrast(gspca_dev
);
634 setcolors(gspca_dev
);
636 switch (sd
->bridge
) {
638 case BRIDGE_SPCA504C
:
642 /* case BRIDGE_SPCA533: */
643 /* case BRIDGE_SPCA504B: */
644 reg_w_riv(gspca_dev
, 0, 0x21ad, 0x00); /* hue */
645 reg_w_riv(gspca_dev
, 0, 0x21ac, 0x01); /* sat/hue */
646 reg_w_riv(gspca_dev
, 0, 0x21a3, 0x00); /* gamma */
649 reg_w_riv(gspca_dev
, 0, 0x20f5, 0x40);
650 reg_w_riv(gspca_dev
, 0, 0x20f4, 0x01);
651 reg_w_riv(gspca_dev
, 0, 0x2089, 0x00);
655 spca504B_PollingDataReady(gspca_dev
);
658 /* this function is called at probe time */
659 static int sd_config(struct gspca_dev
*gspca_dev
,
660 const struct usb_device_id
*id
)
662 struct sd
*sd
= (struct sd
*) gspca_dev
;
665 cam
= &gspca_dev
->cam
;
667 sd
->bridge
= id
->driver_info
>> 8;
668 sd
->subtype
= id
->driver_info
;
670 if (sd
->subtype
== AiptekMiniPenCam13
) {
672 /* try to get the firmware as some cam answer 2.0.1.2.2
673 * and should be a spca504b then overwrite that setting */
674 reg_r(gspca_dev
, 0x20, 0, 1);
675 switch (gspca_dev
->usb_buf
[0]) {
677 break; /* (right bridge/subtype) */
679 sd
->bridge
= BRIDGE_SPCA504B
;
687 switch (sd
->bridge
) {
689 /* case BRIDGE_SPCA504B: */
690 /* case BRIDGE_SPCA504: */
691 /* case BRIDGE_SPCA536: */
692 cam
->cam_mode
= vga_mode
;
693 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
696 cam
->cam_mode
= custom_mode
;
697 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
698 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
700 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
702 case BRIDGE_SPCA504C
:
703 cam
->cam_mode
= vga_mode2
;
704 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
707 sd
->brightness
= BRIGHTNESS_DEF
;
708 sd
->contrast
= CONTRAST_DEF
;
709 sd
->colors
= COLOR_DEF
;
710 sd
->autogain
= AUTOGAIN_DEF
;
711 sd
->quality
= QUALITY_DEF
;
715 /* this function is called at probe and resume time */
716 static int sd_init(struct gspca_dev
*gspca_dev
)
718 struct sd
*sd
= (struct sd
*) gspca_dev
;
720 switch (sd
->bridge
) {
721 case BRIDGE_SPCA504B
:
722 reg_w_riv(gspca_dev
, 0x1d, 0x00, 0);
723 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x01);
724 reg_w_riv(gspca_dev
, 0x00, 0x0d04, 0x00);
725 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x00);
726 reg_w_riv(gspca_dev
, 0x00, 0x2301, 0x13);
727 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x00);
730 spca504B_PollingDataReady(gspca_dev
);
732 spca50x_GetFirmware(gspca_dev
);
737 spca50x_GetFirmware(gspca_dev
);
739 reg_r(gspca_dev
, 0x00, 0x5002, 1);
740 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
741 reg_r(gspca_dev
, 0x24, 0, 1);
742 spca504B_PollingDataReady(gspca_dev
);
743 reg_w_riv(gspca_dev
, 0x34, 0, 0);
744 spca504B_WaitCmdStatus(gspca_dev
);
746 case BRIDGE_SPCA504C
: /* pccam600 */
747 PDEBUG(D_STREAM
, "Opening SPCA504 (PC-CAM 600)");
748 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0000);
749 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0001); /* reset */
750 spca504_wait_status(gspca_dev
);
751 if (sd
->subtype
== LogitechClickSmart420
)
752 write_vector(gspca_dev
,
753 spca504A_clicksmart420_open_data
,
754 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
756 write_vector(gspca_dev
, spca504_pccam600_open_data
,
757 ARRAY_SIZE(spca504_pccam600_open_data
));
758 setup_qtable(gspca_dev
, qtable_creative_pccam
);
761 /* case BRIDGE_SPCA504: */
762 PDEBUG(D_STREAM
, "Opening SPCA504");
763 if (sd
->subtype
== AiptekMiniPenCam13
) {
765 spca504_read_info(gspca_dev
);
768 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
769 spca504A_acknowledged_command(gspca_dev
, 0x24,
771 /* Twice sequential need status 0xff->0x9e->0x9d */
772 spca504A_acknowledged_command(gspca_dev
, 0x24,
775 spca504A_acknowledged_command(gspca_dev
, 0x24,
777 /******************************/
778 /* spca504a aiptek */
779 spca504A_acknowledged_command(gspca_dev
, 0x08,
781 /* reg_write (dev, 0, 0x2000, 0); */
782 /* reg_write (dev, 0, 0x2883, 1); */
783 /* spca504A_acknowledged_command (gspca_dev, 0x08,
785 /* spca504A_acknowledged_command (gspca_dev, 0x24,
787 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
789 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
790 spca504A_acknowledged_command(gspca_dev
, 0x01,
794 reg_w_riv(gspca_dev
, 0, 0x2000, 0);
795 reg_w_riv(gspca_dev
, 0, 0x2883, 1);
796 setup_qtable(gspca_dev
, qtable_spca504_default
);
799 return gspca_dev
->usb_err
;
802 static int sd_start(struct gspca_dev
*gspca_dev
)
804 struct sd
*sd
= (struct sd
*) gspca_dev
;
807 /* create the JPEG header */
808 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->height
, gspca_dev
->width
,
809 0x22); /* JPEG 411 */
810 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
812 if (sd
->bridge
== BRIDGE_SPCA504B
)
813 spca504B_setQtable(gspca_dev
);
814 spca504B_SetSizeType(gspca_dev
);
815 switch (sd
->bridge
) {
817 /* case BRIDGE_SPCA504B: */
818 /* case BRIDGE_SPCA533: */
819 /* case BRIDGE_SPCA536: */
820 switch (sd
->subtype
) {
822 case LogitechClickSmart820
:
824 reg_w_riv(gspca_dev
, 0xf0, 0, 0);
825 spca504B_WaitCmdStatus(gspca_dev
);
826 reg_r(gspca_dev
, 0xf0, 4, 0);
827 spca504B_WaitCmdStatus(gspca_dev
);
830 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
831 spca504B_WaitCmdStatus(gspca_dev
);
832 spca504B_PollingDataReady(gspca_dev
);
837 if (sd
->subtype
== AiptekMiniPenCam13
) {
839 spca504_read_info(gspca_dev
);
842 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
843 spca504A_acknowledged_command(gspca_dev
, 0x24,
845 /* Twice sequential need status 0xff->0x9e->0x9d */
846 spca504A_acknowledged_command(gspca_dev
, 0x24,
848 spca504A_acknowledged_command(gspca_dev
, 0x24,
851 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
853 spca504_read_info(gspca_dev
);
855 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
856 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
858 spca504B_SetSizeType(gspca_dev
);
859 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
861 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
863 case BRIDGE_SPCA504C
:
864 if (sd
->subtype
== LogitechClickSmart420
) {
865 write_vector(gspca_dev
,
866 spca504A_clicksmart420_init_data
,
867 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
869 write_vector(gspca_dev
, spca504_pccam600_init_data
,
870 ARRAY_SIZE(spca504_pccam600_init_data
));
872 enable
= (sd
->autogain
? 0x04 : 0x01);
873 reg_w_riv(gspca_dev
, 0x0c, 0x0000, enable
);
875 reg_w_riv(gspca_dev
, 0xb0, 0x0000, enable
);
878 /* set default exposure compensation and whiteness balance */
879 reg_w_riv(gspca_dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
880 reg_w_riv(gspca_dev
, 0x30, 0x0002, 1600);
881 spca504B_SetSizeType(gspca_dev
);
884 init_ctl_reg(gspca_dev
);
885 return gspca_dev
->usb_err
;
888 static void sd_stopN(struct gspca_dev
*gspca_dev
)
890 struct sd
*sd
= (struct sd
*) gspca_dev
;
892 switch (sd
->bridge
) {
894 /* case BRIDGE_SPCA533: */
895 /* case BRIDGE_SPCA536: */
896 /* case BRIDGE_SPCA504B: */
897 reg_w_riv(gspca_dev
, 0x31, 0, 0);
898 spca504B_WaitCmdStatus(gspca_dev
);
899 spca504B_PollingDataReady(gspca_dev
);
902 case BRIDGE_SPCA504C
:
903 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x0000);
905 if (sd
->subtype
== AiptekMiniPenCam13
) {
906 /* spca504a aiptek */
907 /* spca504A_acknowledged_command(gspca_dev, 0x08,
909 spca504A_acknowledged_command(gspca_dev
, 0x24,
910 0x00, 0x00, 0x9d, 1);
911 spca504A_acknowledged_command(gspca_dev
, 0x01,
912 0x0f, 0x00, 0xff, 1);
914 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
915 reg_w_riv(gspca_dev
, 0x01, 0x000f, 0x0000);
921 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
922 u8
*data
, /* isoc packet */
923 int len
) /* iso packet length */
925 struct sd
*sd
= (struct sd
*) gspca_dev
;
927 static u8 ffd9
[] = {0xff, 0xd9};
929 /* frames are jpeg 4.1.1 without 0xff escape */
930 switch (sd
->bridge
) {
932 if (data
[0] == 0xff) {
933 if (data
[1] != 0x01) { /* drop packet */
934 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
938 data
+= SPCA533_OFFSET_DATA
;
939 len
-= SPCA533_OFFSET_DATA
;
946 if (data
[0] == 0xff) {
948 data
+= SPCA536_OFFSET_DATA
;
949 len
-= SPCA536_OFFSET_DATA
;
956 /* case BRIDGE_SPCA504: */
957 /* case BRIDGE_SPCA504B: */
959 case 0xfe: /* start of frame */
961 data
+= SPCA50X_OFFSET_DATA
;
962 len
-= SPCA50X_OFFSET_DATA
;
964 case 0xff: /* drop packet */
965 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
973 case BRIDGE_SPCA504C
:
975 case 0xfe: /* start of frame */
977 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
978 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
980 case 0xff: /* drop packet */
981 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
990 if (sof
) { /* start of frame */
991 gspca_frame_add(gspca_dev
, LAST_PACKET
,
994 /* put the JPEG header in the new frame */
995 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
996 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
999 /* add 0x00 after 0xff */
1002 if (data
[i
] == 0xff) {
1003 gspca_frame_add(gspca_dev
, INTER_PACKET
,
1012 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
1015 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1017 struct sd
*sd
= (struct sd
*) gspca_dev
;
1019 sd
->brightness
= val
;
1020 if (gspca_dev
->streaming
)
1021 setbrightness(gspca_dev
);
1022 return gspca_dev
->usb_err
;
1025 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1027 struct sd
*sd
= (struct sd
*) gspca_dev
;
1029 *val
= sd
->brightness
;
1033 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
)
1035 struct sd
*sd
= (struct sd
*) gspca_dev
;
1038 if (gspca_dev
->streaming
)
1039 setcontrast(gspca_dev
);
1040 return gspca_dev
->usb_err
;
1043 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
)
1045 struct sd
*sd
= (struct sd
*) gspca_dev
;
1047 *val
= sd
->contrast
;
1051 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
)
1053 struct sd
*sd
= (struct sd
*) gspca_dev
;
1056 if (gspca_dev
->streaming
)
1057 setcolors(gspca_dev
);
1058 return gspca_dev
->usb_err
;
1061 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
)
1063 struct sd
*sd
= (struct sd
*) gspca_dev
;
1069 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
1071 struct sd
*sd
= (struct sd
*) gspca_dev
;
1077 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1079 struct sd
*sd
= (struct sd
*) gspca_dev
;
1081 *val
= sd
->autogain
;
1085 static int sd_set_jcomp(struct gspca_dev
*gspca_dev
,
1086 struct v4l2_jpegcompression
*jcomp
)
1088 struct sd
*sd
= (struct sd
*) gspca_dev
;
1090 if (jcomp
->quality
< QUALITY_MIN
)
1091 sd
->quality
= QUALITY_MIN
;
1092 else if (jcomp
->quality
> QUALITY_MAX
)
1093 sd
->quality
= QUALITY_MAX
;
1095 sd
->quality
= jcomp
->quality
;
1096 if (gspca_dev
->streaming
)
1097 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
1098 return gspca_dev
->usb_err
;
1101 static int sd_get_jcomp(struct gspca_dev
*gspca_dev
,
1102 struct v4l2_jpegcompression
*jcomp
)
1104 struct sd
*sd
= (struct sd
*) gspca_dev
;
1106 memset(jcomp
, 0, sizeof *jcomp
);
1107 jcomp
->quality
= sd
->quality
;
1108 jcomp
->jpeg_markers
= V4L2_JPEG_MARKER_DHT
1109 | V4L2_JPEG_MARKER_DQT
;
1113 /* sub-driver description */
1114 static const struct sd_desc sd_desc
= {
1115 .name
= MODULE_NAME
,
1117 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1118 .config
= sd_config
,
1122 .pkt_scan
= sd_pkt_scan
,
1123 .get_jcomp
= sd_get_jcomp
,
1124 .set_jcomp
= sd_set_jcomp
,
1127 /* -- module initialisation -- */
1128 #define BS(bridge, subtype) \
1129 .driver_info = (BRIDGE_ ## bridge << 8) \
1131 static const struct usb_device_id device_table
[] = {
1132 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
1133 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
1134 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
1135 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
1136 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
1137 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
1138 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
1139 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
1140 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
1141 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
1142 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
1143 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
1144 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
1145 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
1146 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1147 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1148 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1149 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1150 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533
, MegapixV4
)},
1151 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1152 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1153 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1154 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1155 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1156 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1157 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1158 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1159 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1160 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1161 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1162 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1163 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1164 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1165 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1166 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1167 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1168 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1169 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1170 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1171 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1172 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1173 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1174 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1175 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1176 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1177 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1178 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1179 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1180 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1181 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1182 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1183 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1184 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1185 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1186 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1187 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1188 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1189 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1190 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1193 MODULE_DEVICE_TABLE(usb
, device_table
);
1195 /* -- device connect -- */
1196 static int sd_probe(struct usb_interface
*intf
,
1197 const struct usb_device_id
*id
)
1199 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1203 static struct usb_driver sd_driver
= {
1204 .name
= MODULE_NAME
,
1205 .id_table
= device_table
,
1207 .disconnect
= gspca_disconnect
,
1209 .suspend
= gspca_suspend
,
1210 .resume
= gspca_resume
,
1214 module_usb_driver(sd_driver
);