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