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