4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *Notes: * t613 + tas5130A
21 * * Focus to light do not balance well as in win.
22 * Quality in win is not good, but its kinda better.
23 * * Fix some "extraneous bytes", most of apps will show the image anyway
24 * * Gamma table, is there, but its really doing something?
25 * * 7~8 Fps, its ok, max on win its 10.
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31 #define MODULE_NAME "t613"
33 #include <linux/input.h>
34 #include <linux/slab.h>
37 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
39 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
40 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
41 MODULE_LICENSE("GPL");
44 struct gspca_dev gspca_dev
; /* !! must be the first item */
56 u8 awb
; /* set default r/g/b and activate */
67 SENSOR_LT168G
, /* must verify if this is the actual model */
70 /* V4L2 controls supported by the driver */
71 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
);
72 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
);
73 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
);
74 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
);
75 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
);
76 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
);
77 static int sd_setlowlight(struct gspca_dev
*gspca_dev
, __s32 val
);
78 static int sd_getlowlight(struct gspca_dev
*gspca_dev
, __s32
*val
);
79 static int sd_setgamma(struct gspca_dev
*gspca_dev
, __s32 val
);
80 static int sd_getgamma(struct gspca_dev
*gspca_dev
, __s32
*val
);
81 static int sd_setsharpness(struct gspca_dev
*gspca_dev
, __s32 val
);
82 static int sd_getsharpness(struct gspca_dev
*gspca_dev
, __s32
*val
);
83 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
);
84 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
);
86 static int sd_setawb(struct gspca_dev
*gspca_dev
, __s32 val
);
87 static int sd_getawb(struct gspca_dev
*gspca_dev
, __s32
*val
);
88 static int sd_setblue_gain(struct gspca_dev
*gspca_dev
, __s32 val
);
89 static int sd_getblue_gain(struct gspca_dev
*gspca_dev
, __s32
*val
);
90 static int sd_setred_gain(struct gspca_dev
*gspca_dev
, __s32 val
);
91 static int sd_getred_gain(struct gspca_dev
*gspca_dev
, __s32
*val
);
92 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
);
93 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
);
95 static int sd_setmirror(struct gspca_dev
*gspca_dev
, __s32 val
);
96 static int sd_getmirror(struct gspca_dev
*gspca_dev
, __s32
*val
);
97 static int sd_seteffect(struct gspca_dev
*gspca_dev
, __s32 val
);
98 static int sd_geteffect(struct gspca_dev
*gspca_dev
, __s32
*val
);
100 static const struct ctrl sd_ctrls
[] = {
103 .id
= V4L2_CID_BRIGHTNESS
,
104 .type
= V4L2_CTRL_TYPE_INTEGER
,
105 .name
= "Brightness",
109 #define BRIGHTNESS_DEF 8
110 .default_value
= BRIGHTNESS_DEF
,
112 .set
= sd_setbrightness
,
113 .get
= sd_getbrightness
,
117 .id
= V4L2_CID_CONTRAST
,
118 .type
= V4L2_CTRL_TYPE_INTEGER
,
123 #define CONTRAST_DEF 0x07
124 .default_value
= CONTRAST_DEF
,
126 .set
= sd_setcontrast
,
127 .get
= sd_getcontrast
,
131 .id
= V4L2_CID_SATURATION
,
132 .type
= V4L2_CTRL_TYPE_INTEGER
,
137 #define COLORS_DEF 0x05
138 .default_value
= COLORS_DEF
,
147 .id
= V4L2_CID_GAMMA
, /* (gamma on win) */
148 .type
= V4L2_CTRL_TYPE_INTEGER
,
151 .maximum
= GAMMA_MAX
- 1,
153 .default_value
= GAMMA_DEF
,
160 .id
= V4L2_CID_BACKLIGHT_COMPENSATION
, /* Activa lowlight,
161 * some apps dont bring up the
162 * backligth_compensation control) */
163 .type
= V4L2_CTRL_TYPE_INTEGER
,
168 #define AUTOGAIN_DEF 0x01
169 .default_value
= AUTOGAIN_DEF
,
171 .set
= sd_setlowlight
,
172 .get
= sd_getlowlight
,
176 .id
= V4L2_CID_HFLIP
,
177 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
178 .name
= "Mirror Image",
183 .default_value
= MIRROR_DEF
,
190 .id
= V4L2_CID_POWER_LINE_FREQUENCY
,
191 .type
= V4L2_CTRL_TYPE_MENU
,
192 .name
= "Light Frequency Filter",
193 .minimum
= 1, /* 1 -> 0x50, 2->0x60 */
197 .default_value
= FREQ_DEF
,
204 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
205 .type
= V4L2_CTRL_TYPE_INTEGER
,
206 .name
= "Auto White Balance",
211 .default_value
= AWB_DEF
,
218 .id
= V4L2_CID_SHARPNESS
,
219 .type
= V4L2_CTRL_TYPE_INTEGER
,
224 #define SHARPNESS_DEF 0x06
225 .default_value
= SHARPNESS_DEF
,
227 .set
= sd_setsharpness
,
228 .get
= sd_getsharpness
,
232 .id
= V4L2_CID_EFFECTS
,
233 .type
= V4L2_CTRL_TYPE_MENU
,
234 .name
= "Webcam Effects",
238 #define EFFECTS_DEF 0
239 .default_value
= EFFECTS_DEF
,
246 .id
= V4L2_CID_BLUE_BALANCE
,
247 .type
= V4L2_CTRL_TYPE_INTEGER
,
248 .name
= "Blue Balance",
252 #define BLUE_GAIN_DEF 0x20
253 .default_value
= BLUE_GAIN_DEF
,
255 .set
= sd_setblue_gain
,
256 .get
= sd_getblue_gain
,
260 .id
= V4L2_CID_RED_BALANCE
,
261 .type
= V4L2_CTRL_TYPE_INTEGER
,
262 .name
= "Red Balance",
266 #define RED_GAIN_DEF 0x20
267 .default_value
= RED_GAIN_DEF
,
269 .set
= sd_setred_gain
,
270 .get
= sd_getred_gain
,
275 .type
= V4L2_CTRL_TYPE_INTEGER
,
280 #define GAIN_DEF 0x20
281 .default_value
= GAIN_DEF
,
288 static const struct v4l2_pix_format vga_mode_t16
[] = {
289 {160, 120, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
291 .sizeimage
= 160 * 120 * 4 / 8 + 590,
292 .colorspace
= V4L2_COLORSPACE_JPEG
,
294 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
296 .sizeimage
= 176 * 144 * 3 / 8 + 590,
297 .colorspace
= V4L2_COLORSPACE_JPEG
,
299 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
301 .sizeimage
= 320 * 240 * 3 / 8 + 590,
302 .colorspace
= V4L2_COLORSPACE_JPEG
,
304 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
306 .sizeimage
= 352 * 288 * 3 / 8 + 590,
307 .colorspace
= V4L2_COLORSPACE_JPEG
,
309 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
311 .sizeimage
= 640 * 480 * 3 / 8 + 590,
312 .colorspace
= V4L2_COLORSPACE_JPEG
,
316 /* sensor specific data */
317 struct additional_sensor_data
{
320 const u8 reg80
, reg8e
;
329 static const u8 n4_om6802
[] = {
330 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
331 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
332 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
333 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
334 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
335 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
336 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
337 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
338 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
340 static const u8 n4_other
[] = {
341 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
342 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
343 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
344 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
345 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
346 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
347 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
348 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
350 static const u8 n4_tas5130a
[] = {
351 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
352 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
353 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
354 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
355 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
356 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
359 static const u8 n4_lt168g
[] = {
360 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
361 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
362 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
363 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
364 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
365 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
366 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
367 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
368 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
371 static const struct additional_sensor_data sensor_data
[] = {
374 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
376 .n4sz
= sizeof n4_om6802
,
379 .nset8
= {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
381 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
384 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
387 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
389 .data5
= /* this could be removed later */
390 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
392 {0x0b, 0x04, 0x0a, 0x78},
396 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
398 .n4sz
= sizeof n4_other
,
401 .nset8
= {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
403 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
409 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
412 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
414 {0x0b, 0x04, 0x0a, 0x00},
416 [SENSOR_TAS5130A
] = {
418 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
420 .n4sz
= sizeof n4_tas5130a
,
423 .nset8
= {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
425 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
428 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
431 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
434 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
436 {0x0b, 0x04, 0x0a, 0x40},
439 .n3
= {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
441 .n4sz
= sizeof n4_lt168g
,
444 .nset8
= {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
445 .data1
= {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
447 .data2
= {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
449 .data3
= {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
451 .data5
= {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
452 .stream
= {0x0b, 0x04, 0x0a, 0x28},
456 #define MAX_EFFECTS 7
457 /* easily done by soft, this table could be removed,
458 * i keep it here just in case */
459 static char *effects_control
[MAX_EFFECTS
] = {
461 "Emboss", /* disabled */
465 "Sun Effect", /* disabled */
468 static const u8 effects_table
[MAX_EFFECTS
][6] = {
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
470 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
471 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
472 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
473 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
474 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
475 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
478 static const u8 gamma_table
[GAMMA_MAX
][17] = {
479 /* gamma table from cam1690.ini */
480 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
481 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
483 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
484 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
486 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
487 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
489 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
490 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
492 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
493 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
495 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
496 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
498 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
499 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
501 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
502 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
504 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
505 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
507 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
508 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
510 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
511 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
513 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
514 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
516 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
517 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
519 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
520 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
522 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
523 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
525 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
526 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
530 static const u8 tas5130a_sensor_init
[][8] = {
531 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
532 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
533 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
536 static u8 sensor_reset
[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
539 static u8
reg_r(struct gspca_dev
*gspca_dev
,
542 usb_control_msg(gspca_dev
->dev
,
543 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
545 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
548 gspca_dev
->usb_buf
, 1, 500);
549 return gspca_dev
->usb_buf
[0];
552 static void reg_w(struct gspca_dev
*gspca_dev
,
555 usb_control_msg(gspca_dev
->dev
,
556 usb_sndctrlpipe(gspca_dev
->dev
, 0),
558 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
563 static void reg_w_buf(struct gspca_dev
*gspca_dev
,
564 const u8
*buffer
, u16 len
)
566 if (len
<= USB_BUF_SZ
) {
567 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
568 usb_control_msg(gspca_dev
->dev
,
569 usb_sndctrlpipe(gspca_dev
->dev
, 0),
571 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
573 gspca_dev
->usb_buf
, len
, 500);
577 tmpbuf
= kmemdup(buffer
, len
, GFP_KERNEL
);
579 pr_err("Out of memory\n");
582 usb_control_msg(gspca_dev
->dev
,
583 usb_sndctrlpipe(gspca_dev
->dev
, 0),
585 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
592 /* write values to consecutive registers */
593 static void reg_w_ixbuf(struct gspca_dev
*gspca_dev
,
595 const u8
*buffer
, u16 len
)
600 if (len
* 2 <= USB_BUF_SZ
) {
601 p
= tmpbuf
= gspca_dev
->usb_buf
;
603 p
= tmpbuf
= kmalloc(len
* 2, GFP_KERNEL
);
605 pr_err("Out of memory\n");
614 usb_control_msg(gspca_dev
->dev
,
615 usb_sndctrlpipe(gspca_dev
->dev
, 0),
617 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
619 tmpbuf
, len
* 2, 500);
620 if (len
* 2 > USB_BUF_SZ
)
624 static void om6802_sensor_init(struct gspca_dev
*gspca_dev
)
629 u8 val
[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
630 static const u8 sensor_init
[] = {
648 reg_w_buf(gspca_dev
, sensor_reset
, sizeof sensor_reset
);
652 byte
= reg_r(gspca_dev
, 0x0060);
657 byte
= reg_r(gspca_dev
, 0x0063);
659 pr_err("Bad sensor reset %02x\n", byte
);
668 reg_w(gspca_dev
, 0x3c80);
669 reg_w_buf(gspca_dev
, val
, sizeof val
);
673 byte
= reg_r(gspca_dev
, 0x60);
679 reg_w(gspca_dev
, 0x3c80);
682 /* this function is called at probe time */
683 static int sd_config(struct gspca_dev
*gspca_dev
,
684 const struct usb_device_id
*id
)
686 struct sd
*sd
= (struct sd
*) gspca_dev
;
689 cam
= &gspca_dev
->cam
;
691 cam
->cam_mode
= vga_mode_t16
;
692 cam
->nmodes
= ARRAY_SIZE(vga_mode_t16
);
694 sd
->brightness
= BRIGHTNESS_DEF
;
695 sd
->contrast
= CONTRAST_DEF
;
696 sd
->colors
= COLORS_DEF
;
697 sd
->gamma
= GAMMA_DEF
;
698 sd
->autogain
= AUTOGAIN_DEF
;
699 sd
->mirror
= MIRROR_DEF
;
702 sd
->sharpness
= SHARPNESS_DEF
;
703 sd
->effect
= EFFECTS_DEF
;
704 sd
->red_gain
= RED_GAIN_DEF
;
705 sd
->blue_gain
= BLUE_GAIN_DEF
;
706 sd
->green_gain
= GAIN_DEF
* 3 - RED_GAIN_DEF
- BLUE_GAIN_DEF
;
711 static void setbrightness(struct gspca_dev
*gspca_dev
)
713 struct sd
*sd
= (struct sd
*) gspca_dev
;
714 unsigned int brightness
;
715 u8 set6
[4] = { 0x8f, 0x24, 0xc3, 0x00 };
717 brightness
= sd
->brightness
;
718 if (brightness
< 7) {
720 set6
[3] = 0x70 - brightness
* 0x10;
722 set6
[3] = 0x00 + ((brightness
- 7) * 0x10);
725 reg_w_buf(gspca_dev
, set6
, sizeof set6
);
728 static void setcontrast(struct gspca_dev
*gspca_dev
)
730 struct sd
*sd
= (struct sd
*) gspca_dev
;
731 unsigned int contrast
= sd
->contrast
;
735 reg_to_write
= 0x8ea9 - contrast
* 0x200;
737 reg_to_write
= 0x00a9 + (contrast
- 7) * 0x200;
739 reg_w(gspca_dev
, reg_to_write
);
742 static void setcolors(struct gspca_dev
*gspca_dev
)
744 struct sd
*sd
= (struct sd
*) gspca_dev
;
747 reg_to_write
= 0x80bb + sd
->colors
* 0x100; /* was 0xc0 */
748 reg_w(gspca_dev
, reg_to_write
);
751 static void setgamma(struct gspca_dev
*gspca_dev
)
753 struct sd
*sd
= (struct sd
*) gspca_dev
;
755 PDEBUG(D_CONF
, "Gamma: %d", sd
->gamma
);
756 reg_w_ixbuf(gspca_dev
, 0x90,
757 gamma_table
[sd
->gamma
], sizeof gamma_table
[0]);
760 static void setRGB(struct gspca_dev
*gspca_dev
)
762 struct sd
*sd
= (struct sd
*) gspca_dev
;
764 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
766 all_gain_reg
[1] = sd
->red_gain
;
767 all_gain_reg
[3] = sd
->blue_gain
;
768 all_gain_reg
[5] = sd
->green_gain
;
769 reg_w_buf(gspca_dev
, all_gain_reg
, sizeof all_gain_reg
);
772 /* Generic fnc for r/b balance, exposure and awb */
773 static void setawb(struct gspca_dev
*gspca_dev
)
775 struct sd
*sd
= (struct sd
*) gspca_dev
;
778 reg80
= (sensor_data
[sd
->sensor
].reg80
<< 8) | 0x80;
780 /* on awb leave defaults values */
782 /* shoud we wait here.. */
783 /* update and reset RGB gains with webcam values */
784 sd
->red_gain
= reg_r(gspca_dev
, 0x0087);
785 sd
->blue_gain
= reg_r(gspca_dev
, 0x0088);
786 sd
->green_gain
= reg_r(gspca_dev
, 0x0089);
787 reg80
&= ~0x0400; /* AWB off */
789 reg_w(gspca_dev
, reg80
);
790 reg_w(gspca_dev
, reg80
);
793 static void init_gains(struct gspca_dev
*gspca_dev
)
795 struct sd
*sd
= (struct sd
*) gspca_dev
;
798 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
800 all_gain_reg
[1] = sd
->red_gain
;
801 all_gain_reg
[3] = sd
->blue_gain
;
802 all_gain_reg
[5] = sd
->green_gain
;
803 reg80
= sensor_data
[sd
->sensor
].reg80
;
806 all_gain_reg
[7] = reg80
;
807 reg_w_buf(gspca_dev
, all_gain_reg
, sizeof all_gain_reg
);
809 reg_w(gspca_dev
, (sd
->red_gain
<< 8) + 0x87);
810 reg_w(gspca_dev
, (sd
->blue_gain
<< 8) + 0x88);
811 reg_w(gspca_dev
, (sd
->green_gain
<< 8) + 0x89);
814 static void setsharpness(struct gspca_dev
*gspca_dev
)
816 struct sd
*sd
= (struct sd
*) gspca_dev
;
819 reg_to_write
= 0x0aa6 + 0x1000 * sd
->sharpness
;
821 reg_w(gspca_dev
, reg_to_write
);
824 static void setfreq(struct gspca_dev
*gspca_dev
)
826 struct sd
*sd
= (struct sd
*) gspca_dev
;
828 u8 freq
[4] = { 0x66, 0x00, 0xa8, 0xe8 };
830 switch (sd
->sensor
) {
844 case 0: /* no flicker */
853 reg_w_buf(gspca_dev
, freq
, sizeof freq
);
856 /* this function is called at probe and resume time */
857 static int sd_init(struct gspca_dev
*gspca_dev
)
859 /* some of this registers are not really neded, because
860 * they are overriden by setbrigthness, setcontrast, etc,
861 * but wont hurt anyway, and can help someone with similar webcam
862 * to see the initial parameters.*/
863 struct sd
*sd
= (struct sd
*) gspca_dev
;
864 const struct additional_sensor_data
*sensor
;
869 static const u8 read_indexs
[] =
870 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
871 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
872 static const u8 n1
[] =
873 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
874 static const u8 n2
[] =
877 sensor_id
= (reg_r(gspca_dev
, 0x06) << 8)
878 | reg_r(gspca_dev
, 0x07);
879 switch (sensor_id
& 0xff0f) {
881 PDEBUG(D_PROBE
, "sensor tas5130a");
882 sd
->sensor
= SENSOR_TAS5130A
;
885 PDEBUG(D_PROBE
, "sensor lt168g");
886 sd
->sensor
= SENSOR_LT168G
;
889 PDEBUG(D_PROBE
, "sensor 'other'");
890 sd
->sensor
= SENSOR_OTHER
;
893 PDEBUG(D_PROBE
, "sensor om6802");
894 sd
->sensor
= SENSOR_OM6802
;
897 pr_err("unknown sensor %04x\n", sensor_id
);
901 if (sd
->sensor
== SENSOR_OM6802
) {
902 reg_w_buf(gspca_dev
, n1
, sizeof n1
);
905 reg_w_buf(gspca_dev
, sensor_reset
, sizeof sensor_reset
);
906 test_byte
= reg_r(gspca_dev
, 0x0063);
908 if (test_byte
== 0x17)
912 pr_err("Bad sensor reset %02x\n", test_byte
);
915 reg_w_buf(gspca_dev
, n2
, sizeof n2
);
919 while (read_indexs
[i
] != 0x00) {
920 test_byte
= reg_r(gspca_dev
, read_indexs
[i
]);
921 PDEBUG(D_STREAM
, "Reg 0x%02x = 0x%02x", read_indexs
[i
],
926 sensor
= &sensor_data
[sd
->sensor
];
927 reg_w_buf(gspca_dev
, sensor
->n3
, sizeof sensor
->n3
);
928 reg_w_buf(gspca_dev
, sensor
->n4
, sensor
->n4sz
);
930 if (sd
->sensor
== SENSOR_LT168G
) {
931 test_byte
= reg_r(gspca_dev
, 0x80);
932 PDEBUG(D_STREAM
, "Reg 0x%02x = 0x%02x", 0x80,
934 reg_w(gspca_dev
, 0x6c80);
937 reg_w_ixbuf(gspca_dev
, 0xd0, sensor
->data1
, sizeof sensor
->data1
);
938 reg_w_ixbuf(gspca_dev
, 0xc7, sensor
->data2
, sizeof sensor
->data2
);
939 reg_w_ixbuf(gspca_dev
, 0xe0, sensor
->data3
, sizeof sensor
->data3
);
941 reg_w(gspca_dev
, (sensor
->reg80
<< 8) + 0x80);
942 reg_w(gspca_dev
, (sensor
->reg80
<< 8) + 0x80);
943 reg_w(gspca_dev
, (sensor
->reg8e
<< 8) + 0x8e);
945 setbrightness(gspca_dev
);
946 setcontrast(gspca_dev
);
948 setcolors(gspca_dev
);
949 setsharpness(gspca_dev
);
950 init_gains(gspca_dev
);
953 reg_w_buf(gspca_dev
, sensor
->data5
, sizeof sensor
->data5
);
954 reg_w_buf(gspca_dev
, sensor
->nset8
, sizeof sensor
->nset8
);
955 reg_w_buf(gspca_dev
, sensor
->stream
, sizeof sensor
->stream
);
957 if (sd
->sensor
== SENSOR_LT168G
) {
958 test_byte
= reg_r(gspca_dev
, 0x80);
959 PDEBUG(D_STREAM
, "Reg 0x%02x = 0x%02x", 0x80,
961 reg_w(gspca_dev
, 0x6c80);
964 reg_w_ixbuf(gspca_dev
, 0xd0, sensor
->data1
, sizeof sensor
->data1
);
965 reg_w_ixbuf(gspca_dev
, 0xc7, sensor
->data2
, sizeof sensor
->data2
);
966 reg_w_ixbuf(gspca_dev
, 0xe0, sensor
->data3
, sizeof sensor
->data3
);
971 static void setmirror(struct gspca_dev
*gspca_dev
)
973 struct sd
*sd
= (struct sd
*) gspca_dev
;
975 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
980 reg_w_buf(gspca_dev
, hflipcmd
, sizeof hflipcmd
);
983 static void seteffect(struct gspca_dev
*gspca_dev
)
985 struct sd
*sd
= (struct sd
*) gspca_dev
;
987 reg_w_buf(gspca_dev
, effects_table
[sd
->effect
],
988 sizeof effects_table
[0]);
989 if (sd
->effect
== 1 || sd
->effect
== 5) {
991 "This effect have been disabled for webcam \"safety\"");
995 if (sd
->effect
== 1 || sd
->effect
== 4)
996 reg_w(gspca_dev
, 0x4aa6);
998 reg_w(gspca_dev
, 0xfaa6);
1001 /* Is this really needed?
1002 * i added some module parameters for test with some users */
1003 static void poll_sensor(struct gspca_dev
*gspca_dev
)
1005 static const u8 poll1
[] =
1006 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1007 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1008 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1010 static const u8 poll2
[] =
1011 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1012 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1013 static const u8 noise03
[] = /* (some differences / ms-drv) */
1014 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1015 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1016 0xc2, 0x80, 0xc3, 0x10};
1018 PDEBUG(D_STREAM
, "[Sensor requires polling]");
1019 reg_w_buf(gspca_dev
, poll1
, sizeof poll1
);
1020 reg_w_buf(gspca_dev
, poll2
, sizeof poll2
);
1021 reg_w_buf(gspca_dev
, noise03
, sizeof noise03
);
1024 static int sd_start(struct gspca_dev
*gspca_dev
)
1026 struct sd
*sd
= (struct sd
*) gspca_dev
;
1027 const struct additional_sensor_data
*sensor
;
1029 u8 t2
[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1030 static const u8 t3
[] =
1031 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1033 mode
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
1035 case 0: /* 640x480 (0x00) */
1037 case 1: /* 352x288 */
1040 case 2: /* 320x240 */
1043 case 3: /* 176x144 */
1047 /* case 4: * 160x120 */
1052 switch (sd
->sensor
) {
1054 om6802_sensor_init(gspca_dev
);
1056 case SENSOR_TAS5130A
:
1059 reg_w_buf(gspca_dev
, tas5130a_sensor_init
[i
],
1060 sizeof tas5130a_sensor_init
[0]);
1061 if (i
>= ARRAY_SIZE(tas5130a_sensor_init
) - 1)
1065 reg_w(gspca_dev
, 0x3c80);
1066 /* just in case and to keep sync with logs (for mine) */
1067 reg_w_buf(gspca_dev
, tas5130a_sensor_init
[i
],
1068 sizeof tas5130a_sensor_init
[0]);
1069 reg_w(gspca_dev
, 0x3c80);
1072 sensor
= &sensor_data
[sd
->sensor
];
1074 reg_r(gspca_dev
, 0x0012);
1075 reg_w_buf(gspca_dev
, t2
, sizeof t2
);
1076 reg_w_ixbuf(gspca_dev
, 0xb3, t3
, sizeof t3
);
1077 reg_w(gspca_dev
, 0x0013);
1079 reg_w_buf(gspca_dev
, sensor
->stream
, sizeof sensor
->stream
);
1080 reg_w_buf(gspca_dev
, sensor
->stream
, sizeof sensor
->stream
);
1082 if (sd
->sensor
== SENSOR_OM6802
)
1083 poll_sensor(gspca_dev
);
1088 static void sd_stopN(struct gspca_dev
*gspca_dev
)
1090 struct sd
*sd
= (struct sd
*) gspca_dev
;
1092 reg_w_buf(gspca_dev
, sensor_data
[sd
->sensor
].stream
,
1093 sizeof sensor_data
[sd
->sensor
].stream
);
1094 reg_w_buf(gspca_dev
, sensor_data
[sd
->sensor
].stream
,
1095 sizeof sensor_data
[sd
->sensor
].stream
);
1096 if (sd
->sensor
== SENSOR_OM6802
) {
1098 reg_w(gspca_dev
, 0x0309);
1100 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1101 /* If the last button state is pressed, release it now! */
1102 if (sd
->button_pressed
) {
1103 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 0);
1104 input_sync(gspca_dev
->input_dev
);
1105 sd
->button_pressed
= 0;
1110 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
1111 u8
*data
, /* isoc packet */
1112 int len
) /* iso packet length */
1114 struct sd
*sd
= (struct sd
*) gspca_dev
;
1117 if (data
[0] == 0x5a) {
1118 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1120 u8 state
= (data
[20] & 0x80) ? 1 : 0;
1121 if (sd
->button_pressed
!= state
) {
1122 input_report_key(gspca_dev
->input_dev
,
1124 input_sync(gspca_dev
->input_dev
);
1125 sd
->button_pressed
= state
;
1129 /* Control Packet, after this came the header again,
1130 * but extra bytes came in the packet before this,
1131 * sometimes an EOF arrives, sometimes not... */
1136 if (data
[0] == 0xff && data
[1] == 0xd8)
1137 pkt_type
= FIRST_PACKET
;
1138 else if (data
[len
- 2] == 0xff && data
[len
- 1] == 0xd9)
1139 pkt_type
= LAST_PACKET
;
1141 pkt_type
= INTER_PACKET
;
1142 gspca_frame_add(gspca_dev
, pkt_type
, data
, len
);
1145 static int sd_setblue_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
1147 struct sd
*sd
= (struct sd
*) gspca_dev
;
1149 sd
->blue_gain
= val
;
1150 if (gspca_dev
->streaming
)
1151 reg_w(gspca_dev
, (val
<< 8) + 0x88);
1155 static int sd_getblue_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1157 struct sd
*sd
= (struct sd
*) gspca_dev
;
1159 *val
= sd
->blue_gain
;
1163 static int sd_setred_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
1165 struct sd
*sd
= (struct sd
*) gspca_dev
;
1168 if (gspca_dev
->streaming
)
1169 reg_w(gspca_dev
, (val
<< 8) + 0x87);
1174 static int sd_getred_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1176 struct sd
*sd
= (struct sd
*) gspca_dev
;
1178 *val
= sd
->red_gain
;
1182 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
)
1184 struct sd
*sd
= (struct sd
*) gspca_dev
;
1187 psg
= sd
->red_gain
+ sd
->blue_gain
+ sd
->green_gain
;
1189 sd
->red_gain
= sd
->red_gain
* nsg
/ psg
;
1190 if (sd
->red_gain
> 0x40)
1191 sd
->red_gain
= 0x40;
1192 else if (sd
->red_gain
< 0x10)
1193 sd
->red_gain
= 0x10;
1194 sd
->blue_gain
= sd
->blue_gain
* nsg
/ psg
;
1195 if (sd
->blue_gain
> 0x40)
1196 sd
->blue_gain
= 0x40;
1197 else if (sd
->blue_gain
< 0x10)
1198 sd
->blue_gain
= 0x10;
1199 sd
->green_gain
= sd
->green_gain
* nsg
/ psg
;
1200 if (sd
->green_gain
> 0x40)
1201 sd
->green_gain
= 0x40;
1202 else if (sd
->green_gain
< 0x10)
1203 sd
->green_gain
= 0x10;
1205 if (gspca_dev
->streaming
)
1210 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1212 struct sd
*sd
= (struct sd
*) gspca_dev
;
1214 *val
= (sd
->red_gain
+ sd
->blue_gain
+ sd
->green_gain
) / 3;
1218 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1220 struct sd
*sd
= (struct sd
*) gspca_dev
;
1222 sd
->brightness
= val
;
1223 if (gspca_dev
->streaming
)
1224 setbrightness(gspca_dev
);
1228 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1230 struct sd
*sd
= (struct sd
*) gspca_dev
;
1232 *val
= sd
->brightness
;
1236 static int sd_setawb(struct gspca_dev
*gspca_dev
, __s32 val
)
1238 struct sd
*sd
= (struct sd
*) gspca_dev
;
1241 if (gspca_dev
->streaming
)
1246 static int sd_getawb(struct gspca_dev
*gspca_dev
, __s32
*val
)
1248 struct sd
*sd
= (struct sd
*) gspca_dev
;
1254 static int sd_setmirror(struct gspca_dev
*gspca_dev
, __s32 val
)
1256 struct sd
*sd
= (struct sd
*) gspca_dev
;
1259 if (gspca_dev
->streaming
)
1260 setmirror(gspca_dev
);
1264 static int sd_getmirror(struct gspca_dev
*gspca_dev
, __s32
*val
)
1266 struct sd
*sd
= (struct sd
*) gspca_dev
;
1272 static int sd_seteffect(struct gspca_dev
*gspca_dev
, __s32 val
)
1274 struct sd
*sd
= (struct sd
*) gspca_dev
;
1277 if (gspca_dev
->streaming
)
1278 seteffect(gspca_dev
);
1282 static int sd_geteffect(struct gspca_dev
*gspca_dev
, __s32
*val
)
1284 struct sd
*sd
= (struct sd
*) gspca_dev
;
1290 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
)
1292 struct sd
*sd
= (struct sd
*) gspca_dev
;
1295 if (gspca_dev
->streaming
)
1296 setcontrast(gspca_dev
);
1300 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
)
1302 struct sd
*sd
= (struct sd
*) gspca_dev
;
1304 *val
= sd
->contrast
;
1308 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
)
1310 struct sd
*sd
= (struct sd
*) gspca_dev
;
1313 if (gspca_dev
->streaming
)
1314 setcolors(gspca_dev
);
1318 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
)
1320 struct sd
*sd
= (struct sd
*) gspca_dev
;
1326 static int sd_setgamma(struct gspca_dev
*gspca_dev
, __s32 val
)
1328 struct sd
*sd
= (struct sd
*) gspca_dev
;
1331 if (gspca_dev
->streaming
)
1332 setgamma(gspca_dev
);
1336 static int sd_getgamma(struct gspca_dev
*gspca_dev
, __s32
*val
)
1338 struct sd
*sd
= (struct sd
*) gspca_dev
;
1344 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
)
1346 struct sd
*sd
= (struct sd
*) gspca_dev
;
1349 if (gspca_dev
->streaming
)
1354 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
)
1356 struct sd
*sd
= (struct sd
*) gspca_dev
;
1362 static int sd_setsharpness(struct gspca_dev
*gspca_dev
, __s32 val
)
1364 struct sd
*sd
= (struct sd
*) gspca_dev
;
1366 sd
->sharpness
= val
;
1367 if (gspca_dev
->streaming
)
1368 setsharpness(gspca_dev
);
1372 static int sd_getsharpness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1374 struct sd
*sd
= (struct sd
*) gspca_dev
;
1376 *val
= sd
->sharpness
;
1380 /* Low Light set here......*/
1381 static int sd_setlowlight(struct gspca_dev
*gspca_dev
, __s32 val
)
1383 struct sd
*sd
= (struct sd
*) gspca_dev
;
1387 reg_w(gspca_dev
, 0xf48e);
1389 reg_w(gspca_dev
, 0xb48e);
1393 static int sd_getlowlight(struct gspca_dev
*gspca_dev
, __s32
*val
)
1395 struct sd
*sd
= (struct sd
*) gspca_dev
;
1397 *val
= sd
->autogain
;
1401 static int sd_querymenu(struct gspca_dev
*gspca_dev
,
1402 struct v4l2_querymenu
*menu
)
1404 static const char *freq_nm
[3] = {"NoFliker", "50 Hz", "60 Hz"};
1407 case V4L2_CID_POWER_LINE_FREQUENCY
:
1408 if ((unsigned) menu
->index
>= ARRAY_SIZE(freq_nm
))
1410 strcpy((char *) menu
->name
, freq_nm
[menu
->index
]);
1412 case V4L2_CID_EFFECTS
:
1413 if ((unsigned) menu
->index
< ARRAY_SIZE(effects_control
)) {
1414 strlcpy((char *) menu
->name
,
1415 effects_control
[menu
->index
],
1424 /* sub-driver description */
1425 static const struct sd_desc sd_desc
= {
1426 .name
= MODULE_NAME
,
1428 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1429 .config
= sd_config
,
1433 .pkt_scan
= sd_pkt_scan
,
1434 .querymenu
= sd_querymenu
,
1435 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1440 /* -- module initialisation -- */
1441 static const struct usb_device_id device_table
[] = {
1442 {USB_DEVICE(0x17a1, 0x0128)},
1445 MODULE_DEVICE_TABLE(usb
, device_table
);
1447 /* -- device connect -- */
1448 static int sd_probe(struct usb_interface
*intf
,
1449 const struct usb_device_id
*id
)
1451 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1455 static struct usb_driver sd_driver
= {
1456 .name
= MODULE_NAME
,
1457 .id_table
= device_table
,
1459 .disconnect
= gspca_disconnect
,
1461 .suspend
= gspca_suspend
,
1462 .resume
= gspca_resume
,
1466 module_usb_driver(sd_driver
);