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