]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/usb/gspca/sunplus.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / media / usb / gspca / sunplus.c
CommitLineData
6a7eba24
JFM
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.
6a7eba24
JFM
16 */
17
133a9fe9
JP
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
6a7eba24
JFM
20#define MODULE_NAME "sunplus"
21
22#include "gspca.h"
23#include "jpeg.h"
24
6a7eba24
JFM
25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
27MODULE_LICENSE("GPL");
28
b56ab4ca
HG
29#define QUALITY 85
30
6a7eba24
JFM
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
ed5cd6bb
HV
35 bool autogain;
36
2e1794b5 37 u8 bridge;
6a7eba24
JFM
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
2e1794b5 43 u8 subtype;
6a7eba24
JFM
44#define AiptekMiniPenCam13 1
45#define LogitechClickSmart420 2
46#define LogitechClickSmart820 3
47#define MegapixV4 4
af5f88c8 48#define MegaImageVI 5
71cb2764 49
9a731a32 50 u8 jpeg_hdr[JPEG_HDR_SZ];
6a7eba24
JFM
51};
52
cc611b8a 53static const struct v4l2_pix_format vga_mode[] = {
c2446b3e
JFM
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},
6a7eba24
JFM
64};
65
cc611b8a 66static const struct v4l2_pix_format custom_mode[] = {
c2446b3e
JFM
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},
6a7eba24
JFM
77};
78
cc611b8a 79static const struct v4l2_pix_format vga_mode2[] = {
c2446b3e
JFM
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},
6a7eba24
JFM
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 */
2e1794b5 108#define SPCA533_OFFSET_DATA 16
6a7eba24
JFM
109#define SPCA533_OFFSET_FRAMSEQ 15
110/* Frame packet header offsets for the spca536 */
2e1794b5
JFM
111#define SPCA536_OFFSET_DATA 4
112#define SPCA536_OFFSET_FRAMSEQ 1
113
114struct cmd {
115 u8 req;
116 u16 val;
117 u16 idx;
118};
6a7eba24
JFM
119
120/* Initialisation data for the Creative PC-CAM 600 */
2e1794b5 121static const struct cmd spca504_pccam600_init_data[] = {
6a7eba24
JFM
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},
6a7eba24
JFM
145};
146
147/* Creative PC-CAM 600 specific open data, sent before using the
148 * generic initialisation data from spca504_open_data.
149 */
2e1794b5 150static const struct cmd spca504_pccam600_open_data[] = {
6a7eba24
JFM
151 {0x00, 0x0001, 0x2501},
152 {0x20, 0x0500, 0x0001}, /* snapshot mode */
153 {0x00, 0x0003, 0x2880},
154 {0x00, 0x0001, 0x2881},
6a7eba24
JFM
155};
156
157/* Initialisation data for the logitech clicksmart 420 */
2e1794b5 158static const struct cmd spca504A_clicksmart420_init_data[] = {
6a7eba24
JFM
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
2e1794b5 174 {0xa1, 0x0080, 0x0001},
6a7eba24
JFM
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},
6a7eba24
JFM
182};
183
184/* clicksmart 420 open data ? */
2e1794b5 185static const struct cmd spca504A_clicksmart420_open_data[] = {
6a7eba24
JFM
186 {0x00, 0x0001, 0x2501},
187 {0x20, 0x0502, 0x0000},
188 {0x06, 0x0000, 0x0000},
189 {0x00, 0x0004, 0x2880},
190 {0x00, 0x0001, 0x2881},
6a7eba24
JFM
191
192 {0xa0, 0x0000, 0x0503},
6a7eba24
JFM
193};
194
2e1794b5 195static const u8 qtable_creative_pccam[2][64] = {
6a7eba24
JFM
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 */
2e1794b5 220static const u8 qtable_spca504_default[2][64] = {
6a7eba24
JFM
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
8295d99e
JFM
242/* read <len> bytes to gspca_dev->usb_buf */
243static void reg_r(struct gspca_dev *gspca_dev,
2e1794b5
JFM
244 u8 req,
245 u16 index,
246 u16 len)
6a7eba24 247{
ecb77686
JFM
248 int ret;
249
8295d99e 250 if (len > USB_BUF_SZ) {
c93396e1 251 PERR("reg_r: buffer overflow\n");
8295d99e
JFM
252 return;
253 }
ecb77686
JFM
254 if (gspca_dev->usb_err < 0)
255 return;
256 ret = usb_control_msg(gspca_dev->dev,
8295d99e 257 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
258 req,
259 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
260 0, /* value */
8295d99e
JFM
261 index,
262 len ? gspca_dev->usb_buf : NULL, len,
6a7eba24 263 500);
ecb77686 264 if (ret < 0) {
133a9fe9 265 pr_err("reg_r err %d\n", ret);
ecb77686
JFM
266 gspca_dev->usb_err = ret;
267 }
6a7eba24
JFM
268}
269
2e1794b5
JFM
270/* write one byte */
271static void reg_w_1(struct gspca_dev *gspca_dev,
272 u8 req,
273 u16 value,
274 u16 index,
275 u16 byte)
6a7eba24 276{
ecb77686
JFM
277 int ret;
278
279 if (gspca_dev->usb_err < 0)
280 return;
2e1794b5 281 gspca_dev->usb_buf[0] = byte;
ecb77686 282 ret = usb_control_msg(gspca_dev->dev,
8295d99e 283 usb_sndctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
284 req,
285 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
8295d99e 286 value, index,
2e1794b5 287 gspca_dev->usb_buf, 1,
6a7eba24 288 500);
ecb77686 289 if (ret < 0) {
133a9fe9 290 pr_err("reg_w_1 err %d\n", ret);
ecb77686
JFM
291 gspca_dev->usb_err = ret;
292 }
6a7eba24
JFM
293}
294
739570bb 295/* write req / index / value */
ecb77686 296static void reg_w_riv(struct gspca_dev *gspca_dev,
2e1794b5 297 u8 req, u16 index, u16 value)
6a7eba24 298{
ecb77686 299 struct usb_device *dev = gspca_dev->dev;
6a7eba24
JFM
300 int ret;
301
ecb77686
JFM
302 if (gspca_dev->usb_err < 0)
303 return;
6a7eba24
JFM
304 ret = usb_control_msg(dev,
305 usb_sndctrlpipe(dev, 0),
306 req,
bf7f0b98 307 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6a7eba24 308 value, index, NULL, 0, 500);
ecb77686 309 if (ret < 0) {
133a9fe9 310 pr_err("reg_w_riv err %d\n", ret);
ecb77686
JFM
311 gspca_dev->usb_err = ret;
312 return;
313 }
314 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
315 req, index, value);
6a7eba24
JFM
316}
317
ecb77686 318static void write_vector(struct gspca_dev *gspca_dev,
2e1794b5 319 const struct cmd *data, int ncmds)
6a7eba24 320{
2e1794b5 321 while (--ncmds >= 0) {
ecb77686 322 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
2e1794b5 323 data++;
6a7eba24 324 }
6a7eba24
JFM
325}
326
ecb77686
JFM
327static void setup_qtable(struct gspca_dev *gspca_dev,
328 const u8 qtable[2][64])
6a7eba24 329{
ecb77686 330 int i;
6a7eba24
JFM
331
332 /* loop over y components */
ecb77686 333 for (i = 0; i < 64; i++)
780e3121 334 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
6a7eba24
JFM
335
336 /* loop over c components */
ecb77686
JFM
337 for (i = 0; i < 64; i++)
338 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
6a7eba24
JFM
339}
340
341static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
2e1794b5 342 u8 req, u16 idx, u16 val)
6a7eba24 343{
ecb77686 344 reg_w_riv(gspca_dev, req, idx, val);
cf252206
JFM
345 reg_r(gspca_dev, 0x01, 0x0001, 1);
346 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
ecb77686 347 reg_w_riv(gspca_dev, req, idx, val);
6a7eba24 348
6a7eba24 349 msleep(200);
cf252206
JFM
350 reg_r(gspca_dev, 0x01, 0x0001, 1);
351 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
6a7eba24
JFM
352}
353
6f081264
JFM
354static void spca504_read_info(struct gspca_dev *gspca_dev)
355{
356 int i;
357 u8 info[6];
358
c93396e1
TK
359 if (gspca_debug < D_STREAM)
360 return;
361
cf252206
JFM
362 for (i = 0; i < 6; i++) {
363 reg_r(gspca_dev, 0, i, 1);
364 info[i] = gspca_dev->usb_buf[0];
365 }
6f081264 366 PDEBUG(D_STREAM,
1ddc9f75 367 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0",
6f081264
JFM
368 info[0], info[1], info[2],
369 info[3], info[4], info[5]);
370}
371
6a7eba24 372static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
2e1794b5 373 u8 req,
cf252206 374 u16 idx, u16 val, u8 endcode, u8 count)
6a7eba24 375{
ecb77686 376 u16 status;
6a7eba24 377
ecb77686 378 reg_w_riv(gspca_dev, req, idx, val);
cf252206 379 reg_r(gspca_dev, 0x01, 0x0001, 1);
ecb77686
JFM
380 if (gspca_dev->usb_err < 0)
381 return;
cf252206
JFM
382 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
383 gspca_dev->usb_buf[0], endcode);
6a7eba24
JFM
384 if (!count)
385 return;
386 count = 200;
387 while (--count > 0) {
388 msleep(10);
af901ca1 389 /* gsmart mini2 write a each wait setting 1 ms is enough */
ecb77686 390/* reg_w_riv(gspca_dev, req, idx, val); */
cf252206
JFM
391 reg_r(gspca_dev, 0x01, 0x0001, 1);
392 status = gspca_dev->usb_buf[0];
6a7eba24 393 if (status == endcode) {
2e1794b5 394 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
6a7eba24
JFM
395 status, 200 - count);
396 break;
397 }
398 }
399}
400
ecb77686 401static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
6a7eba24 402{
6a7eba24
JFM
403 int count = 10;
404
405 while (--count > 0) {
8295d99e 406 reg_r(gspca_dev, 0x21, 0, 1);
739570bb 407 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
6a7eba24
JFM
408 break;
409 msleep(10);
410 }
6a7eba24
JFM
411}
412
413static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
414{
6a7eba24
JFM
415 int count = 50;
416
417 while (--count > 0) {
8295d99e 418 reg_r(gspca_dev, 0x21, 1, 1);
739570bb 419 if (gspca_dev->usb_buf[0] != 0) {
2e1794b5 420 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
8295d99e 421 reg_r(gspca_dev, 0x21, 1, 1);
739570bb 422 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
423 break;
424 }
425 msleep(10);
426 }
427}
428
429static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
430{
2e1794b5 431 u8 *data;
6a7eba24 432
c93396e1
TK
433 if (gspca_debug < D_STREAM)
434 return;
435
8295d99e
JFM
436 data = gspca_dev->usb_buf;
437 reg_r(gspca_dev, 0x20, 0, 5);
cf252206 438 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
739570bb 439 data[0], data[1], data[2], data[3], data[4]);
8295d99e
JFM
440 reg_r(gspca_dev, 0x23, 0, 64);
441 reg_r(gspca_dev, 0x23, 1, 64);
6a7eba24
JFM
442}
443
444static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
445{
446 struct sd *sd = (struct sd *) gspca_dev;
2e1794b5 447 u8 Size;
6a7eba24 448
2e1794b5 449 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6a7eba24
JFM
450 switch (sd->bridge) {
451 case BRIDGE_SPCA533:
ecb77686 452 reg_w_riv(gspca_dev, 0x31, 0, 0);
6a7eba24 453 spca504B_WaitCmdStatus(gspca_dev);
ecb77686 454 spca504B_PollingDataReady(gspca_dev);
6a7eba24 455 spca50x_GetFirmware(gspca_dev);
c93396e1 456
2e1794b5 457 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
8295d99e 458 reg_r(gspca_dev, 0x24, 8, 1);
6a7eba24 459
2e1794b5 460 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
8295d99e 461 reg_r(gspca_dev, 0x25, 4, 1); /* size */
ecb77686 462 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
463
464 /* Init the cam width height with some values get on init ? */
07d1c69b 465 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
6a7eba24 466 spca504B_WaitCmdStatus(gspca_dev);
ecb77686 467 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
468 break;
469 default:
470/* case BRIDGE_SPCA504B: */
471/* case BRIDGE_SPCA536: */
2e1794b5 472 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
8295d99e 473 reg_r(gspca_dev, 0x25, 4, 1); /* size */
2e1794b5 474 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
8295d99e 475 reg_r(gspca_dev, 0x27, 0, 1); /* type */
ecb77686 476 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
477 break;
478 case BRIDGE_SPCA504:
479 Size += 3;
480 if (sd->subtype == AiptekMiniPenCam13) {
481 /* spca504a aiptek */
482 spca504A_acknowledged_command(gspca_dev,
483 0x08, Size, 0,
484 0x80 | (Size & 0x0f), 1);
485 spca504A_acknowledged_command(gspca_dev,
486 1, 3, 0, 0x9f, 0);
487 } else {
488 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
489 }
490 break;
491 case BRIDGE_SPCA504C:
492 /* capture mode */
ecb77686
JFM
493 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
494 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
6a7eba24
JFM
495 break;
496 }
497}
498
499static void spca504_wait_status(struct gspca_dev *gspca_dev)
500{
6a7eba24
JFM
501 int cnt;
502
503 cnt = 256;
504 while (--cnt > 0) {
505 /* With this we get the status, when return 0 it's all ok */
cf252206
JFM
506 reg_r(gspca_dev, 0x06, 0x00, 1);
507 if (gspca_dev->usb_buf[0] == 0)
6a7eba24
JFM
508 return;
509 msleep(10);
510 }
511}
512
513static void spca504B_setQtable(struct gspca_dev *gspca_dev)
514{
2e1794b5 515 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
8295d99e 516 reg_r(gspca_dev, 0x26, 0, 1);
739570bb 517 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
518}
519
ed5cd6bb 520static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
2e1794b5
JFM
521{
522 struct sd *sd = (struct sd *) gspca_dev;
2e1794b5
JFM
523 u16 reg;
524
525 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
ed5cd6bb 526 reg_w_riv(gspca_dev, 0x00, reg, val);
2e1794b5
JFM
527}
528
ed5cd6bb 529static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
6a7eba24
JFM
530{
531 struct sd *sd = (struct sd *) gspca_dev;
2e1794b5
JFM
532 u16 reg;
533
534 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
ed5cd6bb 535 reg_w_riv(gspca_dev, 0x00, reg, val);
2e1794b5
JFM
536}
537
ed5cd6bb 538static void setcolors(struct gspca_dev *gspca_dev, s32 val)
2e1794b5
JFM
539{
540 struct sd *sd = (struct sd *) gspca_dev;
2e1794b5
JFM
541 u16 reg;
542
543 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
ed5cd6bb 544 reg_w_riv(gspca_dev, 0x00, reg, val);
2e1794b5
JFM
545}
546
547static void init_ctl_reg(struct gspca_dev *gspca_dev)
548{
549 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
550 int pollreg = 1;
551
552 switch (sd->bridge) {
553 case BRIDGE_SPCA504:
554 case BRIDGE_SPCA504C:
555 pollreg = 0;
556 /* fall thru */
557 default:
558/* case BRIDGE_SPCA533: */
559/* case BRIDGE_SPCA504B: */
07d1c69b
JFM
560 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
561 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
562 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
6a7eba24
JFM
563 break;
564 case BRIDGE_SPCA536:
07d1c69b
JFM
565 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
566 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
567 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
6a7eba24
JFM
568 break;
569 }
570 if (pollreg)
739570bb 571 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
572}
573
574/* this function is called at probe time */
575static int sd_config(struct gspca_dev *gspca_dev,
576 const struct usb_device_id *id)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 579 struct cam *cam;
9d64fdb1
JFM
580
581 cam = &gspca_dev->cam;
9d64fdb1
JFM
582
583 sd->bridge = id->driver_info >> 8;
584 sd->subtype = id->driver_info;
585
586 if (sd->subtype == AiptekMiniPenCam13) {
780e3121
JFM
587
588 /* try to get the firmware as some cam answer 2.0.1.2.2
589 * and should be a spca504b then overwrite that setting */
8295d99e 590 reg_r(gspca_dev, 0x20, 0, 1);
9d64fdb1
JFM
591 switch (gspca_dev->usb_buf[0]) {
592 case 1:
593 break; /* (right bridge/subtype) */
594 case 2:
6a7eba24 595 sd->bridge = BRIDGE_SPCA504B;
9d64fdb1 596 sd->subtype = 0;
6a7eba24 597 break;
9d64fdb1
JFM
598 default:
599 return -ENODEV;
6a7eba24 600 }
6a7eba24
JFM
601 }
602
6a7eba24
JFM
603 switch (sd->bridge) {
604 default:
605/* case BRIDGE_SPCA504B: */
606/* case BRIDGE_SPCA504: */
607/* case BRIDGE_SPCA536: */
608 cam->cam_mode = vga_mode;
780e3121 609 cam->nmodes = ARRAY_SIZE(vga_mode);
6a7eba24
JFM
610 break;
611 case BRIDGE_SPCA533:
612 cam->cam_mode = custom_mode;
af5f88c8
JG
613 if (sd->subtype == MegaImageVI) /* 320x240 only */
614 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
615 else
616 cam->nmodes = ARRAY_SIZE(custom_mode);
6a7eba24
JFM
617 break;
618 case BRIDGE_SPCA504C:
619 cam->cam_mode = vga_mode2;
d6f76b97 620 cam->nmodes = ARRAY_SIZE(vga_mode2);
6a7eba24
JFM
621 break;
622 }
6a7eba24
JFM
623 return 0;
624}
625
012d6b02
JFM
626/* this function is called at probe and resume time */
627static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24
JFM
628{
629 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
630
631 switch (sd->bridge) {
632 case BRIDGE_SPCA504B:
ecb77686 633 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
07d1c69b
JFM
634 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
635 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
636 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
637 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
638 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
6a7eba24
JFM
639 /* fall thru */
640 case BRIDGE_SPCA533:
2e1794b5 641 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
642 spca50x_GetFirmware(gspca_dev);
643 break;
644 case BRIDGE_SPCA536:
645 spca50x_GetFirmware(gspca_dev);
8295d99e 646 reg_r(gspca_dev, 0x00, 0x5002, 1);
2e1794b5 647 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
8295d99e 648 reg_r(gspca_dev, 0x24, 0, 1);
2e1794b5 649 spca504B_PollingDataReady(gspca_dev);
ecb77686 650 reg_w_riv(gspca_dev, 0x34, 0, 0);
6a7eba24
JFM
651 spca504B_WaitCmdStatus(gspca_dev);
652 break;
653 case BRIDGE_SPCA504C: /* pccam600 */
654 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
ecb77686
JFM
655 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
656 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
6a7eba24
JFM
657 spca504_wait_status(gspca_dev);
658 if (sd->subtype == LogitechClickSmart420)
659 write_vector(gspca_dev,
2e1794b5
JFM
660 spca504A_clicksmart420_open_data,
661 ARRAY_SIZE(spca504A_clicksmart420_open_data));
6a7eba24 662 else
2e1794b5
JFM
663 write_vector(gspca_dev, spca504_pccam600_open_data,
664 ARRAY_SIZE(spca504_pccam600_open_data));
ecb77686 665 setup_qtable(gspca_dev, qtable_creative_pccam);
6a7eba24
JFM
666 break;
667 default:
668/* case BRIDGE_SPCA504: */
669 PDEBUG(D_STREAM, "Opening SPCA504");
670 if (sd->subtype == AiptekMiniPenCam13) {
6f081264
JFM
671 spca504_read_info(gspca_dev);
672
6a7eba24
JFM
673 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
674 spca504A_acknowledged_command(gspca_dev, 0x24,
675 8, 3, 0x9e, 1);
b27d63d8 676 /* Twice sequential need status 0xff->0x9e->0x9d */
6a7eba24
JFM
677 spca504A_acknowledged_command(gspca_dev, 0x24,
678 8, 3, 0x9e, 0);
679
680 spca504A_acknowledged_command(gspca_dev, 0x24,
681 0, 0, 0x9d, 1);
682 /******************************/
683 /* spca504a aiptek */
684 spca504A_acknowledged_command(gspca_dev, 0x08,
685 6, 0, 0x86, 1);
686/* reg_write (dev, 0, 0x2000, 0); */
687/* reg_write (dev, 0, 0x2883, 1); */
688/* spca504A_acknowledged_command (gspca_dev, 0x08,
689 6, 0, 0x86, 1); */
690/* spca504A_acknowledged_command (gspca_dev, 0x24,
691 0, 0, 0x9D, 1); */
ecb77686
JFM
692 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
693 /* L92 sno1t.txt */
694 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
6a7eba24
JFM
695 spca504A_acknowledged_command(gspca_dev, 0x01,
696 0x0f, 0, 0xff, 0);
697 }
698 /* setup qtable */
ecb77686
JFM
699 reg_w_riv(gspca_dev, 0, 0x2000, 0);
700 reg_w_riv(gspca_dev, 0, 0x2883, 1);
701 setup_qtable(gspca_dev, qtable_spca504_default);
6a7eba24
JFM
702 break;
703 }
ecb77686 704 return gspca_dev->usb_err;
6a7eba24
JFM
705}
706
72ab97ce 707static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24
JFM
708{
709 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 710 int enable;
6a7eba24 711
71cb2764 712 /* create the JPEG header */
1966bc2a
OZ
713 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
714 gspca_dev->pixfmt.width,
71cb2764 715 0x22); /* JPEG 411 */
b56ab4ca 716 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
71cb2764 717
6a7eba24
JFM
718 if (sd->bridge == BRIDGE_SPCA504B)
719 spca504B_setQtable(gspca_dev);
720 spca504B_SetSizeType(gspca_dev);
721 switch (sd->bridge) {
722 default:
723/* case BRIDGE_SPCA504B: */
724/* case BRIDGE_SPCA533: */
725/* case BRIDGE_SPCA536: */
2e1794b5
JFM
726 switch (sd->subtype) {
727 case MegapixV4:
728 case LogitechClickSmart820:
729 case MegaImageVI:
ecb77686 730 reg_w_riv(gspca_dev, 0xf0, 0, 0);
6a7eba24 731 spca504B_WaitCmdStatus(gspca_dev);
8295d99e 732 reg_r(gspca_dev, 0xf0, 4, 0);
6a7eba24 733 spca504B_WaitCmdStatus(gspca_dev);
2e1794b5
JFM
734 break;
735 default:
07d1c69b 736 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
6a7eba24 737 spca504B_WaitCmdStatus(gspca_dev);
2e1794b5
JFM
738 spca504B_PollingDataReady(gspca_dev);
739 break;
6a7eba24
JFM
740 }
741 break;
742 case BRIDGE_SPCA504:
743 if (sd->subtype == AiptekMiniPenCam13) {
6f081264
JFM
744 spca504_read_info(gspca_dev);
745
6a7eba24
JFM
746 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
747 spca504A_acknowledged_command(gspca_dev, 0x24,
748 8, 3, 0x9e, 1);
b27d63d8 749 /* Twice sequential need status 0xff->0x9e->0x9d */
6a7eba24
JFM
750 spca504A_acknowledged_command(gspca_dev, 0x24,
751 8, 3, 0x9e, 0);
752 spca504A_acknowledged_command(gspca_dev, 0x24,
753 0, 0, 0x9d, 1);
754 } else {
755 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
6f081264 756 spca504_read_info(gspca_dev);
6a7eba24
JFM
757 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
758 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
759 }
760 spca504B_SetSizeType(gspca_dev);
ecb77686
JFM
761 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
762 /* L92 sno1t.txt */
763 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
6a7eba24
JFM
764 break;
765 case BRIDGE_SPCA504C:
766 if (sd->subtype == LogitechClickSmart420) {
767 write_vector(gspca_dev,
2e1794b5
JFM
768 spca504A_clicksmart420_init_data,
769 ARRAY_SIZE(spca504A_clicksmart420_init_data));
6a7eba24 770 } else {
2e1794b5
JFM
771 write_vector(gspca_dev, spca504_pccam600_init_data,
772 ARRAY_SIZE(spca504_pccam600_init_data));
6a7eba24 773 }
739570bb 774 enable = (sd->autogain ? 0x04 : 0x01);
ecb77686
JFM
775 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
776 /* auto exposure */
777 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
778 /* auto whiteness */
6a7eba24
JFM
779
780 /* set default exposure compensation and whiteness balance */
ecb77686
JFM
781 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
782 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
6a7eba24
JFM
783 spca504B_SetSizeType(gspca_dev);
784 break;
785 }
2e1794b5 786 init_ctl_reg(gspca_dev);
ecb77686 787 return gspca_dev->usb_err;
6a7eba24
JFM
788}
789
790static void sd_stopN(struct gspca_dev *gspca_dev)
791{
792 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
793
794 switch (sd->bridge) {
795 default:
796/* case BRIDGE_SPCA533: */
797/* case BRIDGE_SPCA536: */
798/* case BRIDGE_SPCA504B: */
ecb77686 799 reg_w_riv(gspca_dev, 0x31, 0, 0);
6a7eba24 800 spca504B_WaitCmdStatus(gspca_dev);
739570bb 801 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
802 break;
803 case BRIDGE_SPCA504:
804 case BRIDGE_SPCA504C:
ecb77686 805 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
6a7eba24
JFM
806
807 if (sd->subtype == AiptekMiniPenCam13) {
808 /* spca504a aiptek */
809/* spca504A_acknowledged_command(gspca_dev, 0x08,
810 6, 0, 0x86, 1); */
811 spca504A_acknowledged_command(gspca_dev, 0x24,
812 0x00, 0x00, 0x9d, 1);
813 spca504A_acknowledged_command(gspca_dev, 0x01,
814 0x0f, 0x00, 0xff, 1);
815 } else {
816 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
ecb77686 817 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
6a7eba24
JFM
818 }
819 break;
820 }
821}
822
6a7eba24 823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2e1794b5 824 u8 *data, /* isoc packet */
6a7eba24
JFM
825 int len) /* iso packet length */
826{
827 struct sd *sd = (struct sd *) gspca_dev;
828 int i, sof = 0;
2e1794b5 829 static u8 ffd9[] = {0xff, 0xd9};
6a7eba24
JFM
830
831/* frames are jpeg 4.1.1 without 0xff escape */
832 switch (sd->bridge) {
833 case BRIDGE_SPCA533:
834 if (data[0] == 0xff) {
835 if (data[1] != 0x01) { /* drop packet */
836/* gspca_dev->last_packet_type = DISCARD_PACKET; */
837 return;
838 }
839 sof = 1;
840 data += SPCA533_OFFSET_DATA;
841 len -= SPCA533_OFFSET_DATA;
842 } else {
843 data += 1;
844 len -= 1;
845 }
846 break;
847 case BRIDGE_SPCA536:
848 if (data[0] == 0xff) {
849 sof = 1;
850 data += SPCA536_OFFSET_DATA;
851 len -= SPCA536_OFFSET_DATA;
852 } else {
853 data += 2;
854 len -= 2;
855 }
856 break;
857 default:
858/* case BRIDGE_SPCA504: */
859/* case BRIDGE_SPCA504B: */
860 switch (data[0]) {
861 case 0xfe: /* start of frame */
862 sof = 1;
863 data += SPCA50X_OFFSET_DATA;
864 len -= SPCA50X_OFFSET_DATA;
865 break;
866 case 0xff: /* drop packet */
867/* gspca_dev->last_packet_type = DISCARD_PACKET; */
868 return;
869 default:
870 data += 1;
871 len -= 1;
872 break;
873 }
874 break;
875 case BRIDGE_SPCA504C:
876 switch (data[0]) {
877 case 0xfe: /* start of frame */
878 sof = 1;
879 data += SPCA504_PCCAM600_OFFSET_DATA;
880 len -= SPCA504_PCCAM600_OFFSET_DATA;
881 break;
882 case 0xff: /* drop packet */
883/* gspca_dev->last_packet_type = DISCARD_PACKET; */
884 return;
885 default:
886 data += 1;
887 len -= 1;
888 break;
889 }
890 break;
891 }
892 if (sof) { /* start of frame */
76dd272b
JFM
893 gspca_frame_add(gspca_dev, LAST_PACKET,
894 ffd9, 2);
6a7eba24
JFM
895
896 /* put the JPEG header in the new frame */
76dd272b 897 gspca_frame_add(gspca_dev, FIRST_PACKET,
71cb2764 898 sd->jpeg_hdr, JPEG_HDR_SZ);
6a7eba24
JFM
899 }
900
901 /* add 0x00 after 0xff */
59746e13
JFM
902 i = 0;
903 do {
904 if (data[i] == 0xff) {
76dd272b 905 gspca_frame_add(gspca_dev, INTER_PACKET,
59746e13
JFM
906 data, i + 1);
907 len -= i;
908 data += i;
909 *data = 0x00;
910 i = 0;
911 }
912 i++;
913 } while (i < len);
76dd272b 914 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
915}
916
ed5cd6bb 917static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
6a7eba24 918{
ed5cd6bb
HV
919 struct gspca_dev *gspca_dev =
920 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
921 struct sd *sd = (struct sd *)gspca_dev;
6a7eba24 922
ed5cd6bb 923 gspca_dev->usb_err = 0;
6a7eba24 924
ed5cd6bb
HV
925 if (!gspca_dev->streaming)
926 return 0;
77ac0baf 927
ed5cd6bb
HV
928 switch (ctrl->id) {
929 case V4L2_CID_BRIGHTNESS:
930 setbrightness(gspca_dev, ctrl->val);
931 break;
932 case V4L2_CID_CONTRAST:
933 setcontrast(gspca_dev, ctrl->val);
934 break;
935 case V4L2_CID_SATURATION:
936 setcolors(gspca_dev, ctrl->val);
937 break;
938 case V4L2_CID_AUTOGAIN:
939 sd->autogain = ctrl->val;
940 break;
ed5cd6bb 941 }
ecb77686 942 return gspca_dev->usb_err;
77ac0baf
JFM
943}
944
ed5cd6bb
HV
945static const struct v4l2_ctrl_ops sd_ctrl_ops = {
946 .s_ctrl = sd_s_ctrl,
947};
77ac0baf 948
ed5cd6bb
HV
949static int sd_init_controls(struct gspca_dev *gspca_dev)
950{
ed5cd6bb
HV
951 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
952
953 gspca_dev->vdev.ctrl_handler = hdl;
b56ab4ca 954 v4l2_ctrl_handler_init(hdl, 4);
ed5cd6bb
HV
955 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
956 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
957 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
958 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
959 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
960 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
961 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
962 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
ed5cd6bb
HV
963
964 if (hdl->error) {
965 pr_err("Could not initialize controls\n");
966 return hdl->error;
967 }
77ac0baf
JFM
968 return 0;
969}
970
6a7eba24 971/* sub-driver description */
a5ae2062 972static const struct sd_desc sd_desc = {
6a7eba24 973 .name = MODULE_NAME,
6a7eba24 974 .config = sd_config,
012d6b02 975 .init = sd_init,
ed5cd6bb 976 .init_controls = sd_init_controls,
6a7eba24
JFM
977 .start = sd_start,
978 .stopN = sd_stopN,
6a7eba24
JFM
979 .pkt_scan = sd_pkt_scan,
980};
981
982/* -- module initialisation -- */
9d64fdb1
JFM
983#define BS(bridge, subtype) \
984 .driver_info = (BRIDGE_ ## bridge << 8) \
985 | (subtype)
95c967c1 986static const struct usb_device_id device_table[] = {
9d64fdb1
JFM
987 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
988 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
989 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
990 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
991 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
992 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
993 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
994 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
995 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
996 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
997 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
998 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
999 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1000 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1001 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1002 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1003 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1004 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
d41592a2 1005 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
9d64fdb1 1006 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
af5f88c8 1007 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
9d64fdb1
JFM
1008 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1009 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1010 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1011 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1012 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1013 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1014 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1015 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1016 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1017 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1018 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1019 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1020 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1021 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1022 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1023 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1024 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
858559a2 1025 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
9d64fdb1
JFM
1026 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1027 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1028 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1030 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1031 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1032 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1033 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1034 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1035 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1037 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1038 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1039 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1040 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1041 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1042 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1043 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1044 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1045 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1046 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
6a7eba24
JFM
1047 {}
1048};
1049MODULE_DEVICE_TABLE(usb, device_table);
1050
1051/* -- device connect -- */
1052static int sd_probe(struct usb_interface *intf,
1053 const struct usb_device_id *id)
1054{
1055 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1056 THIS_MODULE);
1057}
1058
1059static struct usb_driver sd_driver = {
1060 .name = MODULE_NAME,
1061 .id_table = device_table,
1062 .probe = sd_probe,
1063 .disconnect = gspca_disconnect,
6a709749
JFM
1064#ifdef CONFIG_PM
1065 .suspend = gspca_suspend,
1066 .resume = gspca_resume,
8bb58964 1067 .reset_resume = gspca_resume,
6a709749 1068#endif
6a7eba24
JFM
1069};
1070
ecb3b2b3 1071module_usb_driver(sd_driver);