1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Sunplus spca504(abc) spca533 spca536 library
4 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #define MODULE_NAME "sunplus"
16 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
17 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
18 MODULE_LICENSE("GPL");
22 /* specific webcam descriptor */
24 struct gspca_dev gspca_dev
; /* !! must be the first item */
29 #define BRIDGE_SPCA504 0
30 #define BRIDGE_SPCA504B 1
31 #define BRIDGE_SPCA504C 2
32 #define BRIDGE_SPCA533 3
33 #define BRIDGE_SPCA536 4
35 #define AiptekMiniPenCam13 1
36 #define LogitechClickSmart420 2
37 #define LogitechClickSmart820 3
41 u8 jpeg_hdr
[JPEG_HDR_SZ
];
44 static const struct v4l2_pix_format vga_mode
[] = {
45 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
47 .sizeimage
= 320 * 240 * 3 / 8 + 590,
48 .colorspace
= V4L2_COLORSPACE_JPEG
,
50 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
52 .sizeimage
= 640 * 480 * 3 / 8 + 590,
53 .colorspace
= V4L2_COLORSPACE_JPEG
,
57 static const struct v4l2_pix_format custom_mode
[] = {
58 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
60 .sizeimage
= 320 * 240 * 3 / 8 + 590,
61 .colorspace
= V4L2_COLORSPACE_JPEG
,
63 {464, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
65 .sizeimage
= 464 * 480 * 3 / 8 + 590,
66 .colorspace
= V4L2_COLORSPACE_JPEG
,
70 static const struct v4l2_pix_format vga_mode2
[] = {
71 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
73 .sizeimage
= 176 * 144 * 3 / 8 + 590,
74 .colorspace
= V4L2_COLORSPACE_JPEG
,
76 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
78 .sizeimage
= 320 * 240 * 3 / 8 + 590,
79 .colorspace
= V4L2_COLORSPACE_JPEG
,
81 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
83 .sizeimage
= 352 * 288 * 3 / 8 + 590,
84 .colorspace
= V4L2_COLORSPACE_JPEG
,
86 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
88 .sizeimage
= 640 * 480 * 3 / 8 + 590,
89 .colorspace
= V4L2_COLORSPACE_JPEG
,
93 #define SPCA50X_OFFSET_DATA 10
94 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
95 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
96 #define SPCA504_PCCAM600_OFFSET_MODE 5
97 #define SPCA504_PCCAM600_OFFSET_DATA 14
98 /* Frame packet header offsets for the spca533 */
99 #define SPCA533_OFFSET_DATA 16
100 #define SPCA533_OFFSET_FRAMSEQ 15
101 /* Frame packet header offsets for the spca536 */
102 #define SPCA536_OFFSET_DATA 4
103 #define SPCA536_OFFSET_FRAMSEQ 1
111 /* Initialisation data for the Creative PC-CAM 600 */
112 static const struct cmd spca504_pccam600_init_data
[] = {
113 /* {0xa0, 0x0000, 0x0503}, * capture mode */
114 {0x00, 0x0000, 0x2000},
115 {0x00, 0x0013, 0x2301},
116 {0x00, 0x0003, 0x2000},
117 {0x00, 0x0001, 0x21ac},
118 {0x00, 0x0001, 0x21a6},
119 {0x00, 0x0000, 0x21a7}, /* brightness */
120 {0x00, 0x0020, 0x21a8}, /* contrast */
121 {0x00, 0x0001, 0x21ac}, /* sat/hue */
122 {0x00, 0x0000, 0x21ad}, /* hue */
123 {0x00, 0x001a, 0x21ae}, /* saturation */
124 {0x00, 0x0002, 0x21a3}, /* gamma */
125 {0x30, 0x0154, 0x0008},
126 {0x30, 0x0004, 0x0006},
127 {0x30, 0x0258, 0x0009},
128 {0x30, 0x0004, 0x0000},
129 {0x30, 0x0093, 0x0004},
130 {0x30, 0x0066, 0x0005},
131 {0x00, 0x0000, 0x2000},
132 {0x00, 0x0013, 0x2301},
133 {0x00, 0x0003, 0x2000},
134 {0x00, 0x0013, 0x2301},
135 {0x00, 0x0003, 0x2000},
138 /* Creative PC-CAM 600 specific open data, sent before using the
139 * generic initialisation data from spca504_open_data.
141 static const struct cmd spca504_pccam600_open_data
[] = {
142 {0x00, 0x0001, 0x2501},
143 {0x20, 0x0500, 0x0001}, /* snapshot mode */
144 {0x00, 0x0003, 0x2880},
145 {0x00, 0x0001, 0x2881},
148 /* Initialisation data for the logitech clicksmart 420 */
149 static const struct cmd spca504A_clicksmart420_init_data
[] = {
150 /* {0xa0, 0x0000, 0x0503}, * capture mode */
151 {0x00, 0x0000, 0x2000},
152 {0x00, 0x0013, 0x2301},
153 {0x00, 0x0003, 0x2000},
154 {0x00, 0x0001, 0x21ac},
155 {0x00, 0x0001, 0x21a6},
156 {0x00, 0x0000, 0x21a7}, /* brightness */
157 {0x00, 0x0020, 0x21a8}, /* contrast */
158 {0x00, 0x0001, 0x21ac}, /* sat/hue */
159 {0x00, 0x0000, 0x21ad}, /* hue */
160 {0x00, 0x001a, 0x21ae}, /* saturation */
161 {0x00, 0x0002, 0x21a3}, /* gamma */
162 {0x30, 0x0004, 0x000a},
163 {0xb0, 0x0001, 0x0000},
165 {0xa1, 0x0080, 0x0001},
166 {0x30, 0x0049, 0x0000},
167 {0x30, 0x0060, 0x0005},
168 {0x0c, 0x0004, 0x0000},
169 {0x00, 0x0000, 0x0000},
170 {0x00, 0x0000, 0x2000},
171 {0x00, 0x0013, 0x2301},
172 {0x00, 0x0003, 0x2000},
175 /* clicksmart 420 open data ? */
176 static const struct cmd spca504A_clicksmart420_open_data
[] = {
177 {0x00, 0x0001, 0x2501},
178 {0x20, 0x0502, 0x0000},
179 {0x06, 0x0000, 0x0000},
180 {0x00, 0x0004, 0x2880},
181 {0x00, 0x0001, 0x2881},
183 {0xa0, 0x0000, 0x0503},
186 static const u8 qtable_creative_pccam
[2][64] = {
187 { /* Q-table Y-components */
188 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
189 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
190 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
191 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
192 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
193 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
194 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
195 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
196 { /* Q-table C-components */
197 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
198 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
199 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
200 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
201 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
202 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
203 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
204 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
207 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
208 * except for one byte. Possibly a typo?
211 static const u8 qtable_spca504_default
[2][64] = {
212 { /* Q-table Y-components */
213 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
214 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
215 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
216 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
217 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
218 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
219 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
220 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
222 { /* Q-table C-components */
223 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
224 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
225 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
226 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
227 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
228 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
229 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
230 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
233 /* read <len> bytes to gspca_dev->usb_buf */
234 static void reg_r(struct gspca_dev
*gspca_dev
,
241 if (len
> USB_BUF_SZ
) {
242 gspca_err(gspca_dev
, "reg_r: buffer overflow\n");
245 if (gspca_dev
->usb_err
< 0)
247 ret
= usb_control_msg(gspca_dev
->dev
,
248 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
250 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
253 len
? gspca_dev
->usb_buf
: NULL
, len
,
256 pr_err("reg_r err %d\n", ret
);
257 gspca_dev
->usb_err
= ret
;
259 * Make sure the buffer is zeroed to avoid uninitialized
262 memset(gspca_dev
->usb_buf
, 0, USB_BUF_SZ
);
267 static void reg_w_1(struct gspca_dev
*gspca_dev
,
275 if (gspca_dev
->usb_err
< 0)
277 gspca_dev
->usb_buf
[0] = byte
;
278 ret
= usb_control_msg(gspca_dev
->dev
,
279 usb_sndctrlpipe(gspca_dev
->dev
, 0),
281 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
283 gspca_dev
->usb_buf
, 1,
286 pr_err("reg_w_1 err %d\n", ret
);
287 gspca_dev
->usb_err
= ret
;
291 /* write req / index / value */
292 static void reg_w_riv(struct gspca_dev
*gspca_dev
,
293 u8 req
, u16 index
, u16 value
)
295 struct usb_device
*dev
= gspca_dev
->dev
;
298 if (gspca_dev
->usb_err
< 0)
300 ret
= usb_control_msg(dev
,
301 usb_sndctrlpipe(dev
, 0),
303 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
304 value
, index
, NULL
, 0, 500);
306 pr_err("reg_w_riv err %d\n", ret
);
307 gspca_dev
->usb_err
= ret
;
310 gspca_dbg(gspca_dev
, D_USBO
, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
314 static void write_vector(struct gspca_dev
*gspca_dev
,
315 const struct cmd
*data
, int ncmds
)
317 while (--ncmds
>= 0) {
318 reg_w_riv(gspca_dev
, data
->req
, data
->idx
, data
->val
);
323 static void setup_qtable(struct gspca_dev
*gspca_dev
,
324 const u8 qtable
[2][64])
328 /* loop over y components */
329 for (i
= 0; i
< 64; i
++)
330 reg_w_riv(gspca_dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
332 /* loop over c components */
333 for (i
= 0; i
< 64; i
++)
334 reg_w_riv(gspca_dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
337 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
338 u8 req
, u16 idx
, u16 val
)
340 reg_w_riv(gspca_dev
, req
, idx
, val
);
341 reg_r(gspca_dev
, 0x01, 0x0001, 1);
342 gspca_dbg(gspca_dev
, D_FRAM
, "before wait 0x%04x\n",
343 gspca_dev
->usb_buf
[0]);
344 reg_w_riv(gspca_dev
, req
, idx
, val
);
347 reg_r(gspca_dev
, 0x01, 0x0001, 1);
348 gspca_dbg(gspca_dev
, D_FRAM
, "after wait 0x%04x\n",
349 gspca_dev
->usb_buf
[0]);
352 static void spca504_read_info(struct gspca_dev
*gspca_dev
)
357 if (gspca_debug
< D_STREAM
)
360 for (i
= 0; i
< 6; i
++) {
361 reg_r(gspca_dev
, 0, i
, 1);
362 info
[i
] = gspca_dev
->usb_buf
[0];
364 gspca_dbg(gspca_dev
, D_STREAM
,
365 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
366 info
[0], info
[1], info
[2],
367 info
[3], info
[4], info
[5]);
370 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
372 u16 idx
, u16 val
, u8 endcode
, u8 count
)
376 reg_w_riv(gspca_dev
, req
, idx
, val
);
377 reg_r(gspca_dev
, 0x01, 0x0001, 1);
378 if (gspca_dev
->usb_err
< 0)
380 gspca_dbg(gspca_dev
, D_FRAM
, "Status 0x%02x Need 0x%02x\n",
381 gspca_dev
->usb_buf
[0], endcode
);
385 while (--count
> 0) {
387 /* gsmart mini2 write a each wait setting 1 ms is enough */
388 /* reg_w_riv(gspca_dev, req, idx, val); */
389 reg_r(gspca_dev
, 0x01, 0x0001, 1);
390 status
= gspca_dev
->usb_buf
[0];
391 if (status
== endcode
) {
392 gspca_dbg(gspca_dev
, D_FRAM
, "status 0x%04x after wait %d\n",
393 status
, 200 - count
);
399 static void spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
403 while (--count
> 0) {
404 reg_r(gspca_dev
, 0x21, 0, 1);
405 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
411 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
415 while (--count
> 0) {
416 reg_r(gspca_dev
, 0x21, 1, 1);
417 if (gspca_dev
->usb_buf
[0] != 0) {
418 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
419 reg_r(gspca_dev
, 0x21, 1, 1);
420 spca504B_PollingDataReady(gspca_dev
);
427 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
431 if (gspca_debug
< D_STREAM
)
434 data
= gspca_dev
->usb_buf
;
435 reg_r(gspca_dev
, 0x20, 0, 5);
436 gspca_dbg(gspca_dev
, D_STREAM
, "FirmWare: %d %d %d %d %d\n",
437 data
[0], data
[1], data
[2], data
[3], data
[4]);
438 reg_r(gspca_dev
, 0x23, 0, 64);
439 reg_r(gspca_dev
, 0x23, 1, 64);
442 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
444 struct sd
*sd
= (struct sd
*) gspca_dev
;
447 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
448 switch (sd
->bridge
) {
450 reg_w_riv(gspca_dev
, 0x31, 0, 0);
451 spca504B_WaitCmdStatus(gspca_dev
);
452 spca504B_PollingDataReady(gspca_dev
);
453 spca50x_GetFirmware(gspca_dev
);
455 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
456 reg_r(gspca_dev
, 0x24, 8, 1);
458 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
459 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
460 spca504B_PollingDataReady(gspca_dev
);
462 /* Init the cam width height with some values get on init ? */
463 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
464 spca504B_WaitCmdStatus(gspca_dev
);
465 spca504B_PollingDataReady(gspca_dev
);
468 /* case BRIDGE_SPCA504B: */
469 /* case BRIDGE_SPCA536: */
470 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
471 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
472 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
473 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
474 spca504B_PollingDataReady(gspca_dev
);
478 if (sd
->subtype
== AiptekMiniPenCam13
) {
479 /* spca504a aiptek */
480 spca504A_acknowledged_command(gspca_dev
,
482 0x80 | (Size
& 0x0f), 1);
483 spca504A_acknowledged_command(gspca_dev
,
486 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
489 case BRIDGE_SPCA504C
:
491 reg_w_riv(gspca_dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
492 reg_w_riv(gspca_dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
497 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
503 /* With this we get the status, when return 0 it's all ok */
504 reg_r(gspca_dev
, 0x06, 0x00, 1);
505 if (gspca_dev
->usb_buf
[0] == 0)
511 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
513 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
514 reg_r(gspca_dev
, 0x26, 0, 1);
515 spca504B_PollingDataReady(gspca_dev
);
518 static void setbrightness(struct gspca_dev
*gspca_dev
, s32 val
)
520 struct sd
*sd
= (struct sd
*) gspca_dev
;
523 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
524 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
527 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
529 struct sd
*sd
= (struct sd
*) gspca_dev
;
532 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
533 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
536 static void setcolors(struct gspca_dev
*gspca_dev
, s32 val
)
538 struct sd
*sd
= (struct sd
*) gspca_dev
;
541 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
542 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
545 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
547 struct sd
*sd
= (struct sd
*) gspca_dev
;
550 switch (sd
->bridge
) {
552 case BRIDGE_SPCA504C
:
556 /* case BRIDGE_SPCA533: */
557 /* case BRIDGE_SPCA504B: */
558 reg_w_riv(gspca_dev
, 0, 0x21ad, 0x00); /* hue */
559 reg_w_riv(gspca_dev
, 0, 0x21ac, 0x01); /* sat/hue */
560 reg_w_riv(gspca_dev
, 0, 0x21a3, 0x00); /* gamma */
563 reg_w_riv(gspca_dev
, 0, 0x20f5, 0x40);
564 reg_w_riv(gspca_dev
, 0, 0x20f4, 0x01);
565 reg_w_riv(gspca_dev
, 0, 0x2089, 0x00);
569 spca504B_PollingDataReady(gspca_dev
);
572 /* this function is called at probe time */
573 static int sd_config(struct gspca_dev
*gspca_dev
,
574 const struct usb_device_id
*id
)
576 struct sd
*sd
= (struct sd
*) gspca_dev
;
579 cam
= &gspca_dev
->cam
;
581 sd
->bridge
= id
->driver_info
>> 8;
582 sd
->subtype
= id
->driver_info
;
584 if (sd
->subtype
== AiptekMiniPenCam13
) {
586 /* try to get the firmware as some cam answer 2.0.1.2.2
587 * and should be a spca504b then overwrite that setting */
588 reg_r(gspca_dev
, 0x20, 0, 1);
589 switch (gspca_dev
->usb_buf
[0]) {
591 break; /* (right bridge/subtype) */
593 sd
->bridge
= BRIDGE_SPCA504B
;
601 switch (sd
->bridge
) {
603 /* case BRIDGE_SPCA504B: */
604 /* case BRIDGE_SPCA504: */
605 /* case BRIDGE_SPCA536: */
606 cam
->cam_mode
= vga_mode
;
607 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
610 cam
->cam_mode
= custom_mode
;
611 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
612 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
614 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
616 case BRIDGE_SPCA504C
:
617 cam
->cam_mode
= vga_mode2
;
618 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
624 /* this function is called at probe and resume time */
625 static int sd_init(struct gspca_dev
*gspca_dev
)
627 struct sd
*sd
= (struct sd
*) gspca_dev
;
629 switch (sd
->bridge
) {
630 case BRIDGE_SPCA504B
:
631 reg_w_riv(gspca_dev
, 0x1d, 0x00, 0);
632 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x01);
633 reg_w_riv(gspca_dev
, 0x00, 0x0d04, 0x00);
634 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x00);
635 reg_w_riv(gspca_dev
, 0x00, 0x2301, 0x13);
636 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x00);
639 spca504B_PollingDataReady(gspca_dev
);
640 spca50x_GetFirmware(gspca_dev
);
643 spca50x_GetFirmware(gspca_dev
);
644 reg_r(gspca_dev
, 0x00, 0x5002, 1);
645 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
646 reg_r(gspca_dev
, 0x24, 0, 1);
647 spca504B_PollingDataReady(gspca_dev
);
648 reg_w_riv(gspca_dev
, 0x34, 0, 0);
649 spca504B_WaitCmdStatus(gspca_dev
);
651 case BRIDGE_SPCA504C
: /* pccam600 */
652 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504 (PC-CAM 600)\n");
653 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0000);
654 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0001); /* reset */
655 spca504_wait_status(gspca_dev
);
656 if (sd
->subtype
== LogitechClickSmart420
)
657 write_vector(gspca_dev
,
658 spca504A_clicksmart420_open_data
,
659 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
661 write_vector(gspca_dev
, spca504_pccam600_open_data
,
662 ARRAY_SIZE(spca504_pccam600_open_data
));
663 setup_qtable(gspca_dev
, qtable_creative_pccam
);
666 /* case BRIDGE_SPCA504: */
667 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504\n");
668 if (sd
->subtype
== AiptekMiniPenCam13
) {
669 spca504_read_info(gspca_dev
);
671 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
672 spca504A_acknowledged_command(gspca_dev
, 0x24,
674 /* Twice sequential need status 0xff->0x9e->0x9d */
675 spca504A_acknowledged_command(gspca_dev
, 0x24,
678 spca504A_acknowledged_command(gspca_dev
, 0x24,
680 /******************************/
681 /* spca504a aiptek */
682 spca504A_acknowledged_command(gspca_dev
, 0x08,
684 /* reg_write (dev, 0, 0x2000, 0); */
685 /* reg_write (dev, 0, 0x2883, 1); */
686 /* spca504A_acknowledged_command (gspca_dev, 0x08,
688 /* spca504A_acknowledged_command (gspca_dev, 0x24,
690 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
692 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
693 spca504A_acknowledged_command(gspca_dev
, 0x01,
697 reg_w_riv(gspca_dev
, 0, 0x2000, 0);
698 reg_w_riv(gspca_dev
, 0, 0x2883, 1);
699 setup_qtable(gspca_dev
, qtable_spca504_default
);
702 return gspca_dev
->usb_err
;
705 static int sd_start(struct gspca_dev
*gspca_dev
)
707 struct sd
*sd
= (struct sd
*) gspca_dev
;
710 /* create the JPEG header */
711 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->pixfmt
.height
,
712 gspca_dev
->pixfmt
.width
,
713 0x22); /* JPEG 411 */
714 jpeg_set_qual(sd
->jpeg_hdr
, QUALITY
);
716 if (sd
->bridge
== BRIDGE_SPCA504B
)
717 spca504B_setQtable(gspca_dev
);
718 spca504B_SetSizeType(gspca_dev
);
719 switch (sd
->bridge
) {
721 /* case BRIDGE_SPCA504B: */
722 /* case BRIDGE_SPCA533: */
723 /* case BRIDGE_SPCA536: */
724 switch (sd
->subtype
) {
726 case LogitechClickSmart820
:
728 reg_w_riv(gspca_dev
, 0xf0, 0, 0);
729 spca504B_WaitCmdStatus(gspca_dev
);
730 reg_r(gspca_dev
, 0xf0, 4, 0);
731 spca504B_WaitCmdStatus(gspca_dev
);
734 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
735 spca504B_WaitCmdStatus(gspca_dev
);
736 spca504B_PollingDataReady(gspca_dev
);
741 if (sd
->subtype
== AiptekMiniPenCam13
) {
742 spca504_read_info(gspca_dev
);
744 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
745 spca504A_acknowledged_command(gspca_dev
, 0x24,
747 /* Twice sequential need status 0xff->0x9e->0x9d */
748 spca504A_acknowledged_command(gspca_dev
, 0x24,
750 spca504A_acknowledged_command(gspca_dev
, 0x24,
753 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
754 spca504_read_info(gspca_dev
);
755 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
756 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
758 spca504B_SetSizeType(gspca_dev
);
759 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
761 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
763 case BRIDGE_SPCA504C
:
764 if (sd
->subtype
== LogitechClickSmart420
) {
765 write_vector(gspca_dev
,
766 spca504A_clicksmart420_init_data
,
767 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
769 write_vector(gspca_dev
, spca504_pccam600_init_data
,
770 ARRAY_SIZE(spca504_pccam600_init_data
));
772 enable
= (sd
->autogain
? 0x04 : 0x01);
773 reg_w_riv(gspca_dev
, 0x0c, 0x0000, enable
);
775 reg_w_riv(gspca_dev
, 0xb0, 0x0000, enable
);
778 /* set default exposure compensation and whiteness balance */
779 reg_w_riv(gspca_dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
780 reg_w_riv(gspca_dev
, 0x30, 0x0002, 1600);
781 spca504B_SetSizeType(gspca_dev
);
784 init_ctl_reg(gspca_dev
);
785 return gspca_dev
->usb_err
;
788 static void sd_stopN(struct gspca_dev
*gspca_dev
)
790 struct sd
*sd
= (struct sd
*) gspca_dev
;
792 switch (sd
->bridge
) {
794 /* case BRIDGE_SPCA533: */
795 /* case BRIDGE_SPCA536: */
796 /* case BRIDGE_SPCA504B: */
797 reg_w_riv(gspca_dev
, 0x31, 0, 0);
798 spca504B_WaitCmdStatus(gspca_dev
);
799 spca504B_PollingDataReady(gspca_dev
);
802 case BRIDGE_SPCA504C
:
803 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x0000);
805 if (sd
->subtype
== AiptekMiniPenCam13
) {
806 /* spca504a aiptek */
807 /* spca504A_acknowledged_command(gspca_dev, 0x08,
809 spca504A_acknowledged_command(gspca_dev
, 0x24,
810 0x00, 0x00, 0x9d, 1);
811 spca504A_acknowledged_command(gspca_dev
, 0x01,
812 0x0f, 0x00, 0xff, 1);
814 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
815 reg_w_riv(gspca_dev
, 0x01, 0x000f, 0x0000);
821 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
822 u8
*data
, /* isoc packet */
823 int len
) /* iso packet length */
825 struct sd
*sd
= (struct sd
*) gspca_dev
;
827 static u8 ffd9
[] = {0xff, 0xd9};
829 /* frames are jpeg 4.1.1 without 0xff escape */
830 switch (sd
->bridge
) {
832 if (data
[0] == 0xff) {
833 if (data
[1] != 0x01) { /* drop packet */
834 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
838 data
+= SPCA533_OFFSET_DATA
;
839 len
-= SPCA533_OFFSET_DATA
;
846 if (data
[0] == 0xff) {
848 data
+= SPCA536_OFFSET_DATA
;
849 len
-= SPCA536_OFFSET_DATA
;
856 /* case BRIDGE_SPCA504: */
857 /* case BRIDGE_SPCA504B: */
859 case 0xfe: /* start of frame */
861 data
+= SPCA50X_OFFSET_DATA
;
862 len
-= SPCA50X_OFFSET_DATA
;
864 case 0xff: /* drop packet */
865 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
873 case BRIDGE_SPCA504C
:
875 case 0xfe: /* start of frame */
877 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
878 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
880 case 0xff: /* drop packet */
881 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
890 if (sof
) { /* start of frame */
891 gspca_frame_add(gspca_dev
, LAST_PACKET
,
894 /* put the JPEG header in the new frame */
895 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
896 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
899 /* add 0x00 after 0xff */
902 if (data
[i
] == 0xff) {
903 gspca_frame_add(gspca_dev
, INTER_PACKET
,
912 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
915 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
917 struct gspca_dev
*gspca_dev
=
918 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
919 struct sd
*sd
= (struct sd
*)gspca_dev
;
921 gspca_dev
->usb_err
= 0;
923 if (!gspca_dev
->streaming
)
927 case V4L2_CID_BRIGHTNESS
:
928 setbrightness(gspca_dev
, ctrl
->val
);
930 case V4L2_CID_CONTRAST
:
931 setcontrast(gspca_dev
, ctrl
->val
);
933 case V4L2_CID_SATURATION
:
934 setcolors(gspca_dev
, ctrl
->val
);
936 case V4L2_CID_AUTOGAIN
:
937 sd
->autogain
= ctrl
->val
;
940 return gspca_dev
->usb_err
;
943 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
947 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
949 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
951 gspca_dev
->vdev
.ctrl_handler
= hdl
;
952 v4l2_ctrl_handler_init(hdl
, 4);
953 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
954 V4L2_CID_BRIGHTNESS
, -128, 127, 1, 0);
955 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
956 V4L2_CID_CONTRAST
, 0, 255, 1, 0x20);
957 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
958 V4L2_CID_SATURATION
, 0, 255, 1, 0x1a);
959 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
960 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
963 pr_err("Could not initialize controls\n");
969 /* sub-driver description */
970 static const struct sd_desc sd_desc
= {
974 .init_controls
= sd_init_controls
,
977 .pkt_scan
= sd_pkt_scan
,
980 /* -- module initialisation -- */
981 #define BS(bridge, subtype) \
982 .driver_info = (BRIDGE_ ## bridge << 8) \
984 static const struct usb_device_id device_table
[] = {
985 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
986 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
987 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
988 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
989 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
990 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
991 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
992 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
993 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
994 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
995 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
996 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
997 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
998 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
999 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1000 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1001 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1002 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1003 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533
, MegapixV4
)},
1004 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1005 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1006 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1007 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1008 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1009 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1010 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1011 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1012 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1013 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1014 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1015 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1016 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1017 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1018 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1019 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1020 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1021 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1022 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1023 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B
, 0)},
1024 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1025 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1026 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1027 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1028 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1029 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1030 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1031 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1032 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1033 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1034 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1035 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1036 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1037 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1038 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1039 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1040 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1041 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1042 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1043 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1044 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1047 MODULE_DEVICE_TABLE(usb
, device_table
);
1049 /* -- device connect -- */
1050 static int sd_probe(struct usb_interface
*intf
,
1051 const struct usb_device_id
*id
)
1053 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1057 static struct usb_driver sd_driver
= {
1058 .name
= MODULE_NAME
,
1059 .id_table
= device_table
,
1061 .disconnect
= gspca_disconnect
,
1063 .suspend
= gspca_suspend
,
1064 .resume
= gspca_resume
,
1065 .reset_resume
= gspca_resume
,
1069 module_usb_driver(sd_driver
);