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