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.
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
22 #define MODULE_NAME "conex"
25 #define CONEX_CAM 1 /* special JPEG header */
26 #define QUANT_VAL 0 /* quantization table */
29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
31 MODULE_LICENSE("GPL");
33 /* specific webcam descriptor */
35 struct gspca_dev gspca_dev; /* !! must be the first item */
37 unsigned char brightness;
38 unsigned char contrast;
42 /* V4L2 controls supported by the driver */
43 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
44 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
45 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
46 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
47 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
48 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
50 static struct ctrl sd_ctrls[] = {
53 .id = V4L2_CID_BRIGHTNESS,
54 .type = V4L2_CTRL_TYPE_INTEGER,
59 #define BRIGHTNESS_DEF 0xd4
60 .default_value = BRIGHTNESS_DEF,
62 .set = sd_setbrightness,
63 .get = sd_getbrightness,
67 .id = V4L2_CID_CONTRAST,
68 .type = V4L2_CTRL_TYPE_INTEGER,
73 #define CONTRAST_DEF 0x0c
74 .default_value = CONTRAST_DEF,
76 .set = sd_setcontrast,
77 .get = sd_getcontrast,
81 .id = V4L2_CID_SATURATION,
82 .type = V4L2_CTRL_TYPE_INTEGER,
88 .default_value = COLOR_DEF,
95 static const struct v4l2_pix_format vga_mode[] = {
96 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
98 .sizeimage = 176 * 144 * 3 / 8 + 590,
99 .colorspace = V4L2_COLORSPACE_JPEG,
101 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
103 .sizeimage = 320 * 240 * 3 / 8 + 590,
104 .colorspace = V4L2_COLORSPACE_JPEG,
106 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
108 .sizeimage = 352 * 288 * 3 / 8 + 590,
109 .colorspace = V4L2_COLORSPACE_JPEG,
111 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
113 .sizeimage = 640 * 480 * 3 / 8 + 590,
114 .colorspace = V4L2_COLORSPACE_JPEG,
118 /* the read bytes are found in gspca_dev->usb_buf */
119 static void reg_r(struct gspca_dev *gspca_dev,
123 struct usb_device *dev = gspca_dev->dev;
126 if (len > USB_BUF_SZ) {
127 err("reg_r: buffer overflow");
132 usb_rcvctrlpipe(dev, 0),
134 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
136 index, gspca_dev->usb_buf, len,
138 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
139 index, gspca_dev->usb_buf[0]);
142 /* the bytes to write are in gspca_dev->usb_buf */
143 static void reg_w_val(struct gspca_dev *gspca_dev,
147 struct usb_device *dev = gspca_dev->dev;
149 gspca_dev->usb_buf[0] = val;
151 usb_sndctrlpipe(dev, 0),
153 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
155 index, gspca_dev->usb_buf, 1, 500);
158 static void reg_w(struct gspca_dev *gspca_dev,
163 struct usb_device *dev = gspca_dev->dev;
166 if (len > USB_BUF_SZ) {
167 err("reg_w: buffer overflow");
170 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
172 memcpy(gspca_dev->usb_buf, buffer, len);
174 usb_sndctrlpipe(dev, 0),
176 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
178 index, gspca_dev->usb_buf, len, 500);
181 static const __u8 cx_sensor_init[][4] = {
182 {0x88, 0x11, 0x01, 0x01},
183 {0x88, 0x12, 0x70, 0x01},
184 {0x88, 0x0f, 0x00, 0x01},
185 {0x88, 0x05, 0x01, 0x01},
189 static const __u8 cx11646_fw1[][3] = {
256 static void cx11646_fw(struct gspca_dev*gspca_dev)
260 reg_w_val(gspca_dev, 0x006a, 0x02);
261 while (cx11646_fw1[i][1]) {
262 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
265 reg_w_val(gspca_dev, 0x006a, 0x00);
268 static const __u8 cxsensor[] = {
269 0x88, 0x12, 0x70, 0x01,
270 0x88, 0x0d, 0x02, 0x01,
271 0x88, 0x0f, 0x00, 0x01,
272 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
273 0x88, 0x02, 0x10, 0x01,
274 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
275 0x88, 0x0B, 0x00, 0x01,
276 0x88, 0x0A, 0x0A, 0x01,
277 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
278 0x88, 0x05, 0x01, 0x01,
279 0xA1, 0x18, 0x00, 0x01,
283 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
284 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
285 static const __u8 reg10[] = { 0xb1, 0xb1 };
286 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
287 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
288 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
289 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
290 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
291 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
292 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
294 static void cx_sensor(struct gspca_dev*gspca_dev)
298 const __u8 *ptsensor = cxsensor;
300 reg_w(gspca_dev, 0x0020, reg20, 8);
301 reg_w(gspca_dev, 0x0028, reg28, 8);
302 reg_w(gspca_dev, 0x0010, reg10, 8);
303 reg_w_val(gspca_dev, 0x0092, 0x03);
305 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
307 reg_w(gspca_dev, 0x0071, reg71a, 4);
310 reg_w(gspca_dev, 0x0071, reg71b, 4);
314 reg_w(gspca_dev, 0x0071, reg71c, 4);
317 reg_w(gspca_dev, 0x0071, reg71d, 4);
320 reg_w(gspca_dev, 0x007b, reg7b, 6);
321 reg_w_val(gspca_dev, 0x00f8, 0x00);
322 reg_w(gspca_dev, 0x0010, reg10, 8);
323 reg_w_val(gspca_dev, 0x0098, 0x41);
324 for (i = 0; i < 11; i++) {
325 if (i == 3 || i == 5 || i == 8)
329 reg_w(gspca_dev, 0x00e5, ptsensor, length);
331 reg_r(gspca_dev, 0x00e8, 1);
333 reg_r(gspca_dev, 0x00e8, length);
336 reg_r(gspca_dev, 0x00e7, 8);
339 static const __u8 cx_inits_176[] = {
340 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
341 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
342 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
343 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
344 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
345 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
346 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
348 static const __u8 cx_inits_320[] = {
349 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
350 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
351 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
352 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
353 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
354 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
355 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
357 static const __u8 cx_inits_352[] = {
358 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
359 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
360 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
361 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
362 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
363 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
364 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
366 static const __u8 cx_inits_640[] = {
367 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
368 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
369 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
370 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
371 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
372 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
373 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
376 static void cx11646_initsize(struct gspca_dev *gspca_dev)
379 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
380 static const __u8 reg17[] =
381 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
383 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
385 cxinit = cx_inits_640;
388 cxinit = cx_inits_352;
392 cxinit = cx_inits_320;
395 cxinit = cx_inits_176;
398 reg_w_val(gspca_dev, 0x009a, 0x01);
399 reg_w_val(gspca_dev, 0x0010, 0x10);
400 reg_w(gspca_dev, 0x0012, reg12, 5);
401 reg_w(gspca_dev, 0x0017, reg17, 8);
402 reg_w_val(gspca_dev, 0x00c0, 0x00);
403 reg_w_val(gspca_dev, 0x00c1, 0x04);
404 reg_w_val(gspca_dev, 0x00c2, 0x04);
406 reg_w(gspca_dev, 0x0061, cxinit, 8);
408 reg_w(gspca_dev, 0x00ca, cxinit, 8);
410 reg_w(gspca_dev, 0x00d2, cxinit, 8);
412 reg_w(gspca_dev, 0x00da, cxinit, 6);
414 reg_w(gspca_dev, 0x0041, cxinit, 8);
416 reg_w(gspca_dev, 0x0049, cxinit, 8);
418 reg_w(gspca_dev, 0x0051, cxinit, 2);
420 reg_r(gspca_dev, 0x0010, 1);
423 static const __u8 cx_jpeg_init[][8] = {
424 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
425 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
426 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
427 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
428 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
429 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
430 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
431 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
432 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
433 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
434 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
435 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
436 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
437 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
438 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
439 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
440 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
441 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
442 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
443 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
444 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
445 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
446 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
448 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
449 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
450 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
451 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
452 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
453 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
454 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
455 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
456 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
457 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
458 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
459 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
460 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
461 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
462 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
463 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
464 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
465 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
466 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
467 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
468 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
469 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
470 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
471 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
472 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
473 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
474 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
475 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
476 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
477 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
478 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
479 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
480 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
481 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
482 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
483 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
484 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
485 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
486 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
487 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
488 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
489 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
490 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
491 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
492 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
493 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
494 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
495 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
496 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
497 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
498 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
499 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
500 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
501 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
502 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
506 static const __u8 cxjpeg_640[][8] = {
507 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
508 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
509 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
510 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
511 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
512 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
513 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
514 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
515 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
516 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
517 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
518 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
519 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
520 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
521 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
522 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
523 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
524 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
525 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
526 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
527 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
528 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
529 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
530 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
531 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
532 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
533 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
535 static const __u8 cxjpeg_352[][8] = {
536 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
537 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
538 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
539 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
540 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
541 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
542 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
543 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
544 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
545 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
546 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
547 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
548 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
549 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
550 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
551 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
552 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
553 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
554 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
555 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
556 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
557 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
558 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
559 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
560 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
561 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
562 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
564 static const __u8 cxjpeg_320[][8] = {
565 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
566 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
567 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
568 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
569 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
570 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
571 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
572 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
573 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
574 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
575 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
576 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
577 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
578 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
579 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
580 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
581 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
582 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
583 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
584 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
585 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
586 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
587 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
588 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
589 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
590 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
591 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
593 static const __u8 cxjpeg_176[][8] = {
594 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
595 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
596 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
597 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
598 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
599 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
600 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
601 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
602 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
603 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
604 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
605 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
606 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
607 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
608 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
609 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
610 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
611 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
612 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
613 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
614 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
615 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
616 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
617 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
618 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
619 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
620 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
622 /* 640 take with the zcx30x part */
623 static const __u8 cxjpeg_qtable[][8] = {
624 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
625 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
626 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
627 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
628 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
629 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
630 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
631 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
632 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
633 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
634 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
635 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 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 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
645 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
650 reg_w_val(gspca_dev, 0x00c0, 0x01);
651 reg_w_val(gspca_dev, 0x00c3, 0x00);
652 reg_w_val(gspca_dev, 0x00c0, 0x00);
653 reg_r(gspca_dev, 0x0001, 1);
655 for (i = 0; i < 79; i++) {
658 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
660 reg_r(gspca_dev, 0x0002, 1);
661 reg_w_val(gspca_dev, 0x0055, 0x14);
664 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
665 static const __u8 regE5_8[] =
666 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
667 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
668 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
669 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
670 static const __u8 reg51[] = { 0x77, 0x03 };
673 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
680 reg_w_val(gspca_dev, 0x00c0, 0x01);
681 reg_w_val(gspca_dev, 0x00c3, 0x00);
682 reg_w_val(gspca_dev, 0x00c0, 0x00);
683 reg_r(gspca_dev, 0x0001, 1);
685 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
687 for (i = 0; i < 27; i++) {
690 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
695 for (i = 0; i < 27; i++) {
698 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
704 for (i = 0; i < 27; i++) {
707 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
712 for (i = 0; i < 27; i++) {
715 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
721 reg_r(gspca_dev, 0x0002, 1);
722 reg_w_val(gspca_dev, 0x0055, Reg55);
723 reg_r(gspca_dev, 0x0002, 1);
724 reg_w(gspca_dev, 0x0010, reg10, 2);
725 reg_w_val(gspca_dev, 0x0054, 0x02);
726 reg_w_val(gspca_dev, 0x0054, 0x01);
727 reg_w_val(gspca_dev, 0x0000, 0x94);
728 reg_w_val(gspca_dev, 0x0053, 0xc0);
729 reg_w_val(gspca_dev, 0x00fc, 0xe1);
730 reg_w_val(gspca_dev, 0x0000, 0x00);
731 /* wait for completion */
734 reg_r(gspca_dev, 0x0002, 1);
735 /* 0x07 until 0x00 */
736 if (gspca_dev->usb_buf[0] == 0x00)
738 reg_w_val(gspca_dev, 0x0053, 0x00);
741 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
742 /* send the qtable now */
743 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
745 for (i = 0; i < 18; i++) {
748 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
751 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
752 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
753 reg_w_val(gspca_dev, 0x0054, 0x02);
754 reg_w_val(gspca_dev, 0x0054, 0x01);
755 reg_w_val(gspca_dev, 0x0000, 0x94);
756 reg_w_val(gspca_dev, 0x0053, 0xc0);
758 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
759 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
760 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
761 reg_w(gspca_dev, 0x0012, reg12, 5);
762 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
763 reg_r(gspca_dev, 0x00e8, 8);
764 reg_w(gspca_dev, 0x00e5, regE5a, 4);
765 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
766 reg_w_val(gspca_dev, 0x009a, 0x01);
767 reg_w(gspca_dev, 0x00e5, regE5b, 4);
768 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
769 reg_w(gspca_dev, 0x00e5, regE5c, 4);
770 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
772 reg_w(gspca_dev, 0x0051, reg51, 2);
773 reg_w(gspca_dev, 0x0010, reg10, 2);
774 reg_w_val(gspca_dev, 0x0070, reg70);
777 static void cx11646_init1(struct gspca_dev *gspca_dev)
781 reg_w_val(gspca_dev, 0x0010, 0x00);
782 reg_w_val(gspca_dev, 0x0053, 0x00);
783 reg_w_val(gspca_dev, 0x0052, 0x00);
784 reg_w_val(gspca_dev, 0x009b, 0x2f);
785 reg_w_val(gspca_dev, 0x009c, 0x10);
786 reg_r(gspca_dev, 0x0098, 1);
787 reg_w_val(gspca_dev, 0x0098, 0x40);
788 reg_r(gspca_dev, 0x0099, 1);
789 reg_w_val(gspca_dev, 0x0099, 0x07);
790 reg_w_val(gspca_dev, 0x0039, 0x40);
791 reg_w_val(gspca_dev, 0x003c, 0xff);
792 reg_w_val(gspca_dev, 0x003f, 0x1f);
793 reg_w_val(gspca_dev, 0x003d, 0x40);
794 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
795 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
797 while (cx_sensor_init[i][0]) {
798 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
799 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
801 reg_w_val(gspca_dev, 0x00ed, 0x01);
802 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
806 reg_w_val(gspca_dev, 0x00c3, 0x00);
809 /* this function is called at probe time */
810 static int sd_config(struct gspca_dev *gspca_dev,
811 const struct usb_device_id *id)
813 struct sd *sd = (struct sd *) gspca_dev;
816 cam = &gspca_dev->cam;
817 cam->cam_mode = vga_mode;
818 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
820 sd->brightness = BRIGHTNESS_DEF;
821 sd->contrast = CONTRAST_DEF;
822 sd->colors = COLOR_DEF;
826 /* this function is called at probe and resume time */
827 static int sd_init(struct gspca_dev *gspca_dev)
829 cx11646_init1(gspca_dev);
830 cx11646_initsize(gspca_dev);
831 cx11646_fw(gspca_dev);
832 cx_sensor(gspca_dev);
833 cx11646_jpegInit(gspca_dev);
837 static int sd_start(struct gspca_dev *gspca_dev)
839 cx11646_initsize(gspca_dev);
840 cx11646_fw(gspca_dev);
841 cx_sensor(gspca_dev);
842 cx11646_jpeg(gspca_dev);
846 /* called on streamoff with alt 0 and on disconnect */
847 static void sd_stop0(struct gspca_dev *gspca_dev)
851 if (!gspca_dev->present)
853 reg_w_val(gspca_dev, 0x0000, 0x00);
854 reg_r(gspca_dev, 0x0002, 1);
855 reg_w_val(gspca_dev, 0x0053, 0x00);
858 /* reg_r(gspca_dev, 0x0002, 1);*/
859 reg_r(gspca_dev, 0x0053, 1);
860 if (gspca_dev->usb_buf[0] == 0)
863 reg_w_val(gspca_dev, 0x0000, 0x00);
864 reg_r(gspca_dev, 0x0002, 1);
866 reg_w_val(gspca_dev, 0x0010, 0x00);
867 reg_r(gspca_dev, 0x0033, 1);
868 reg_w_val(gspca_dev, 0x00fc, 0xe0);
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 */
876 if (data[0] == 0xff && data[1] == 0xd8) {
879 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
882 /* put the JPEG header in the new frame */
883 jpeg_put_header(gspca_dev, frame, 0x22);
887 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
890 static void setbrightness(struct gspca_dev*gspca_dev)
892 struct sd *sd = (struct sd *) gspca_dev;
893 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
898 bright = sd->brightness;
899 regE5cbx[2] = bright;
900 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
901 reg_r(gspca_dev, 0x00e8, 8);
902 reg_w(gspca_dev, 0x00e5, regE5c, 4);
903 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
908 reg_w(gspca_dev, 0x0051, reg51c, 2);
909 reg_w(gspca_dev, 0x0010, reg10, 2);
910 reg_w_val(gspca_dev, 0x0070, reg70);
913 static void setcontrast(struct gspca_dev*gspca_dev)
915 struct sd *sd = (struct sd *) gspca_dev;
916 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
917 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
920 regE5acx[2] = sd->contrast;
921 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
922 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
924 reg51c[1] = sd->colors;
925 reg_w(gspca_dev, 0x0051, reg51c, 2);
926 reg_w(gspca_dev, 0x0010, reg10, 2);
927 reg_w_val(gspca_dev, 0x0070, reg70);
930 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
932 struct sd *sd = (struct sd *) gspca_dev;
934 sd->brightness = val;
935 if (gspca_dev->streaming)
936 setbrightness(gspca_dev);
940 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
942 struct sd *sd = (struct sd *) gspca_dev;
944 *val = sd->brightness;
948 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
950 struct sd *sd = (struct sd *) gspca_dev;
953 if (gspca_dev->streaming)
954 setcontrast(gspca_dev);
958 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
960 struct sd *sd = (struct sd *) gspca_dev;
966 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
968 struct sd *sd = (struct sd *) gspca_dev;
971 if (gspca_dev->streaming) {
972 setbrightness(gspca_dev);
973 setcontrast(gspca_dev);
978 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
980 struct sd *sd = (struct sd *) gspca_dev;
986 /* sub-driver description */
987 static struct sd_desc sd_desc = {
990 .nctrls = ARRAY_SIZE(sd_ctrls),
995 .pkt_scan = sd_pkt_scan,
998 /* -- module initialisation -- */
999 static __devinitdata struct usb_device_id device_table[] = {
1000 {USB_DEVICE(0x0572, 0x0041)},
1003 MODULE_DEVICE_TABLE(usb, device_table);
1005 /* -- device connect -- */
1006 static int sd_probe(struct usb_interface *intf,
1007 const struct usb_device_id *id)
1009 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1013 static struct usb_driver sd_driver = {
1014 .name = MODULE_NAME,
1015 .id_table = device_table,
1017 .disconnect = gspca_disconnect,
1019 .suspend = gspca_suspend,
1020 .resume = gspca_resume,
1024 /* -- module insert / remove -- */
1025 static int __init sd_mod_init(void)
1028 ret = usb_register(&sd_driver);
1031 PDEBUG(D_PROBE, "registered");
1034 static void __exit sd_mod_exit(void)
1036 usb_deregister(&sd_driver);
1037 PDEBUG(D_PROBE, "deregistered");
1040 module_init(sd_mod_init);
1041 module_exit(sd_mod_exit);