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