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