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