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