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