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
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33#define QUALITY 85
34
35/* specific webcam descriptor */
36struct sd {
37	struct gspca_dev gspca_dev;	/* !! must be the first item */
38
39	bool autogain;
40
41	u8 bridge;
42#define BRIDGE_SPCA504 0
43#define BRIDGE_SPCA504B 1
44#define BRIDGE_SPCA504C 2
45#define BRIDGE_SPCA533 3
46#define BRIDGE_SPCA536 4
47	u8 subtype;
48#define AiptekMiniPenCam13 1
49#define LogitechClickSmart420 2
50#define LogitechClickSmart820 3
51#define MegapixV4 4
52#define MegaImageVI 5
53
54	u8 jpeg_hdr[JPEG_HDR_SZ];
55};
56
57static const struct v4l2_pix_format vga_mode[] = {
58	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
59		.bytesperline = 320,
60		.sizeimage = 320 * 240 * 3 / 8 + 590,
61		.colorspace = V4L2_COLORSPACE_JPEG,
62		.priv = 2},
63	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
64		.bytesperline = 640,
65		.sizeimage = 640 * 480 * 3 / 8 + 590,
66		.colorspace = V4L2_COLORSPACE_JPEG,
67		.priv = 1},
68};
69
70static const struct v4l2_pix_format custom_mode[] = {
71	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
72		.bytesperline = 320,
73		.sizeimage = 320 * 240 * 3 / 8 + 590,
74		.colorspace = V4L2_COLORSPACE_JPEG,
75		.priv = 2},
76	{464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
77		.bytesperline = 464,
78		.sizeimage = 464 * 480 * 3 / 8 + 590,
79		.colorspace = V4L2_COLORSPACE_JPEG,
80		.priv = 1},
81};
82
83static const struct v4l2_pix_format vga_mode2[] = {
84	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
85		.bytesperline = 176,
86		.sizeimage = 176 * 144 * 3 / 8 + 590,
87		.colorspace = V4L2_COLORSPACE_JPEG,
88		.priv = 4},
89	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
90		.bytesperline = 320,
91		.sizeimage = 320 * 240 * 3 / 8 + 590,
92		.colorspace = V4L2_COLORSPACE_JPEG,
93		.priv = 3},
94	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
95		.bytesperline = 352,
96		.sizeimage = 352 * 288 * 3 / 8 + 590,
97		.colorspace = V4L2_COLORSPACE_JPEG,
98		.priv = 2},
99	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100		.bytesperline = 640,
101		.sizeimage = 640 * 480 * 3 / 8 + 590,
102		.colorspace = V4L2_COLORSPACE_JPEG,
103		.priv = 1},
104};
105
106#define SPCA50X_OFFSET_DATA 10
107#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
108#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
109#define SPCA504_PCCAM600_OFFSET_MODE	 5
110#define SPCA504_PCCAM600_OFFSET_DATA	 14
111 /* Frame packet header offsets for the spca533 */
112#define SPCA533_OFFSET_DATA	16
113#define SPCA533_OFFSET_FRAMSEQ	15
114/* Frame packet header offsets for the spca536 */
115#define SPCA536_OFFSET_DATA	4
116#define SPCA536_OFFSET_FRAMSEQ	1
117
118struct cmd {
119	u8 req;
120	u16 val;
121	u16 idx;
122};
123
124/* Initialisation data for the Creative PC-CAM 600 */
125static const struct cmd spca504_pccam600_init_data[] = {
126/*	{0xa0, 0x0000, 0x0503},  * capture mode */
127	{0x00, 0x0000, 0x2000},
128	{0x00, 0x0013, 0x2301},
129	{0x00, 0x0003, 0x2000},
130	{0x00, 0x0001, 0x21ac},
131	{0x00, 0x0001, 0x21a6},
132	{0x00, 0x0000, 0x21a7},	/* brightness */
133	{0x00, 0x0020, 0x21a8},	/* contrast */
134	{0x00, 0x0001, 0x21ac},	/* sat/hue */
135	{0x00, 0x0000, 0x21ad},	/* hue */
136	{0x00, 0x001a, 0x21ae},	/* saturation */
137	{0x00, 0x0002, 0x21a3},	/* gamma */
138	{0x30, 0x0154, 0x0008},
139	{0x30, 0x0004, 0x0006},
140	{0x30, 0x0258, 0x0009},
141	{0x30, 0x0004, 0x0000},
142	{0x30, 0x0093, 0x0004},
143	{0x30, 0x0066, 0x0005},
144	{0x00, 0x0000, 0x2000},
145	{0x00, 0x0013, 0x2301},
146	{0x00, 0x0003, 0x2000},
147	{0x00, 0x0013, 0x2301},
148	{0x00, 0x0003, 0x2000},
149};
150
151/* Creative PC-CAM 600 specific open data, sent before using the
152 * generic initialisation data from spca504_open_data.
153 */
154static const struct cmd spca504_pccam600_open_data[] = {
155	{0x00, 0x0001, 0x2501},
156	{0x20, 0x0500, 0x0001},	/* snapshot mode */
157	{0x00, 0x0003, 0x2880},
158	{0x00, 0x0001, 0x2881},
159};
160
161/* Initialisation data for the logitech clicksmart 420 */
162static const struct cmd spca504A_clicksmart420_init_data[] = {
163/*	{0xa0, 0x0000, 0x0503},  * capture mode */
164	{0x00, 0x0000, 0x2000},
165	{0x00, 0x0013, 0x2301},
166	{0x00, 0x0003, 0x2000},
167	{0x00, 0x0001, 0x21ac},
168	{0x00, 0x0001, 0x21a6},
169	{0x00, 0x0000, 0x21a7},	/* brightness */
170	{0x00, 0x0020, 0x21a8},	/* contrast */
171	{0x00, 0x0001, 0x21ac},	/* sat/hue */
172	{0x00, 0x0000, 0x21ad},	/* hue */
173	{0x00, 0x001a, 0x21ae},	/* saturation */
174	{0x00, 0x0002, 0x21a3},	/* gamma */
175	{0x30, 0x0004, 0x000a},
176	{0xb0, 0x0001, 0x0000},
177
178	{0xa1, 0x0080, 0x0001},
179	{0x30, 0x0049, 0x0000},
180	{0x30, 0x0060, 0x0005},
181	{0x0c, 0x0004, 0x0000},
182	{0x00, 0x0000, 0x0000},
183	{0x00, 0x0000, 0x2000},
184	{0x00, 0x0013, 0x2301},
185	{0x00, 0x0003, 0x2000},
186};
187
188/* clicksmart 420 open data ? */
189static const struct cmd spca504A_clicksmart420_open_data[] = {
190	{0x00, 0x0001, 0x2501},
191	{0x20, 0x0502, 0x0000},
192	{0x06, 0x0000, 0x0000},
193	{0x00, 0x0004, 0x2880},
194	{0x00, 0x0001, 0x2881},
195
196	{0xa0, 0x0000, 0x0503},
197};
198
199static const u8 qtable_creative_pccam[2][64] = {
200	{				/* Q-table Y-components */
201	 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
202	 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
203	 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
204	 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
205	 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
206	 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
207	 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
208	 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
209	{				/* Q-table C-components */
210	 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
211	 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
212	 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213	 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
214	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
215	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
216	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
217	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
218};
219
220/* FIXME: This Q-table is identical to the Creative PC-CAM one,
221 *		except for one byte. Possibly a typo?
222 *		NWG: 18/05/2003.
223 */
224static const u8 qtable_spca504_default[2][64] = {
225	{				/* Q-table Y-components */
226	 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
227	 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
228	 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
229	 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
230	 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
231	 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
232	 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
233	 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
234	 },
235	{				/* Q-table C-components */
236	 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
237	 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
238	 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239	 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
240	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
241	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
242	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
243	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
244};
245
246/* read <len> bytes to gspca_dev->usb_buf */
247static void reg_r(struct gspca_dev *gspca_dev,
248		  u8 req,
249		  u16 index,
250		  u16 len)
251{
252	int ret;
253
254	if (len > USB_BUF_SZ) {
255		PERR("reg_r: buffer overflow\n");
256		return;
257	}
258	if (gspca_dev->usb_err < 0)
259		return;
260	ret = usb_control_msg(gspca_dev->dev,
261			usb_rcvctrlpipe(gspca_dev->dev, 0),
262			req,
263			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
264			0,		/* value */
265			index,
266			len ? gspca_dev->usb_buf : NULL, len,
267			500);
268	if (ret < 0) {
269		pr_err("reg_r err %d\n", ret);
270		gspca_dev->usb_err = ret;
271	}
272}
273
274/* write one byte */
275static void reg_w_1(struct gspca_dev *gspca_dev,
276		   u8 req,
277		   u16 value,
278		   u16 index,
279		   u16 byte)
280{
281	int ret;
282
283	if (gspca_dev->usb_err < 0)
284		return;
285	gspca_dev->usb_buf[0] = byte;
286	ret = usb_control_msg(gspca_dev->dev,
287			usb_sndctrlpipe(gspca_dev->dev, 0),
288			req,
289			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
290			value, index,
291			gspca_dev->usb_buf, 1,
292			500);
293	if (ret < 0) {
294		pr_err("reg_w_1 err %d\n", ret);
295		gspca_dev->usb_err = ret;
296	}
297}
298
299/* write req / index / value */
300static void reg_w_riv(struct gspca_dev *gspca_dev,
301		     u8 req, u16 index, u16 value)
302{
303	struct usb_device *dev = gspca_dev->dev;
304	int ret;
305
306	if (gspca_dev->usb_err < 0)
307		return;
308	ret = usb_control_msg(dev,
309			usb_sndctrlpipe(dev, 0),
310			req,
311			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312			value, index, NULL, 0, 500);
313	if (ret < 0) {
314		pr_err("reg_w_riv err %d\n", ret);
315		gspca_dev->usb_err = ret;
316		return;
317	}
318	PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
319		req, index, value);
320}
321
322static void write_vector(struct gspca_dev *gspca_dev,
323			const struct cmd *data, int ncmds)
324{
325	while (--ncmds >= 0) {
326		reg_w_riv(gspca_dev, data->req, data->idx, data->val);
327		data++;
328	}
329}
330
331static void setup_qtable(struct gspca_dev *gspca_dev,
332			const u8 qtable[2][64])
333{
334	int i;
335
336	/* loop over y components */
337	for (i = 0; i < 64; i++)
338		reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
339
340	/* loop over c components */
341	for (i = 0; i < 64; i++)
342		reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
343}
344
345static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
346			     u8 req, u16 idx, u16 val)
347{
348	reg_w_riv(gspca_dev, req, idx, val);
349	reg_r(gspca_dev, 0x01, 0x0001, 1);
350	PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
351	reg_w_riv(gspca_dev, req, idx, val);
352
353	msleep(200);
354	reg_r(gspca_dev, 0x01, 0x0001, 1);
355	PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
356}
357
358static void spca504_read_info(struct gspca_dev *gspca_dev)
359{
360	int i;
361	u8 info[6];
362
363	if (gspca_debug < D_STREAM)
364		return;
365
366	for (i = 0; i < 6; i++) {
367		reg_r(gspca_dev, 0, i, 1);
368		info[i] = gspca_dev->usb_buf[0];
369	}
370	PDEBUG(D_STREAM,
371		"Read info: %d %d %d %d %d %d."
372		" Should be 1,0,2,2,0,0",
373		info[0], info[1], info[2],
374		info[3], info[4], info[5]);
375}
376
377static 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
406static 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
418static 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
434static 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
449static 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
504static 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
518static 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
525static 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
534static 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
543static 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
552static 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 */
580static 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 */
632static 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
712static 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
795static 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
828static 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
922static 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
950static const struct v4l2_ctrl_ops sd_ctrl_ops = {
951	.s_ctrl = sd_s_ctrl,
952};
953
954static 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 */
977static 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)
991static 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};
1054MODULE_DEVICE_TABLE(usb, device_table);
1055
1056/* -- device connect -- */
1057static 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
1064static 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
1076module_usb_driver(sd_driver);
1077