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