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