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");
246 gspca_err(gspca_dev
, "reg_r: zero-length read\n");
249 if (gspca_dev
->usb_err
< 0)
251 ret
= usb_control_msg(gspca_dev
->dev
,
252 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
254 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
257 gspca_dev
->usb_buf
, len
,
260 pr_err("reg_r err %d\n", ret
);
261 gspca_dev
->usb_err
= ret
;
263 * Make sure the buffer is zeroed to avoid uninitialized
266 memset(gspca_dev
->usb_buf
, 0, USB_BUF_SZ
);
271 static void reg_w_1(struct gspca_dev
*gspca_dev
,
279 if (gspca_dev
->usb_err
< 0)
281 gspca_dev
->usb_buf
[0] = byte
;
282 ret
= usb_control_msg(gspca_dev
->dev
,
283 usb_sndctrlpipe(gspca_dev
->dev
, 0),
285 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
287 gspca_dev
->usb_buf
, 1,
290 pr_err("reg_w_1 err %d\n", ret
);
291 gspca_dev
->usb_err
= ret
;
295 /* write req / index / value */
296 static void reg_w_riv(struct gspca_dev
*gspca_dev
,
297 u8 req
, u16 index
, u16 value
)
299 struct usb_device
*dev
= gspca_dev
->dev
;
302 if (gspca_dev
->usb_err
< 0)
304 ret
= usb_control_msg(dev
,
305 usb_sndctrlpipe(dev
, 0),
307 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
308 value
, index
, NULL
, 0, 500);
310 pr_err("reg_w_riv err %d\n", ret
);
311 gspca_dev
->usb_err
= ret
;
314 gspca_dbg(gspca_dev
, D_USBO
, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
318 static void write_vector(struct gspca_dev
*gspca_dev
,
319 const struct cmd
*data
, int ncmds
)
321 while (--ncmds
>= 0) {
322 reg_w_riv(gspca_dev
, data
->req
, data
->idx
, data
->val
);
327 static void setup_qtable(struct gspca_dev
*gspca_dev
,
328 const u8 qtable
[2][64])
332 /* loop over y components */
333 for (i
= 0; i
< 64; i
++)
334 reg_w_riv(gspca_dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
336 /* loop over c components */
337 for (i
= 0; i
< 64; i
++)
338 reg_w_riv(gspca_dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
341 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
342 u8 req
, u16 idx
, u16 val
)
344 reg_w_riv(gspca_dev
, req
, idx
, val
);
345 reg_r(gspca_dev
, 0x01, 0x0001, 1);
346 gspca_dbg(gspca_dev
, D_FRAM
, "before wait 0x%04x\n",
347 gspca_dev
->usb_buf
[0]);
348 reg_w_riv(gspca_dev
, req
, idx
, val
);
351 reg_r(gspca_dev
, 0x01, 0x0001, 1);
352 gspca_dbg(gspca_dev
, D_FRAM
, "after wait 0x%04x\n",
353 gspca_dev
->usb_buf
[0]);
356 static void spca504_read_info(struct gspca_dev
*gspca_dev
)
361 if (gspca_debug
< D_STREAM
)
364 for (i
= 0; i
< 6; i
++) {
365 reg_r(gspca_dev
, 0, i
, 1);
366 info
[i
] = gspca_dev
->usb_buf
[0];
368 gspca_dbg(gspca_dev
, D_STREAM
,
369 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
370 info
[0], info
[1], info
[2],
371 info
[3], info
[4], info
[5]);
374 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
376 u16 idx
, u16 val
, u8 endcode
, u8 count
)
380 reg_w_riv(gspca_dev
, req
, idx
, val
);
381 reg_r(gspca_dev
, 0x01, 0x0001, 1);
382 if (gspca_dev
->usb_err
< 0)
384 gspca_dbg(gspca_dev
, D_FRAM
, "Status 0x%02x Need 0x%02x\n",
385 gspca_dev
->usb_buf
[0], endcode
);
389 while (--count
> 0) {
391 /* gsmart mini2 write a each wait setting 1 ms is enough */
392 /* reg_w_riv(gspca_dev, req, idx, val); */
393 reg_r(gspca_dev
, 0x01, 0x0001, 1);
394 status
= gspca_dev
->usb_buf
[0];
395 if (status
== endcode
) {
396 gspca_dbg(gspca_dev
, D_FRAM
, "status 0x%04x after wait %d\n",
397 status
, 200 - count
);
403 static void spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
407 while (--count
> 0) {
408 reg_r(gspca_dev
, 0x21, 0, 1);
409 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
415 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
419 while (--count
> 0) {
420 reg_r(gspca_dev
, 0x21, 1, 1);
421 if (gspca_dev
->usb_buf
[0] != 0) {
422 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
423 reg_r(gspca_dev
, 0x21, 1, 1);
424 spca504B_PollingDataReady(gspca_dev
);
431 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
435 if (gspca_debug
< D_STREAM
)
438 data
= gspca_dev
->usb_buf
;
439 reg_r(gspca_dev
, 0x20, 0, 5);
440 gspca_dbg(gspca_dev
, D_STREAM
, "FirmWare: %d %d %d %d %d\n",
441 data
[0], data
[1], data
[2], data
[3], data
[4]);
442 reg_r(gspca_dev
, 0x23, 0, 64);
443 reg_r(gspca_dev
, 0x23, 1, 64);
446 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
448 struct sd
*sd
= (struct sd
*) gspca_dev
;
451 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
452 switch (sd
->bridge
) {
454 reg_w_riv(gspca_dev
, 0x31, 0, 0);
455 spca504B_WaitCmdStatus(gspca_dev
);
456 spca504B_PollingDataReady(gspca_dev
);
457 spca50x_GetFirmware(gspca_dev
);
459 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
460 reg_r(gspca_dev
, 0x24, 8, 1);
462 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
463 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
464 spca504B_PollingDataReady(gspca_dev
);
466 /* Init the cam width height with some values get on init ? */
467 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
468 spca504B_WaitCmdStatus(gspca_dev
);
469 spca504B_PollingDataReady(gspca_dev
);
472 /* case BRIDGE_SPCA504B: */
473 /* case BRIDGE_SPCA536: */
474 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
475 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
476 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
477 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
478 spca504B_PollingDataReady(gspca_dev
);
482 if (sd
->subtype
== AiptekMiniPenCam13
) {
483 /* spca504a aiptek */
484 spca504A_acknowledged_command(gspca_dev
,
486 0x80 | (Size
& 0x0f), 1);
487 spca504A_acknowledged_command(gspca_dev
,
490 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
493 case BRIDGE_SPCA504C
:
495 reg_w_riv(gspca_dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
496 reg_w_riv(gspca_dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
501 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
507 /* With this we get the status, when return 0 it's all ok */
508 reg_r(gspca_dev
, 0x06, 0x00, 1);
509 if (gspca_dev
->usb_buf
[0] == 0)
515 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
517 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
518 reg_r(gspca_dev
, 0x26, 0, 1);
519 spca504B_PollingDataReady(gspca_dev
);
522 static void setbrightness(struct gspca_dev
*gspca_dev
, s32 val
)
524 struct sd
*sd
= (struct sd
*) gspca_dev
;
527 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
528 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
531 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
533 struct sd
*sd
= (struct sd
*) gspca_dev
;
536 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
537 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
540 static void setcolors(struct gspca_dev
*gspca_dev
, s32 val
)
542 struct sd
*sd
= (struct sd
*) gspca_dev
;
545 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
546 reg_w_riv(gspca_dev
, 0x00, reg
, val
);
549 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
551 struct sd
*sd
= (struct sd
*) gspca_dev
;
554 switch (sd
->bridge
) {
556 case BRIDGE_SPCA504C
:
560 /* case BRIDGE_SPCA533: */
561 /* case BRIDGE_SPCA504B: */
562 reg_w_riv(gspca_dev
, 0, 0x21ad, 0x00); /* hue */
563 reg_w_riv(gspca_dev
, 0, 0x21ac, 0x01); /* sat/hue */
564 reg_w_riv(gspca_dev
, 0, 0x21a3, 0x00); /* gamma */
567 reg_w_riv(gspca_dev
, 0, 0x20f5, 0x40);
568 reg_w_riv(gspca_dev
, 0, 0x20f4, 0x01);
569 reg_w_riv(gspca_dev
, 0, 0x2089, 0x00);
573 spca504B_PollingDataReady(gspca_dev
);
576 /* this function is called at probe time */
577 static int sd_config(struct gspca_dev
*gspca_dev
,
578 const struct usb_device_id
*id
)
580 struct sd
*sd
= (struct sd
*) gspca_dev
;
583 cam
= &gspca_dev
->cam
;
585 sd
->bridge
= id
->driver_info
>> 8;
586 sd
->subtype
= id
->driver_info
;
588 if (sd
->subtype
== AiptekMiniPenCam13
) {
590 /* try to get the firmware as some cam answer 2.0.1.2.2
591 * and should be a spca504b then overwrite that setting */
592 reg_r(gspca_dev
, 0x20, 0, 1);
593 switch (gspca_dev
->usb_buf
[0]) {
595 break; /* (right bridge/subtype) */
597 sd
->bridge
= BRIDGE_SPCA504B
;
605 switch (sd
->bridge
) {
607 /* case BRIDGE_SPCA504B: */
608 /* case BRIDGE_SPCA504: */
609 /* case BRIDGE_SPCA536: */
610 cam
->cam_mode
= vga_mode
;
611 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
614 cam
->cam_mode
= custom_mode
;
615 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
616 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
618 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
620 case BRIDGE_SPCA504C
:
621 cam
->cam_mode
= vga_mode2
;
622 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
628 /* this function is called at probe and resume time */
629 static int sd_init(struct gspca_dev
*gspca_dev
)
631 struct sd
*sd
= (struct sd
*) gspca_dev
;
633 switch (sd
->bridge
) {
634 case BRIDGE_SPCA504B
:
635 reg_w_riv(gspca_dev
, 0x1d, 0x00, 0);
636 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x01);
637 reg_w_riv(gspca_dev
, 0x00, 0x0d04, 0x00);
638 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x00);
639 reg_w_riv(gspca_dev
, 0x00, 0x2301, 0x13);
640 reg_w_riv(gspca_dev
, 0x00, 0x2306, 0x00);
643 spca504B_PollingDataReady(gspca_dev
);
644 spca50x_GetFirmware(gspca_dev
);
647 spca50x_GetFirmware(gspca_dev
);
648 reg_r(gspca_dev
, 0x00, 0x5002, 1);
649 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
650 reg_r(gspca_dev
, 0x24, 0, 1);
651 spca504B_PollingDataReady(gspca_dev
);
652 reg_w_riv(gspca_dev
, 0x34, 0, 0);
653 spca504B_WaitCmdStatus(gspca_dev
);
655 case BRIDGE_SPCA504C
: /* pccam600 */
656 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504 (PC-CAM 600)\n");
657 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0000);
658 reg_w_riv(gspca_dev
, 0xe0, 0x0000, 0x0001); /* reset */
659 spca504_wait_status(gspca_dev
);
660 if (sd
->subtype
== LogitechClickSmart420
)
661 write_vector(gspca_dev
,
662 spca504A_clicksmart420_open_data
,
663 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
665 write_vector(gspca_dev
, spca504_pccam600_open_data
,
666 ARRAY_SIZE(spca504_pccam600_open_data
));
667 setup_qtable(gspca_dev
, qtable_creative_pccam
);
670 /* case BRIDGE_SPCA504: */
671 gspca_dbg(gspca_dev
, D_STREAM
, "Opening SPCA504\n");
672 if (sd
->subtype
== AiptekMiniPenCam13
) {
673 spca504_read_info(gspca_dev
);
675 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
676 spca504A_acknowledged_command(gspca_dev
, 0x24,
678 /* Twice sequential need status 0xff->0x9e->0x9d */
679 spca504A_acknowledged_command(gspca_dev
, 0x24,
682 spca504A_acknowledged_command(gspca_dev
, 0x24,
684 /******************************/
685 /* spca504a aiptek */
686 spca504A_acknowledged_command(gspca_dev
, 0x08,
688 /* reg_write (dev, 0, 0x2000, 0); */
689 /* reg_write (dev, 0, 0x2883, 1); */
690 /* spca504A_acknowledged_command (gspca_dev, 0x08,
692 /* spca504A_acknowledged_command (gspca_dev, 0x24,
694 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
696 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
697 spca504A_acknowledged_command(gspca_dev
, 0x01,
701 reg_w_riv(gspca_dev
, 0, 0x2000, 0);
702 reg_w_riv(gspca_dev
, 0, 0x2883, 1);
703 setup_qtable(gspca_dev
, qtable_spca504_default
);
706 return gspca_dev
->usb_err
;
709 static int sd_start(struct gspca_dev
*gspca_dev
)
711 struct sd
*sd
= (struct sd
*) gspca_dev
;
714 /* create the JPEG header */
715 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->pixfmt
.height
,
716 gspca_dev
->pixfmt
.width
,
717 0x22); /* JPEG 411 */
718 jpeg_set_qual(sd
->jpeg_hdr
, QUALITY
);
720 if (sd
->bridge
== BRIDGE_SPCA504B
)
721 spca504B_setQtable(gspca_dev
);
722 spca504B_SetSizeType(gspca_dev
);
723 switch (sd
->bridge
) {
725 /* case BRIDGE_SPCA504B: */
726 /* case BRIDGE_SPCA533: */
727 /* case BRIDGE_SPCA536: */
728 switch (sd
->subtype
) {
730 case LogitechClickSmart820
:
732 reg_w_riv(gspca_dev
, 0xf0, 0, 0);
733 spca504B_WaitCmdStatus(gspca_dev
);
734 reg_w_riv(gspca_dev
, 0xf0, 4, 0);
735 spca504B_WaitCmdStatus(gspca_dev
);
738 reg_w_riv(gspca_dev
, 0x31, 0x0004, 0x00);
739 spca504B_WaitCmdStatus(gspca_dev
);
740 spca504B_PollingDataReady(gspca_dev
);
745 if (sd
->subtype
== AiptekMiniPenCam13
) {
746 spca504_read_info(gspca_dev
);
748 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
749 spca504A_acknowledged_command(gspca_dev
, 0x24,
751 /* Twice sequential need status 0xff->0x9e->0x9d */
752 spca504A_acknowledged_command(gspca_dev
, 0x24,
754 spca504A_acknowledged_command(gspca_dev
, 0x24,
757 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
758 spca504_read_info(gspca_dev
);
759 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
760 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
762 spca504B_SetSizeType(gspca_dev
);
763 reg_w_riv(gspca_dev
, 0x00, 0x270c, 0x05);
765 reg_w_riv(gspca_dev
, 0x00, 0x2310, 0x05);
767 case BRIDGE_SPCA504C
:
768 if (sd
->subtype
== LogitechClickSmart420
) {
769 write_vector(gspca_dev
,
770 spca504A_clicksmart420_init_data
,
771 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
773 write_vector(gspca_dev
, spca504_pccam600_init_data
,
774 ARRAY_SIZE(spca504_pccam600_init_data
));
776 enable
= (sd
->autogain
? 0x04 : 0x01);
777 reg_w_riv(gspca_dev
, 0x0c, 0x0000, enable
);
779 reg_w_riv(gspca_dev
, 0xb0, 0x0000, enable
);
782 /* set default exposure compensation and whiteness balance */
783 reg_w_riv(gspca_dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
784 reg_w_riv(gspca_dev
, 0x30, 0x0002, 1600);
785 spca504B_SetSizeType(gspca_dev
);
788 init_ctl_reg(gspca_dev
);
789 return gspca_dev
->usb_err
;
792 static void sd_stopN(struct gspca_dev
*gspca_dev
)
794 struct sd
*sd
= (struct sd
*) gspca_dev
;
796 switch (sd
->bridge
) {
798 /* case BRIDGE_SPCA533: */
799 /* case BRIDGE_SPCA536: */
800 /* case BRIDGE_SPCA504B: */
801 reg_w_riv(gspca_dev
, 0x31, 0, 0);
802 spca504B_WaitCmdStatus(gspca_dev
);
803 spca504B_PollingDataReady(gspca_dev
);
806 case BRIDGE_SPCA504C
:
807 reg_w_riv(gspca_dev
, 0x00, 0x2000, 0x0000);
809 if (sd
->subtype
== AiptekMiniPenCam13
) {
810 /* spca504a aiptek */
811 /* spca504A_acknowledged_command(gspca_dev, 0x08,
813 spca504A_acknowledged_command(gspca_dev
, 0x24,
814 0x00, 0x00, 0x9d, 1);
815 spca504A_acknowledged_command(gspca_dev
, 0x01,
816 0x0f, 0x00, 0xff, 1);
818 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
819 reg_w_riv(gspca_dev
, 0x01, 0x000f, 0x0000);
825 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
826 u8
*data
, /* isoc packet */
827 int len
) /* iso packet length */
829 struct sd
*sd
= (struct sd
*) gspca_dev
;
831 static u8 ffd9
[] = {0xff, 0xd9};
833 /* frames are jpeg 4.1.1 without 0xff escape */
834 switch (sd
->bridge
) {
836 if (data
[0] == 0xff) {
837 if (data
[1] != 0x01) { /* drop packet */
838 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
842 data
+= SPCA533_OFFSET_DATA
;
843 len
-= SPCA533_OFFSET_DATA
;
850 if (data
[0] == 0xff) {
852 data
+= SPCA536_OFFSET_DATA
;
853 len
-= SPCA536_OFFSET_DATA
;
860 /* case BRIDGE_SPCA504: */
861 /* case BRIDGE_SPCA504B: */
863 case 0xfe: /* start of frame */
865 data
+= SPCA50X_OFFSET_DATA
;
866 len
-= SPCA50X_OFFSET_DATA
;
868 case 0xff: /* drop packet */
869 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
877 case BRIDGE_SPCA504C
:
879 case 0xfe: /* start of frame */
881 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
882 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
884 case 0xff: /* drop packet */
885 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
894 if (sof
) { /* start of frame */
895 gspca_frame_add(gspca_dev
, LAST_PACKET
,
898 /* put the JPEG header in the new frame */
899 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
900 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
903 /* add 0x00 after 0xff */
906 if (data
[i
] == 0xff) {
907 gspca_frame_add(gspca_dev
, INTER_PACKET
,
916 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
919 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
921 struct gspca_dev
*gspca_dev
=
922 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
923 struct sd
*sd
= (struct sd
*)gspca_dev
;
925 gspca_dev
->usb_err
= 0;
927 if (!gspca_dev
->streaming
)
931 case V4L2_CID_BRIGHTNESS
:
932 setbrightness(gspca_dev
, ctrl
->val
);
934 case V4L2_CID_CONTRAST
:
935 setcontrast(gspca_dev
, ctrl
->val
);
937 case V4L2_CID_SATURATION
:
938 setcolors(gspca_dev
, ctrl
->val
);
940 case V4L2_CID_AUTOGAIN
:
941 sd
->autogain
= ctrl
->val
;
944 return gspca_dev
->usb_err
;
947 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
951 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
953 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
955 gspca_dev
->vdev
.ctrl_handler
= hdl
;
956 v4l2_ctrl_handler_init(hdl
, 4);
957 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
958 V4L2_CID_BRIGHTNESS
, -128, 127, 1, 0);
959 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
960 V4L2_CID_CONTRAST
, 0, 255, 1, 0x20);
961 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
962 V4L2_CID_SATURATION
, 0, 255, 1, 0x1a);
963 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
964 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
967 pr_err("Could not initialize controls\n");
973 /* sub-driver description */
974 static const struct sd_desc sd_desc
= {
978 .init_controls
= sd_init_controls
,
981 .pkt_scan
= sd_pkt_scan
,
984 /* -- module initialisation -- */
985 #define BS(bridge, subtype) \
986 .driver_info = (BRIDGE_ ## bridge << 8) \
988 static const struct usb_device_id device_table
[] = {
989 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
990 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
991 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
992 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
993 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
994 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
995 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
996 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
997 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
998 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
999 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
1000 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
1001 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
1002 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
1003 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1004 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1005 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1006 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1007 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533
, MegapixV4
)},
1008 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1009 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1010 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1011 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1012 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1013 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1014 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1015 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1016 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1017 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1018 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1019 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1020 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1021 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1022 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1023 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1024 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1025 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1026 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1027 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B
, 0)},
1028 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1029 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1030 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1031 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1032 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1033 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1034 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1035 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1036 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1037 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1038 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1039 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1040 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1041 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1042 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1043 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1044 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1045 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1046 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1047 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1048 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1051 MODULE_DEVICE_TABLE(usb
, device_table
);
1053 /* -- device connect -- */
1054 static int sd_probe(struct usb_interface
*intf
,
1055 const struct usb_device_id
*id
)
1057 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1061 static struct usb_driver sd_driver
= {
1062 .name
= MODULE_NAME
,
1063 .id_table
= device_table
,
1065 .disconnect
= gspca_disconnect
,
1067 .suspend
= gspca_suspend
,
1068 .resume
= gspca_resume
,
1069 .reset_resume
= gspca_resume
,
1073 module_usb_driver(sd_driver
);