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");
35 /* specific webcam descriptor */
37 struct gspca_dev gspca_dev; /* !! must be the first item */
42 #define BRIDGE_SPCA504 0
43 #define BRIDGE_SPCA504B 1
44 #define BRIDGE_SPCA504C 2
45 #define BRIDGE_SPCA533 3
46 #define BRIDGE_SPCA536 4
48 #define AiptekMiniPenCam13 1
49 #define LogitechClickSmart420 2
50 #define LogitechClickSmart820 3
54 u8 jpeg_hdr[JPEG_HDR_SZ];
57 static const struct v4l2_pix_format vga_mode[] = {
58 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
60 .sizeimage = 320 * 240 * 3 / 8 + 590,
61 .colorspace = V4L2_COLORSPACE_JPEG,
63 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
65 .sizeimage = 640 * 480 * 3 / 8 + 590,
66 .colorspace = V4L2_COLORSPACE_JPEG,
70 static const struct v4l2_pix_format custom_mode[] = {
71 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
73 .sizeimage = 320 * 240 * 3 / 8 + 590,
74 .colorspace = V4L2_COLORSPACE_JPEG,
76 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
78 .sizeimage = 464 * 480 * 3 / 8 + 590,
79 .colorspace = V4L2_COLORSPACE_JPEG,
83 static const struct v4l2_pix_format vga_mode2[] = {
84 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
86 .sizeimage = 176 * 144 * 3 / 8 + 590,
87 .colorspace = V4L2_COLORSPACE_JPEG,
89 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
91 .sizeimage = 320 * 240 * 3 / 8 + 590,
92 .colorspace = V4L2_COLORSPACE_JPEG,
94 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
96 .sizeimage = 352 * 288 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
99 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
106 #define SPCA50X_OFFSET_DATA 10
107 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
108 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
109 #define SPCA504_PCCAM600_OFFSET_MODE 5
110 #define SPCA504_PCCAM600_OFFSET_DATA 14
111 /* Frame packet header offsets for the spca533 */
112 #define SPCA533_OFFSET_DATA 16
113 #define SPCA533_OFFSET_FRAMSEQ 15
114 /* Frame packet header offsets for the spca536 */
115 #define SPCA536_OFFSET_DATA 4
116 #define SPCA536_OFFSET_FRAMSEQ 1
124 /* Initialisation data for the Creative PC-CAM 600 */
125 static const struct cmd spca504_pccam600_init_data[] = {
126 /* {0xa0, 0x0000, 0x0503}, * capture mode */
127 {0x00, 0x0000, 0x2000},
128 {0x00, 0x0013, 0x2301},
129 {0x00, 0x0003, 0x2000},
130 {0x00, 0x0001, 0x21ac},
131 {0x00, 0x0001, 0x21a6},
132 {0x00, 0x0000, 0x21a7}, /* brightness */
133 {0x00, 0x0020, 0x21a8}, /* contrast */
134 {0x00, 0x0001, 0x21ac}, /* sat/hue */
135 {0x00, 0x0000, 0x21ad}, /* hue */
136 {0x00, 0x001a, 0x21ae}, /* saturation */
137 {0x00, 0x0002, 0x21a3}, /* gamma */
138 {0x30, 0x0154, 0x0008},
139 {0x30, 0x0004, 0x0006},
140 {0x30, 0x0258, 0x0009},
141 {0x30, 0x0004, 0x0000},
142 {0x30, 0x0093, 0x0004},
143 {0x30, 0x0066, 0x0005},
144 {0x00, 0x0000, 0x2000},
145 {0x00, 0x0013, 0x2301},
146 {0x00, 0x0003, 0x2000},
147 {0x00, 0x0013, 0x2301},
148 {0x00, 0x0003, 0x2000},
151 /* Creative PC-CAM 600 specific open data, sent before using the
152 * generic initialisation data from spca504_open_data.
154 static const struct cmd spca504_pccam600_open_data[] = {
155 {0x00, 0x0001, 0x2501},
156 {0x20, 0x0500, 0x0001}, /* snapshot mode */
157 {0x00, 0x0003, 0x2880},
158 {0x00, 0x0001, 0x2881},
161 /* Initialisation data for the logitech clicksmart 420 */
162 static const struct cmd spca504A_clicksmart420_init_data[] = {
163 /* {0xa0, 0x0000, 0x0503}, * capture mode */
164 {0x00, 0x0000, 0x2000},
165 {0x00, 0x0013, 0x2301},
166 {0x00, 0x0003, 0x2000},
167 {0x00, 0x0001, 0x21ac},
168 {0x00, 0x0001, 0x21a6},
169 {0x00, 0x0000, 0x21a7}, /* brightness */
170 {0x00, 0x0020, 0x21a8}, /* contrast */
171 {0x00, 0x0001, 0x21ac}, /* sat/hue */
172 {0x00, 0x0000, 0x21ad}, /* hue */
173 {0x00, 0x001a, 0x21ae}, /* saturation */
174 {0x00, 0x0002, 0x21a3}, /* gamma */
175 {0x30, 0x0004, 0x000a},
176 {0xb0, 0x0001, 0x0000},
178 {0xa1, 0x0080, 0x0001},
179 {0x30, 0x0049, 0x0000},
180 {0x30, 0x0060, 0x0005},
181 {0x0c, 0x0004, 0x0000},
182 {0x00, 0x0000, 0x0000},
183 {0x00, 0x0000, 0x2000},
184 {0x00, 0x0013, 0x2301},
185 {0x00, 0x0003, 0x2000},
188 /* clicksmart 420 open data ? */
189 static const struct cmd spca504A_clicksmart420_open_data[] = {
190 {0x00, 0x0001, 0x2501},
191 {0x20, 0x0502, 0x0000},
192 {0x06, 0x0000, 0x0000},
193 {0x00, 0x0004, 0x2880},
194 {0x00, 0x0001, 0x2881},
196 {0xa0, 0x0000, 0x0503},
199 static const u8 qtable_creative_pccam[2][64] = {
200 { /* Q-table Y-components */
201 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
202 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
203 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
204 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
205 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
206 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
207 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
208 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
209 { /* Q-table C-components */
210 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
211 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
212 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
214 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
215 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
216 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
217 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
220 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
221 * except for one byte. Possibly a typo?
224 static const u8 qtable_spca504_default[2][64] = {
225 { /* Q-table Y-components */
226 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
227 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
228 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
229 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
230 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
231 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
232 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
233 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
235 { /* Q-table C-components */
236 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
237 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
238 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
240 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
241 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
242 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
243 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
246 /* read <len> bytes to gspca_dev->usb_buf */
247 static void reg_r(struct gspca_dev *gspca_dev,
254 if (len > USB_BUF_SZ) {
255 PERR("reg_r: buffer overflow\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 len ? gspca_dev->usb_buf : NULL, len,
269 pr_err("reg_r err %d\n", ret);
270 gspca_dev->usb_err = ret;
275 static void reg_w_1(struct gspca_dev *gspca_dev,
283 if (gspca_dev->usb_err < 0)
285 gspca_dev->usb_buf[0] = byte;
286 ret = usb_control_msg(gspca_dev->dev,
287 usb_sndctrlpipe(gspca_dev->dev, 0),
289 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
291 gspca_dev->usb_buf, 1,
294 pr_err("reg_w_1 err %d\n", ret);
295 gspca_dev->usb_err = ret;
299 /* write req / index / value */
300 static void reg_w_riv(struct gspca_dev *gspca_dev,
301 u8 req, u16 index, u16 value)
303 struct usb_device *dev = gspca_dev->dev;
306 if (gspca_dev->usb_err < 0)
308 ret = usb_control_msg(dev,
309 usb_sndctrlpipe(dev, 0),
311 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312 value, index, NULL, 0, 500);
314 pr_err("reg_w_riv err %d\n", ret);
315 gspca_dev->usb_err = ret;
318 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
322 static void write_vector(struct gspca_dev *gspca_dev,
323 const struct cmd *data, int ncmds)
325 while (--ncmds >= 0) {
326 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
331 static void setup_qtable(struct gspca_dev *gspca_dev,
332 const u8 qtable[2][64])
336 /* loop over y components */
337 for (i = 0; i < 64; i++)
338 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
340 /* loop over c components */
341 for (i = 0; i < 64; i++)
342 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
345 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
346 u8 req, u16 idx, u16 val)
348 reg_w_riv(gspca_dev, req, idx, val);
349 reg_r(gspca_dev, 0x01, 0x0001, 1);
350 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
351 reg_w_riv(gspca_dev, req, idx, val);
354 reg_r(gspca_dev, 0x01, 0x0001, 1);
355 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
358 static void spca504_read_info(struct gspca_dev *gspca_dev)
363 if (gspca_debug < D_STREAM)
366 for (i = 0; i < 6; i++) {
367 reg_r(gspca_dev, 0, i, 1);
368 info[i] = gspca_dev->usb_buf[0];
371 "Read info: %d %d %d %d %d %d."
372 " Should be 1,0,2,2,0,0",
373 info[0], info[1], info[2],
374 info[3], info[4], info[5]);
377 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
379 u16 idx, u16 val, u8 endcode, u8 count)
383 reg_w_riv(gspca_dev, req, idx, val);
384 reg_r(gspca_dev, 0x01, 0x0001, 1);
385 if (gspca_dev->usb_err < 0)
387 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
388 gspca_dev->usb_buf[0], endcode);
392 while (--count > 0) {
394 /* gsmart mini2 write a each wait setting 1 ms is enough */
395 /* reg_w_riv(gspca_dev, req, idx, val); */
396 reg_r(gspca_dev, 0x01, 0x0001, 1);
397 status = gspca_dev->usb_buf[0];
398 if (status == endcode) {
399 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
400 status, 200 - count);
406 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
410 while (--count > 0) {
411 reg_r(gspca_dev, 0x21, 0, 1);
412 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
418 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
422 while (--count > 0) {
423 reg_r(gspca_dev, 0x21, 1, 1);
424 if (gspca_dev->usb_buf[0] != 0) {
425 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
426 reg_r(gspca_dev, 0x21, 1, 1);
427 spca504B_PollingDataReady(gspca_dev);
434 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
438 if (gspca_debug < D_STREAM)
441 data = gspca_dev->usb_buf;
442 reg_r(gspca_dev, 0x20, 0, 5);
443 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
444 data[0], data[1], data[2], data[3], data[4]);
445 reg_r(gspca_dev, 0x23, 0, 64);
446 reg_r(gspca_dev, 0x23, 1, 64);
449 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
451 struct sd *sd = (struct sd *) gspca_dev;
454 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
455 switch (sd->bridge) {
457 reg_w_riv(gspca_dev, 0x31, 0, 0);
458 spca504B_WaitCmdStatus(gspca_dev);
459 spca504B_PollingDataReady(gspca_dev);
460 spca50x_GetFirmware(gspca_dev);
462 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
463 reg_r(gspca_dev, 0x24, 8, 1);
465 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
466 reg_r(gspca_dev, 0x25, 4, 1); /* size */
467 spca504B_PollingDataReady(gspca_dev);
469 /* Init the cam width height with some values get on init ? */
470 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
471 spca504B_WaitCmdStatus(gspca_dev);
472 spca504B_PollingDataReady(gspca_dev);
475 /* case BRIDGE_SPCA504B: */
476 /* case BRIDGE_SPCA536: */
477 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
478 reg_r(gspca_dev, 0x25, 4, 1); /* size */
479 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
480 reg_r(gspca_dev, 0x27, 0, 1); /* type */
481 spca504B_PollingDataReady(gspca_dev);
485 if (sd->subtype == AiptekMiniPenCam13) {
486 /* spca504a aiptek */
487 spca504A_acknowledged_command(gspca_dev,
489 0x80 | (Size & 0x0f), 1);
490 spca504A_acknowledged_command(gspca_dev,
493 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
496 case BRIDGE_SPCA504C:
498 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
499 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
504 static void spca504_wait_status(struct gspca_dev *gspca_dev)
510 /* With this we get the status, when return 0 it's all ok */
511 reg_r(gspca_dev, 0x06, 0x00, 1);
512 if (gspca_dev->usb_buf[0] == 0)
518 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
520 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
521 reg_r(gspca_dev, 0x26, 0, 1);
522 spca504B_PollingDataReady(gspca_dev);
525 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
527 struct sd *sd = (struct sd *) gspca_dev;
530 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
531 reg_w_riv(gspca_dev, 0x00, reg, val);
534 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
536 struct sd *sd = (struct sd *) gspca_dev;
539 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
540 reg_w_riv(gspca_dev, 0x00, reg, val);
543 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
545 struct sd *sd = (struct sd *) gspca_dev;
548 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
549 reg_w_riv(gspca_dev, 0x00, reg, val);
552 static void init_ctl_reg(struct gspca_dev *gspca_dev)
554 struct sd *sd = (struct sd *) gspca_dev;
557 switch (sd->bridge) {
559 case BRIDGE_SPCA504C:
563 /* case BRIDGE_SPCA533: */
564 /* case BRIDGE_SPCA504B: */
565 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
566 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
567 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
570 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
571 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
572 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
576 spca504B_PollingDataReady(gspca_dev);
579 /* this function is called at probe time */
580 static int sd_config(struct gspca_dev *gspca_dev,
581 const struct usb_device_id *id)
583 struct sd *sd = (struct sd *) gspca_dev;
586 cam = &gspca_dev->cam;
588 sd->bridge = id->driver_info >> 8;
589 sd->subtype = id->driver_info;
591 if (sd->subtype == AiptekMiniPenCam13) {
593 /* try to get the firmware as some cam answer 2.0.1.2.2
594 * and should be a spca504b then overwrite that setting */
595 reg_r(gspca_dev, 0x20, 0, 1);
596 switch (gspca_dev->usb_buf[0]) {
598 break; /* (right bridge/subtype) */
600 sd->bridge = BRIDGE_SPCA504B;
608 switch (sd->bridge) {
610 /* case BRIDGE_SPCA504B: */
611 /* case BRIDGE_SPCA504: */
612 /* case BRIDGE_SPCA536: */
613 cam->cam_mode = vga_mode;
614 cam->nmodes = ARRAY_SIZE(vga_mode);
617 cam->cam_mode = custom_mode;
618 if (sd->subtype == MegaImageVI) /* 320x240 only */
619 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
621 cam->nmodes = ARRAY_SIZE(custom_mode);
623 case BRIDGE_SPCA504C:
624 cam->cam_mode = vga_mode2;
625 cam->nmodes = ARRAY_SIZE(vga_mode2);
631 /* this function is called at probe and resume time */
632 static int sd_init(struct gspca_dev *gspca_dev)
634 struct sd *sd = (struct sd *) gspca_dev;
636 switch (sd->bridge) {
637 case BRIDGE_SPCA504B:
638 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
639 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
640 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
641 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
642 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
643 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
646 spca504B_PollingDataReady(gspca_dev);
647 spca50x_GetFirmware(gspca_dev);
650 spca50x_GetFirmware(gspca_dev);
651 reg_r(gspca_dev, 0x00, 0x5002, 1);
652 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
653 reg_r(gspca_dev, 0x24, 0, 1);
654 spca504B_PollingDataReady(gspca_dev);
655 reg_w_riv(gspca_dev, 0x34, 0, 0);
656 spca504B_WaitCmdStatus(gspca_dev);
658 case BRIDGE_SPCA504C: /* pccam600 */
659 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
660 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
661 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
662 spca504_wait_status(gspca_dev);
663 if (sd->subtype == LogitechClickSmart420)
664 write_vector(gspca_dev,
665 spca504A_clicksmart420_open_data,
666 ARRAY_SIZE(spca504A_clicksmart420_open_data));
668 write_vector(gspca_dev, spca504_pccam600_open_data,
669 ARRAY_SIZE(spca504_pccam600_open_data));
670 setup_qtable(gspca_dev, qtable_creative_pccam);
673 /* case BRIDGE_SPCA504: */
674 PDEBUG(D_STREAM, "Opening SPCA504");
675 if (sd->subtype == AiptekMiniPenCam13) {
676 spca504_read_info(gspca_dev);
678 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
679 spca504A_acknowledged_command(gspca_dev, 0x24,
681 /* Twice sequential need status 0xff->0x9e->0x9d */
682 spca504A_acknowledged_command(gspca_dev, 0x24,
685 spca504A_acknowledged_command(gspca_dev, 0x24,
687 /******************************/
688 /* spca504a aiptek */
689 spca504A_acknowledged_command(gspca_dev, 0x08,
691 /* reg_write (dev, 0, 0x2000, 0); */
692 /* reg_write (dev, 0, 0x2883, 1); */
693 /* spca504A_acknowledged_command (gspca_dev, 0x08,
695 /* spca504A_acknowledged_command (gspca_dev, 0x24,
697 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
699 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
700 spca504A_acknowledged_command(gspca_dev, 0x01,
704 reg_w_riv(gspca_dev, 0, 0x2000, 0);
705 reg_w_riv(gspca_dev, 0, 0x2883, 1);
706 setup_qtable(gspca_dev, qtable_spca504_default);
709 return gspca_dev->usb_err;
712 static int sd_start(struct gspca_dev *gspca_dev)
714 struct sd *sd = (struct sd *) gspca_dev;
717 /* create the JPEG header */
718 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
719 gspca_dev->pixfmt.width,
720 0x22); /* JPEG 411 */
721 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
723 if (sd->bridge == BRIDGE_SPCA504B)
724 spca504B_setQtable(gspca_dev);
725 spca504B_SetSizeType(gspca_dev);
726 switch (sd->bridge) {
728 /* case BRIDGE_SPCA504B: */
729 /* case BRIDGE_SPCA533: */
730 /* case BRIDGE_SPCA536: */
731 switch (sd->subtype) {
733 case LogitechClickSmart820:
735 reg_w_riv(gspca_dev, 0xf0, 0, 0);
736 spca504B_WaitCmdStatus(gspca_dev);
737 reg_r(gspca_dev, 0xf0, 4, 0);
738 spca504B_WaitCmdStatus(gspca_dev);
741 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
742 spca504B_WaitCmdStatus(gspca_dev);
743 spca504B_PollingDataReady(gspca_dev);
748 if (sd->subtype == AiptekMiniPenCam13) {
749 spca504_read_info(gspca_dev);
751 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
752 spca504A_acknowledged_command(gspca_dev, 0x24,
754 /* Twice sequential need status 0xff->0x9e->0x9d */
755 spca504A_acknowledged_command(gspca_dev, 0x24,
757 spca504A_acknowledged_command(gspca_dev, 0x24,
760 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
761 spca504_read_info(gspca_dev);
762 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
763 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
765 spca504B_SetSizeType(gspca_dev);
766 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
768 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
770 case BRIDGE_SPCA504C:
771 if (sd->subtype == LogitechClickSmart420) {
772 write_vector(gspca_dev,
773 spca504A_clicksmart420_init_data,
774 ARRAY_SIZE(spca504A_clicksmart420_init_data));
776 write_vector(gspca_dev, spca504_pccam600_init_data,
777 ARRAY_SIZE(spca504_pccam600_init_data));
779 enable = (sd->autogain ? 0x04 : 0x01);
780 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
782 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
785 /* set default exposure compensation and whiteness balance */
786 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
787 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
788 spca504B_SetSizeType(gspca_dev);
791 init_ctl_reg(gspca_dev);
792 return gspca_dev->usb_err;
795 static void sd_stopN(struct gspca_dev *gspca_dev)
797 struct sd *sd = (struct sd *) gspca_dev;
799 switch (sd->bridge) {
801 /* case BRIDGE_SPCA533: */
802 /* case BRIDGE_SPCA536: */
803 /* case BRIDGE_SPCA504B: */
804 reg_w_riv(gspca_dev, 0x31, 0, 0);
805 spca504B_WaitCmdStatus(gspca_dev);
806 spca504B_PollingDataReady(gspca_dev);
809 case BRIDGE_SPCA504C:
810 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
812 if (sd->subtype == AiptekMiniPenCam13) {
813 /* spca504a aiptek */
814 /* spca504A_acknowledged_command(gspca_dev, 0x08,
816 spca504A_acknowledged_command(gspca_dev, 0x24,
817 0x00, 0x00, 0x9d, 1);
818 spca504A_acknowledged_command(gspca_dev, 0x01,
819 0x0f, 0x00, 0xff, 1);
821 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
822 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
828 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
829 u8 *data, /* isoc packet */
830 int len) /* iso packet length */
832 struct sd *sd = (struct sd *) gspca_dev;
834 static u8 ffd9[] = {0xff, 0xd9};
836 /* frames are jpeg 4.1.1 without 0xff escape */
837 switch (sd->bridge) {
839 if (data[0] == 0xff) {
840 if (data[1] != 0x01) { /* drop packet */
841 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
845 data += SPCA533_OFFSET_DATA;
846 len -= SPCA533_OFFSET_DATA;
853 if (data[0] == 0xff) {
855 data += SPCA536_OFFSET_DATA;
856 len -= SPCA536_OFFSET_DATA;
863 /* case BRIDGE_SPCA504: */
864 /* case BRIDGE_SPCA504B: */
866 case 0xfe: /* start of frame */
868 data += SPCA50X_OFFSET_DATA;
869 len -= SPCA50X_OFFSET_DATA;
871 case 0xff: /* drop packet */
872 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
880 case BRIDGE_SPCA504C:
882 case 0xfe: /* start of frame */
884 data += SPCA504_PCCAM600_OFFSET_DATA;
885 len -= SPCA504_PCCAM600_OFFSET_DATA;
887 case 0xff: /* drop packet */
888 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
897 if (sof) { /* start of frame */
898 gspca_frame_add(gspca_dev, LAST_PACKET,
901 /* put the JPEG header in the new frame */
902 gspca_frame_add(gspca_dev, FIRST_PACKET,
903 sd->jpeg_hdr, JPEG_HDR_SZ);
906 /* add 0x00 after 0xff */
909 if (data[i] == 0xff) {
910 gspca_frame_add(gspca_dev, INTER_PACKET,
919 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
922 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
924 struct gspca_dev *gspca_dev =
925 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
926 struct sd *sd = (struct sd *)gspca_dev;
928 gspca_dev->usb_err = 0;
930 if (!gspca_dev->streaming)
934 case V4L2_CID_BRIGHTNESS:
935 setbrightness(gspca_dev, ctrl->val);
937 case V4L2_CID_CONTRAST:
938 setcontrast(gspca_dev, ctrl->val);
940 case V4L2_CID_SATURATION:
941 setcolors(gspca_dev, ctrl->val);
943 case V4L2_CID_AUTOGAIN:
944 sd->autogain = ctrl->val;
947 return gspca_dev->usb_err;
950 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
954 static int sd_init_controls(struct gspca_dev *gspca_dev)
956 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
958 gspca_dev->vdev.ctrl_handler = hdl;
959 v4l2_ctrl_handler_init(hdl, 4);
960 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
961 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
962 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
963 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
964 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
965 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
966 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
967 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
970 pr_err("Could not initialize controls\n");
976 /* sub-driver description */
977 static const struct sd_desc sd_desc = {
981 .init_controls = sd_init_controls,
984 .pkt_scan = sd_pkt_scan,
987 /* -- module initialisation -- */
988 #define BS(bridge, subtype) \
989 .driver_info = (BRIDGE_ ## bridge << 8) \
991 static const struct usb_device_id device_table[] = {
992 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
993 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
994 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
995 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
996 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
997 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
998 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
999 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1000 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1001 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1002 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1003 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1004 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1005 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1006 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1007 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1008 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1009 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1010 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1011 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1012 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1013 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1014 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1015 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1016 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1017 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1018 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1019 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1020 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1021 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1022 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1023 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1024 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1025 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1026 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1027 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1028 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1029 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1030 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1031 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1033 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1034 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1035 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1036 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1037 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1038 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1039 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1040 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1041 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1042 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1043 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1044 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1045 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1046 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1047 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1048 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1049 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1050 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1053 MODULE_DEVICE_TABLE(usb, device_table);
1055 /* -- device connect -- */
1056 static int sd_probe(struct usb_interface *intf,
1057 const struct usb_device_id *id)
1059 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1063 static struct usb_driver sd_driver = {
1064 .name = MODULE_NAME,
1065 .id_table = device_table,
1067 .disconnect = gspca_disconnect,
1069 .suspend = gspca_suspend,
1070 .resume = gspca_resume,
1071 .reset_resume = gspca_resume,
1075 module_usb_driver(sd_driver);