]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - drivers/media/usb/gspca/sunplus.c
Merge branches 'for-5.1/upstream-fixes', 'for-5.2/core', 'for-5.2/ish', 'for-5.2...
[mirror_ubuntu-kernels.git] / drivers / media / usb / gspca / sunplus.c
1 /*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
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.
11 *
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.
16 */
17
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20 #define MODULE_NAME "sunplus"
21
22 #include "gspca.h"
23 #include "jpeg.h"
24
25 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
27 MODULE_LICENSE("GPL");
28
29 #define QUALITY 85
30
31 /* specific webcam descriptor */
32 struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
35 bool autogain;
36
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
49
50 u8 jpeg_hdr[JPEG_HDR_SZ];
51 };
52
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},
64 };
65
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},
77 };
78
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},
100 };
101
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
113
114 struct cmd {
115 u8 req;
116 u16 val;
117 u16 idx;
118 };
119
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},
145 };
146
147 /* Creative PC-CAM 600 specific open data, sent before using the
148 * generic initialisation data from spca504_open_data.
149 */
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},
155 };
156
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},
173
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},
182 };
183
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},
191
192 {0xa0, 0x0000, 0x0503},
193 };
194
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}
214 };
215
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.
219 */
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,
230 },
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}
240 };
241
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)
247 {
248 int ret;
249
250 if (len > USB_BUF_SZ) {
251 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
252 return;
253 }
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;
267 }
268 }
269
270 /* write one byte */
271 static void reg_w_1(struct gspca_dev *gspca_dev,
272 u8 req,
273 u16 value,
274 u16 index,
275 u16 byte)
276 {
277 int ret;
278
279 if (gspca_dev->usb_err < 0)
280 return;
281 gspca_dev->usb_buf[0] = byte;
282 ret = usb_control_msg(gspca_dev->dev,
283 usb_sndctrlpipe(gspca_dev->dev, 0),
284 req,
285 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
286 value, index,
287 gspca_dev->usb_buf, 1,
288 500);
289 if (ret < 0) {
290 pr_err("reg_w_1 err %d\n", ret);
291 gspca_dev->usb_err = ret;
292 }
293 }
294
295 /* write req / index / value */
296 static void reg_w_riv(struct gspca_dev *gspca_dev,
297 u8 req, u16 index, u16 value)
298 {
299 struct usb_device *dev = gspca_dev->dev;
300 int ret;
301
302 if (gspca_dev->usb_err < 0)
303 return;
304 ret = usb_control_msg(dev,
305 usb_sndctrlpipe(dev, 0),
306 req,
307 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
308 value, index, NULL, 0, 500);
309 if (ret < 0) {
310 pr_err("reg_w_riv err %d\n", ret);
311 gspca_dev->usb_err = ret;
312 return;
313 }
314 gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
315 req, index, value);
316 }
317
318 static void write_vector(struct gspca_dev *gspca_dev,
319 const struct cmd *data, int ncmds)
320 {
321 while (--ncmds >= 0) {
322 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
323 data++;
324 }
325 }
326
327 static void setup_qtable(struct gspca_dev *gspca_dev,
328 const u8 qtable[2][64])
329 {
330 int i;
331
332 /* loop over y components */
333 for (i = 0; i < 64; i++)
334 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
335
336 /* loop over c components */
337 for (i = 0; i < 64; i++)
338 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
339 }
340
341 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
342 u8 req, u16 idx, u16 val)
343 {
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);
349
350 msleep(200);
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]);
354 }
355
356 static void spca504_read_info(struct gspca_dev *gspca_dev)
357 {
358 int i;
359 u8 info[6];
360
361 if (gspca_debug < D_STREAM)
362 return;
363
364 for (i = 0; i < 6; i++) {
365 reg_r(gspca_dev, 0, i, 1);
366 info[i] = gspca_dev->usb_buf[0];
367 }
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]);
372 }
373
374 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
375 u8 req,
376 u16 idx, u16 val, u8 endcode, u8 count)
377 {
378 u16 status;
379
380 reg_w_riv(gspca_dev, req, idx, val);
381 reg_r(gspca_dev, 0x01, 0x0001, 1);
382 if (gspca_dev->usb_err < 0)
383 return;
384 gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
385 gspca_dev->usb_buf[0], endcode);
386 if (!count)
387 return;
388 count = 200;
389 while (--count > 0) {
390 msleep(10);
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);
398 break;
399 }
400 }
401 }
402
403 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
404 {
405 int count = 10;
406
407 while (--count > 0) {
408 reg_r(gspca_dev, 0x21, 0, 1);
409 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
410 break;
411 msleep(10);
412 }
413 }
414
415 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
416 {
417 int count = 50;
418
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);
425 break;
426 }
427 msleep(10);
428 }
429 }
430
431 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
432 {
433 u8 *data;
434
435 if (gspca_debug < D_STREAM)
436 return;
437
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);
444 }
445
446 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
447 {
448 struct sd *sd = (struct sd *) gspca_dev;
449 u8 Size;
450
451 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
452 switch (sd->bridge) {
453 case BRIDGE_SPCA533:
454 reg_w_riv(gspca_dev, 0x31, 0, 0);
455 spca504B_WaitCmdStatus(gspca_dev);
456 spca504B_PollingDataReady(gspca_dev);
457 spca50x_GetFirmware(gspca_dev);
458
459 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
460 reg_r(gspca_dev, 0x24, 8, 1);
461
462 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
463 reg_r(gspca_dev, 0x25, 4, 1); /* size */
464 spca504B_PollingDataReady(gspca_dev);
465
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);
470 break;
471 default:
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);
479 break;
480 case BRIDGE_SPCA504:
481 Size += 3;
482 if (sd->subtype == AiptekMiniPenCam13) {
483 /* spca504a aiptek */
484 spca504A_acknowledged_command(gspca_dev,
485 0x08, Size, 0,
486 0x80 | (Size & 0x0f), 1);
487 spca504A_acknowledged_command(gspca_dev,
488 1, 3, 0, 0x9f, 0);
489 } else {
490 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
491 }
492 break;
493 case BRIDGE_SPCA504C:
494 /* capture mode */
495 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
496 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
497 break;
498 }
499 }
500
501 static void spca504_wait_status(struct gspca_dev *gspca_dev)
502 {
503 int cnt;
504
505 cnt = 256;
506 while (--cnt > 0) {
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)
510 return;
511 msleep(10);
512 }
513 }
514
515 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
516 {
517 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
518 reg_r(gspca_dev, 0x26, 0, 1);
519 spca504B_PollingDataReady(gspca_dev);
520 }
521
522 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
523 {
524 struct sd *sd = (struct sd *) gspca_dev;
525 u16 reg;
526
527 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
528 reg_w_riv(gspca_dev, 0x00, reg, val);
529 }
530
531 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
532 {
533 struct sd *sd = (struct sd *) gspca_dev;
534 u16 reg;
535
536 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
537 reg_w_riv(gspca_dev, 0x00, reg, val);
538 }
539
540 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
541 {
542 struct sd *sd = (struct sd *) gspca_dev;
543 u16 reg;
544
545 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
546 reg_w_riv(gspca_dev, 0x00, reg, val);
547 }
548
549 static void init_ctl_reg(struct gspca_dev *gspca_dev)
550 {
551 struct sd *sd = (struct sd *) gspca_dev;
552 int pollreg = 1;
553
554 switch (sd->bridge) {
555 case BRIDGE_SPCA504:
556 case BRIDGE_SPCA504C:
557 pollreg = 0;
558 /* fall through */
559 default:
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 */
565 break;
566 case BRIDGE_SPCA536:
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);
570 break;
571 }
572 if (pollreg)
573 spca504B_PollingDataReady(gspca_dev);
574 }
575
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)
579 {
580 struct sd *sd = (struct sd *) gspca_dev;
581 struct cam *cam;
582
583 cam = &gspca_dev->cam;
584
585 sd->bridge = id->driver_info >> 8;
586 sd->subtype = id->driver_info;
587
588 if (sd->subtype == AiptekMiniPenCam13) {
589
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]) {
594 case 1:
595 break; /* (right bridge/subtype) */
596 case 2:
597 sd->bridge = BRIDGE_SPCA504B;
598 sd->subtype = 0;
599 break;
600 default:
601 return -ENODEV;
602 }
603 }
604
605 switch (sd->bridge) {
606 default:
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);
612 break;
613 case BRIDGE_SPCA533:
614 cam->cam_mode = custom_mode;
615 if (sd->subtype == MegaImageVI) /* 320x240 only */
616 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
617 else
618 cam->nmodes = ARRAY_SIZE(custom_mode);
619 break;
620 case BRIDGE_SPCA504C:
621 cam->cam_mode = vga_mode2;
622 cam->nmodes = ARRAY_SIZE(vga_mode2);
623 break;
624 }
625 return 0;
626 }
627
628 /* this function is called at probe and resume time */
629 static int sd_init(struct gspca_dev *gspca_dev)
630 {
631 struct sd *sd = (struct sd *) gspca_dev;
632
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);
641 /* fall through */
642 case BRIDGE_SPCA533:
643 spca504B_PollingDataReady(gspca_dev);
644 spca50x_GetFirmware(gspca_dev);
645 break;
646 case BRIDGE_SPCA536:
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);
654 break;
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));
664 else
665 write_vector(gspca_dev, spca504_pccam600_open_data,
666 ARRAY_SIZE(spca504_pccam600_open_data));
667 setup_qtable(gspca_dev, qtable_creative_pccam);
668 break;
669 default:
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);
674
675 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
676 spca504A_acknowledged_command(gspca_dev, 0x24,
677 8, 3, 0x9e, 1);
678 /* Twice sequential need status 0xff->0x9e->0x9d */
679 spca504A_acknowledged_command(gspca_dev, 0x24,
680 8, 3, 0x9e, 0);
681
682 spca504A_acknowledged_command(gspca_dev, 0x24,
683 0, 0, 0x9d, 1);
684 /******************************/
685 /* spca504a aiptek */
686 spca504A_acknowledged_command(gspca_dev, 0x08,
687 6, 0, 0x86, 1);
688 /* reg_write (dev, 0, 0x2000, 0); */
689 /* reg_write (dev, 0, 0x2883, 1); */
690 /* spca504A_acknowledged_command (gspca_dev, 0x08,
691 6, 0, 0x86, 1); */
692 /* spca504A_acknowledged_command (gspca_dev, 0x24,
693 0, 0, 0x9D, 1); */
694 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
695 /* L92 sno1t.txt */
696 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
697 spca504A_acknowledged_command(gspca_dev, 0x01,
698 0x0f, 0, 0xff, 0);
699 }
700 /* setup qtable */
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);
704 break;
705 }
706 return gspca_dev->usb_err;
707 }
708
709 static int sd_start(struct gspca_dev *gspca_dev)
710 {
711 struct sd *sd = (struct sd *) gspca_dev;
712 int enable;
713
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);
719
720 if (sd->bridge == BRIDGE_SPCA504B)
721 spca504B_setQtable(gspca_dev);
722 spca504B_SetSizeType(gspca_dev);
723 switch (sd->bridge) {
724 default:
725 /* case BRIDGE_SPCA504B: */
726 /* case BRIDGE_SPCA533: */
727 /* case BRIDGE_SPCA536: */
728 switch (sd->subtype) {
729 case MegapixV4:
730 case LogitechClickSmart820:
731 case MegaImageVI:
732 reg_w_riv(gspca_dev, 0xf0, 0, 0);
733 spca504B_WaitCmdStatus(gspca_dev);
734 reg_r(gspca_dev, 0xf0, 4, 0);
735 spca504B_WaitCmdStatus(gspca_dev);
736 break;
737 default:
738 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
739 spca504B_WaitCmdStatus(gspca_dev);
740 spca504B_PollingDataReady(gspca_dev);
741 break;
742 }
743 break;
744 case BRIDGE_SPCA504:
745 if (sd->subtype == AiptekMiniPenCam13) {
746 spca504_read_info(gspca_dev);
747
748 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
749 spca504A_acknowledged_command(gspca_dev, 0x24,
750 8, 3, 0x9e, 1);
751 /* Twice sequential need status 0xff->0x9e->0x9d */
752 spca504A_acknowledged_command(gspca_dev, 0x24,
753 8, 3, 0x9e, 0);
754 spca504A_acknowledged_command(gspca_dev, 0x24,
755 0, 0, 0x9d, 1);
756 } else {
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);
761 }
762 spca504B_SetSizeType(gspca_dev);
763 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
764 /* L92 sno1t.txt */
765 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
766 break;
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));
772 } else {
773 write_vector(gspca_dev, spca504_pccam600_init_data,
774 ARRAY_SIZE(spca504_pccam600_init_data));
775 }
776 enable = (sd->autogain ? 0x04 : 0x01);
777 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
778 /* auto exposure */
779 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
780 /* auto whiteness */
781
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);
786 break;
787 }
788 init_ctl_reg(gspca_dev);
789 return gspca_dev->usb_err;
790 }
791
792 static void sd_stopN(struct gspca_dev *gspca_dev)
793 {
794 struct sd *sd = (struct sd *) gspca_dev;
795
796 switch (sd->bridge) {
797 default:
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);
804 break;
805 case BRIDGE_SPCA504:
806 case BRIDGE_SPCA504C:
807 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
808
809 if (sd->subtype == AiptekMiniPenCam13) {
810 /* spca504a aiptek */
811 /* spca504A_acknowledged_command(gspca_dev, 0x08,
812 6, 0, 0x86, 1); */
813 spca504A_acknowledged_command(gspca_dev, 0x24,
814 0x00, 0x00, 0x9d, 1);
815 spca504A_acknowledged_command(gspca_dev, 0x01,
816 0x0f, 0x00, 0xff, 1);
817 } else {
818 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
819 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
820 }
821 break;
822 }
823 }
824
825 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
826 u8 *data, /* isoc packet */
827 int len) /* iso packet length */
828 {
829 struct sd *sd = (struct sd *) gspca_dev;
830 int i, sof = 0;
831 static u8 ffd9[] = {0xff, 0xd9};
832
833 /* frames are jpeg 4.1.1 without 0xff escape */
834 switch (sd->bridge) {
835 case BRIDGE_SPCA533:
836 if (data[0] == 0xff) {
837 if (data[1] != 0x01) { /* drop packet */
838 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
839 return;
840 }
841 sof = 1;
842 data += SPCA533_OFFSET_DATA;
843 len -= SPCA533_OFFSET_DATA;
844 } else {
845 data += 1;
846 len -= 1;
847 }
848 break;
849 case BRIDGE_SPCA536:
850 if (data[0] == 0xff) {
851 sof = 1;
852 data += SPCA536_OFFSET_DATA;
853 len -= SPCA536_OFFSET_DATA;
854 } else {
855 data += 2;
856 len -= 2;
857 }
858 break;
859 default:
860 /* case BRIDGE_SPCA504: */
861 /* case BRIDGE_SPCA504B: */
862 switch (data[0]) {
863 case 0xfe: /* start of frame */
864 sof = 1;
865 data += SPCA50X_OFFSET_DATA;
866 len -= SPCA50X_OFFSET_DATA;
867 break;
868 case 0xff: /* drop packet */
869 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
870 return;
871 default:
872 data += 1;
873 len -= 1;
874 break;
875 }
876 break;
877 case BRIDGE_SPCA504C:
878 switch (data[0]) {
879 case 0xfe: /* start of frame */
880 sof = 1;
881 data += SPCA504_PCCAM600_OFFSET_DATA;
882 len -= SPCA504_PCCAM600_OFFSET_DATA;
883 break;
884 case 0xff: /* drop packet */
885 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
886 return;
887 default:
888 data += 1;
889 len -= 1;
890 break;
891 }
892 break;
893 }
894 if (sof) { /* start of frame */
895 gspca_frame_add(gspca_dev, LAST_PACKET,
896 ffd9, 2);
897
898 /* put the JPEG header in the new frame */
899 gspca_frame_add(gspca_dev, FIRST_PACKET,
900 sd->jpeg_hdr, JPEG_HDR_SZ);
901 }
902
903 /* add 0x00 after 0xff */
904 i = 0;
905 do {
906 if (data[i] == 0xff) {
907 gspca_frame_add(gspca_dev, INTER_PACKET,
908 data, i + 1);
909 len -= i;
910 data += i;
911 *data = 0x00;
912 i = 0;
913 }
914 i++;
915 } while (i < len);
916 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
917 }
918
919 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
920 {
921 struct gspca_dev *gspca_dev =
922 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
923 struct sd *sd = (struct sd *)gspca_dev;
924
925 gspca_dev->usb_err = 0;
926
927 if (!gspca_dev->streaming)
928 return 0;
929
930 switch (ctrl->id) {
931 case V4L2_CID_BRIGHTNESS:
932 setbrightness(gspca_dev, ctrl->val);
933 break;
934 case V4L2_CID_CONTRAST:
935 setcontrast(gspca_dev, ctrl->val);
936 break;
937 case V4L2_CID_SATURATION:
938 setcolors(gspca_dev, ctrl->val);
939 break;
940 case V4L2_CID_AUTOGAIN:
941 sd->autogain = ctrl->val;
942 break;
943 }
944 return gspca_dev->usb_err;
945 }
946
947 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
948 .s_ctrl = sd_s_ctrl,
949 };
950
951 static int sd_init_controls(struct gspca_dev *gspca_dev)
952 {
953 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
954
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);
965
966 if (hdl->error) {
967 pr_err("Could not initialize controls\n");
968 return hdl->error;
969 }
970 return 0;
971 }
972
973 /* sub-driver description */
974 static const struct sd_desc sd_desc = {
975 .name = MODULE_NAME,
976 .config = sd_config,
977 .init = sd_init,
978 .init_controls = sd_init_controls,
979 .start = sd_start,
980 .stopN = sd_stopN,
981 .pkt_scan = sd_pkt_scan,
982 };
983
984 /* -- module initialisation -- */
985 #define BS(bridge, subtype) \
986 .driver_info = (BRIDGE_ ## bridge << 8) \
987 | (subtype)
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)},
1049 {}
1050 };
1051 MODULE_DEVICE_TABLE(usb, device_table);
1052
1053 /* -- device connect -- */
1054 static int sd_probe(struct usb_interface *intf,
1055 const struct usb_device_id *id)
1056 {
1057 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1058 THIS_MODULE);
1059 }
1060
1061 static struct usb_driver sd_driver = {
1062 .name = MODULE_NAME,
1063 .id_table = device_table,
1064 .probe = sd_probe,
1065 .disconnect = gspca_disconnect,
1066 #ifdef CONFIG_PM
1067 .suspend = gspca_suspend,
1068 .resume = gspca_resume,
1069 .reset_resume = gspca_resume,
1070 #endif
1071 };
1072
1073 module_usb_driver(sd_driver);