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 PERR("reg_r: buffer overflow\n");
255 PERR("reg_r: zero-length read\n");
258 if (gspca_dev->usb_err < 0)
260 ret = usb_control_msg(gspca_dev->dev,
261 usb_rcvctrlpipe(gspca_dev->dev, 0),
263 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
266 gspca_dev->usb_buf, len,
269 pr_err("reg_r err %d\n", ret);
270 gspca_dev->usb_err = ret;
272 * Make sure the buffer is zeroed to avoid uninitialized
275 memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
280 static void reg_w_1(struct gspca_dev *gspca_dev,
288 if (gspca_dev->usb_err < 0)
290 gspca_dev->usb_buf[0] = byte;
291 ret = usb_control_msg(gspca_dev->dev,
292 usb_sndctrlpipe(gspca_dev->dev, 0),
294 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
296 gspca_dev->usb_buf, 1,
299 pr_err("reg_w_1 err %d\n", ret);
300 gspca_dev->usb_err = ret;
304 /* write req / index / value */
305 static void reg_w_riv(struct gspca_dev *gspca_dev,
306 u8 req, u16 index, u16 value)
308 struct usb_device *dev = gspca_dev->dev;
311 if (gspca_dev->usb_err < 0)
313 ret = usb_control_msg(dev,
314 usb_sndctrlpipe(dev, 0),
316 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
317 value, index, NULL, 0, 500);
319 pr_err("reg_w_riv err %d\n", ret);
320 gspca_dev->usb_err = ret;
323 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
327 static void write_vector(struct gspca_dev *gspca_dev,
328 const struct cmd *data, int ncmds)
330 while (--ncmds >= 0) {
331 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
336 static void setup_qtable(struct gspca_dev *gspca_dev,
337 const u8 qtable[2][64])
341 /* loop over y components */
342 for (i = 0; i < 64; i++)
343 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
345 /* loop over c components */
346 for (i = 0; i < 64; i++)
347 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
350 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
351 u8 req, u16 idx, u16 val)
353 reg_w_riv(gspca_dev, req, idx, val);
354 reg_r(gspca_dev, 0x01, 0x0001, 1);
355 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
356 reg_w_riv(gspca_dev, req, idx, val);
359 reg_r(gspca_dev, 0x01, 0x0001, 1);
360 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
363 static void spca504_read_info(struct gspca_dev *gspca_dev)
368 if (gspca_debug < D_STREAM)
371 for (i = 0; i < 6; i++) {
372 reg_r(gspca_dev, 0, i, 1);
373 info[i] = gspca_dev->usb_buf[0];
376 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0",
377 info[0], info[1], info[2],
378 info[3], info[4], info[5]);
381 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
383 u16 idx, u16 val, u8 endcode, u8 count)
387 reg_w_riv(gspca_dev, req, idx, val);
388 reg_r(gspca_dev, 0x01, 0x0001, 1);
389 if (gspca_dev->usb_err < 0)
391 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
392 gspca_dev->usb_buf[0], endcode);
396 while (--count > 0) {
398 /* gsmart mini2 write a each wait setting 1 ms is enough */
399 /* reg_w_riv(gspca_dev, req, idx, val); */
400 reg_r(gspca_dev, 0x01, 0x0001, 1);
401 status = gspca_dev->usb_buf[0];
402 if (status == endcode) {
403 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
404 status, 200 - count);
410 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
414 while (--count > 0) {
415 reg_r(gspca_dev, 0x21, 0, 1);
416 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
422 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
426 while (--count > 0) {
427 reg_r(gspca_dev, 0x21, 1, 1);
428 if (gspca_dev->usb_buf[0] != 0) {
429 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
430 reg_r(gspca_dev, 0x21, 1, 1);
431 spca504B_PollingDataReady(gspca_dev);
438 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
442 if (gspca_debug < D_STREAM)
445 data = gspca_dev->usb_buf;
446 reg_r(gspca_dev, 0x20, 0, 5);
447 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
448 data[0], data[1], data[2], data[3], data[4]);
449 reg_r(gspca_dev, 0x23, 0, 64);
450 reg_r(gspca_dev, 0x23, 1, 64);
453 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
455 struct sd *sd = (struct sd *) gspca_dev;
458 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
459 switch (sd->bridge) {
461 reg_w_riv(gspca_dev, 0x31, 0, 0);
462 spca504B_WaitCmdStatus(gspca_dev);
463 spca504B_PollingDataReady(gspca_dev);
464 spca50x_GetFirmware(gspca_dev);
466 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
467 reg_r(gspca_dev, 0x24, 8, 1);
469 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
470 reg_r(gspca_dev, 0x25, 4, 1); /* size */
471 spca504B_PollingDataReady(gspca_dev);
473 /* Init the cam width height with some values get on init ? */
474 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
475 spca504B_WaitCmdStatus(gspca_dev);
476 spca504B_PollingDataReady(gspca_dev);
479 /* case BRIDGE_SPCA504B: */
480 /* case BRIDGE_SPCA536: */
481 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
482 reg_r(gspca_dev, 0x25, 4, 1); /* size */
483 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
484 reg_r(gspca_dev, 0x27, 0, 1); /* type */
485 spca504B_PollingDataReady(gspca_dev);
489 if (sd->subtype == AiptekMiniPenCam13) {
490 /* spca504a aiptek */
491 spca504A_acknowledged_command(gspca_dev,
493 0x80 | (Size & 0x0f), 1);
494 spca504A_acknowledged_command(gspca_dev,
497 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
500 case BRIDGE_SPCA504C:
502 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
503 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
508 static void spca504_wait_status(struct gspca_dev *gspca_dev)
514 /* With this we get the status, when return 0 it's all ok */
515 reg_r(gspca_dev, 0x06, 0x00, 1);
516 if (gspca_dev->usb_buf[0] == 0)
522 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
524 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
525 reg_r(gspca_dev, 0x26, 0, 1);
526 spca504B_PollingDataReady(gspca_dev);
529 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
531 struct sd *sd = (struct sd *) gspca_dev;
534 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
535 reg_w_riv(gspca_dev, 0x00, reg, val);
538 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
540 struct sd *sd = (struct sd *) gspca_dev;
543 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
544 reg_w_riv(gspca_dev, 0x00, reg, val);
547 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
549 struct sd *sd = (struct sd *) gspca_dev;
552 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
553 reg_w_riv(gspca_dev, 0x00, reg, val);
556 static void init_ctl_reg(struct gspca_dev *gspca_dev)
558 struct sd *sd = (struct sd *) gspca_dev;
561 switch (sd->bridge) {
563 case BRIDGE_SPCA504C:
567 /* case BRIDGE_SPCA533: */
568 /* case BRIDGE_SPCA504B: */
569 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
570 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
571 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
574 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
575 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
576 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
580 spca504B_PollingDataReady(gspca_dev);
583 /* this function is called at probe time */
584 static int sd_config(struct gspca_dev *gspca_dev,
585 const struct usb_device_id *id)
587 struct sd *sd = (struct sd *) gspca_dev;
590 cam = &gspca_dev->cam;
592 sd->bridge = id->driver_info >> 8;
593 sd->subtype = id->driver_info;
595 if (sd->subtype == AiptekMiniPenCam13) {
597 /* try to get the firmware as some cam answer 2.0.1.2.2
598 * and should be a spca504b then overwrite that setting */
599 reg_r(gspca_dev, 0x20, 0, 1);
600 switch (gspca_dev->usb_buf[0]) {
602 break; /* (right bridge/subtype) */
604 sd->bridge = BRIDGE_SPCA504B;
612 switch (sd->bridge) {
614 /* case BRIDGE_SPCA504B: */
615 /* case BRIDGE_SPCA504: */
616 /* case BRIDGE_SPCA536: */
617 cam->cam_mode = vga_mode;
618 cam->nmodes = ARRAY_SIZE(vga_mode);
621 cam->cam_mode = custom_mode;
622 if (sd->subtype == MegaImageVI) /* 320x240 only */
623 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
625 cam->nmodes = ARRAY_SIZE(custom_mode);
627 case BRIDGE_SPCA504C:
628 cam->cam_mode = vga_mode2;
629 cam->nmodes = ARRAY_SIZE(vga_mode2);
635 /* this function is called at probe and resume time */
636 static int sd_init(struct gspca_dev *gspca_dev)
638 struct sd *sd = (struct sd *) gspca_dev;
640 switch (sd->bridge) {
641 case BRIDGE_SPCA504B:
642 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
643 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
644 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
645 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
646 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
647 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
650 spca504B_PollingDataReady(gspca_dev);
651 spca50x_GetFirmware(gspca_dev);
654 spca50x_GetFirmware(gspca_dev);
655 reg_r(gspca_dev, 0x00, 0x5002, 1);
656 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
657 reg_r(gspca_dev, 0x24, 0, 1);
658 spca504B_PollingDataReady(gspca_dev);
659 reg_w_riv(gspca_dev, 0x34, 0, 0);
660 spca504B_WaitCmdStatus(gspca_dev);
662 case BRIDGE_SPCA504C: /* pccam600 */
663 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
664 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
665 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
666 spca504_wait_status(gspca_dev);
667 if (sd->subtype == LogitechClickSmart420)
668 write_vector(gspca_dev,
669 spca504A_clicksmart420_open_data,
670 ARRAY_SIZE(spca504A_clicksmart420_open_data));
672 write_vector(gspca_dev, spca504_pccam600_open_data,
673 ARRAY_SIZE(spca504_pccam600_open_data));
674 setup_qtable(gspca_dev, qtable_creative_pccam);
677 /* case BRIDGE_SPCA504: */
678 PDEBUG(D_STREAM, "Opening SPCA504");
679 if (sd->subtype == AiptekMiniPenCam13) {
680 spca504_read_info(gspca_dev);
682 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
683 spca504A_acknowledged_command(gspca_dev, 0x24,
685 /* Twice sequential need status 0xff->0x9e->0x9d */
686 spca504A_acknowledged_command(gspca_dev, 0x24,
689 spca504A_acknowledged_command(gspca_dev, 0x24,
691 /******************************/
692 /* spca504a aiptek */
693 spca504A_acknowledged_command(gspca_dev, 0x08,
695 /* reg_write (dev, 0, 0x2000, 0); */
696 /* reg_write (dev, 0, 0x2883, 1); */
697 /* spca504A_acknowledged_command (gspca_dev, 0x08,
699 /* spca504A_acknowledged_command (gspca_dev, 0x24,
701 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
703 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
704 spca504A_acknowledged_command(gspca_dev, 0x01,
708 reg_w_riv(gspca_dev, 0, 0x2000, 0);
709 reg_w_riv(gspca_dev, 0, 0x2883, 1);
710 setup_qtable(gspca_dev, qtable_spca504_default);
713 return gspca_dev->usb_err;
716 static int sd_start(struct gspca_dev *gspca_dev)
718 struct sd *sd = (struct sd *) gspca_dev;
721 /* create the JPEG header */
722 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
723 gspca_dev->pixfmt.width,
724 0x22); /* JPEG 411 */
725 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
727 if (sd->bridge == BRIDGE_SPCA504B)
728 spca504B_setQtable(gspca_dev);
729 spca504B_SetSizeType(gspca_dev);
730 switch (sd->bridge) {
732 /* case BRIDGE_SPCA504B: */
733 /* case BRIDGE_SPCA533: */
734 /* case BRIDGE_SPCA536: */
735 switch (sd->subtype) {
737 case LogitechClickSmart820:
739 reg_w_riv(gspca_dev, 0xf0, 0, 0);
740 spca504B_WaitCmdStatus(gspca_dev);
741 reg_w_riv(gspca_dev, 0xf0, 4, 0);
742 spca504B_WaitCmdStatus(gspca_dev);
745 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
746 spca504B_WaitCmdStatus(gspca_dev);
747 spca504B_PollingDataReady(gspca_dev);
752 if (sd->subtype == AiptekMiniPenCam13) {
753 spca504_read_info(gspca_dev);
755 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
756 spca504A_acknowledged_command(gspca_dev, 0x24,
758 /* Twice sequential need status 0xff->0x9e->0x9d */
759 spca504A_acknowledged_command(gspca_dev, 0x24,
761 spca504A_acknowledged_command(gspca_dev, 0x24,
764 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
765 spca504_read_info(gspca_dev);
766 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
767 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
769 spca504B_SetSizeType(gspca_dev);
770 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
772 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
774 case BRIDGE_SPCA504C:
775 if (sd->subtype == LogitechClickSmart420) {
776 write_vector(gspca_dev,
777 spca504A_clicksmart420_init_data,
778 ARRAY_SIZE(spca504A_clicksmart420_init_data));
780 write_vector(gspca_dev, spca504_pccam600_init_data,
781 ARRAY_SIZE(spca504_pccam600_init_data));
783 enable = (sd->autogain ? 0x04 : 0x01);
784 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
786 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
789 /* set default exposure compensation and whiteness balance */
790 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
791 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
792 spca504B_SetSizeType(gspca_dev);
795 init_ctl_reg(gspca_dev);
796 return gspca_dev->usb_err;
799 static void sd_stopN(struct gspca_dev *gspca_dev)
801 struct sd *sd = (struct sd *) gspca_dev;
803 switch (sd->bridge) {
805 /* case BRIDGE_SPCA533: */
806 /* case BRIDGE_SPCA536: */
807 /* case BRIDGE_SPCA504B: */
808 reg_w_riv(gspca_dev, 0x31, 0, 0);
809 spca504B_WaitCmdStatus(gspca_dev);
810 spca504B_PollingDataReady(gspca_dev);
813 case BRIDGE_SPCA504C:
814 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
816 if (sd->subtype == AiptekMiniPenCam13) {
817 /* spca504a aiptek */
818 /* spca504A_acknowledged_command(gspca_dev, 0x08,
820 spca504A_acknowledged_command(gspca_dev, 0x24,
821 0x00, 0x00, 0x9d, 1);
822 spca504A_acknowledged_command(gspca_dev, 0x01,
823 0x0f, 0x00, 0xff, 1);
825 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
826 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
832 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
833 u8 *data, /* isoc packet */
834 int len) /* iso packet length */
836 struct sd *sd = (struct sd *) gspca_dev;
838 static u8 ffd9[] = {0xff, 0xd9};
840 /* frames are jpeg 4.1.1 without 0xff escape */
841 switch (sd->bridge) {
843 if (data[0] == 0xff) {
844 if (data[1] != 0x01) { /* drop packet */
845 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
849 data += SPCA533_OFFSET_DATA;
850 len -= SPCA533_OFFSET_DATA;
857 if (data[0] == 0xff) {
859 data += SPCA536_OFFSET_DATA;
860 len -= SPCA536_OFFSET_DATA;
867 /* case BRIDGE_SPCA504: */
868 /* case BRIDGE_SPCA504B: */
870 case 0xfe: /* start of frame */
872 data += SPCA50X_OFFSET_DATA;
873 len -= SPCA50X_OFFSET_DATA;
875 case 0xff: /* drop packet */
876 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
884 case BRIDGE_SPCA504C:
886 case 0xfe: /* start of frame */
888 data += SPCA504_PCCAM600_OFFSET_DATA;
889 len -= SPCA504_PCCAM600_OFFSET_DATA;
891 case 0xff: /* drop packet */
892 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
901 if (sof) { /* start of frame */
902 gspca_frame_add(gspca_dev, LAST_PACKET,
905 /* put the JPEG header in the new frame */
906 gspca_frame_add(gspca_dev, FIRST_PACKET,
907 sd->jpeg_hdr, JPEG_HDR_SZ);
910 /* add 0x00 after 0xff */
913 if (data[i] == 0xff) {
914 gspca_frame_add(gspca_dev, INTER_PACKET,
923 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
926 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
928 struct gspca_dev *gspca_dev =
929 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
930 struct sd *sd = (struct sd *)gspca_dev;
932 gspca_dev->usb_err = 0;
934 if (!gspca_dev->streaming)
938 case V4L2_CID_BRIGHTNESS:
939 setbrightness(gspca_dev, ctrl->val);
941 case V4L2_CID_CONTRAST:
942 setcontrast(gspca_dev, ctrl->val);
944 case V4L2_CID_SATURATION:
945 setcolors(gspca_dev, ctrl->val);
947 case V4L2_CID_AUTOGAIN:
948 sd->autogain = ctrl->val;
951 return gspca_dev->usb_err;
954 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
958 static int sd_init_controls(struct gspca_dev *gspca_dev)
960 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
962 gspca_dev->vdev.ctrl_handler = hdl;
963 v4l2_ctrl_handler_init(hdl, 4);
964 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
965 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
966 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
967 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
968 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
969 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
970 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
971 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
974 pr_err("Could not initialize controls\n");
980 /* sub-driver description */
981 static const struct sd_desc sd_desc = {
985 .init_controls = sd_init_controls,
988 .pkt_scan = sd_pkt_scan,
991 /* -- module initialisation -- */
992 #define BS(bridge, subtype) \
993 .driver_info = (BRIDGE_ ## bridge << 8) \
995 static const struct usb_device_id device_table[] = {
996 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
997 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
998 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
999 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1000 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1001 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1002 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1003 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1004 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1005 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1006 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1007 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1008 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1009 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1010 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1011 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1012 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1013 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1014 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1015 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1016 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1017 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1018 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1019 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1020 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1021 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1022 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1023 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1024 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1025 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1026 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1027 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1028 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1030 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1031 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1033 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1034 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1035 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1037 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1038 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1039 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1040 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1041 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1042 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1043 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1044 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1045 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1046 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1047 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1048 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1049 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1050 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1051 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1052 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1053 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1054 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1055 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1058 MODULE_DEVICE_TABLE(usb, device_table);
1060 /* -- device connect -- */
1061 static int sd_probe(struct usb_interface *intf,
1062 const struct usb_device_id *id)
1064 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1068 static struct usb_driver sd_driver = {
1069 .name = MODULE_NAME,
1070 .id_table = device_table,
1072 .disconnect = gspca_disconnect,
1074 .suspend = gspca_suspend,
1075 .resume = gspca_resume,
1076 .reset_resume = gspca_resume,
1080 module_usb_driver(sd_driver);