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