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