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