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