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