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 MODULE_NAME "sunplus"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev
; /* !! must be the first item */
40 #define QUALITY_MIN 70
41 #define QUALITY_MAX 95
42 #define QUALITY_DEF 85
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
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
57 u8 jpeg_hdr
[JPEG_HDR_SZ
];
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
);
70 static const struct ctrl sd_ctrls
[] = {
73 .id
= V4L2_CID_BRIGHTNESS
,
74 .type
= V4L2_CTRL_TYPE_INTEGER
,
79 #define BRIGHTNESS_DEF 0
80 .default_value
= BRIGHTNESS_DEF
,
82 .set
= sd_setbrightness
,
83 .get
= sd_getbrightness
,
87 .id
= V4L2_CID_CONTRAST
,
88 .type
= V4L2_CTRL_TYPE_INTEGER
,
93 #define CONTRAST_DEF 0x20
94 .default_value
= CONTRAST_DEF
,
96 .set
= sd_setcontrast
,
97 .get
= sd_getcontrast
,
101 .id
= V4L2_CID_SATURATION
,
102 .type
= V4L2_CTRL_TYPE_INTEGER
,
107 #define COLOR_DEF 0x1a
108 .default_value
= COLOR_DEF
,
115 .id
= V4L2_CID_AUTOGAIN
,
116 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
121 #define AUTOGAIN_DEF 1
122 .default_value
= AUTOGAIN_DEF
,
124 .set
= sd_setautogain
,
125 .get
= sd_getautogain
,
129 static const struct v4l2_pix_format vga_mode
[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
132 .sizeimage
= 320 * 240 * 3 / 8 + 590,
133 .colorspace
= V4L2_COLORSPACE_JPEG
,
135 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
137 .sizeimage
= 640 * 480 * 3 / 8 + 590,
138 .colorspace
= V4L2_COLORSPACE_JPEG
,
142 static const struct v4l2_pix_format custom_mode
[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
145 .sizeimage
= 320 * 240 * 3 / 8 + 590,
146 .colorspace
= V4L2_COLORSPACE_JPEG
,
148 {464, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
150 .sizeimage
= 464 * 480 * 3 / 8 + 590,
151 .colorspace
= V4L2_COLORSPACE_JPEG
,
155 static const struct v4l2_pix_format vga_mode2
[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
158 .sizeimage
= 176 * 144 * 3 / 8 + 590,
159 .colorspace
= V4L2_COLORSPACE_JPEG
,
161 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
163 .sizeimage
= 320 * 240 * 3 / 8 + 590,
164 .colorspace
= V4L2_COLORSPACE_JPEG
,
166 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
168 .sizeimage
= 352 * 288 * 3 / 8 + 590,
169 .colorspace
= V4L2_COLORSPACE_JPEG
,
171 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
173 .sizeimage
= 640 * 480 * 3 / 8 + 590,
174 .colorspace
= V4L2_COLORSPACE_JPEG
,
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
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},
223 /* Creative PC-CAM 600 specific open data, sent before using the
224 * generic initialisation data from spca504_open_data.
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},
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},
250 {0xa1, 0x0080, 0x0001},
251 {0x30, 0x0049, 0x0000},
252 {0x30, 0x0060, 0x0005},
253 {0x0c, 0x0004, 0x0000},
254 {0x00, 0x0000, 0x0000},
255 {0x00, 0x0000, 0x2000},
256 {0x00, 0x0013, 0x2301},
257 {0x00, 0x0003, 0x2000},
260 /* clicksmart 420 open data ? */
261 static const struct cmd spca504A_clicksmart420_open_data
[] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
268 {0xa0, 0x0000, 0x0503},
271 static const u8 qtable_creative_pccam
[2][64] = {
272 { /* Q-table Y-components */
273 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
274 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
275 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
276 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
277 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
278 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
279 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
280 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
281 { /* Q-table C-components */
282 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
283 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
284 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
292 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
293 * except for one byte. Possibly a typo?
296 static const u8 qtable_spca504_default
[2][64] = {
297 { /* Q-table Y-components */
298 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
299 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
300 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
301 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
302 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
303 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
304 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
305 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
307 { /* Q-table C-components */
308 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
309 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
310 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
318 /* read <len> bytes to gspca_dev->usb_buf */
319 static void reg_r(struct gspca_dev
*gspca_dev
,
327 if (len
> USB_BUF_SZ
) {
328 err("reg_r: buffer overflow");
332 if (gspca_dev
->usb_err
< 0)
334 ret
= usb_control_msg(gspca_dev
->dev
,
335 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
337 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
340 len
? gspca_dev
->usb_buf
: NULL
, len
,
343 err("reg_r err %d", ret
);
344 gspca_dev
->usb_err
= ret
;
349 static void reg_w_1(struct gspca_dev
*gspca_dev
,
357 if (gspca_dev
->usb_err
< 0)
359 gspca_dev
->usb_buf
[0] = byte
;
360 ret
= usb_control_msg(gspca_dev
->dev
,
361 usb_sndctrlpipe(gspca_dev
->dev
, 0),
363 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
365 gspca_dev
->usb_buf
, 1,
368 err("reg_w_1 err %d", ret
);
369 gspca_dev
->usb_err
= ret
;
373 /* write req / index / value */
374 static void reg_w_riv(struct gspca_dev
*gspca_dev
,
375 u8 req
, u16 index
, u16 value
)
377 struct usb_device
*dev
= gspca_dev
->dev
;
380 if (gspca_dev
->usb_err
< 0)
382 ret
= usb_control_msg(dev
,
383 usb_sndctrlpipe(dev
, 0),
385 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
386 value
, index
, NULL
, 0, 500);
388 err("reg_w_riv err %d", ret
);
389 gspca_dev
->usb_err
= ret
;
392 PDEBUG(D_USBO
, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
396 static void write_vector(struct gspca_dev
*gspca_dev
,
397 const struct cmd
*data
, int ncmds
)
399 while (--ncmds
>= 0) {
400 reg_w_riv(gspca_dev
, data
->req
, data
->idx
, data
->val
);
405 static void setup_qtable(struct gspca_dev
*gspca_dev
,
406 const u8 qtable
[2][64])
410 /* loop over y components */
411 for (i
= 0; i
< 64; i
++)
412 reg_w_riv(gspca_dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
414 /* loop over c components */
415 for (i
= 0; i
< 64; i
++)
416 reg_w_riv(gspca_dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
419 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
420 u8 req
, u16 idx
, u16 val
)
422 reg_w_riv(gspca_dev
, req
, idx
, val
);
423 reg_r(gspca_dev
, 0x01, 0x0001, 1);
424 PDEBUG(D_FRAM
, "before wait 0x%04x", gspca_dev
->usb_buf
[0]);
425 reg_w_riv(gspca_dev
, req
, idx
, val
);
428 reg_r(gspca_dev
, 0x01, 0x0001, 1);
429 PDEBUG(D_FRAM
, "after wait 0x%04x", gspca_dev
->usb_buf
[0]);
433 static void spca504_read_info(struct gspca_dev
*gspca_dev
)
438 for (i
= 0; i
< 6; i
++) {
439 reg_r(gspca_dev
, 0, i
, 1);
440 info
[i
] = gspca_dev
->usb_buf
[0];
443 "Read info: %d %d %d %d %d %d."
444 " Should be 1,0,2,2,0,0",
445 info
[0], info
[1], info
[2],
446 info
[3], info
[4], info
[5]);
450 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
452 u16 idx
, u16 val
, u8 endcode
, u8 count
)
456 reg_w_riv(gspca_dev
, req
, idx
, val
);
457 reg_r(gspca_dev
, 0x01, 0x0001, 1);
458 if (gspca_dev
->usb_err
< 0)
460 PDEBUG(D_FRAM
, "Status 0x%02x Need 0x%02x",
461 gspca_dev
->usb_buf
[0], endcode
);
465 while (--count
> 0) {
467 /* gsmart mini2 write a each wait setting 1 ms is enough */
468 /* reg_w_riv(gspca_dev, req, idx, val); */
469 reg_r(gspca_dev
, 0x01, 0x0001, 1);
470 status
= gspca_dev
->usb_buf
[0];
471 if (status
== endcode
) {
472 PDEBUG(D_FRAM
, "status 0x%04x after wait %d",
473 status
, 200 - count
);
479 static void spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
483 while (--count
> 0) {
484 reg_r(gspca_dev
, 0x21, 0, 1);
485 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
491 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
495 while (--count
> 0) {
496 reg_r(gspca_dev
, 0x21, 1, 1);
497 if (gspca_dev
->usb_buf
[0] != 0) {
498 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
499 reg_r(gspca_dev
, 0x21, 1, 1);
500 spca504B_PollingDataReady(gspca_dev
);
508 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
512 data
= gspca_dev
->usb_buf
;
513 reg_r(gspca_dev
, 0x20, 0, 5);
514 PDEBUG(D_STREAM
, "FirmWare: %d %d %d %d %d",
515 data
[0], data
[1], data
[2], data
[3], data
[4]);
516 reg_r(gspca_dev
, 0x23, 0, 64);
517 reg_r(gspca_dev
, 0x23, 1, 64);
521 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
523 struct sd
*sd
= (struct sd
*) gspca_dev
;
526 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
527 switch (sd
->bridge
) {
529 reg_w_riv(gspca_dev
, 0x31, 0, 0);
530 spca504B_WaitCmdStatus(gspca_dev
);
531 spca504B_PollingDataReady(gspca_dev
);
533 spca50x_GetFirmware(gspca_dev
);
535 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
536 reg_r(gspca_dev
, 0x24, 8, 1);
538 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
539 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
540 spca504B_PollingDataReady(gspca_dev
);
542 /* Init the cam width height with some values get on init ? */
543 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
544 spca504B_WaitCmdStatus(gspca_dev
);
545 spca504B_PollingDataReady(gspca_dev
);
548 /* case BRIDGE_SPCA504B: */
549 /* case BRIDGE_SPCA536: */
550 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
551 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
552 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
553 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
554 spca504B_PollingDataReady(gspca_dev
);
558 if (sd
->subtype
== AiptekMiniPenCam13
) {
559 /* spca504a aiptek */
560 spca504A_acknowledged_command(gspca_dev
,
562 0x80 | (Size
& 0x0f), 1);
563 spca504A_acknowledged_command(gspca_dev
,
566 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
569 case BRIDGE_SPCA504C
:
571 reg_w_riv(gspca_dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
572 reg_w_riv(gspca_dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
577 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
583 /* With this we get the status, when return 0 it's all ok */
584 reg_r(gspca_dev
, 0x06, 0x00, 1);
585 if (gspca_dev
->usb_buf
[0] == 0)
591 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
593 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
594 reg_r(gspca_dev
, 0x26, 0, 1);
595 spca504B_PollingDataReady(gspca_dev
);
598 static void setbrightness(struct gspca_dev
*gspca_dev
)
600 struct sd
*sd
= (struct sd
*) gspca_dev
;
603 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
604 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->brightness
);
607 static void setcontrast(struct gspca_dev
*gspca_dev
)
609 struct sd
*sd
= (struct sd
*) gspca_dev
;
612 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
613 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->contrast
);
616 static void setcolors(struct gspca_dev
*gspca_dev
)
618 struct sd
*sd
= (struct sd
*) gspca_dev
;
621 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
622 reg_w_riv(gspca_dev
, 0x00, reg
, sd
->colors
);
625 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
627 struct sd
*sd
= (struct sd
*) gspca_dev
;
630 setbrightness(gspca_dev
);
631 setcontrast(gspca_dev
);
632 setcolors(gspca_dev
);
634 switch (sd
->bridge
) {
636 case BRIDGE_SPCA504C
:
640 /* case BRIDGE_SPCA533: */
641 /* case BRIDGE_SPCA504B: */
642 reg_w_riv(gspca_dev
, 0, 0x21ad, 0x00); /* hue */
643 reg_w_riv(gspca_dev
, 0, 0x21ac, 0x01); /* sat/hue */
644 reg_w_riv(gspca_dev
, 0, 0x21a3, 0x00); /* gamma */
647 reg_w_riv(gspca_dev
, 0, 0x20f5, 0x40);
648 reg_w_riv(gspca_dev
, 0, 0x20f4, 0x01);
649 reg_w_riv(gspca_dev
, 0, 0x2089, 0x00);
653 spca504B_PollingDataReady(gspca_dev
);
656 /* this function is called at probe time */
657 static int sd_config(struct gspca_dev
*gspca_dev
,
658 const struct usb_device_id
*id
)
660 struct sd
*sd
= (struct sd
*) gspca_dev
;
663 cam
= &gspca_dev
->cam
;
665 sd
->bridge
= id
->driver_info
>> 8;
666 sd
->subtype
= id
->driver_info
;
668 if (sd
->subtype
== AiptekMiniPenCam13
) {
670 /* try to get the firmware as some cam answer 2.0.1.2.2
671 * and should be a spca504b then overwrite that setting */
672 reg_r(gspca_dev
, 0x20, 0, 1);
673 switch (gspca_dev
->usb_buf
[0]) {
675 break; /* (right bridge/subtype) */
677 sd
->bridge
= BRIDGE_SPCA504B
;
685 switch (sd
->bridge
) {
687 /* case BRIDGE_SPCA504B: */
688 /* case BRIDGE_SPCA504: */
689 /* case BRIDGE_SPCA536: */
690 cam
->cam_mode
= vga_mode
;
691 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
694 cam
->cam_mode
= custom_mode
;
695 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
696 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
698 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
700 case BRIDGE_SPCA504C
:
701 cam
->cam_mode
= vga_mode2
;
702 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
705 sd
->brightness
= BRIGHTNESS_DEF
;
706 sd
->contrast
= CONTRAST_DEF
;
707 sd
->colors
= COLOR_DEF
;
708 sd
->autogain
= AUTOGAIN_DEF
;
709 sd
->quality
= QUALITY_DEF
;
713 /* this function is called at probe and resume time */
714 static int sd_init(struct gspca_dev
*gspca_dev
)
716 struct sd
*sd
= (struct sd
*) gspca_dev
;
718 switch (sd
->bridge
) {
719 case BRIDGE_SPCA504B
:
720 reg_w_riv(gspca_dev
, 0x1d, 0x00, 0);
721 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x01);
722 reg_w_riv(gspca_dev
, 0x00, 0x0d04, 0x00);
723 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x00);
724 reg_w_riv(gspca_dev
, 0x00, 0x2301, 0x13);
725 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x00);
728 spca504B_PollingDataReady(gspca_dev
);
730 spca50x_GetFirmware(gspca_dev
);
735 spca50x_GetFirmware(gspca_dev
);
737 reg_r(gspca_dev
, 0x00, 0x5002, 1);
738 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
739 reg_r(gspca_dev
, 0x24, 0, 1);
740 spca504B_PollingDataReady(gspca_dev
);
741 reg_w_riv(gspca_dev
, 0x34, 0, 0);
742 spca504B_WaitCmdStatus(gspca_dev
);
744 case BRIDGE_SPCA504C
: /* pccam600 */
745 PDEBUG(D_STREAM
, "Opening SPCA504 (PC-CAM 600)");
746 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0000);
747 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0001); /* reset */
748 spca504_wait_status(gspca_dev
);
749 if (sd
->subtype
== LogitechClickSmart420
)
750 write_vector(gspca_dev
,
751 spca504A_clicksmart420_open_data
,
752 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
754 write_vector(gspca_dev
, spca504_pccam600_open_data
,
755 ARRAY_SIZE(spca504_pccam600_open_data
));
756 setup_qtable(gspca_dev
, qtable_creative_pccam
);
759 /* case BRIDGE_SPCA504: */
760 PDEBUG(D_STREAM
, "Opening SPCA504");
761 if (sd
->subtype
== AiptekMiniPenCam13
) {
763 spca504_read_info(gspca_dev
);
766 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
767 spca504A_acknowledged_command(gspca_dev
, 0x24,
769 /* Twice sequential need status 0xff->0x9e->0x9d */
770 spca504A_acknowledged_command(gspca_dev
, 0x24,
773 spca504A_acknowledged_command(gspca_dev
, 0x24,
775 /******************************/
776 /* spca504a aiptek */
777 spca504A_acknowledged_command(gspca_dev
, 0x08,
779 /* reg_write (dev, 0, 0x2000, 0); */
780 /* reg_write (dev, 0, 0x2883, 1); */
781 /* spca504A_acknowledged_command (gspca_dev, 0x08,
783 /* spca504A_acknowledged_command (gspca_dev, 0x24,
785 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
787 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
788 spca504A_acknowledged_command(gspca_dev
, 0x01,
792 reg_w_riv(gspca_dev
, 0, 0x2000, 0);
793 reg_w_riv(gspca_dev
, 0, 0x2883, 1);
794 setup_qtable(gspca_dev
, qtable_spca504_default
);
797 return gspca_dev
->usb_err
;
800 static int sd_start(struct gspca_dev
*gspca_dev
)
802 struct sd
*sd
= (struct sd
*) gspca_dev
;
805 /* create the JPEG header */
806 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->height
, gspca_dev
->width
,
807 0x22); /* JPEG 411 */
808 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
810 if (sd
->bridge
== BRIDGE_SPCA504B
)
811 spca504B_setQtable(gspca_dev
);
812 spca504B_SetSizeType(gspca_dev
);
813 switch (sd
->bridge
) {
815 /* case BRIDGE_SPCA504B: */
816 /* case BRIDGE_SPCA533: */
817 /* case BRIDGE_SPCA536: */
818 switch (sd
->subtype
) {
820 case LogitechClickSmart820
:
822 reg_w_riv(gspca_dev
, 0xf0, 0, 0);
823 spca504B_WaitCmdStatus(gspca_dev
);
824 reg_r(gspca_dev
, 0xf0, 4, 0);
825 spca504B_WaitCmdStatus(gspca_dev
);
828 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
829 spca504B_WaitCmdStatus(gspca_dev
);
830 spca504B_PollingDataReady(gspca_dev
);
835 if (sd
->subtype
== AiptekMiniPenCam13
) {
837 spca504_read_info(gspca_dev
);
840 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
841 spca504A_acknowledged_command(gspca_dev
, 0x24,
843 /* Twice sequential need status 0xff->0x9e->0x9d */
844 spca504A_acknowledged_command(gspca_dev
, 0x24,
846 spca504A_acknowledged_command(gspca_dev
, 0x24,
849 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
851 spca504_read_info(gspca_dev
);
853 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
854 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
856 spca504B_SetSizeType(gspca_dev
);
857 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
859 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
861 case BRIDGE_SPCA504C
:
862 if (sd
->subtype
== LogitechClickSmart420
) {
863 write_vector(gspca_dev
,
864 spca504A_clicksmart420_init_data
,
865 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
867 write_vector(gspca_dev
, spca504_pccam600_init_data
,
868 ARRAY_SIZE(spca504_pccam600_init_data
));
870 enable
= (sd
->autogain
? 0x04 : 0x01);
871 reg_w_riv(gspca_dev
, 0x0c, 0x0000, enable
);
873 reg_w_riv(gspca_dev
, 0xb0, 0x0000, enable
);
876 /* set default exposure compensation and whiteness balance */
877 reg_w_riv(gspca_dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
878 reg_w_riv(gspca_dev
, 0x30, 0x0002, 1600);
879 spca504B_SetSizeType(gspca_dev
);
882 init_ctl_reg(gspca_dev
);
883 return gspca_dev
->usb_err
;
886 static void sd_stopN(struct gspca_dev
*gspca_dev
)
888 struct sd
*sd
= (struct sd
*) gspca_dev
;
890 switch (sd
->bridge
) {
892 /* case BRIDGE_SPCA533: */
893 /* case BRIDGE_SPCA536: */
894 /* case BRIDGE_SPCA504B: */
895 reg_w_riv(gspca_dev
, 0x31, 0, 0);
896 spca504B_WaitCmdStatus(gspca_dev
);
897 spca504B_PollingDataReady(gspca_dev
);
900 case BRIDGE_SPCA504C
:
901 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x0000);
903 if (sd
->subtype
== AiptekMiniPenCam13
) {
904 /* spca504a aiptek */
905 /* spca504A_acknowledged_command(gspca_dev, 0x08,
907 spca504A_acknowledged_command(gspca_dev
, 0x24,
908 0x00, 0x00, 0x9d, 1);
909 spca504A_acknowledged_command(gspca_dev
, 0x01,
910 0x0f, 0x00, 0xff, 1);
912 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
913 reg_w_riv(gspca_dev
, 0x01, 0x000f, 0x0000);
919 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
920 u8
*data
, /* isoc packet */
921 int len
) /* iso packet length */
923 struct sd
*sd
= (struct sd
*) gspca_dev
;
925 static u8 ffd9
[] = {0xff, 0xd9};
927 /* frames are jpeg 4.1.1 without 0xff escape */
928 switch (sd
->bridge
) {
930 if (data
[0] == 0xff) {
931 if (data
[1] != 0x01) { /* drop packet */
932 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
936 data
+= SPCA533_OFFSET_DATA
;
937 len
-= SPCA533_OFFSET_DATA
;
944 if (data
[0] == 0xff) {
946 data
+= SPCA536_OFFSET_DATA
;
947 len
-= SPCA536_OFFSET_DATA
;
954 /* case BRIDGE_SPCA504: */
955 /* case BRIDGE_SPCA504B: */
957 case 0xfe: /* start of frame */
959 data
+= SPCA50X_OFFSET_DATA
;
960 len
-= SPCA50X_OFFSET_DATA
;
962 case 0xff: /* drop packet */
963 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
971 case BRIDGE_SPCA504C
:
973 case 0xfe: /* start of frame */
975 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
976 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
978 case 0xff: /* drop packet */
979 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
988 if (sof
) { /* start of frame */
989 gspca_frame_add(gspca_dev
, LAST_PACKET
,
992 /* put the JPEG header in the new frame */
993 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
994 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
997 /* add 0x00 after 0xff */
1000 if (data
[i
] == 0xff) {
1001 gspca_frame_add(gspca_dev
, INTER_PACKET
,
1010 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
1013 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1015 struct sd
*sd
= (struct sd
*) gspca_dev
;
1017 sd
->brightness
= val
;
1018 if (gspca_dev
->streaming
)
1019 setbrightness(gspca_dev
);
1020 return gspca_dev
->usb_err
;
1023 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1025 struct sd
*sd
= (struct sd
*) gspca_dev
;
1027 *val
= sd
->brightness
;
1031 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
)
1033 struct sd
*sd
= (struct sd
*) gspca_dev
;
1036 if (gspca_dev
->streaming
)
1037 setcontrast(gspca_dev
);
1038 return gspca_dev
->usb_err
;
1041 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
)
1043 struct sd
*sd
= (struct sd
*) gspca_dev
;
1045 *val
= sd
->contrast
;
1049 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
)
1051 struct sd
*sd
= (struct sd
*) gspca_dev
;
1054 if (gspca_dev
->streaming
)
1055 setcolors(gspca_dev
);
1056 return gspca_dev
->usb_err
;
1059 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
)
1061 struct sd
*sd
= (struct sd
*) gspca_dev
;
1067 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
1069 struct sd
*sd
= (struct sd
*) gspca_dev
;
1075 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1077 struct sd
*sd
= (struct sd
*) gspca_dev
;
1079 *val
= sd
->autogain
;
1083 static int sd_set_jcomp(struct gspca_dev
*gspca_dev
,
1084 struct v4l2_jpegcompression
*jcomp
)
1086 struct sd
*sd
= (struct sd
*) gspca_dev
;
1088 if (jcomp
->quality
< QUALITY_MIN
)
1089 sd
->quality
= QUALITY_MIN
;
1090 else if (jcomp
->quality
> QUALITY_MAX
)
1091 sd
->quality
= QUALITY_MAX
;
1093 sd
->quality
= jcomp
->quality
;
1094 if (gspca_dev
->streaming
)
1095 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
1096 return gspca_dev
->usb_err
;
1099 static int sd_get_jcomp(struct gspca_dev
*gspca_dev
,
1100 struct v4l2_jpegcompression
*jcomp
)
1102 struct sd
*sd
= (struct sd
*) gspca_dev
;
1104 memset(jcomp
, 0, sizeof *jcomp
);
1105 jcomp
->quality
= sd
->quality
;
1106 jcomp
->jpeg_markers
= V4L2_JPEG_MARKER_DHT
1107 | V4L2_JPEG_MARKER_DQT
;
1111 /* sub-driver description */
1112 static const struct sd_desc sd_desc
= {
1113 .name
= MODULE_NAME
,
1115 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1116 .config
= sd_config
,
1120 .pkt_scan
= sd_pkt_scan
,
1121 .get_jcomp
= sd_get_jcomp
,
1122 .set_jcomp
= sd_set_jcomp
,
1125 /* -- module initialisation -- */
1126 #define BS(bridge, subtype) \
1127 .driver_info = (BRIDGE_ ## bridge << 8) \
1129 static const struct usb_device_id device_table
[] = {
1130 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
1131 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
1132 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
1133 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
1134 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
1135 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
1136 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
1137 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
1138 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
1139 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
1140 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
1141 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
1142 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
1143 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
1144 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1145 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1146 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1147 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1148 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533
, MegapixV4
)},
1149 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1150 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1151 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1152 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1153 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1154 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1155 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1156 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1157 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1158 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1159 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1160 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1161 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1162 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1163 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1164 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1165 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1166 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1167 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1168 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1169 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1170 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1171 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1172 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1173 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1174 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1175 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1176 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1177 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1178 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1179 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1180 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1181 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1182 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1183 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1184 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1185 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1186 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1187 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1188 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1191 MODULE_DEVICE_TABLE(usb
, device_table
);
1193 /* -- device connect -- */
1194 static int sd_probe(struct usb_interface
*intf
,
1195 const struct usb_device_id
*id
)
1197 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1201 static struct usb_driver sd_driver
= {
1202 .name
= MODULE_NAME
,
1203 .id_table
= device_table
,
1205 .disconnect
= gspca_disconnect
,
1207 .suspend
= gspca_suspend
,
1208 .resume
= gspca_resume
,
1212 /* -- module insert / remove -- */
1213 static int __init
sd_mod_init(void)
1215 return usb_register(&sd_driver
);
1217 static void __exit
sd_mod_exit(void)
1219 usb_deregister(&sd_driver
);
1222 module_init(sd_mod_init
);
1223 module_exit(sd_mod_exit
);