2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #define MODULE_NAME "sunplus"
25 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
27 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
38 #define BRIDGE_SPCA504 0
39 #define BRIDGE_SPCA504B 1
40 #define BRIDGE_SPCA504C 2
41 #define BRIDGE_SPCA533 3
42 #define BRIDGE_SPCA536 4
44 #define AiptekMiniPenCam13 1
45 #define LogitechClickSmart420 2
46 #define LogitechClickSmart820 3
50 u8 jpeg_hdr[JPEG_HDR_SZ];
53 static const struct v4l2_pix_format vga_mode[] = {
54 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
56 .sizeimage = 320 * 240 * 3 / 8 + 590,
57 .colorspace = V4L2_COLORSPACE_JPEG,
59 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
61 .sizeimage = 640 * 480 * 3 / 8 + 590,
62 .colorspace = V4L2_COLORSPACE_JPEG,
66 static const struct v4l2_pix_format custom_mode[] = {
67 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
69 .sizeimage = 320 * 240 * 3 / 8 + 590,
70 .colorspace = V4L2_COLORSPACE_JPEG,
72 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
74 .sizeimage = 464 * 480 * 3 / 8 + 590,
75 .colorspace = V4L2_COLORSPACE_JPEG,
79 static const struct v4l2_pix_format vga_mode2[] = {
80 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
82 .sizeimage = 176 * 144 * 3 / 8 + 590,
83 .colorspace = V4L2_COLORSPACE_JPEG,
85 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
87 .sizeimage = 320 * 240 * 3 / 8 + 590,
88 .colorspace = V4L2_COLORSPACE_JPEG,
90 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
92 .sizeimage = 352 * 288 * 3 / 8 + 590,
93 .colorspace = V4L2_COLORSPACE_JPEG,
95 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
97 .sizeimage = 640 * 480 * 3 / 8 + 590,
98 .colorspace = V4L2_COLORSPACE_JPEG,
102 #define SPCA50X_OFFSET_DATA 10
103 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
104 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
105 #define SPCA504_PCCAM600_OFFSET_MODE 5
106 #define SPCA504_PCCAM600_OFFSET_DATA 14
107 /* Frame packet header offsets for the spca533 */
108 #define SPCA533_OFFSET_DATA 16
109 #define SPCA533_OFFSET_FRAMSEQ 15
110 /* Frame packet header offsets for the spca536 */
111 #define SPCA536_OFFSET_DATA 4
112 #define SPCA536_OFFSET_FRAMSEQ 1
120 /* Initialisation data for the Creative PC-CAM 600 */
121 static const struct cmd spca504_pccam600_init_data[] = {
122 /* {0xa0, 0x0000, 0x0503}, * capture mode */
123 {0x00, 0x0000, 0x2000},
124 {0x00, 0x0013, 0x2301},
125 {0x00, 0x0003, 0x2000},
126 {0x00, 0x0001, 0x21ac},
127 {0x00, 0x0001, 0x21a6},
128 {0x00, 0x0000, 0x21a7}, /* brightness */
129 {0x00, 0x0020, 0x21a8}, /* contrast */
130 {0x00, 0x0001, 0x21ac}, /* sat/hue */
131 {0x00, 0x0000, 0x21ad}, /* hue */
132 {0x00, 0x001a, 0x21ae}, /* saturation */
133 {0x00, 0x0002, 0x21a3}, /* gamma */
134 {0x30, 0x0154, 0x0008},
135 {0x30, 0x0004, 0x0006},
136 {0x30, 0x0258, 0x0009},
137 {0x30, 0x0004, 0x0000},
138 {0x30, 0x0093, 0x0004},
139 {0x30, 0x0066, 0x0005},
140 {0x00, 0x0000, 0x2000},
141 {0x00, 0x0013, 0x2301},
142 {0x00, 0x0003, 0x2000},
143 {0x00, 0x0013, 0x2301},
144 {0x00, 0x0003, 0x2000},
147 /* Creative PC-CAM 600 specific open data, sent before using the
148 * generic initialisation data from spca504_open_data.
150 static const struct cmd spca504_pccam600_open_data[] = {
151 {0x00, 0x0001, 0x2501},
152 {0x20, 0x0500, 0x0001}, /* snapshot mode */
153 {0x00, 0x0003, 0x2880},
154 {0x00, 0x0001, 0x2881},
157 /* Initialisation data for the logitech clicksmart 420 */
158 static const struct cmd spca504A_clicksmart420_init_data[] = {
159 /* {0xa0, 0x0000, 0x0503}, * capture mode */
160 {0x00, 0x0000, 0x2000},
161 {0x00, 0x0013, 0x2301},
162 {0x00, 0x0003, 0x2000},
163 {0x00, 0x0001, 0x21ac},
164 {0x00, 0x0001, 0x21a6},
165 {0x00, 0x0000, 0x21a7}, /* brightness */
166 {0x00, 0x0020, 0x21a8}, /* contrast */
167 {0x00, 0x0001, 0x21ac}, /* sat/hue */
168 {0x00, 0x0000, 0x21ad}, /* hue */
169 {0x00, 0x001a, 0x21ae}, /* saturation */
170 {0x00, 0x0002, 0x21a3}, /* gamma */
171 {0x30, 0x0004, 0x000a},
172 {0xb0, 0x0001, 0x0000},
174 {0xa1, 0x0080, 0x0001},
175 {0x30, 0x0049, 0x0000},
176 {0x30, 0x0060, 0x0005},
177 {0x0c, 0x0004, 0x0000},
178 {0x00, 0x0000, 0x0000},
179 {0x00, 0x0000, 0x2000},
180 {0x00, 0x0013, 0x2301},
181 {0x00, 0x0003, 0x2000},
184 /* clicksmart 420 open data ? */
185 static const struct cmd spca504A_clicksmart420_open_data[] = {
186 {0x00, 0x0001, 0x2501},
187 {0x20, 0x0502, 0x0000},
188 {0x06, 0x0000, 0x0000},
189 {0x00, 0x0004, 0x2880},
190 {0x00, 0x0001, 0x2881},
192 {0xa0, 0x0000, 0x0503},
195 static const u8 qtable_creative_pccam[2][64] = {
196 { /* Q-table Y-components */
197 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
198 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
199 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
200 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
201 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
202 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
203 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
204 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
205 { /* Q-table C-components */
206 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
207 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
208 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
209 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
210 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
211 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
212 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
216 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
217 * except for one byte. Possibly a typo?
220 static const u8 qtable_spca504_default[2][64] = {
221 { /* Q-table Y-components */
222 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
223 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
224 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
225 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
226 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
227 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
228 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
229 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
231 { /* Q-table C-components */
232 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
233 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
234 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
235 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
236 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
237 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
238 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
242 /* read <len> bytes to gspca_dev->usb_buf */
243 static void reg_r(struct gspca_dev *gspca_dev,
250 if (len > USB_BUF_SZ) {
251 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
255 gspca_err(gspca_dev, "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 gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
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 gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n",
356 gspca_dev->usb_buf[0]);
357 reg_w_riv(gspca_dev, req, idx, val);
360 reg_r(gspca_dev, 0x01, 0x0001, 1);
361 gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n",
362 gspca_dev->usb_buf[0]);
365 static void spca504_read_info(struct gspca_dev *gspca_dev)
370 if (gspca_debug < D_STREAM)
373 for (i = 0; i < 6; i++) {
374 reg_r(gspca_dev, 0, i, 1);
375 info[i] = gspca_dev->usb_buf[0];
377 gspca_dbg(gspca_dev, D_STREAM,
378 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
379 info[0], info[1], info[2],
380 info[3], info[4], info[5]);
383 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
385 u16 idx, u16 val, u8 endcode, u8 count)
389 reg_w_riv(gspca_dev, req, idx, val);
390 reg_r(gspca_dev, 0x01, 0x0001, 1);
391 if (gspca_dev->usb_err < 0)
393 gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
394 gspca_dev->usb_buf[0], endcode);
398 while (--count > 0) {
400 /* gsmart mini2 write a each wait setting 1 ms is enough */
401 /* reg_w_riv(gspca_dev, req, idx, val); */
402 reg_r(gspca_dev, 0x01, 0x0001, 1);
403 status = gspca_dev->usb_buf[0];
404 if (status == endcode) {
405 gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n",
406 status, 200 - count);
412 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
416 while (--count > 0) {
417 reg_r(gspca_dev, 0x21, 0, 1);
418 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
424 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
428 while (--count > 0) {
429 reg_r(gspca_dev, 0x21, 1, 1);
430 if (gspca_dev->usb_buf[0] != 0) {
431 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
432 reg_r(gspca_dev, 0x21, 1, 1);
433 spca504B_PollingDataReady(gspca_dev);
440 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
444 if (gspca_debug < D_STREAM)
447 data = gspca_dev->usb_buf;
448 reg_r(gspca_dev, 0x20, 0, 5);
449 gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n",
450 data[0], data[1], data[2], data[3], data[4]);
451 reg_r(gspca_dev, 0x23, 0, 64);
452 reg_r(gspca_dev, 0x23, 1, 64);
455 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
457 struct sd *sd = (struct sd *) gspca_dev;
460 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
461 switch (sd->bridge) {
463 reg_w_riv(gspca_dev, 0x31, 0, 0);
464 spca504B_WaitCmdStatus(gspca_dev);
465 spca504B_PollingDataReady(gspca_dev);
466 spca50x_GetFirmware(gspca_dev);
468 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
469 reg_r(gspca_dev, 0x24, 8, 1);
471 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
472 reg_r(gspca_dev, 0x25, 4, 1); /* size */
473 spca504B_PollingDataReady(gspca_dev);
475 /* Init the cam width height with some values get on init ? */
476 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
477 spca504B_WaitCmdStatus(gspca_dev);
478 spca504B_PollingDataReady(gspca_dev);
481 /* case BRIDGE_SPCA504B: */
482 /* case BRIDGE_SPCA536: */
483 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
484 reg_r(gspca_dev, 0x25, 4, 1); /* size */
485 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
486 reg_r(gspca_dev, 0x27, 0, 1); /* type */
487 spca504B_PollingDataReady(gspca_dev);
491 if (sd->subtype == AiptekMiniPenCam13) {
492 /* spca504a aiptek */
493 spca504A_acknowledged_command(gspca_dev,
495 0x80 | (Size & 0x0f), 1);
496 spca504A_acknowledged_command(gspca_dev,
499 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
502 case BRIDGE_SPCA504C:
504 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
505 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
510 static void spca504_wait_status(struct gspca_dev *gspca_dev)
516 /* With this we get the status, when return 0 it's all ok */
517 reg_r(gspca_dev, 0x06, 0x00, 1);
518 if (gspca_dev->usb_buf[0] == 0)
524 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
526 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
527 reg_r(gspca_dev, 0x26, 0, 1);
528 spca504B_PollingDataReady(gspca_dev);
531 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
533 struct sd *sd = (struct sd *) gspca_dev;
536 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
537 reg_w_riv(gspca_dev, 0x00, reg, val);
540 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
542 struct sd *sd = (struct sd *) gspca_dev;
545 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
546 reg_w_riv(gspca_dev, 0x00, reg, val);
549 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
551 struct sd *sd = (struct sd *) gspca_dev;
554 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
555 reg_w_riv(gspca_dev, 0x00, reg, val);
558 static void init_ctl_reg(struct gspca_dev *gspca_dev)
560 struct sd *sd = (struct sd *) gspca_dev;
563 switch (sd->bridge) {
565 case BRIDGE_SPCA504C:
569 /* case BRIDGE_SPCA533: */
570 /* case BRIDGE_SPCA504B: */
571 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
572 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
573 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
576 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
577 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
578 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
582 spca504B_PollingDataReady(gspca_dev);
585 /* this function is called at probe time */
586 static int sd_config(struct gspca_dev *gspca_dev,
587 const struct usb_device_id *id)
589 struct sd *sd = (struct sd *) gspca_dev;
592 cam = &gspca_dev->cam;
594 sd->bridge = id->driver_info >> 8;
595 sd->subtype = id->driver_info;
597 if (sd->subtype == AiptekMiniPenCam13) {
599 /* try to get the firmware as some cam answer 2.0.1.2.2
600 * and should be a spca504b then overwrite that setting */
601 reg_r(gspca_dev, 0x20, 0, 1);
602 switch (gspca_dev->usb_buf[0]) {
604 break; /* (right bridge/subtype) */
606 sd->bridge = BRIDGE_SPCA504B;
614 switch (sd->bridge) {
616 /* case BRIDGE_SPCA504B: */
617 /* case BRIDGE_SPCA504: */
618 /* case BRIDGE_SPCA536: */
619 cam->cam_mode = vga_mode;
620 cam->nmodes = ARRAY_SIZE(vga_mode);
623 cam->cam_mode = custom_mode;
624 if (sd->subtype == MegaImageVI) /* 320x240 only */
625 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
627 cam->nmodes = ARRAY_SIZE(custom_mode);
629 case BRIDGE_SPCA504C:
630 cam->cam_mode = vga_mode2;
631 cam->nmodes = ARRAY_SIZE(vga_mode2);
637 /* this function is called at probe and resume time */
638 static int sd_init(struct gspca_dev *gspca_dev)
640 struct sd *sd = (struct sd *) gspca_dev;
642 switch (sd->bridge) {
643 case BRIDGE_SPCA504B:
644 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
645 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
646 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
647 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
648 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
649 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
652 spca504B_PollingDataReady(gspca_dev);
653 spca50x_GetFirmware(gspca_dev);
656 spca50x_GetFirmware(gspca_dev);
657 reg_r(gspca_dev, 0x00, 0x5002, 1);
658 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
659 reg_r(gspca_dev, 0x24, 0, 1);
660 spca504B_PollingDataReady(gspca_dev);
661 reg_w_riv(gspca_dev, 0x34, 0, 0);
662 spca504B_WaitCmdStatus(gspca_dev);
664 case BRIDGE_SPCA504C: /* pccam600 */
665 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n");
666 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
667 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
668 spca504_wait_status(gspca_dev);
669 if (sd->subtype == LogitechClickSmart420)
670 write_vector(gspca_dev,
671 spca504A_clicksmart420_open_data,
672 ARRAY_SIZE(spca504A_clicksmart420_open_data));
674 write_vector(gspca_dev, spca504_pccam600_open_data,
675 ARRAY_SIZE(spca504_pccam600_open_data));
676 setup_qtable(gspca_dev, qtable_creative_pccam);
679 /* case BRIDGE_SPCA504: */
680 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n");
681 if (sd->subtype == AiptekMiniPenCam13) {
682 spca504_read_info(gspca_dev);
684 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
685 spca504A_acknowledged_command(gspca_dev, 0x24,
687 /* Twice sequential need status 0xff->0x9e->0x9d */
688 spca504A_acknowledged_command(gspca_dev, 0x24,
691 spca504A_acknowledged_command(gspca_dev, 0x24,
693 /******************************/
694 /* spca504a aiptek */
695 spca504A_acknowledged_command(gspca_dev, 0x08,
697 /* reg_write (dev, 0, 0x2000, 0); */
698 /* reg_write (dev, 0, 0x2883, 1); */
699 /* spca504A_acknowledged_command (gspca_dev, 0x08,
701 /* spca504A_acknowledged_command (gspca_dev, 0x24,
703 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
705 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
706 spca504A_acknowledged_command(gspca_dev, 0x01,
710 reg_w_riv(gspca_dev, 0, 0x2000, 0);
711 reg_w_riv(gspca_dev, 0, 0x2883, 1);
712 setup_qtable(gspca_dev, qtable_spca504_default);
715 return gspca_dev->usb_err;
718 static int sd_start(struct gspca_dev *gspca_dev)
720 struct sd *sd = (struct sd *) gspca_dev;
723 /* create the JPEG header */
724 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
725 gspca_dev->pixfmt.width,
726 0x22); /* JPEG 411 */
727 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
729 if (sd->bridge == BRIDGE_SPCA504B)
730 spca504B_setQtable(gspca_dev);
731 spca504B_SetSizeType(gspca_dev);
732 switch (sd->bridge) {
734 /* case BRIDGE_SPCA504B: */
735 /* case BRIDGE_SPCA533: */
736 /* case BRIDGE_SPCA536: */
737 switch (sd->subtype) {
739 case LogitechClickSmart820:
741 reg_w_riv(gspca_dev, 0xf0, 0, 0);
742 spca504B_WaitCmdStatus(gspca_dev);
743 reg_w_riv(gspca_dev, 0xf0, 4, 0);
744 spca504B_WaitCmdStatus(gspca_dev);
747 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
748 spca504B_WaitCmdStatus(gspca_dev);
749 spca504B_PollingDataReady(gspca_dev);
754 if (sd->subtype == AiptekMiniPenCam13) {
755 spca504_read_info(gspca_dev);
757 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
758 spca504A_acknowledged_command(gspca_dev, 0x24,
760 /* Twice sequential need status 0xff->0x9e->0x9d */
761 spca504A_acknowledged_command(gspca_dev, 0x24,
763 spca504A_acknowledged_command(gspca_dev, 0x24,
766 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
767 spca504_read_info(gspca_dev);
768 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
769 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
771 spca504B_SetSizeType(gspca_dev);
772 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
774 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
776 case BRIDGE_SPCA504C:
777 if (sd->subtype == LogitechClickSmart420) {
778 write_vector(gspca_dev,
779 spca504A_clicksmart420_init_data,
780 ARRAY_SIZE(spca504A_clicksmart420_init_data));
782 write_vector(gspca_dev, spca504_pccam600_init_data,
783 ARRAY_SIZE(spca504_pccam600_init_data));
785 enable = (sd->autogain ? 0x04 : 0x01);
786 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
788 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
791 /* set default exposure compensation and whiteness balance */
792 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
793 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
794 spca504B_SetSizeType(gspca_dev);
797 init_ctl_reg(gspca_dev);
798 return gspca_dev->usb_err;
801 static void sd_stopN(struct gspca_dev *gspca_dev)
803 struct sd *sd = (struct sd *) gspca_dev;
805 switch (sd->bridge) {
807 /* case BRIDGE_SPCA533: */
808 /* case BRIDGE_SPCA536: */
809 /* case BRIDGE_SPCA504B: */
810 reg_w_riv(gspca_dev, 0x31, 0, 0);
811 spca504B_WaitCmdStatus(gspca_dev);
812 spca504B_PollingDataReady(gspca_dev);
815 case BRIDGE_SPCA504C:
816 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
818 if (sd->subtype == AiptekMiniPenCam13) {
819 /* spca504a aiptek */
820 /* spca504A_acknowledged_command(gspca_dev, 0x08,
822 spca504A_acknowledged_command(gspca_dev, 0x24,
823 0x00, 0x00, 0x9d, 1);
824 spca504A_acknowledged_command(gspca_dev, 0x01,
825 0x0f, 0x00, 0xff, 1);
827 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
828 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
834 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
835 u8 *data, /* isoc packet */
836 int len) /* iso packet length */
838 struct sd *sd = (struct sd *) gspca_dev;
840 static u8 ffd9[] = {0xff, 0xd9};
842 /* frames are jpeg 4.1.1 without 0xff escape */
843 switch (sd->bridge) {
845 if (data[0] == 0xff) {
846 if (data[1] != 0x01) { /* drop packet */
847 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
851 data += SPCA533_OFFSET_DATA;
852 len -= SPCA533_OFFSET_DATA;
859 if (data[0] == 0xff) {
861 data += SPCA536_OFFSET_DATA;
862 len -= SPCA536_OFFSET_DATA;
869 /* case BRIDGE_SPCA504: */
870 /* case BRIDGE_SPCA504B: */
872 case 0xfe: /* start of frame */
874 data += SPCA50X_OFFSET_DATA;
875 len -= SPCA50X_OFFSET_DATA;
877 case 0xff: /* drop packet */
878 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
886 case BRIDGE_SPCA504C:
888 case 0xfe: /* start of frame */
890 data += SPCA504_PCCAM600_OFFSET_DATA;
891 len -= SPCA504_PCCAM600_OFFSET_DATA;
893 case 0xff: /* drop packet */
894 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
903 if (sof) { /* start of frame */
904 gspca_frame_add(gspca_dev, LAST_PACKET,
907 /* put the JPEG header in the new frame */
908 gspca_frame_add(gspca_dev, FIRST_PACKET,
909 sd->jpeg_hdr, JPEG_HDR_SZ);
912 /* add 0x00 after 0xff */
915 if (data[i] == 0xff) {
916 gspca_frame_add(gspca_dev, INTER_PACKET,
925 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
928 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
930 struct gspca_dev *gspca_dev =
931 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
932 struct sd *sd = (struct sd *)gspca_dev;
934 gspca_dev->usb_err = 0;
936 if (!gspca_dev->streaming)
940 case V4L2_CID_BRIGHTNESS:
941 setbrightness(gspca_dev, ctrl->val);
943 case V4L2_CID_CONTRAST:
944 setcontrast(gspca_dev, ctrl->val);
946 case V4L2_CID_SATURATION:
947 setcolors(gspca_dev, ctrl->val);
949 case V4L2_CID_AUTOGAIN:
950 sd->autogain = ctrl->val;
953 return gspca_dev->usb_err;
956 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
960 static int sd_init_controls(struct gspca_dev *gspca_dev)
962 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
964 gspca_dev->vdev.ctrl_handler = hdl;
965 v4l2_ctrl_handler_init(hdl, 4);
966 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
967 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
968 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
969 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
970 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
971 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
972 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
973 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
976 pr_err("Could not initialize controls\n");
982 /* sub-driver description */
983 static const struct sd_desc sd_desc = {
987 .init_controls = sd_init_controls,
990 .pkt_scan = sd_pkt_scan,
993 /* -- module initialisation -- */
994 #define BS(bridge, subtype) \
995 .driver_info = (BRIDGE_ ## bridge << 8) \
997 static const struct usb_device_id device_table[] = {
998 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
999 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1000 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1001 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1002 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1003 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1004 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1005 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1006 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1007 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1008 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1009 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1010 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1011 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1012 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1013 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1014 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1015 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1016 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1017 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1018 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1019 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1020 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1021 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1022 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1023 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1024 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1025 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1026 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1027 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1028 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1030 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1031 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1033 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1034 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1035 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1037 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1038 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1039 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1040 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1041 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1042 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1043 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1044 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1045 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1046 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1047 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1048 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1049 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1050 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1051 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1052 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1053 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1054 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1055 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1056 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1057 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1060 MODULE_DEVICE_TABLE(usb, device_table);
1062 /* -- device connect -- */
1063 static int sd_probe(struct usb_interface *intf,
1064 const struct usb_device_id *id)
1066 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1070 static struct usb_driver sd_driver = {
1071 .name = MODULE_NAME,
1072 .id_table = device_table,
1074 .disconnect = gspca_disconnect,
1076 .suspend = gspca_suspend,
1077 .resume = gspca_resume,
1078 .reset_resume = gspca_resume,
1082 module_usb_driver(sd_driver);