• 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 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 */
reg_r(struct gspca_dev * gspca_dev,__u16 index,__u16 len)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 */
reg_w_val(struct gspca_dev * gspca_dev,__u16 index,__u8 val)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 
reg_w(struct gspca_dev * gspca_dev,__u16 index,const __u8 * buffer,__u16 len)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 };
cx11646_fw(struct gspca_dev * gspca_dev)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 
cx_sensor(struct gspca_dev * gspca_dev)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 
cx11646_initsize(struct gspca_dev * gspca_dev)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 
cx11646_jpegInit(struct gspca_dev * gspca_dev)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 
cx11646_jpeg(struct gspca_dev * gspca_dev)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 
cx11646_init1(struct gspca_dev * gspca_dev)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 */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)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 */
sd_init(struct gspca_dev * gspca_dev)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 
sd_start(struct gspca_dev * gspca_dev)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->height, gspca_dev->width,
787 			0x22);		/* JPEG 411 */
788 	jpeg_set_qual(sd->jpeg_hdr, QUALITY);
789 
790 	cx11646_initsize(gspca_dev);
791 	cx11646_fw(gspca_dev);
792 	cx_sensor(gspca_dev);
793 	cx11646_jpeg(gspca_dev);
794 	return 0;
795 }
796 
797 /* called on streamoff with alt 0 and on disconnect */
sd_stop0(struct gspca_dev * gspca_dev)798 static void sd_stop0(struct gspca_dev *gspca_dev)
799 {
800 	int retry = 50;
801 
802 	if (!gspca_dev->present)
803 		return;
804 	reg_w_val(gspca_dev, 0x0000, 0x00);
805 	reg_r(gspca_dev, 0x0002, 1);
806 	reg_w_val(gspca_dev, 0x0053, 0x00);
807 
808 	while (retry--) {
809 /*		reg_r(gspca_dev, 0x0002, 1);*/
810 		reg_r(gspca_dev, 0x0053, 1);
811 		if (gspca_dev->usb_buf[0] == 0)
812 			break;
813 	}
814 	reg_w_val(gspca_dev, 0x0000, 0x00);
815 	reg_r(gspca_dev, 0x0002, 1);
816 
817 	reg_w_val(gspca_dev, 0x0010, 0x00);
818 	reg_r(gspca_dev, 0x0033, 1);
819 	reg_w_val(gspca_dev, 0x00fc, 0xe0);
820 }
821 
sd_pkt_scan(struct gspca_dev * gspca_dev,u8 * data,int len)822 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
823 			u8 *data,			/* isoc packet */
824 			int len)			/* iso packet length */
825 {
826 	struct sd *sd = (struct sd *) gspca_dev;
827 
828 	if (data[0] == 0xff && data[1] == 0xd8) {
829 
830 		/* start of frame */
831 		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
832 
833 		/* put the JPEG header in the new frame */
834 		gspca_frame_add(gspca_dev, FIRST_PACKET,
835 				sd->jpeg_hdr, JPEG_HDR_SZ);
836 		data += 2;
837 		len -= 2;
838 	}
839 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
840 }
841 
setbrightness(struct gspca_dev * gspca_dev,s32 val,s32 sat)842 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
843 {
844 	__u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
845 	__u8 reg51c[2];
846 
847 	regE5cbx[2] = val;
848 	reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
849 	reg_r(gspca_dev, 0x00e8, 8);
850 	reg_w(gspca_dev, 0x00e5, regE5c, 4);
851 	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
852 
853 	reg51c[0] = 0x77;
854 	reg51c[1] = sat;
855 	reg_w(gspca_dev, 0x0051, reg51c, 2);
856 	reg_w(gspca_dev, 0x0010, reg10, 2);
857 	reg_w_val(gspca_dev, 0x0070, reg70);
858 }
859 
setcontrast(struct gspca_dev * gspca_dev,s32 val,s32 sat)860 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
861 {
862 	__u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };	/* seem MSB */
863 /*	__u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};	 * LSB */
864 	__u8 reg51c[2];
865 
866 	regE5acx[2] = val;
867 	reg_w(gspca_dev, 0x00e5, regE5acx, 4);
868 	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
869 	reg51c[0] = 0x77;
870 	reg51c[1] = sat;
871 	reg_w(gspca_dev, 0x0051, reg51c, 2);
872 	reg_w(gspca_dev, 0x0010, reg10, 2);
873 	reg_w_val(gspca_dev, 0x0070, reg70);
874 }
875 
sd_s_ctrl(struct v4l2_ctrl * ctrl)876 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
877 {
878 	struct gspca_dev *gspca_dev =
879 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
880 	struct sd *sd = (struct sd *)gspca_dev;
881 
882 	gspca_dev->usb_err = 0;
883 
884 	if (!gspca_dev->streaming)
885 		return 0;
886 
887 	switch (ctrl->id) {
888 	case V4L2_CID_BRIGHTNESS:
889 		setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
890 		break;
891 	case V4L2_CID_CONTRAST:
892 		setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
893 		break;
894 	case V4L2_CID_SATURATION:
895 		setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
896 		setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
897 		break;
898 	}
899 	return gspca_dev->usb_err;
900 }
901 
902 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
903 	.s_ctrl = sd_s_ctrl,
904 };
905 
sd_init_controls(struct gspca_dev * gspca_dev)906 static int sd_init_controls(struct gspca_dev *gspca_dev)
907 {
908 	struct sd *sd = (struct sd *)gspca_dev;
909 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
910 
911 	gspca_dev->vdev.ctrl_handler = hdl;
912 	v4l2_ctrl_handler_init(hdl, 3);
913 	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
914 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
915 	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
916 			V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
917 	sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
918 			V4L2_CID_SATURATION, 0, 7, 1, 3);
919 	if (hdl->error) {
920 		pr_err("Could not initialize controls\n");
921 		return hdl->error;
922 	}
923 	return 0;
924 }
925 
926 /* sub-driver description */
927 static const struct sd_desc sd_desc = {
928 	.name = MODULE_NAME,
929 	.config = sd_config,
930 	.init = sd_init,
931 	.init_controls = sd_init_controls,
932 	.start = sd_start,
933 	.stop0 = sd_stop0,
934 	.pkt_scan = sd_pkt_scan,
935 };
936 
937 /* -- module initialisation -- */
938 static const struct usb_device_id device_table[] = {
939 	{USB_DEVICE(0x0572, 0x0041)},
940 	{}
941 };
942 MODULE_DEVICE_TABLE(usb, device_table);
943 
944 /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)945 static int sd_probe(struct usb_interface *intf,
946 			const struct usb_device_id *id)
947 {
948 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
949 				THIS_MODULE);
950 }
951 
952 static struct usb_driver sd_driver = {
953 	.name = MODULE_NAME,
954 	.id_table = device_table,
955 	.probe = sd_probe,
956 	.disconnect = gspca_disconnect,
957 #ifdef CONFIG_PM
958 	.suspend = gspca_suspend,
959 	.resume = gspca_resume,
960 	.reset_resume = gspca_resume,
961 #endif
962 };
963 
964 module_usb_driver(sd_driver);
965