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