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