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