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