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