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