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 */
28 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29 static const char version[] = "2.1.7";
31 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
33 MODULE_LICENSE("GPL");
35 /* specific webcam descriptor */
37 struct gspca_dev gspca_dev; /* !! must be the first item */
39 unsigned char brightness;
40 unsigned char contrast;
46 /* V4L2 controls supported by the driver */
47 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
54 static struct ctrl sd_ctrls[] = {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
63 #define BRIGHTNESS_DEF 0xd4
64 .default_value = BRIGHTNESS_DEF,
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
77 #define CONTRAST_DEF 0x0c
78 .default_value = CONTRAST_DEF,
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
85 .id = V4L2_CID_SATURATION,
86 .type = V4L2_CTRL_TYPE_INTEGER,
92 .default_value = COLOR_DEF,
99 static struct v4l2_pix_format vga_mode[] = {
100 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
102 .sizeimage = 176 * 144 * 3 / 8 + 590,
103 .colorspace = V4L2_COLORSPACE_JPEG,
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
110 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
112 .sizeimage = 352 * 288 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
115 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .sizeimage = 640 * 480 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
122 /* the read bytes are found in gspca_dev->usb_buf */
123 static void reg_r(struct gspca_dev *gspca_dev,
127 struct usb_device *dev = gspca_dev->dev;
129 #ifdef CONFIG_VIDEO_ADV_DEBUG
130 if (len > sizeof gspca_dev->usb_buf) {
131 err("reg_r: buffer overflow");
136 usb_rcvctrlpipe(dev, 0),
138 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
140 index, gspca_dev->usb_buf, len,
142 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
143 index, gspca_dev->usb_buf[0]);
146 /* the bytes to write are in gspca_dev->usb_buf */
147 static void reg_w_val(struct gspca_dev *gspca_dev,
151 struct usb_device *dev = gspca_dev->dev;
153 gspca_dev->usb_buf[0] = val;
155 usb_sndctrlpipe(dev, 0),
157 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 index, gspca_dev->usb_buf, 1, 500);
162 static void reg_w(struct gspca_dev *gspca_dev,
167 struct usb_device *dev = gspca_dev->dev;
169 #ifdef CONFIG_VIDEO_ADV_DEBUG
170 if (len > sizeof gspca_dev->usb_buf) {
171 err("reg_w: buffer overflow");
174 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
176 memcpy(gspca_dev->usb_buf, buffer, len);
178 usb_sndctrlpipe(dev, 0),
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
182 index, gspca_dev->usb_buf, len, 500);
185 static const __u8 cx_sensor_init[][4] = {
186 {0x88, 0x11, 0x01, 0x01},
187 {0x88, 0x12, 0x70, 0x01},
188 {0x88, 0x0f, 0x00, 0x01},
189 {0x88, 0x05, 0x01, 0x01},
193 static const __u8 cx11646_fw1[][3] = {
260 static void cx11646_fw(struct gspca_dev*gspca_dev)
264 reg_w_val(gspca_dev, 0x006a, 0x02);
265 while (cx11646_fw1[i][1]) {
266 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
269 reg_w_val(gspca_dev, 0x006a, 0x00);
272 static const __u8 cxsensor[] = {
273 0x88, 0x12, 0x70, 0x01,
274 0x88, 0x0d, 0x02, 0x01,
275 0x88, 0x0f, 0x00, 0x01,
276 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
277 0x88, 0x02, 0x10, 0x01,
278 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
279 0x88, 0x0B, 0x00, 0x01,
280 0x88, 0x0A, 0x0A, 0x01,
281 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
282 0x88, 0x05, 0x01, 0x01,
283 0xA1, 0x18, 0x00, 0x01,
287 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
288 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
289 static const __u8 reg10[] = { 0xb1, 0xb1 };
290 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
291 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
292 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
293 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
294 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
295 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
296 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
298 static void cx_sensor(struct gspca_dev*gspca_dev)
302 const __u8 *ptsensor = cxsensor;
304 reg_w(gspca_dev, 0x0020, reg20, 8);
305 reg_w(gspca_dev, 0x0028, reg28, 8);
306 reg_w(gspca_dev, 0x0010, reg10, 8);
307 reg_w_val(gspca_dev, 0x0092, 0x03);
309 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
311 reg_w(gspca_dev, 0x0071, reg71a, 4);
314 reg_w(gspca_dev, 0x0071, reg71b, 4);
318 reg_w(gspca_dev, 0x0071, reg71c, 4);
321 reg_w(gspca_dev, 0x0071, reg71d, 4);
324 reg_w(gspca_dev, 0x007b, reg7b, 6);
325 reg_w_val(gspca_dev, 0x00f8, 0x00);
326 reg_w(gspca_dev, 0x0010, reg10, 8);
327 reg_w_val(gspca_dev, 0x0098, 0x41);
328 for (i = 0; i < 11; i++) {
329 if (i == 3 || i == 5 || i == 8)
333 reg_w(gspca_dev, 0x00e5, ptsensor, length);
335 reg_r(gspca_dev, 0x00e8, 1);
337 reg_r(gspca_dev, 0x00e8, length);
340 reg_r(gspca_dev, 0x00e7, 8);
343 static const __u8 cx_inits_176[] = {
344 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
345 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
346 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
347 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
348 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
349 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
350 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
352 static const __u8 cx_inits_320[] = {
353 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
354 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
355 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
356 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
357 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
358 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
359 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
361 static const __u8 cx_inits_352[] = {
362 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
363 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
364 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
365 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
366 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
367 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
368 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
370 static const __u8 cx_inits_640[] = {
371 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
372 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
373 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
374 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
375 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
376 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
377 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
380 static void cx11646_initsize(struct gspca_dev *gspca_dev)
383 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
384 static const __u8 reg17[] =
385 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
387 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
389 cxinit = cx_inits_640;
392 cxinit = cx_inits_352;
396 cxinit = cx_inits_320;
399 cxinit = cx_inits_176;
402 reg_w_val(gspca_dev, 0x009a, 0x01);
403 reg_w_val(gspca_dev, 0x0010, 0x10);
404 reg_w(gspca_dev, 0x0012, reg12, 5);
405 reg_w(gspca_dev, 0x0017, reg17, 8);
406 reg_w_val(gspca_dev, 0x00c0, 0x00);
407 reg_w_val(gspca_dev, 0x00c1, 0x04);
408 reg_w_val(gspca_dev, 0x00c2, 0x04);
410 reg_w(gspca_dev, 0x0061, cxinit, 8);
412 reg_w(gspca_dev, 0x00ca, cxinit, 8);
414 reg_w(gspca_dev, 0x00d2, cxinit, 8);
416 reg_w(gspca_dev, 0x00da, cxinit, 6);
418 reg_w(gspca_dev, 0x0041, cxinit, 8);
420 reg_w(gspca_dev, 0x0049, cxinit, 8);
422 reg_w(gspca_dev, 0x0051, cxinit, 2);
424 reg_r(gspca_dev, 0x0010, 1);
427 static const __u8 cx_jpeg_init[][8] = {
428 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
429 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
430 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
431 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
432 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
433 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
434 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
435 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
436 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
437 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
438 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
439 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
440 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
441 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
442 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
443 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
444 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
445 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
446 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
448 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
449 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
450 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
451 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
452 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
453 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
454 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
455 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
456 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
457 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
458 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
459 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
460 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
461 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
462 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
463 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
464 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
465 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
466 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
467 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
468 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
469 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
470 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
471 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
472 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
473 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
474 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
475 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
476 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
477 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
478 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
479 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
480 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
481 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
482 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
483 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
484 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
485 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
486 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
487 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
488 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
489 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
490 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
491 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
492 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
493 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
494 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
495 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
496 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
497 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
498 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
499 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
500 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
501 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
502 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
503 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
504 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
505 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
506 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
510 static const __u8 cxjpeg_640[][8] = {
511 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
512 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
513 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
514 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
515 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
516 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
517 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
518 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
519 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
520 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
521 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
522 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
523 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
524 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
525 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
526 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
527 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
528 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
529 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
530 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
531 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
532 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
533 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
534 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
535 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
536 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
537 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
539 static const __u8 cxjpeg_352[][8] = {
540 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
541 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
542 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
543 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
544 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
545 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
546 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
547 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
548 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
549 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
550 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
551 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
552 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
553 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
554 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
555 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
556 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
557 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
558 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
559 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
560 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
561 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
562 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
563 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
564 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
565 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
566 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
568 static const __u8 cxjpeg_320[][8] = {
569 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
570 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
571 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
572 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
573 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
574 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
575 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
576 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
577 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
578 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
579 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
580 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
581 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
582 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
583 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
584 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
585 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
586 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
587 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
588 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
589 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
590 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
591 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
592 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
593 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
594 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
595 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
597 static const __u8 cxjpeg_176[][8] = {
598 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
599 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
600 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
601 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
602 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
603 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
604 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
605 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
606 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
607 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
608 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
609 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
610 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
611 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
612 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
613 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
614 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
615 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
616 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
617 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
618 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
619 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
620 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
621 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
622 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
623 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
624 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
626 /* 640 take with the zcx30x part */
627 static const __u8 cxjpeg_qtable[][8] = {
628 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
629 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
630 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
631 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
632 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
633 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
634 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
635 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
636 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
637 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
638 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 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 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
649 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
654 reg_w_val(gspca_dev, 0x00c0, 0x01);
655 reg_w_val(gspca_dev, 0x00c3, 0x00);
656 reg_w_val(gspca_dev, 0x00c0, 0x00);
657 reg_r(gspca_dev, 0x0001, 1);
659 for (i = 0; i < 79; i++) {
662 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
664 reg_r(gspca_dev, 0x0002, 1);
665 reg_w_val(gspca_dev, 0x0055, 0x14);
668 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
669 static const __u8 regE5_8[] =
670 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
671 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
672 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
673 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
674 static const __u8 reg51[] = { 0x77, 0x03 };
677 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
684 reg_w_val(gspca_dev, 0x00c0, 0x01);
685 reg_w_val(gspca_dev, 0x00c3, 0x00);
686 reg_w_val(gspca_dev, 0x00c0, 0x00);
687 reg_r(gspca_dev, 0x0001, 1);
689 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
691 for (i = 0; i < 27; i++) {
694 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
699 for (i = 0; i < 27; i++) {
702 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
708 for (i = 0; i < 27; i++) {
711 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
716 for (i = 0; i < 27; i++) {
719 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
725 reg_r(gspca_dev, 0x0002, 1);
726 reg_w_val(gspca_dev, 0x0055, Reg55);
727 reg_r(gspca_dev, 0x0002, 1);
728 reg_w(gspca_dev, 0x0010, reg10, 2);
729 reg_w_val(gspca_dev, 0x0054, 0x02);
730 reg_w_val(gspca_dev, 0x0054, 0x01);
731 reg_w_val(gspca_dev, 0x0000, 0x94);
732 reg_w_val(gspca_dev, 0x0053, 0xc0);
733 reg_w_val(gspca_dev, 0x00fc, 0xe1);
734 reg_w_val(gspca_dev, 0x0000, 0x00);
735 /* wait for completion */
738 reg_r(gspca_dev, 0x0002, 1);
739 /* 0x07 until 0x00 */
740 if (gspca_dev->usb_buf[0] == 0x00)
742 reg_w_val(gspca_dev, 0x0053, 0x00);
745 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
746 /* send the qtable now */
747 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
749 for (i = 0; i < 18; i++) {
752 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
755 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
756 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
757 reg_w_val(gspca_dev, 0x0054, 0x02);
758 reg_w_val(gspca_dev, 0x0054, 0x01);
759 reg_w_val(gspca_dev, 0x0000, 0x94);
760 reg_w_val(gspca_dev, 0x0053, 0xc0);
762 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
763 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
764 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
765 reg_w(gspca_dev, 0x0012, reg12, 5);
766 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
767 reg_r(gspca_dev, 0x00e8, 8);
768 reg_w(gspca_dev, 0x00e5, regE5a, 4);
769 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
770 reg_w_val(gspca_dev, 0x009a, 0x01);
771 reg_w(gspca_dev, 0x00e5, regE5b, 4);
772 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
773 reg_w(gspca_dev, 0x00e5, regE5c, 4);
774 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
776 reg_w(gspca_dev, 0x0051, reg51, 2);
777 reg_w(gspca_dev, 0x0010, reg10, 2);
778 reg_w_val(gspca_dev, 0x0070, reg70);
781 static void cx11646_init1(struct gspca_dev *gspca_dev)
785 reg_w_val(gspca_dev, 0x0010, 0x00);
786 reg_w_val(gspca_dev, 0x0053, 0x00);
787 reg_w_val(gspca_dev, 0x0052, 0x00);
788 reg_w_val(gspca_dev, 0x009b, 0x2f);
789 reg_w_val(gspca_dev, 0x009c, 0x10);
790 reg_r(gspca_dev, 0x0098, 1);
791 reg_w_val(gspca_dev, 0x0098, 0x40);
792 reg_r(gspca_dev, 0x0099, 1);
793 reg_w_val(gspca_dev, 0x0099, 0x07);
794 reg_w_val(gspca_dev, 0x0039, 0x40);
795 reg_w_val(gspca_dev, 0x003c, 0xff);
796 reg_w_val(gspca_dev, 0x003f, 0x1f);
797 reg_w_val(gspca_dev, 0x003d, 0x40);
798 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
799 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
801 while (cx_sensor_init[i][0]) {
802 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
803 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
805 reg_w_val(gspca_dev, 0x00ed, 0x01);
806 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
810 reg_w_val(gspca_dev, 0x00c3, 0x00);
813 /* this function is called at probe time */
814 static int sd_config(struct gspca_dev *gspca_dev,
815 const struct usb_device_id *id)
817 struct sd *sd = (struct sd *) gspca_dev;
820 cam = &gspca_dev->cam;
821 cam->dev_name = (char *) id->driver_info;
823 cam->cam_mode = vga_mode;
824 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
826 sd->qindex = 0; /* set the quantization */
827 sd->brightness = BRIGHTNESS_DEF;
828 sd->contrast = CONTRAST_DEF;
829 sd->colors = COLOR_DEF;
833 /* this function is called at open time */
834 static int sd_open(struct gspca_dev *gspca_dev)
836 cx11646_init1(gspca_dev);
837 cx11646_initsize(gspca_dev);
838 cx11646_fw(gspca_dev);
839 cx_sensor(gspca_dev);
840 cx11646_jpegInit(gspca_dev);
844 static void sd_start(struct gspca_dev *gspca_dev)
846 cx11646_initsize(gspca_dev);
847 cx11646_fw(gspca_dev);
848 cx_sensor(gspca_dev);
849 cx11646_jpeg(gspca_dev);
852 static void sd_stopN(struct gspca_dev *gspca_dev)
856 static void sd_stop0(struct gspca_dev *gspca_dev)
860 reg_w_val(gspca_dev, 0x0000, 0x00);
861 reg_r(gspca_dev, 0x0002, 1);
862 reg_w_val(gspca_dev, 0x0053, 0x00);
865 /* reg_r(gspca_dev, 0x0002, 1);*/
866 reg_r(gspca_dev, 0x0053, 1);
867 if (gspca_dev->usb_buf[0] == 0)
870 reg_w_val(gspca_dev, 0x0000, 0x00);
871 reg_r(gspca_dev, 0x0002, 1);
873 reg_w_val(gspca_dev, 0x0010, 0x00);
874 reg_r(gspca_dev, 0x0033, 1);
875 reg_w_val(gspca_dev, 0x00fc, 0xe0);
878 static void sd_close(struct gspca_dev *gspca_dev)
882 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
883 struct gspca_frame *frame, /* target */
884 __u8 *data, /* isoc packet */
885 int len) /* iso packet length */
887 if (data[0] == 0xff && data[1] == 0xd8) {
890 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
893 /* put the JPEG header in the new frame */
894 jpeg_put_header(gspca_dev, frame,
895 ((struct sd *) gspca_dev)->qindex,
900 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
903 static void setbrightness(struct gspca_dev*gspca_dev)
905 struct sd *sd = (struct sd *) gspca_dev;
906 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
911 bright = sd->brightness;
912 regE5cbx[2] = bright;
913 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
914 reg_r(gspca_dev, 0x00e8, 8);
915 reg_w(gspca_dev, 0x00e5, regE5c, 4);
916 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
921 reg_w(gspca_dev, 0x0051, reg51c, 2);
922 reg_w(gspca_dev, 0x0010, reg10, 2);
923 reg_w_val(gspca_dev, 0x0070, reg70);
926 static void setcontrast(struct gspca_dev*gspca_dev)
928 struct sd *sd = (struct sd *) gspca_dev;
929 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
930 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
933 regE5acx[2] = sd->contrast;
934 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
935 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
937 reg51c[1] = sd->colors;
938 reg_w(gspca_dev, 0x0051, reg51c, 2);
939 reg_w(gspca_dev, 0x0010, reg10, 2);
940 reg_w_val(gspca_dev, 0x0070, reg70);
943 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
945 struct sd *sd = (struct sd *) gspca_dev;
947 sd->brightness = val;
948 if (gspca_dev->streaming)
949 setbrightness(gspca_dev);
953 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
955 struct sd *sd = (struct sd *) gspca_dev;
957 *val = sd->brightness;
961 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
963 struct sd *sd = (struct sd *) gspca_dev;
966 if (gspca_dev->streaming)
967 setcontrast(gspca_dev);
971 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
973 struct sd *sd = (struct sd *) gspca_dev;
979 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
981 struct sd *sd = (struct sd *) gspca_dev;
984 if (gspca_dev->streaming) {
985 setbrightness(gspca_dev);
986 setcontrast(gspca_dev);
991 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
993 struct sd *sd = (struct sd *) gspca_dev;
999 /* sub-driver description */
1000 static struct sd_desc sd_desc = {
1001 .name = MODULE_NAME,
1003 .nctrls = ARRAY_SIZE(sd_ctrls),
1004 .config = sd_config,
1010 .pkt_scan = sd_pkt_scan,
1013 /* -- module initialisation -- */
1014 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1015 static __devinitdata struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1019 MODULE_DEVICE_TABLE(usb, device_table);
1021 /* -- device connect -- */
1022 static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1025 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1029 static struct usb_driver sd_driver = {
1030 .name = MODULE_NAME,
1031 .id_table = device_table,
1033 .disconnect = gspca_disconnect,
1036 /* -- module insert / remove -- */
1037 static int __init sd_mod_init(void)
1039 if (usb_register(&sd_driver) < 0)
1041 PDEBUG(D_PROBE, "v%s registered", version);
1044 static void __exit sd_mod_exit(void)
1046 usb_deregister(&sd_driver);
1047 PDEBUG(D_PROBE, "deregistered");
1050 module_init(sd_mod_init);
1051 module_exit(sd_mod_exit);