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