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