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