• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/gspca/
1/*
2 *		Connexant Cx11646 library
3 *		Copyright (C) 2004 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 MODULE_NAME "conex"
23
24#include "gspca.h"
25#define CONEX_CAM 1		/* special JPEG header */
26#include "jpeg.h"
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34	struct gspca_dev gspca_dev;	/* !! must be the first item */
35
36	unsigned char brightness;
37	unsigned char contrast;
38	unsigned char colors;
39	u8 quality;
40#define QUALITY_MIN 30
41#define QUALITY_MAX 60
42#define QUALITY_DEF 40
43
44	u8 jpeg_hdr[JPEG_HDR_SZ];
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
54
55static const struct ctrl sd_ctrls[] = {
56	{
57	    {
58		.id	 = V4L2_CID_BRIGHTNESS,
59		.type	 = V4L2_CTRL_TYPE_INTEGER,
60		.name	 = "Brightness",
61		.minimum = 0,
62		.maximum = 255,
63		.step	 = 1,
64#define BRIGHTNESS_DEF 0xd4
65		.default_value = BRIGHTNESS_DEF,
66	    },
67	    .set = sd_setbrightness,
68	    .get = sd_getbrightness,
69	},
70	{
71	    {
72		.id      = V4L2_CID_CONTRAST,
73		.type    = V4L2_CTRL_TYPE_INTEGER,
74		.name    = "Contrast",
75		.minimum = 0x0a,
76		.maximum = 0x1f,
77		.step    = 1,
78#define CONTRAST_DEF 0x0c
79		.default_value = CONTRAST_DEF,
80	    },
81	    .set = sd_setcontrast,
82	    .get = sd_getcontrast,
83	},
84	{
85	    {
86		.id      = V4L2_CID_SATURATION,
87		.type    = V4L2_CTRL_TYPE_INTEGER,
88		.name    = "Color",
89		.minimum = 0,
90		.maximum = 7,
91		.step    = 1,
92#define COLOR_DEF 3
93		.default_value = COLOR_DEF,
94	    },
95	    .set = sd_setcolors,
96	    .get = sd_getcolors,
97	},
98};
99
100static const struct v4l2_pix_format vga_mode[] = {
101	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
102		.bytesperline = 176,
103		.sizeimage = 176 * 144 * 3 / 8 + 590,
104		.colorspace = V4L2_COLORSPACE_JPEG,
105		.priv = 3},
106	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
107		.bytesperline = 320,
108		.sizeimage = 320 * 240 * 3 / 8 + 590,
109		.colorspace = V4L2_COLORSPACE_JPEG,
110		.priv = 2},
111	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
112		.bytesperline = 352,
113		.sizeimage = 352 * 288 * 3 / 8 + 590,
114		.colorspace = V4L2_COLORSPACE_JPEG,
115		.priv = 1},
116	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117		.bytesperline = 640,
118		.sizeimage = 640 * 480 * 3 / 8 + 590,
119		.colorspace = V4L2_COLORSPACE_JPEG,
120		.priv = 0},
121};
122
123/* the read bytes are found in gspca_dev->usb_buf */
124static void reg_r(struct gspca_dev *gspca_dev,
125		  __u16 index,
126		  __u16 len)
127{
128	struct usb_device *dev = gspca_dev->dev;
129
130#ifdef GSPCA_DEBUG
131	if (len > USB_BUF_SZ) {
132		err("reg_r: buffer overflow");
133		return;
134	}
135#endif
136	usb_control_msg(dev,
137			usb_rcvctrlpipe(dev, 0),
138			0,
139			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
140			0,
141			index, gspca_dev->usb_buf, len,
142			500);
143	PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
144			index, gspca_dev->usb_buf[0]);
145}
146
147/* the bytes to write are in gspca_dev->usb_buf */
148static void reg_w_val(struct gspca_dev *gspca_dev,
149			__u16 index,
150			__u8 val)
151{
152	struct usb_device *dev = gspca_dev->dev;
153
154	gspca_dev->usb_buf[0] = val;
155	usb_control_msg(dev,
156			usb_sndctrlpipe(dev, 0),
157			0,
158			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159			0,
160			index, gspca_dev->usb_buf, 1, 500);
161}
162
163static void reg_w(struct gspca_dev *gspca_dev,
164		  __u16 index,
165		  const __u8 *buffer,
166		  __u16 len)
167{
168	struct usb_device *dev = gspca_dev->dev;
169
170#ifdef GSPCA_DEBUG
171	if (len > USB_BUF_SZ) {
172		err("reg_w: buffer overflow");
173		return;
174	}
175	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
176#endif
177	memcpy(gspca_dev->usb_buf, buffer, len);
178	usb_control_msg(dev,
179			usb_sndctrlpipe(dev, 0),
180			0,
181			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
182			0,
183			index, gspca_dev->usb_buf, len, 500);
184}
185
186static const __u8 cx_sensor_init[][4] = {
187	{0x88, 0x11, 0x01, 0x01},
188	{0x88, 0x12, 0x70, 0x01},
189	{0x88, 0x0f, 0x00, 0x01},
190	{0x88, 0x05, 0x01, 0x01},
191	{}
192};
193
194static const __u8 cx11646_fw1[][3] = {
195	{0x00, 0x02, 0x00},
196	{0x01, 0x43, 0x00},
197	{0x02, 0xA7, 0x00},
198	{0x03, 0x8B, 0x01},
199	{0x04, 0xE9, 0x02},
200	{0x05, 0x08, 0x04},
201	{0x06, 0x08, 0x05},
202	{0x07, 0x07, 0x06},
203	{0x08, 0xE7, 0x06},
204	{0x09, 0xC6, 0x07},
205	{0x0A, 0x86, 0x08},
206	{0x0B, 0x46, 0x09},
207	{0x0C, 0x05, 0x0A},
208	{0x0D, 0xA5, 0x0A},
209	{0x0E, 0x45, 0x0B},
210	{0x0F, 0xE5, 0x0B},
211	{0x10, 0x85, 0x0C},
212	{0x11, 0x25, 0x0D},
213	{0x12, 0xC4, 0x0D},
214	{0x13, 0x45, 0x0E},
215	{0x14, 0xE4, 0x0E},
216	{0x15, 0x64, 0x0F},
217	{0x16, 0xE4, 0x0F},
218	{0x17, 0x64, 0x10},
219	{0x18, 0xE4, 0x10},
220	{0x19, 0x64, 0x11},
221	{0x1A, 0xE4, 0x11},
222	{0x1B, 0x64, 0x12},
223	{0x1C, 0xE3, 0x12},
224	{0x1D, 0x44, 0x13},
225	{0x1E, 0xC3, 0x13},
226	{0x1F, 0x24, 0x14},
227	{0x20, 0xA3, 0x14},
228	{0x21, 0x04, 0x15},
229	{0x22, 0x83, 0x15},
230	{0x23, 0xE3, 0x15},
231	{0x24, 0x43, 0x16},
232	{0x25, 0xA4, 0x16},
233	{0x26, 0x23, 0x17},
234	{0x27, 0x83, 0x17},
235	{0x28, 0xE3, 0x17},
236	{0x29, 0x43, 0x18},
237	{0x2A, 0xA3, 0x18},
238	{0x2B, 0x03, 0x19},
239	{0x2C, 0x63, 0x19},
240	{0x2D, 0xC3, 0x19},
241	{0x2E, 0x22, 0x1A},
242	{0x2F, 0x63, 0x1A},
243	{0x30, 0xC3, 0x1A},
244	{0x31, 0x23, 0x1B},
245	{0x32, 0x83, 0x1B},
246	{0x33, 0xE2, 0x1B},
247	{0x34, 0x23, 0x1C},
248	{0x35, 0x83, 0x1C},
249	{0x36, 0xE2, 0x1C},
250	{0x37, 0x23, 0x1D},
251	{0x38, 0x83, 0x1D},
252	{0x39, 0xE2, 0x1D},
253	{0x3A, 0x23, 0x1E},
254	{0x3B, 0x82, 0x1E},
255	{0x3C, 0xC3, 0x1E},
256	{0x3D, 0x22, 0x1F},
257	{0x3E, 0x63, 0x1F},
258	{0x3F, 0xC1, 0x1F},
259	{}
260};
261static void cx11646_fw(struct gspca_dev*gspca_dev)
262{
263	int i = 0;
264
265	reg_w_val(gspca_dev, 0x006a, 0x02);
266	while (cx11646_fw1[i][1]) {
267		reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
268		i++;
269	}
270	reg_w_val(gspca_dev, 0x006a, 0x00);
271}
272
273static const __u8 cxsensor[] = {
274	0x88, 0x12, 0x70, 0x01,
275	0x88, 0x0d, 0x02, 0x01,
276	0x88, 0x0f, 0x00, 0x01,
277	0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01,	/* 3 */
278	0x88, 0x02, 0x10, 0x01,
279	0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01,	/* 5 */
280	0x88, 0x0B, 0x00, 0x01,
281	0x88, 0x0A, 0x0A, 0x01,
282	0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01,	/* 8 */
283	0x88, 0x05, 0x01, 0x01,
284	0xA1, 0x18, 0x00, 0x01,
285	0x00
286};
287
288static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
289static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
290static const __u8 reg10[] = { 0xb1, 0xb1 };
291static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };	/* 640 */
292static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
293	/* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
294static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
295					/* 320{0x04,0x0c,0x05,0x0f}; //320 */
296static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };	/* 176 */
297static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
298
299static void cx_sensor(struct gspca_dev*gspca_dev)
300{
301	int i = 0;
302	int length;
303	const __u8 *ptsensor = cxsensor;
304
305	reg_w(gspca_dev, 0x0020, reg20, 8);
306	reg_w(gspca_dev, 0x0028, reg28, 8);
307	reg_w(gspca_dev, 0x0010, reg10, 8);
308	reg_w_val(gspca_dev, 0x0092, 0x03);
309
310	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
311	case 0:
312		reg_w(gspca_dev, 0x0071, reg71a, 4);
313		break;
314	case 1:
315		reg_w(gspca_dev, 0x0071, reg71b, 4);
316		break;
317	default:
318/*	case 2: */
319		reg_w(gspca_dev, 0x0071, reg71c, 4);
320		break;
321	case 3:
322		reg_w(gspca_dev, 0x0071, reg71d, 4);
323		break;
324	}
325	reg_w(gspca_dev, 0x007b, reg7b, 6);
326	reg_w_val(gspca_dev, 0x00f8, 0x00);
327	reg_w(gspca_dev, 0x0010, reg10, 8);
328	reg_w_val(gspca_dev, 0x0098, 0x41);
329	for (i = 0; i < 11; i++) {
330		if (i == 3 || i == 5 || i == 8)
331			length = 8;
332		else
333			length = 4;
334		reg_w(gspca_dev, 0x00e5, ptsensor, length);
335		if (length == 4)
336			reg_r(gspca_dev, 0x00e8, 1);
337		else
338			reg_r(gspca_dev, 0x00e8, length);
339		ptsensor += length;
340	}
341	reg_r(gspca_dev, 0x00e7, 8);
342}
343
344static const __u8 cx_inits_176[] = {
345	0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03,	/* 176x144 */
346	0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
347	0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
348	0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
349	0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
350	0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
351	0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
352};
353static const __u8 cx_inits_320[] = {
354	0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
355	0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
356	0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
357	0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
358	0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
359	0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
360	0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
361};
362static const __u8 cx_inits_352[] = {
363	0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
364	0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
365	0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
366	0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
367	0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
368	0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
369	0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
370};
371static const __u8 cx_inits_640[] = {
372	0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
373	0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
374	0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
375	0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
376	0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
377	0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
378	0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
379};
380
381static void cx11646_initsize(struct gspca_dev *gspca_dev)
382{
383	const __u8 *cxinit;
384	static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
385	static const __u8 reg17[] =
386			{ 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
387
388	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
389	case 0:
390		cxinit = cx_inits_640;
391		break;
392	case 1:
393		cxinit = cx_inits_352;
394		break;
395	default:
396/*	case 2: */
397		cxinit = cx_inits_320;
398		break;
399	case 3:
400		cxinit = cx_inits_176;
401		break;
402	}
403	reg_w_val(gspca_dev, 0x009a, 0x01);
404	reg_w_val(gspca_dev, 0x0010, 0x10);
405	reg_w(gspca_dev, 0x0012, reg12, 5);
406	reg_w(gspca_dev, 0x0017, reg17, 8);
407	reg_w_val(gspca_dev, 0x00c0, 0x00);
408	reg_w_val(gspca_dev, 0x00c1, 0x04);
409	reg_w_val(gspca_dev, 0x00c2, 0x04);
410
411	reg_w(gspca_dev, 0x0061, cxinit, 8);
412	cxinit += 8;
413	reg_w(gspca_dev, 0x00ca, cxinit, 8);
414	cxinit += 8;
415	reg_w(gspca_dev, 0x00d2, cxinit, 8);
416	cxinit += 8;
417	reg_w(gspca_dev, 0x00da, cxinit, 6);
418	cxinit += 8;
419	reg_w(gspca_dev, 0x0041, cxinit, 8);
420	cxinit += 8;
421	reg_w(gspca_dev, 0x0049, cxinit, 8);
422	cxinit += 8;
423	reg_w(gspca_dev, 0x0051, cxinit, 2);
424
425	reg_r(gspca_dev, 0x0010, 1);
426}
427
428static const __u8 cx_jpeg_init[][8] = {
429	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},	/* 1 */
430	{0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
431	{0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
432	{0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
433	{0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
434	{0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
435	{0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
436	{0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
437	{0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
438	{0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
439	{0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
440	{0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
441	{0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
442	{0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
443	{0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
444	{0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
445	{0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
446	{0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
447	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
448	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
449	{0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
450	{0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
451	{0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
452	{0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
453	{0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
454	{0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
455	{0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
456	{0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
457	{0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
458	{0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
459	{0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
460	{0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
461	{0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
462	{0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
463	{0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
464	{0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
465	{0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
466	{0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
467	{0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
468	{0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
469	{0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
470	{0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
471	{0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
472	{0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
473	{0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
474	{0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
475	{0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
476	{0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
477	{0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
478	{0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
479	{0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
480	{0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
481	{0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
482	{0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
483	{0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
484	{0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
485	{0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
486	{0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
487	{0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
488	{0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
489	{0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
490	{0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
491	{0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
492	{0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
493	{0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
494	{0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
495	{0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
496	{0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
497	{0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
498	{0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
499	{0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
500	{0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
501	{0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
502	{0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
503	{0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
504	{0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
505	{0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
506	{0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
507	{0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}	/* 79 */
508};
509
510
511static const __u8 cxjpeg_640[][8] = {
512	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},	/* 1 */
513	{0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
514	{0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
515	{0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
516	{0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
517	{0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
518	{0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
519	{0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
520	{0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
521	{0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
522	{0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
523	{0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
524	{0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
525	{0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
526	{0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
527	{0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
528	{0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
529	{0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
530	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
531	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
532	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
533	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
534	{0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
535	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
536	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
537	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
538	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 27 */
539};
540static const __u8 cxjpeg_352[][8] = {
541	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
542	{0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
543	{0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
544	{0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
545	{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
546	{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
547	{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
548	{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
549	{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
550	{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
551	{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
552	{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
553	{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
554	{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
555	{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
556	{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
557	{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
558	{0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
559	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
560	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
561	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
562	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
563	{0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
564	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
565	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
566	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
567	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
568};
569static const __u8 cxjpeg_320[][8] = {
570	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
571	{0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
572	{0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
573	{0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
574	{0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
575	{0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
576	{0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
577	{0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
578	{0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
579	{0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
580	{0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
581	{0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
582	{0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
583	{0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
584	{0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
585	{0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
586	{0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
587	{0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
588	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
589	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
590	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
591	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
592	{0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
593	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
594	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
595	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
596	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 27 */
597};
598static const __u8 cxjpeg_176[][8] = {
599	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
600	{0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
601	{0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
602	{0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
603	{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
604	{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
605	{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
606	{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
607	{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
608	{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
609	{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
610	{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
611	{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
612	{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
613	{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
614	{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
615	{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
616	{0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
617	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
618	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
619	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
620	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
621	{0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
622	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
623	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
624	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
625	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
626};
627/* 640 take with the zcx30x part */
628static const __u8 cxjpeg_qtable[][8] = {
629	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
630	{0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
631	{0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
632	{0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
633	{0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
634	{0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
635	{0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
636	{0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
637	{0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
638	{0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
639	{0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
640	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
646	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 18 */
647};
648
649
650static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
651{
652	int i;
653	int length;
654
655	reg_w_val(gspca_dev, 0x00c0, 0x01);
656	reg_w_val(gspca_dev, 0x00c3, 0x00);
657	reg_w_val(gspca_dev, 0x00c0, 0x00);
658	reg_r(gspca_dev, 0x0001, 1);
659	length = 8;
660	for (i = 0; i < 79; i++) {
661		if (i == 78)
662			length = 6;
663		reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
664	}
665	reg_r(gspca_dev, 0x0002, 1);
666	reg_w_val(gspca_dev, 0x0055, 0x14);
667}
668
669static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
670static const __u8 regE5_8[] =
671		{ 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
672static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
673static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
674static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
675static const __u8 reg51[] = { 0x77, 0x03 };
676#define reg70 0x03
677
678static void cx11646_jpeg(struct gspca_dev*gspca_dev)
679{
680	int i;
681	int length;
682	__u8 Reg55;
683	int retry;
684
685	reg_w_val(gspca_dev, 0x00c0, 0x01);
686	reg_w_val(gspca_dev, 0x00c3, 0x00);
687	reg_w_val(gspca_dev, 0x00c0, 0x00);
688	reg_r(gspca_dev, 0x0001, 1);
689	length = 8;
690	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
691	case 0:
692		for (i = 0; i < 27; i++) {
693			if (i == 26)
694				length = 2;
695			reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
696		}
697		Reg55 = 0x28;
698		break;
699	case 1:
700		for (i = 0; i < 27; i++) {
701			if (i == 26)
702				length = 2;
703			reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
704		}
705		Reg55 = 0x16;
706		break;
707	default:
708/*	case 2: */
709		for (i = 0; i < 27; i++) {
710			if (i == 26)
711				length = 2;
712			reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
713		}
714		Reg55 = 0x14;
715		break;
716	case 3:
717		for (i = 0; i < 27; i++) {
718			if (i == 26)
719				length = 2;
720			reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
721		}
722		Reg55 = 0x0B;
723		break;
724	}
725
726	reg_r(gspca_dev, 0x0002, 1);
727	reg_w_val(gspca_dev, 0x0055, Reg55);
728	reg_r(gspca_dev, 0x0002, 1);
729	reg_w(gspca_dev, 0x0010, reg10, 2);
730	reg_w_val(gspca_dev, 0x0054, 0x02);
731	reg_w_val(gspca_dev, 0x0054, 0x01);
732	reg_w_val(gspca_dev, 0x0000, 0x94);
733	reg_w_val(gspca_dev, 0x0053, 0xc0);
734	reg_w_val(gspca_dev, 0x00fc, 0xe1);
735	reg_w_val(gspca_dev, 0x0000, 0x00);
736	/* wait for completion */
737	retry = 50;
738	do {
739		reg_r(gspca_dev, 0x0002, 1);
740							/* 0x07 until 0x00 */
741		if (gspca_dev->usb_buf[0] == 0x00)
742			break;
743		reg_w_val(gspca_dev, 0x0053, 0x00);
744	} while (--retry);
745	if (retry == 0)
746		PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
747	/* send the qtable now */
748	reg_r(gspca_dev, 0x0001, 1);		/* -> 0x18 */
749	length = 8;
750	for (i = 0; i < 18; i++) {
751		if (i == 17)
752			length = 2;
753		reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
754
755	}
756	reg_r(gspca_dev, 0x0002, 1);	/* 0x00 */
757	reg_r(gspca_dev, 0x0053, 1);	/* 0x00 */
758	reg_w_val(gspca_dev, 0x0054, 0x02);
759	reg_w_val(gspca_dev, 0x0054, 0x01);
760	reg_w_val(gspca_dev, 0x0000, 0x94);
761	reg_w_val(gspca_dev, 0x0053, 0xc0);
762
763	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
764	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
765	reg_r(gspca_dev, 0x001f, 1);		/* 0x38 */
766	reg_w(gspca_dev, 0x0012, reg12, 5);
767	reg_w(gspca_dev, 0x00e5, regE5_8, 8);
768	reg_r(gspca_dev, 0x00e8, 8);
769	reg_w(gspca_dev, 0x00e5, regE5a, 4);
770	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
771	reg_w_val(gspca_dev, 0x009a, 0x01);
772	reg_w(gspca_dev, 0x00e5, regE5b, 4);
773	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
774	reg_w(gspca_dev, 0x00e5, regE5c, 4);
775	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
776
777	reg_w(gspca_dev, 0x0051, reg51, 2);
778	reg_w(gspca_dev, 0x0010, reg10, 2);
779	reg_w_val(gspca_dev, 0x0070, reg70);
780}
781
782static void cx11646_init1(struct gspca_dev *gspca_dev)
783{
784	int i = 0;
785
786	reg_w_val(gspca_dev, 0x0010, 0x00);
787	reg_w_val(gspca_dev, 0x0053, 0x00);
788	reg_w_val(gspca_dev, 0x0052, 0x00);
789	reg_w_val(gspca_dev, 0x009b, 0x2f);
790	reg_w_val(gspca_dev, 0x009c, 0x10);
791	reg_r(gspca_dev, 0x0098, 1);
792	reg_w_val(gspca_dev, 0x0098, 0x40);
793	reg_r(gspca_dev, 0x0099, 1);
794	reg_w_val(gspca_dev, 0x0099, 0x07);
795	reg_w_val(gspca_dev, 0x0039, 0x40);
796	reg_w_val(gspca_dev, 0x003c, 0xff);
797	reg_w_val(gspca_dev, 0x003f, 0x1f);
798	reg_w_val(gspca_dev, 0x003d, 0x40);
799/*	reg_w_val(gspca_dev, 0x003d, 0x60); */
800	reg_r(gspca_dev, 0x0099, 1);			/* ->0x07 */
801
802	while (cx_sensor_init[i][0]) {
803		reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
804		reg_r(gspca_dev, 0x00e8, 1);		/* -> 0x00 */
805		if (i == 1) {
806			reg_w_val(gspca_dev, 0x00ed, 0x01);
807			reg_r(gspca_dev, 0x00ed, 1);	/* -> 0x01 */
808		}
809		i++;
810	}
811	reg_w_val(gspca_dev, 0x00c3, 0x00);
812}
813
814/* this function is called at probe time */
815static int sd_config(struct gspca_dev *gspca_dev,
816			const struct usb_device_id *id)
817{
818	struct sd *sd = (struct sd *) gspca_dev;
819	struct cam *cam;
820
821	cam = &gspca_dev->cam;
822	cam->cam_mode = vga_mode;
823	cam->nmodes = ARRAY_SIZE(vga_mode);
824
825	sd->brightness = BRIGHTNESS_DEF;
826	sd->contrast = CONTRAST_DEF;
827	sd->colors = COLOR_DEF;
828	sd->quality = QUALITY_DEF;
829	return 0;
830}
831
832/* this function is called at probe and resume time */
833static int sd_init(struct gspca_dev *gspca_dev)
834{
835	cx11646_init1(gspca_dev);
836	cx11646_initsize(gspca_dev);
837	cx11646_fw(gspca_dev);
838	cx_sensor(gspca_dev);
839	cx11646_jpegInit(gspca_dev);
840	return 0;
841}
842
843static int sd_start(struct gspca_dev *gspca_dev)
844{
845	struct sd *sd = (struct sd *) gspca_dev;
846
847	/* create the JPEG header */
848	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
849			0x22);		/* JPEG 411 */
850	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
851
852	cx11646_initsize(gspca_dev);
853	cx11646_fw(gspca_dev);
854	cx_sensor(gspca_dev);
855	cx11646_jpeg(gspca_dev);
856	return 0;
857}
858
859/* called on streamoff with alt 0 and on disconnect */
860static void sd_stop0(struct gspca_dev *gspca_dev)
861{
862	int retry = 50;
863
864	if (!gspca_dev->present)
865		return;
866	reg_w_val(gspca_dev, 0x0000, 0x00);
867	reg_r(gspca_dev, 0x0002, 1);
868	reg_w_val(gspca_dev, 0x0053, 0x00);
869
870	while (retry--) {
871/*		reg_r(gspca_dev, 0x0002, 1);*/
872		reg_r(gspca_dev, 0x0053, 1);
873		if (gspca_dev->usb_buf[0] == 0)
874			break;
875	}
876	reg_w_val(gspca_dev, 0x0000, 0x00);
877	reg_r(gspca_dev, 0x0002, 1);
878
879	reg_w_val(gspca_dev, 0x0010, 0x00);
880	reg_r(gspca_dev, 0x0033, 1);
881	reg_w_val(gspca_dev, 0x00fc, 0xe0);
882}
883
884static void sd_pkt_scan(struct gspca_dev *gspca_dev,
885			u8 *data,			/* isoc packet */
886			int len)			/* iso packet length */
887{
888	struct sd *sd = (struct sd *) gspca_dev;
889
890	if (data[0] == 0xff && data[1] == 0xd8) {
891
892		/* start of frame */
893		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
894
895		/* put the JPEG header in the new frame */
896		gspca_frame_add(gspca_dev, FIRST_PACKET,
897				sd->jpeg_hdr, JPEG_HDR_SZ);
898		data += 2;
899		len -= 2;
900	}
901	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
902}
903
904static void setbrightness(struct gspca_dev*gspca_dev)
905{
906	struct sd *sd = (struct sd *) gspca_dev;
907	__u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
908	__u8 reg51c[2];
909	__u8 bright;
910	__u8 colors;
911
912	bright = sd->brightness;
913	regE5cbx[2] = bright;
914	reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
915	reg_r(gspca_dev, 0x00e8, 8);
916	reg_w(gspca_dev, 0x00e5, regE5c, 4);
917	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
918
919	colors = sd->colors;
920	reg51c[0] = 0x77;
921	reg51c[1] = colors;
922	reg_w(gspca_dev, 0x0051, reg51c, 2);
923	reg_w(gspca_dev, 0x0010, reg10, 2);
924	reg_w_val(gspca_dev, 0x0070, reg70);
925}
926
927static void setcontrast(struct gspca_dev*gspca_dev)
928{
929	struct sd *sd = (struct sd *) gspca_dev;
930	__u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };	/* seem MSB */
931/*	__u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};	 * LSB */
932	__u8 reg51c[2];
933
934	regE5acx[2] = sd->contrast;
935	reg_w(gspca_dev, 0x00e5, regE5acx, 4);
936	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
937	reg51c[0] = 0x77;
938	reg51c[1] = sd->colors;
939	reg_w(gspca_dev, 0x0051, reg51c, 2);
940	reg_w(gspca_dev, 0x0010, reg10, 2);
941	reg_w_val(gspca_dev, 0x0070, reg70);
942}
943
944static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
945{
946	struct sd *sd = (struct sd *) gspca_dev;
947
948	sd->brightness = val;
949	if (gspca_dev->streaming)
950		setbrightness(gspca_dev);
951	return 0;
952}
953
954static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
955{
956	struct sd *sd = (struct sd *) gspca_dev;
957
958	*val = sd->brightness;
959	return 0;
960}
961
962static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
963{
964	struct sd *sd = (struct sd *) gspca_dev;
965
966	sd->contrast = val;
967	if (gspca_dev->streaming)
968		setcontrast(gspca_dev);
969	return 0;
970}
971
972static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
973{
974	struct sd *sd = (struct sd *) gspca_dev;
975
976	*val = sd->contrast;
977	return 0;
978}
979
980static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
981{
982	struct sd *sd = (struct sd *) gspca_dev;
983
984	sd->colors = val;
985	if (gspca_dev->streaming) {
986		setbrightness(gspca_dev);
987		setcontrast(gspca_dev);
988	}
989	return 0;
990}
991
992static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
993{
994	struct sd *sd = (struct sd *) gspca_dev;
995
996	*val = sd->colors;
997	return 0;
998}
999
1000static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1001			struct v4l2_jpegcompression *jcomp)
1002{
1003	struct sd *sd = (struct sd *) gspca_dev;
1004
1005	if (jcomp->quality < QUALITY_MIN)
1006		sd->quality = QUALITY_MIN;
1007	else if (jcomp->quality > QUALITY_MAX)
1008		sd->quality = QUALITY_MAX;
1009	else
1010		sd->quality = jcomp->quality;
1011	if (gspca_dev->streaming)
1012		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1013	return 0;
1014}
1015
1016static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1017			struct v4l2_jpegcompression *jcomp)
1018{
1019	struct sd *sd = (struct sd *) gspca_dev;
1020
1021	memset(jcomp, 0, sizeof *jcomp);
1022	jcomp->quality = sd->quality;
1023	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1024			| V4L2_JPEG_MARKER_DQT;
1025	return 0;
1026}
1027
1028/* sub-driver description */
1029static const struct sd_desc sd_desc = {
1030	.name = MODULE_NAME,
1031	.ctrls = sd_ctrls,
1032	.nctrls = ARRAY_SIZE(sd_ctrls),
1033	.config = sd_config,
1034	.init = sd_init,
1035	.start = sd_start,
1036	.stop0 = sd_stop0,
1037	.pkt_scan = sd_pkt_scan,
1038	.get_jcomp = sd_get_jcomp,
1039	.set_jcomp = sd_set_jcomp,
1040};
1041
1042/* -- module initialisation -- */
1043static const struct usb_device_id device_table[] __devinitconst = {
1044	{USB_DEVICE(0x0572, 0x0041)},
1045	{}
1046};
1047MODULE_DEVICE_TABLE(usb, device_table);
1048
1049/* -- device connect -- */
1050static int __devinit sd_probe(struct usb_interface *intf,
1051			const struct usb_device_id *id)
1052{
1053	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1054				THIS_MODULE);
1055}
1056
1057static struct usb_driver sd_driver = {
1058	.name = MODULE_NAME,
1059	.id_table = device_table,
1060	.probe = sd_probe,
1061	.disconnect = gspca_disconnect,
1062#ifdef CONFIG_PM
1063	.suspend = gspca_suspend,
1064	.resume = gspca_resume,
1065#endif
1066};
1067
1068/* -- module insert / remove -- */
1069static int __init sd_mod_init(void)
1070{
1071	int ret;
1072	ret = usb_register(&sd_driver);
1073	if (ret < 0)
1074		return ret;
1075	PDEBUG(D_PROBE, "registered");
1076	return 0;
1077}
1078static void __exit sd_mod_exit(void)
1079{
1080	usb_deregister(&sd_driver);
1081	PDEBUG(D_PROBE, "deregistered");
1082}
1083
1084module_init(sd_mod_init);
1085module_exit(sd_mod_exit);
1086