de28354ea5bac3e0a6a9650ac2266aba2a026ee3
[linux-2.6.git] / 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 GSPCA_DEBUG
127         if (len > USB_BUF_SZ) {
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 GSPCA_DEBUG
167         if (len > USB_BUF_SZ) {
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         do {
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         } while (--retry);
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 probe and resume time */
830 static int sd_init(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 int 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         return 0;
847 }
848
849 /* called on streamoff with alt 0 and on disconnect */
850 static void sd_stop0(struct gspca_dev *gspca_dev)
851 {
852         int retry = 50;
853
854         if (!gspca_dev->present)
855                 return;
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_pkt_scan(struct gspca_dev *gspca_dev,
875                         struct gspca_frame *frame,      /* target */
876                         __u8 *data,                     /* isoc packet */
877                         int len)                        /* iso packet length */
878 {
879         if (data[0] == 0xff && data[1] == 0xd8) {
880
881                 /* start of frame */
882                 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
883                                         data, 0);
884
885                 /* put the JPEG header in the new frame */
886                 jpeg_put_header(gspca_dev, frame,
887                                 ((struct sd *) gspca_dev)->qindex,
888                                 0x22);
889                 data += 2;
890                 len -= 2;
891         }
892         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
893 }
894
895 static void setbrightness(struct gspca_dev*gspca_dev)
896 {
897         struct sd *sd = (struct sd *) gspca_dev;
898         __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
899         __u8 reg51c[2];
900         __u8 bright;
901         __u8 colors;
902
903         bright = sd->brightness;
904         regE5cbx[2] = bright;
905         reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
906         reg_r(gspca_dev, 0x00e8, 8);
907         reg_w(gspca_dev, 0x00e5, regE5c, 4);
908         reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
909
910         colors = sd->colors;
911         reg51c[0] = 0x77;
912         reg51c[1] = colors;
913         reg_w(gspca_dev, 0x0051, reg51c, 2);
914         reg_w(gspca_dev, 0x0010, reg10, 2);
915         reg_w_val(gspca_dev, 0x0070, reg70);
916 }
917
918 static void setcontrast(struct gspca_dev*gspca_dev)
919 {
920         struct sd *sd = (struct sd *) gspca_dev;
921         __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
922 /*      __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
923         __u8 reg51c[2];
924
925         regE5acx[2] = sd->contrast;
926         reg_w(gspca_dev, 0x00e5, regE5acx, 4);
927         reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
928         reg51c[0] = 0x77;
929         reg51c[1] = sd->colors;
930         reg_w(gspca_dev, 0x0051, reg51c, 2);
931         reg_w(gspca_dev, 0x0010, reg10, 2);
932         reg_w_val(gspca_dev, 0x0070, reg70);
933 }
934
935 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
936 {
937         struct sd *sd = (struct sd *) gspca_dev;
938
939         sd->brightness = val;
940         if (gspca_dev->streaming)
941                 setbrightness(gspca_dev);
942         return 0;
943 }
944
945 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
946 {
947         struct sd *sd = (struct sd *) gspca_dev;
948
949         *val = sd->brightness;
950         return 0;
951 }
952
953 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
954 {
955         struct sd *sd = (struct sd *) gspca_dev;
956
957         sd->contrast = val;
958         if (gspca_dev->streaming)
959                 setcontrast(gspca_dev);
960         return 0;
961 }
962
963 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
964 {
965         struct sd *sd = (struct sd *) gspca_dev;
966
967         *val = sd->contrast;
968         return 0;
969 }
970
971 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
972 {
973         struct sd *sd = (struct sd *) gspca_dev;
974
975         sd->colors = val;
976         if (gspca_dev->streaming) {
977                 setbrightness(gspca_dev);
978                 setcontrast(gspca_dev);
979         }
980         return 0;
981 }
982
983 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
984 {
985         struct sd *sd = (struct sd *) gspca_dev;
986
987         *val = sd->colors;
988         return 0;
989 }
990
991 /* sub-driver description */
992 static struct sd_desc sd_desc = {
993         .name = MODULE_NAME,
994         .ctrls = sd_ctrls,
995         .nctrls = ARRAY_SIZE(sd_ctrls),
996         .config = sd_config,
997         .init = sd_init,
998         .start = sd_start,
999         .stop0 = sd_stop0,
1000         .pkt_scan = sd_pkt_scan,
1001 };
1002
1003 /* -- module initialisation -- */
1004 static __devinitdata struct usb_device_id device_table[] = {
1005         {USB_DEVICE(0x0572, 0x0041)},
1006         {}
1007 };
1008 MODULE_DEVICE_TABLE(usb, device_table);
1009
1010 /* -- device connect -- */
1011 static int sd_probe(struct usb_interface *intf,
1012                         const struct usb_device_id *id)
1013 {
1014         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1015                                 THIS_MODULE);
1016 }
1017
1018 static struct usb_driver sd_driver = {
1019         .name = MODULE_NAME,
1020         .id_table = device_table,
1021         .probe = sd_probe,
1022         .disconnect = gspca_disconnect,
1023 #ifdef CONFIG_PM
1024         .suspend = gspca_suspend,
1025         .resume = gspca_resume,
1026 #endif
1027 };
1028
1029 /* -- module insert / remove -- */
1030 static int __init sd_mod_init(void)
1031 {
1032         if (usb_register(&sd_driver) < 0)
1033                 return -1;
1034         PDEBUG(D_PROBE, "registered");
1035         return 0;
1036 }
1037 static void __exit sd_mod_exit(void)
1038 {
1039         usb_deregister(&sd_driver);
1040         PDEBUG(D_PROBE, "deregistered");
1041 }
1042
1043 module_init(sd_mod_init);
1044 module_exit(sd_mod_exit);