Linux 4.19.133
[linux/fpc-iii.git] / drivers / media / usb / gspca / sunplus.c
blob26eae69a2562f565a51f8f41895cbd44a2bb12f4
1 /*
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
10 * any later version.
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"
22 #include "gspca.h"
23 #include "jpeg.h"
25 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
27 MODULE_LICENSE("GPL");
29 #define QUALITY 85
31 /* specific webcam descriptor */
32 struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
35 bool autogain;
37 u8 bridge;
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
43 u8 subtype;
44 #define AiptekMiniPenCam13 1
45 #define LogitechClickSmart420 2
46 #define LogitechClickSmart820 3
47 #define MegapixV4 4
48 #define MegaImageVI 5
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,
55 .bytesperline = 320,
56 .sizeimage = 320 * 240 * 3 / 8 + 590,
57 .colorspace = V4L2_COLORSPACE_JPEG,
58 .priv = 2},
59 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
60 .bytesperline = 640,
61 .sizeimage = 640 * 480 * 3 / 8 + 590,
62 .colorspace = V4L2_COLORSPACE_JPEG,
63 .priv = 1},
66 static const struct v4l2_pix_format custom_mode[] = {
67 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
68 .bytesperline = 320,
69 .sizeimage = 320 * 240 * 3 / 8 + 590,
70 .colorspace = V4L2_COLORSPACE_JPEG,
71 .priv = 2},
72 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
73 .bytesperline = 464,
74 .sizeimage = 464 * 480 * 3 / 8 + 590,
75 .colorspace = V4L2_COLORSPACE_JPEG,
76 .priv = 1},
79 static const struct v4l2_pix_format vga_mode2[] = {
80 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
81 .bytesperline = 176,
82 .sizeimage = 176 * 144 * 3 / 8 + 590,
83 .colorspace = V4L2_COLORSPACE_JPEG,
84 .priv = 4},
85 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
86 .bytesperline = 320,
87 .sizeimage = 320 * 240 * 3 / 8 + 590,
88 .colorspace = V4L2_COLORSPACE_JPEG,
89 .priv = 3},
90 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
91 .bytesperline = 352,
92 .sizeimage = 352 * 288 * 3 / 8 + 590,
93 .colorspace = V4L2_COLORSPACE_JPEG,
94 .priv = 2},
95 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
96 .bytesperline = 640,
97 .sizeimage = 640 * 480 * 3 / 8 + 590,
98 .colorspace = V4L2_COLORSPACE_JPEG,
99 .priv = 1},
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
114 struct cmd {
115 u8 req;
116 u16 val;
117 u16 idx;
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?
218 * NWG: 18/05/2003.
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,
244 u8 req,
245 u16 index,
246 u16 len)
248 int ret;
250 if (len > USB_BUF_SZ) {
251 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
252 return;
254 if (gspca_dev->usb_err < 0)
255 return;
256 ret = usb_control_msg(gspca_dev->dev,
257 usb_rcvctrlpipe(gspca_dev->dev, 0),
258 req,
259 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
260 0, /* value */
261 index,
262 len ? gspca_dev->usb_buf : NULL, len,
263 500);
264 if (ret < 0) {
265 pr_err("reg_r err %d\n", ret);
266 gspca_dev->usb_err = ret;
268 * Make sure the buffer is zeroed to avoid uninitialized
269 * values.
271 memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
275 /* write one byte */
276 static void reg_w_1(struct gspca_dev *gspca_dev,
277 u8 req,
278 u16 value,
279 u16 index,
280 u16 byte)
282 int ret;
284 if (gspca_dev->usb_err < 0)
285 return;
286 gspca_dev->usb_buf[0] = byte;
287 ret = usb_control_msg(gspca_dev->dev,
288 usb_sndctrlpipe(gspca_dev->dev, 0),
289 req,
290 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
291 value, index,
292 gspca_dev->usb_buf, 1,
293 500);
294 if (ret < 0) {
295 pr_err("reg_w_1 err %d\n", ret);
296 gspca_dev->usb_err = ret;
300 /* write req / index / value */
301 static void reg_w_riv(struct gspca_dev *gspca_dev,
302 u8 req, u16 index, u16 value)
304 struct usb_device *dev = gspca_dev->dev;
305 int ret;
307 if (gspca_dev->usb_err < 0)
308 return;
309 ret = usb_control_msg(dev,
310 usb_sndctrlpipe(dev, 0),
311 req,
312 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 value, index, NULL, 0, 500);
314 if (ret < 0) {
315 pr_err("reg_w_riv err %d\n", ret);
316 gspca_dev->usb_err = ret;
317 return;
319 gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
320 req, index, value);
323 static void write_vector(struct gspca_dev *gspca_dev,
324 const struct cmd *data, int ncmds)
326 while (--ncmds >= 0) {
327 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
328 data++;
332 static void setup_qtable(struct gspca_dev *gspca_dev,
333 const u8 qtable[2][64])
335 int i;
337 /* loop over y components */
338 for (i = 0; i < 64; i++)
339 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
341 /* loop over c components */
342 for (i = 0; i < 64; i++)
343 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
346 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
347 u8 req, u16 idx, u16 val)
349 reg_w_riv(gspca_dev, req, idx, val);
350 reg_r(gspca_dev, 0x01, 0x0001, 1);
351 gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n",
352 gspca_dev->usb_buf[0]);
353 reg_w_riv(gspca_dev, req, idx, val);
355 msleep(200);
356 reg_r(gspca_dev, 0x01, 0x0001, 1);
357 gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n",
358 gspca_dev->usb_buf[0]);
361 static void spca504_read_info(struct gspca_dev *gspca_dev)
363 int i;
364 u8 info[6];
366 if (gspca_debug < D_STREAM)
367 return;
369 for (i = 0; i < 6; i++) {
370 reg_r(gspca_dev, 0, i, 1);
371 info[i] = gspca_dev->usb_buf[0];
373 gspca_dbg(gspca_dev, D_STREAM,
374 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
375 info[0], info[1], info[2],
376 info[3], info[4], info[5]);
379 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
380 u8 req,
381 u16 idx, u16 val, u8 endcode, u8 count)
383 u16 status;
385 reg_w_riv(gspca_dev, req, idx, val);
386 reg_r(gspca_dev, 0x01, 0x0001, 1);
387 if (gspca_dev->usb_err < 0)
388 return;
389 gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
390 gspca_dev->usb_buf[0], endcode);
391 if (!count)
392 return;
393 count = 200;
394 while (--count > 0) {
395 msleep(10);
396 /* gsmart mini2 write a each wait setting 1 ms is enough */
397 /* reg_w_riv(gspca_dev, req, idx, val); */
398 reg_r(gspca_dev, 0x01, 0x0001, 1);
399 status = gspca_dev->usb_buf[0];
400 if (status == endcode) {
401 gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n",
402 status, 200 - count);
403 break;
408 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
410 int count = 10;
412 while (--count > 0) {
413 reg_r(gspca_dev, 0x21, 0, 1);
414 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
415 break;
416 msleep(10);
420 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
422 int count = 50;
424 while (--count > 0) {
425 reg_r(gspca_dev, 0x21, 1, 1);
426 if (gspca_dev->usb_buf[0] != 0) {
427 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
428 reg_r(gspca_dev, 0x21, 1, 1);
429 spca504B_PollingDataReady(gspca_dev);
430 break;
432 msleep(10);
436 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
438 u8 *data;
440 if (gspca_debug < D_STREAM)
441 return;
443 data = gspca_dev->usb_buf;
444 reg_r(gspca_dev, 0x20, 0, 5);
445 gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n",
446 data[0], data[1], data[2], data[3], data[4]);
447 reg_r(gspca_dev, 0x23, 0, 64);
448 reg_r(gspca_dev, 0x23, 1, 64);
451 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
453 struct sd *sd = (struct sd *) gspca_dev;
454 u8 Size;
456 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
457 switch (sd->bridge) {
458 case BRIDGE_SPCA533:
459 reg_w_riv(gspca_dev, 0x31, 0, 0);
460 spca504B_WaitCmdStatus(gspca_dev);
461 spca504B_PollingDataReady(gspca_dev);
462 spca50x_GetFirmware(gspca_dev);
464 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
465 reg_r(gspca_dev, 0x24, 8, 1);
467 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
468 reg_r(gspca_dev, 0x25, 4, 1); /* size */
469 spca504B_PollingDataReady(gspca_dev);
471 /* Init the cam width height with some values get on init ? */
472 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
473 spca504B_WaitCmdStatus(gspca_dev);
474 spca504B_PollingDataReady(gspca_dev);
475 break;
476 default:
477 /* case BRIDGE_SPCA504B: */
478 /* case BRIDGE_SPCA536: */
479 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
480 reg_r(gspca_dev, 0x25, 4, 1); /* size */
481 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
482 reg_r(gspca_dev, 0x27, 0, 1); /* type */
483 spca504B_PollingDataReady(gspca_dev);
484 break;
485 case BRIDGE_SPCA504:
486 Size += 3;
487 if (sd->subtype == AiptekMiniPenCam13) {
488 /* spca504a aiptek */
489 spca504A_acknowledged_command(gspca_dev,
490 0x08, Size, 0,
491 0x80 | (Size & 0x0f), 1);
492 spca504A_acknowledged_command(gspca_dev,
493 1, 3, 0, 0x9f, 0);
494 } else {
495 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
497 break;
498 case BRIDGE_SPCA504C:
499 /* capture mode */
500 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
501 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
502 break;
506 static void spca504_wait_status(struct gspca_dev *gspca_dev)
508 int cnt;
510 cnt = 256;
511 while (--cnt > 0) {
512 /* With this we get the status, when return 0 it's all ok */
513 reg_r(gspca_dev, 0x06, 0x00, 1);
514 if (gspca_dev->usb_buf[0] == 0)
515 return;
516 msleep(10);
520 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
522 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
523 reg_r(gspca_dev, 0x26, 0, 1);
524 spca504B_PollingDataReady(gspca_dev);
527 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
529 struct sd *sd = (struct sd *) gspca_dev;
530 u16 reg;
532 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
533 reg_w_riv(gspca_dev, 0x00, reg, val);
536 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
538 struct sd *sd = (struct sd *) gspca_dev;
539 u16 reg;
541 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
542 reg_w_riv(gspca_dev, 0x00, reg, val);
545 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
547 struct sd *sd = (struct sd *) gspca_dev;
548 u16 reg;
550 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
551 reg_w_riv(gspca_dev, 0x00, reg, val);
554 static void init_ctl_reg(struct gspca_dev *gspca_dev)
556 struct sd *sd = (struct sd *) gspca_dev;
557 int pollreg = 1;
559 switch (sd->bridge) {
560 case BRIDGE_SPCA504:
561 case BRIDGE_SPCA504C:
562 pollreg = 0;
563 /* fall thru */
564 default:
565 /* case BRIDGE_SPCA533: */
566 /* case BRIDGE_SPCA504B: */
567 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
568 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
569 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
570 break;
571 case BRIDGE_SPCA536:
572 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
573 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
574 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
575 break;
577 if (pollreg)
578 spca504B_PollingDataReady(gspca_dev);
581 /* this function is called at probe time */
582 static int sd_config(struct gspca_dev *gspca_dev,
583 const struct usb_device_id *id)
585 struct sd *sd = (struct sd *) gspca_dev;
586 struct cam *cam;
588 cam = &gspca_dev->cam;
590 sd->bridge = id->driver_info >> 8;
591 sd->subtype = id->driver_info;
593 if (sd->subtype == AiptekMiniPenCam13) {
595 /* try to get the firmware as some cam answer 2.0.1.2.2
596 * and should be a spca504b then overwrite that setting */
597 reg_r(gspca_dev, 0x20, 0, 1);
598 switch (gspca_dev->usb_buf[0]) {
599 case 1:
600 break; /* (right bridge/subtype) */
601 case 2:
602 sd->bridge = BRIDGE_SPCA504B;
603 sd->subtype = 0;
604 break;
605 default:
606 return -ENODEV;
610 switch (sd->bridge) {
611 default:
612 /* case BRIDGE_SPCA504B: */
613 /* case BRIDGE_SPCA504: */
614 /* case BRIDGE_SPCA536: */
615 cam->cam_mode = vga_mode;
616 cam->nmodes = ARRAY_SIZE(vga_mode);
617 break;
618 case BRIDGE_SPCA533:
619 cam->cam_mode = custom_mode;
620 if (sd->subtype == MegaImageVI) /* 320x240 only */
621 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
622 else
623 cam->nmodes = ARRAY_SIZE(custom_mode);
624 break;
625 case BRIDGE_SPCA504C:
626 cam->cam_mode = vga_mode2;
627 cam->nmodes = ARRAY_SIZE(vga_mode2);
628 break;
630 return 0;
633 /* this function is called at probe and resume time */
634 static int sd_init(struct gspca_dev *gspca_dev)
636 struct sd *sd = (struct sd *) gspca_dev;
638 switch (sd->bridge) {
639 case BRIDGE_SPCA504B:
640 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
641 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
642 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
643 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
644 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
645 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
646 /* fall thru */
647 case BRIDGE_SPCA533:
648 spca504B_PollingDataReady(gspca_dev);
649 spca50x_GetFirmware(gspca_dev);
650 break;
651 case BRIDGE_SPCA536:
652 spca50x_GetFirmware(gspca_dev);
653 reg_r(gspca_dev, 0x00, 0x5002, 1);
654 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
655 reg_r(gspca_dev, 0x24, 0, 1);
656 spca504B_PollingDataReady(gspca_dev);
657 reg_w_riv(gspca_dev, 0x34, 0, 0);
658 spca504B_WaitCmdStatus(gspca_dev);
659 break;
660 case BRIDGE_SPCA504C: /* pccam600 */
661 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n");
662 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
663 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
664 spca504_wait_status(gspca_dev);
665 if (sd->subtype == LogitechClickSmart420)
666 write_vector(gspca_dev,
667 spca504A_clicksmart420_open_data,
668 ARRAY_SIZE(spca504A_clicksmart420_open_data));
669 else
670 write_vector(gspca_dev, spca504_pccam600_open_data,
671 ARRAY_SIZE(spca504_pccam600_open_data));
672 setup_qtable(gspca_dev, qtable_creative_pccam);
673 break;
674 default:
675 /* case BRIDGE_SPCA504: */
676 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n");
677 if (sd->subtype == AiptekMiniPenCam13) {
678 spca504_read_info(gspca_dev);
680 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
681 spca504A_acknowledged_command(gspca_dev, 0x24,
682 8, 3, 0x9e, 1);
683 /* Twice sequential need status 0xff->0x9e->0x9d */
684 spca504A_acknowledged_command(gspca_dev, 0x24,
685 8, 3, 0x9e, 0);
687 spca504A_acknowledged_command(gspca_dev, 0x24,
688 0, 0, 0x9d, 1);
689 /******************************/
690 /* spca504a aiptek */
691 spca504A_acknowledged_command(gspca_dev, 0x08,
692 6, 0, 0x86, 1);
693 /* reg_write (dev, 0, 0x2000, 0); */
694 /* reg_write (dev, 0, 0x2883, 1); */
695 /* spca504A_acknowledged_command (gspca_dev, 0x08,
696 6, 0, 0x86, 1); */
697 /* spca504A_acknowledged_command (gspca_dev, 0x24,
698 0, 0, 0x9D, 1); */
699 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
700 /* L92 sno1t.txt */
701 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
702 spca504A_acknowledged_command(gspca_dev, 0x01,
703 0x0f, 0, 0xff, 0);
705 /* setup qtable */
706 reg_w_riv(gspca_dev, 0, 0x2000, 0);
707 reg_w_riv(gspca_dev, 0, 0x2883, 1);
708 setup_qtable(gspca_dev, qtable_spca504_default);
709 break;
711 return gspca_dev->usb_err;
714 static int sd_start(struct gspca_dev *gspca_dev)
716 struct sd *sd = (struct sd *) gspca_dev;
717 int enable;
719 /* create the JPEG header */
720 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
721 gspca_dev->pixfmt.width,
722 0x22); /* JPEG 411 */
723 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
725 if (sd->bridge == BRIDGE_SPCA504B)
726 spca504B_setQtable(gspca_dev);
727 spca504B_SetSizeType(gspca_dev);
728 switch (sd->bridge) {
729 default:
730 /* case BRIDGE_SPCA504B: */
731 /* case BRIDGE_SPCA533: */
732 /* case BRIDGE_SPCA536: */
733 switch (sd->subtype) {
734 case MegapixV4:
735 case LogitechClickSmart820:
736 case MegaImageVI:
737 reg_w_riv(gspca_dev, 0xf0, 0, 0);
738 spca504B_WaitCmdStatus(gspca_dev);
739 reg_r(gspca_dev, 0xf0, 4, 0);
740 spca504B_WaitCmdStatus(gspca_dev);
741 break;
742 default:
743 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
744 spca504B_WaitCmdStatus(gspca_dev);
745 spca504B_PollingDataReady(gspca_dev);
746 break;
748 break;
749 case BRIDGE_SPCA504:
750 if (sd->subtype == AiptekMiniPenCam13) {
751 spca504_read_info(gspca_dev);
753 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
754 spca504A_acknowledged_command(gspca_dev, 0x24,
755 8, 3, 0x9e, 1);
756 /* Twice sequential need status 0xff->0x9e->0x9d */
757 spca504A_acknowledged_command(gspca_dev, 0x24,
758 8, 3, 0x9e, 0);
759 spca504A_acknowledged_command(gspca_dev, 0x24,
760 0, 0, 0x9d, 1);
761 } else {
762 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
763 spca504_read_info(gspca_dev);
764 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
765 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
767 spca504B_SetSizeType(gspca_dev);
768 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
769 /* L92 sno1t.txt */
770 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
771 break;
772 case BRIDGE_SPCA504C:
773 if (sd->subtype == LogitechClickSmart420) {
774 write_vector(gspca_dev,
775 spca504A_clicksmart420_init_data,
776 ARRAY_SIZE(spca504A_clicksmart420_init_data));
777 } else {
778 write_vector(gspca_dev, spca504_pccam600_init_data,
779 ARRAY_SIZE(spca504_pccam600_init_data));
781 enable = (sd->autogain ? 0x04 : 0x01);
782 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
783 /* auto exposure */
784 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
785 /* auto whiteness */
787 /* set default exposure compensation and whiteness balance */
788 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
789 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
790 spca504B_SetSizeType(gspca_dev);
791 break;
793 init_ctl_reg(gspca_dev);
794 return gspca_dev->usb_err;
797 static void sd_stopN(struct gspca_dev *gspca_dev)
799 struct sd *sd = (struct sd *) gspca_dev;
801 switch (sd->bridge) {
802 default:
803 /* case BRIDGE_SPCA533: */
804 /* case BRIDGE_SPCA536: */
805 /* case BRIDGE_SPCA504B: */
806 reg_w_riv(gspca_dev, 0x31, 0, 0);
807 spca504B_WaitCmdStatus(gspca_dev);
808 spca504B_PollingDataReady(gspca_dev);
809 break;
810 case BRIDGE_SPCA504:
811 case BRIDGE_SPCA504C:
812 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
814 if (sd->subtype == AiptekMiniPenCam13) {
815 /* spca504a aiptek */
816 /* spca504A_acknowledged_command(gspca_dev, 0x08,
817 6, 0, 0x86, 1); */
818 spca504A_acknowledged_command(gspca_dev, 0x24,
819 0x00, 0x00, 0x9d, 1);
820 spca504A_acknowledged_command(gspca_dev, 0x01,
821 0x0f, 0x00, 0xff, 1);
822 } else {
823 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
824 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
826 break;
830 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
831 u8 *data, /* isoc packet */
832 int len) /* iso packet length */
834 struct sd *sd = (struct sd *) gspca_dev;
835 int i, sof = 0;
836 static u8 ffd9[] = {0xff, 0xd9};
838 /* frames are jpeg 4.1.1 without 0xff escape */
839 switch (sd->bridge) {
840 case BRIDGE_SPCA533:
841 if (data[0] == 0xff) {
842 if (data[1] != 0x01) { /* drop packet */
843 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
844 return;
846 sof = 1;
847 data += SPCA533_OFFSET_DATA;
848 len -= SPCA533_OFFSET_DATA;
849 } else {
850 data += 1;
851 len -= 1;
853 break;
854 case BRIDGE_SPCA536:
855 if (data[0] == 0xff) {
856 sof = 1;
857 data += SPCA536_OFFSET_DATA;
858 len -= SPCA536_OFFSET_DATA;
859 } else {
860 data += 2;
861 len -= 2;
863 break;
864 default:
865 /* case BRIDGE_SPCA504: */
866 /* case BRIDGE_SPCA504B: */
867 switch (data[0]) {
868 case 0xfe: /* start of frame */
869 sof = 1;
870 data += SPCA50X_OFFSET_DATA;
871 len -= SPCA50X_OFFSET_DATA;
872 break;
873 case 0xff: /* drop packet */
874 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
875 return;
876 default:
877 data += 1;
878 len -= 1;
879 break;
881 break;
882 case BRIDGE_SPCA504C:
883 switch (data[0]) {
884 case 0xfe: /* start of frame */
885 sof = 1;
886 data += SPCA504_PCCAM600_OFFSET_DATA;
887 len -= SPCA504_PCCAM600_OFFSET_DATA;
888 break;
889 case 0xff: /* drop packet */
890 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
891 return;
892 default:
893 data += 1;
894 len -= 1;
895 break;
897 break;
899 if (sof) { /* start of frame */
900 gspca_frame_add(gspca_dev, LAST_PACKET,
901 ffd9, 2);
903 /* put the JPEG header in the new frame */
904 gspca_frame_add(gspca_dev, FIRST_PACKET,
905 sd->jpeg_hdr, JPEG_HDR_SZ);
908 /* add 0x00 after 0xff */
909 i = 0;
910 do {
911 if (data[i] == 0xff) {
912 gspca_frame_add(gspca_dev, INTER_PACKET,
913 data, i + 1);
914 len -= i;
915 data += i;
916 *data = 0x00;
917 i = 0;
919 i++;
920 } while (i < len);
921 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
924 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
926 struct gspca_dev *gspca_dev =
927 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
928 struct sd *sd = (struct sd *)gspca_dev;
930 gspca_dev->usb_err = 0;
932 if (!gspca_dev->streaming)
933 return 0;
935 switch (ctrl->id) {
936 case V4L2_CID_BRIGHTNESS:
937 setbrightness(gspca_dev, ctrl->val);
938 break;
939 case V4L2_CID_CONTRAST:
940 setcontrast(gspca_dev, ctrl->val);
941 break;
942 case V4L2_CID_SATURATION:
943 setcolors(gspca_dev, ctrl->val);
944 break;
945 case V4L2_CID_AUTOGAIN:
946 sd->autogain = ctrl->val;
947 break;
949 return gspca_dev->usb_err;
952 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
953 .s_ctrl = sd_s_ctrl,
956 static int sd_init_controls(struct gspca_dev *gspca_dev)
958 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
960 gspca_dev->vdev.ctrl_handler = hdl;
961 v4l2_ctrl_handler_init(hdl, 4);
962 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
963 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
964 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
965 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
966 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
967 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
968 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
969 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
971 if (hdl->error) {
972 pr_err("Could not initialize controls\n");
973 return hdl->error;
975 return 0;
978 /* sub-driver description */
979 static const struct sd_desc sd_desc = {
980 .name = MODULE_NAME,
981 .config = sd_config,
982 .init = sd_init,
983 .init_controls = sd_init_controls,
984 .start = sd_start,
985 .stopN = sd_stopN,
986 .pkt_scan = sd_pkt_scan,
989 /* -- module initialisation -- */
990 #define BS(bridge, subtype) \
991 .driver_info = (BRIDGE_ ## bridge << 8) \
992 | (subtype)
993 static const struct usb_device_id device_table[] = {
994 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
995 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
996 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
997 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
998 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
999 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1000 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1001 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1002 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1003 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1004 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1005 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1006 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1007 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1008 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1009 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1010 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1011 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1012 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1013 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1014 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1015 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1016 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1017 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1018 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1019 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1020 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1021 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1022 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1023 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1024 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1025 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1026 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1027 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1028 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1030 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1031 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1033 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1034 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1035 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1037 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1038 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1039 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1040 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1041 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1042 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1043 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1044 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1045 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1046 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1047 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1048 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1049 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1050 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1051 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1052 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1053 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1056 MODULE_DEVICE_TABLE(usb, device_table);
1058 /* -- device connect -- */
1059 static int sd_probe(struct usb_interface *intf,
1060 const struct usb_device_id *id)
1062 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1063 THIS_MODULE);
1066 static struct usb_driver sd_driver = {
1067 .name = MODULE_NAME,
1068 .id_table = device_table,
1069 .probe = sd_probe,
1070 .disconnect = gspca_disconnect,
1071 #ifdef CONFIG_PM
1072 .suspend = gspca_suspend,
1073 .resume = gspca_resume,
1074 .reset_resume = gspca_resume,
1075 #endif
1078 module_usb_driver(sd_driver);