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