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