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