2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
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.
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #define MODULE_NAME "conex"
23 #define CONEX_CAM 1 /* special JPEG header */
26 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
27 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
28 MODULE_LICENSE("GPL");
32 /* specific webcam descriptor */
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35 struct v4l2_ctrl *brightness;
36 struct v4l2_ctrl *contrast;
37 struct v4l2_ctrl *sat;
39 u8 jpeg_hdr[JPEG_HDR_SZ];
42 static const struct v4l2_pix_format vga_mode[] = {
43 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
45 .sizeimage = 176 * 144 * 3 / 8 + 590,
46 .colorspace = V4L2_COLORSPACE_JPEG,
48 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
50 .sizeimage = 320 * 240 * 3 / 8 + 590,
51 .colorspace = V4L2_COLORSPACE_JPEG,
53 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
55 .sizeimage = 352 * 288 * 3 / 8 + 590,
56 .colorspace = V4L2_COLORSPACE_JPEG,
58 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
60 .sizeimage = 640 * 480 * 3 / 8 + 590,
61 .colorspace = V4L2_COLORSPACE_JPEG,
65 /* the read bytes are found in gspca_dev->usb_buf */
66 static void reg_r(struct gspca_dev *gspca_dev,
70 struct usb_device *dev = gspca_dev->dev;
72 if (len > USB_BUF_SZ) {
73 PERR("reg_r: buffer overflow\n");
78 usb_rcvctrlpipe(dev, 0),
80 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
82 index, gspca_dev->usb_buf, len,
84 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
85 index, gspca_dev->usb_buf[0]);
88 /* the bytes to write are in gspca_dev->usb_buf */
89 static void reg_w_val(struct gspca_dev *gspca_dev,
93 struct usb_device *dev = gspca_dev->dev;
95 gspca_dev->usb_buf[0] = val;
97 usb_sndctrlpipe(dev, 0),
99 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
101 index, gspca_dev->usb_buf, 1, 500);
104 static void reg_w(struct gspca_dev *gspca_dev,
109 struct usb_device *dev = gspca_dev->dev;
111 if (len > USB_BUF_SZ) {
112 PERR("reg_w: buffer overflow\n");
115 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
117 memcpy(gspca_dev->usb_buf, buffer, len);
119 usb_sndctrlpipe(dev, 0),
121 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
123 index, gspca_dev->usb_buf, len, 500);
126 static const __u8 cx_sensor_init[][4] = {
127 {0x88, 0x11, 0x01, 0x01},
128 {0x88, 0x12, 0x70, 0x01},
129 {0x88, 0x0f, 0x00, 0x01},
130 {0x88, 0x05, 0x01, 0x01},
134 static const __u8 cx11646_fw1[][3] = {
201 static void cx11646_fw(struct gspca_dev*gspca_dev)
205 reg_w_val(gspca_dev, 0x006a, 0x02);
206 while (cx11646_fw1[i][1]) {
207 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
210 reg_w_val(gspca_dev, 0x006a, 0x00);
213 static const __u8 cxsensor[] = {
214 0x88, 0x12, 0x70, 0x01,
215 0x88, 0x0d, 0x02, 0x01,
216 0x88, 0x0f, 0x00, 0x01,
217 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
218 0x88, 0x02, 0x10, 0x01,
219 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
220 0x88, 0x0B, 0x00, 0x01,
221 0x88, 0x0A, 0x0A, 0x01,
222 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
223 0x88, 0x05, 0x01, 0x01,
224 0xA1, 0x18, 0x00, 0x01,
228 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
229 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
230 static const __u8 reg10[] = { 0xb1, 0xb1 };
231 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
232 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
233 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
234 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
235 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
236 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
237 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
239 static void cx_sensor(struct gspca_dev*gspca_dev)
243 const __u8 *ptsensor = cxsensor;
245 reg_w(gspca_dev, 0x0020, reg20, 8);
246 reg_w(gspca_dev, 0x0028, reg28, 8);
247 reg_w(gspca_dev, 0x0010, reg10, 2);
248 reg_w_val(gspca_dev, 0x0092, 0x03);
250 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
252 reg_w(gspca_dev, 0x0071, reg71a, 4);
255 reg_w(gspca_dev, 0x0071, reg71b, 4);
259 reg_w(gspca_dev, 0x0071, reg71c, 4);
262 reg_w(gspca_dev, 0x0071, reg71d, 4);
265 reg_w(gspca_dev, 0x007b, reg7b, 6);
266 reg_w_val(gspca_dev, 0x00f8, 0x00);
267 reg_w(gspca_dev, 0x0010, reg10, 2);
268 reg_w_val(gspca_dev, 0x0098, 0x41);
269 for (i = 0; i < 11; i++) {
270 if (i == 3 || i == 5 || i == 8)
274 reg_w(gspca_dev, 0x00e5, ptsensor, length);
276 reg_r(gspca_dev, 0x00e8, 1);
278 reg_r(gspca_dev, 0x00e8, length);
281 reg_r(gspca_dev, 0x00e7, 8);
284 static const __u8 cx_inits_176[] = {
285 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
286 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
287 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
288 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
289 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
290 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
291 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
293 static const __u8 cx_inits_320[] = {
294 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
295 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
296 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
297 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
298 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
299 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
300 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
302 static const __u8 cx_inits_352[] = {
303 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
304 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
305 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
306 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
307 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
308 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
309 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
311 static const __u8 cx_inits_640[] = {
312 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
313 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
314 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
315 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
316 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
317 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
318 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
321 static void cx11646_initsize(struct gspca_dev *gspca_dev)
324 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
325 static const __u8 reg17[] =
326 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
328 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
330 cxinit = cx_inits_640;
333 cxinit = cx_inits_352;
337 cxinit = cx_inits_320;
340 cxinit = cx_inits_176;
343 reg_w_val(gspca_dev, 0x009a, 0x01);
344 reg_w_val(gspca_dev, 0x0010, 0x10);
345 reg_w(gspca_dev, 0x0012, reg12, 5);
346 reg_w(gspca_dev, 0x0017, reg17, 8);
347 reg_w_val(gspca_dev, 0x00c0, 0x00);
348 reg_w_val(gspca_dev, 0x00c1, 0x04);
349 reg_w_val(gspca_dev, 0x00c2, 0x04);
351 reg_w(gspca_dev, 0x0061, cxinit, 8);
353 reg_w(gspca_dev, 0x00ca, cxinit, 8);
355 reg_w(gspca_dev, 0x00d2, cxinit, 8);
357 reg_w(gspca_dev, 0x00da, cxinit, 6);
359 reg_w(gspca_dev, 0x0041, cxinit, 8);
361 reg_w(gspca_dev, 0x0049, cxinit, 8);
363 reg_w(gspca_dev, 0x0051, cxinit, 2);
365 reg_r(gspca_dev, 0x0010, 1);
368 static const __u8 cx_jpeg_init[][8] = {
369 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
370 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
371 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
372 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
373 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
374 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
375 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
376 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
377 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
378 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
379 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
380 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
381 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
382 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
383 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
384 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
385 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
386 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
387 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
388 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
389 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
390 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
391 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
392 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
393 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
394 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
395 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
396 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
397 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
398 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
399 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
400 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
401 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
402 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
403 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
404 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
405 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
406 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
407 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
408 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
409 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
410 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
411 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
412 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
413 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
414 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
415 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
416 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
417 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
418 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
419 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
420 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
421 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
422 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
423 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
424 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
425 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
426 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
427 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
428 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
429 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
430 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
431 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
432 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
433 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
434 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
435 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
436 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
437 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
438 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
439 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
440 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
441 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
442 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
443 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
444 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
445 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
446 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
447 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
451 static const __u8 cxjpeg_640[][8] = {
452 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
453 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
454 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
455 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
456 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
457 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
458 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
459 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
460 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
461 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
462 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
463 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
464 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
465 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
466 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
467 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
468 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
469 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
470 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
471 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
472 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
473 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
474 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
475 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
476 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
477 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
478 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
480 static const __u8 cxjpeg_352[][8] = {
481 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
482 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
483 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
484 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
485 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
486 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
487 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
488 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
489 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
490 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
491 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
492 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
493 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
494 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
495 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
496 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
497 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
498 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
499 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
500 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
501 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
502 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
503 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
504 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
505 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
506 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
507 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
509 static const __u8 cxjpeg_320[][8] = {
510 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
511 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
512 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
513 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
514 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
515 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
516 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
517 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
518 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
519 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
520 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
521 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
522 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
523 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
524 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
525 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
526 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
527 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
528 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
529 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
530 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
531 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
532 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
533 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
534 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
535 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
536 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
538 static const __u8 cxjpeg_176[][8] = {
539 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
540 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
541 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
542 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
543 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
544 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
545 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
546 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
547 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
548 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
549 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
550 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
551 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
552 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
553 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
554 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
555 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
556 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
557 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
558 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
559 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
560 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
561 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
562 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
563 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
564 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
565 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
567 /* 640 take with the zcx30x part */
568 static const __u8 cxjpeg_qtable[][8] = {
569 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
570 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
571 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
572 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
573 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
574 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
575 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
576 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
577 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
578 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
579 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
580 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
581 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
582 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
583 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
584 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
585 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
586 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
590 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
595 reg_w_val(gspca_dev, 0x00c0, 0x01);
596 reg_w_val(gspca_dev, 0x00c3, 0x00);
597 reg_w_val(gspca_dev, 0x00c0, 0x00);
598 reg_r(gspca_dev, 0x0001, 1);
600 for (i = 0; i < 79; i++) {
603 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
605 reg_r(gspca_dev, 0x0002, 1);
606 reg_w_val(gspca_dev, 0x0055, 0x14);
609 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
610 static const __u8 regE5_8[] =
611 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
612 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
613 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
614 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
615 static const __u8 reg51[] = { 0x77, 0x03 };
618 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
625 reg_w_val(gspca_dev, 0x00c0, 0x01);
626 reg_w_val(gspca_dev, 0x00c3, 0x00);
627 reg_w_val(gspca_dev, 0x00c0, 0x00);
628 reg_r(gspca_dev, 0x0001, 1);
630 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
632 for (i = 0; i < 27; i++) {
635 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
640 for (i = 0; i < 27; i++) {
643 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
649 for (i = 0; i < 27; i++) {
652 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
657 for (i = 0; i < 27; i++) {
660 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
666 reg_r(gspca_dev, 0x0002, 1);
667 reg_w_val(gspca_dev, 0x0055, Reg55);
668 reg_r(gspca_dev, 0x0002, 1);
669 reg_w(gspca_dev, 0x0010, reg10, 2);
670 reg_w_val(gspca_dev, 0x0054, 0x02);
671 reg_w_val(gspca_dev, 0x0054, 0x01);
672 reg_w_val(gspca_dev, 0x0000, 0x94);
673 reg_w_val(gspca_dev, 0x0053, 0xc0);
674 reg_w_val(gspca_dev, 0x00fc, 0xe1);
675 reg_w_val(gspca_dev, 0x0000, 0x00);
676 /* wait for completion */
679 reg_r(gspca_dev, 0x0002, 1);
680 /* 0x07 until 0x00 */
681 if (gspca_dev->usb_buf[0] == 0x00)
683 reg_w_val(gspca_dev, 0x0053, 0x00);
686 PERR("Damned Errors sending jpeg Table");
687 /* send the qtable now */
688 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
690 for (i = 0; i < 18; i++) {
693 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
696 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
697 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
698 reg_w_val(gspca_dev, 0x0054, 0x02);
699 reg_w_val(gspca_dev, 0x0054, 0x01);
700 reg_w_val(gspca_dev, 0x0000, 0x94);
701 reg_w_val(gspca_dev, 0x0053, 0xc0);
703 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
704 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
705 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
706 reg_w(gspca_dev, 0x0012, reg12, 5);
707 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
708 reg_r(gspca_dev, 0x00e8, 8);
709 reg_w(gspca_dev, 0x00e5, regE5a, 4);
710 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
711 reg_w_val(gspca_dev, 0x009a, 0x01);
712 reg_w(gspca_dev, 0x00e5, regE5b, 4);
713 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
714 reg_w(gspca_dev, 0x00e5, regE5c, 4);
715 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
717 reg_w(gspca_dev, 0x0051, reg51, 2);
718 reg_w(gspca_dev, 0x0010, reg10, 2);
719 reg_w_val(gspca_dev, 0x0070, reg70);
722 static void cx11646_init1(struct gspca_dev *gspca_dev)
726 reg_w_val(gspca_dev, 0x0010, 0x00);
727 reg_w_val(gspca_dev, 0x0053, 0x00);
728 reg_w_val(gspca_dev, 0x0052, 0x00);
729 reg_w_val(gspca_dev, 0x009b, 0x2f);
730 reg_w_val(gspca_dev, 0x009c, 0x10);
731 reg_r(gspca_dev, 0x0098, 1);
732 reg_w_val(gspca_dev, 0x0098, 0x40);
733 reg_r(gspca_dev, 0x0099, 1);
734 reg_w_val(gspca_dev, 0x0099, 0x07);
735 reg_w_val(gspca_dev, 0x0039, 0x40);
736 reg_w_val(gspca_dev, 0x003c, 0xff);
737 reg_w_val(gspca_dev, 0x003f, 0x1f);
738 reg_w_val(gspca_dev, 0x003d, 0x40);
739 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
740 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
742 while (cx_sensor_init[i][0]) {
743 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
744 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
746 reg_w_val(gspca_dev, 0x00ed, 0x01);
747 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
751 reg_w_val(gspca_dev, 0x00c3, 0x00);
754 /* this function is called at probe time */
755 static int sd_config(struct gspca_dev *gspca_dev,
756 const struct usb_device_id *id)
760 cam = &gspca_dev->cam;
761 cam->cam_mode = vga_mode;
762 cam->nmodes = ARRAY_SIZE(vga_mode);
766 /* this function is called at probe and resume time */
767 static int sd_init(struct gspca_dev *gspca_dev)
769 cx11646_init1(gspca_dev);
770 cx11646_initsize(gspca_dev);
771 cx11646_fw(gspca_dev);
772 cx_sensor(gspca_dev);
773 cx11646_jpegInit(gspca_dev);
777 static int sd_start(struct gspca_dev *gspca_dev)
779 struct sd *sd = (struct sd *) gspca_dev;
781 /* create the JPEG header */
782 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
783 gspca_dev->pixfmt.width,
784 0x22); /* JPEG 411 */
785 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
787 cx11646_initsize(gspca_dev);
788 cx11646_fw(gspca_dev);
789 cx_sensor(gspca_dev);
790 cx11646_jpeg(gspca_dev);
794 /* called on streamoff with alt 0 and on disconnect */
795 static void sd_stop0(struct gspca_dev *gspca_dev)
799 if (!gspca_dev->present)
801 reg_w_val(gspca_dev, 0x0000, 0x00);
802 reg_r(gspca_dev, 0x0002, 1);
803 reg_w_val(gspca_dev, 0x0053, 0x00);
806 /* reg_r(gspca_dev, 0x0002, 1);*/
807 reg_r(gspca_dev, 0x0053, 1);
808 if (gspca_dev->usb_buf[0] == 0)
811 reg_w_val(gspca_dev, 0x0000, 0x00);
812 reg_r(gspca_dev, 0x0002, 1);
814 reg_w_val(gspca_dev, 0x0010, 0x00);
815 reg_r(gspca_dev, 0x0033, 1);
816 reg_w_val(gspca_dev, 0x00fc, 0xe0);
819 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
820 u8 *data, /* isoc packet */
821 int len) /* iso packet length */
823 struct sd *sd = (struct sd *) gspca_dev;
825 if (data[0] == 0xff && data[1] == 0xd8) {
828 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
830 /* put the JPEG header in the new frame */
831 gspca_frame_add(gspca_dev, FIRST_PACKET,
832 sd->jpeg_hdr, JPEG_HDR_SZ);
836 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
839 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
841 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
845 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
846 reg_r(gspca_dev, 0x00e8, 8);
847 reg_w(gspca_dev, 0x00e5, regE5c, 4);
848 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
852 reg_w(gspca_dev, 0x0051, reg51c, 2);
853 reg_w(gspca_dev, 0x0010, reg10, 2);
854 reg_w_val(gspca_dev, 0x0070, reg70);
857 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
859 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
860 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
864 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
865 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
868 reg_w(gspca_dev, 0x0051, reg51c, 2);
869 reg_w(gspca_dev, 0x0010, reg10, 2);
870 reg_w_val(gspca_dev, 0x0070, reg70);
873 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
875 struct gspca_dev *gspca_dev =
876 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
877 struct sd *sd = (struct sd *)gspca_dev;
879 gspca_dev->usb_err = 0;
881 if (!gspca_dev->streaming)
885 case V4L2_CID_BRIGHTNESS:
886 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
888 case V4L2_CID_CONTRAST:
889 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
891 case V4L2_CID_SATURATION:
892 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
893 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
896 return gspca_dev->usb_err;
899 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
903 static int sd_init_controls(struct gspca_dev *gspca_dev)
905 struct sd *sd = (struct sd *)gspca_dev;
906 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
908 gspca_dev->vdev.ctrl_handler = hdl;
909 v4l2_ctrl_handler_init(hdl, 3);
910 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
911 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
912 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
913 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
914 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
915 V4L2_CID_SATURATION, 0, 7, 1, 3);
917 pr_err("Could not initialize controls\n");
923 /* sub-driver description */
924 static const struct sd_desc sd_desc = {
928 .init_controls = sd_init_controls,
931 .pkt_scan = sd_pkt_scan,
934 /* -- module initialisation -- */
935 static const struct usb_device_id device_table[] = {
936 {USB_DEVICE(0x0572, 0x0041)},
939 MODULE_DEVICE_TABLE(usb, device_table);
941 /* -- device connect -- */
942 static int sd_probe(struct usb_interface *intf,
943 const struct usb_device_id *id)
945 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
949 static struct usb_driver sd_driver = {
951 .id_table = device_table,
953 .disconnect = gspca_disconnect,
955 .suspend = gspca_suspend,
956 .resume = gspca_resume,
957 .reset_resume = gspca_resume,
961 module_usb_driver(sd_driver);