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