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 MODULE_NAME "t613"
33 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
35 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
36 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
37 MODULE_LICENSE("GPL");
40 struct gspca_dev gspca_dev; /* !! must be the first item */
49 u8 red_balance; /* split balance */
51 u8 global_gain; /* aka gain */
52 u8 awb; /* set default r/g/b and activate */
61 SENSOR_LT168G, /* must verify if this is the actual model */
65 /* V4L2 controls supported by the driver */
66 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
73 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
74 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
75 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
76 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
77 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
78 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
79 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
81 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
82 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
83 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
85 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_querymenu(struct gspca_dev *gspca_dev,
95 struct v4l2_querymenu *menu);
97 static const struct ctrl sd_ctrls[] = {
100 .id = V4L2_CID_BRIGHTNESS,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Brightness",
106 #define BRIGHTNESS_DEF 8
107 .default_value = BRIGHTNESS_DEF,
109 .set = sd_setbrightness,
110 .get = sd_getbrightness,
114 .id = V4L2_CID_CONTRAST,
115 .type = V4L2_CTRL_TYPE_INTEGER,
120 #define CONTRAST_DEF 0x07
121 .default_value = CONTRAST_DEF,
123 .set = sd_setcontrast,
124 .get = sd_getcontrast,
128 .id = V4L2_CID_SATURATION,
129 .type = V4L2_CTRL_TYPE_INTEGER,
134 #define COLORS_DEF 0x05
135 .default_value = COLORS_DEF,
144 .id = V4L2_CID_GAMMA, /* (gamma on win) */
145 .type = V4L2_CTRL_TYPE_INTEGER,
148 .maximum = GAMMA_MAX - 1,
150 .default_value = GAMMA_DEF,
157 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
158 * some apps dont bring up the
159 * backligth_compensation control) */
160 .type = V4L2_CTRL_TYPE_INTEGER,
165 #define AUTOGAIN_DEF 0x01
166 .default_value = AUTOGAIN_DEF,
168 .set = sd_setlowlight,
169 .get = sd_getlowlight,
173 .id = V4L2_CID_HFLIP,
174 .type = V4L2_CTRL_TYPE_BOOLEAN,
175 .name = "Mirror Image",
180 .default_value = MIRROR_DEF,
187 .id = V4L2_CID_POWER_LINE_FREQUENCY,
188 .type = V4L2_CTRL_TYPE_MENU,
189 .name = "Light Frequency Filter",
190 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
194 .default_value = FREQ_DEF,
201 .id = V4L2_CID_AUTO_WHITE_BALANCE,
202 .type = V4L2_CTRL_TYPE_INTEGER,
203 .name = "Auto White Balance",
208 .default_value = AWB_DEF,
215 .id = V4L2_CID_SHARPNESS,
216 .type = V4L2_CTRL_TYPE_INTEGER,
221 #define SHARPNESS_DEF 0x06
222 .default_value = SHARPNESS_DEF,
224 .set = sd_setsharpness,
225 .get = sd_getsharpness,
229 .id = V4L2_CID_EFFECTS,
230 .type = V4L2_CTRL_TYPE_MENU,
231 .name = "Webcam Effects",
235 #define EFFECTS_DEF 0
236 .default_value = EFFECTS_DEF,
243 .id = V4L2_CID_BLUE_BALANCE,
244 .type = V4L2_CTRL_TYPE_INTEGER,
245 .name = "Blue Balance",
249 #define BLUE_BALANCE_DEF 0x20
250 .default_value = BLUE_BALANCE_DEF,
252 .set = sd_setblue_balance,
253 .get = sd_getblue_balance,
257 .id = V4L2_CID_RED_BALANCE,
258 .type = V4L2_CTRL_TYPE_INTEGER,
259 .name = "Red Balance",
263 #define RED_BALANCE_DEF 0x20
264 .default_value = RED_BALANCE_DEF,
266 .set = sd_setred_balance,
267 .get = sd_getred_balance,
272 .type = V4L2_CTRL_TYPE_INTEGER,
277 #define global_gain_DEF 0x20
278 .default_value = global_gain_DEF,
280 .set = sd_setglobal_gain,
281 .get = sd_getglobal_gain,
285 static const struct v4l2_pix_format vga_mode_t16[] = {
286 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
288 .sizeimage = 160 * 120 * 4 / 8 + 590,
289 .colorspace = V4L2_COLORSPACE_JPEG,
291 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
293 .sizeimage = 176 * 144 * 3 / 8 + 590,
294 .colorspace = V4L2_COLORSPACE_JPEG,
296 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
298 .sizeimage = 320 * 240 * 3 / 8 + 590,
299 .colorspace = V4L2_COLORSPACE_JPEG,
301 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
303 .sizeimage = 352 * 288 * 3 / 8 + 590,
304 .colorspace = V4L2_COLORSPACE_JPEG,
306 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
308 .sizeimage = 640 * 480 * 3 / 8 + 590,
309 .colorspace = V4L2_COLORSPACE_JPEG,
313 /* sensor specific data */
314 struct additional_sensor_data {
317 const u8 reg80, reg8e;
326 static const u8 n4_om6802[] = {
327 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
328 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
329 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
330 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
331 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
332 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
333 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
334 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
335 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
337 static const u8 n4_other[] = {
338 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
339 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
340 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
341 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
342 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
343 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
344 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
345 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
347 static const u8 n4_tas5130a[] = {
348 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
349 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
350 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
351 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
352 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
353 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
356 static const u8 n4_lt168g[] = {
357 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
358 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
359 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
360 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
361 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
362 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
363 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
364 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
365 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
368 static const struct additional_sensor_data sensor_data[] = {
371 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
373 .n4sz = sizeof n4_om6802,
376 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
378 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
381 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
384 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
386 .data5 = /* this could be removed later */
387 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
389 {0x0b, 0x04, 0x0a, 0x78},
393 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
395 .n4sz = sizeof n4_other,
398 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
400 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
403 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
409 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
411 {0x0b, 0x04, 0x0a, 0x00},
413 [SENSOR_TAS5130A] = {
415 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
417 .n4sz = sizeof n4_tas5130a,
420 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
422 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
425 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
428 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
431 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
433 {0x0b, 0x04, 0x0a, 0x40},
436 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
438 .n4sz = sizeof n4_lt168g,
441 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
442 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
444 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
448 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
449 .stream = {0x0b, 0x04, 0x0a, 0x28},
453 #define MAX_EFFECTS 7
454 /* easily done by soft, this table could be removed,
455 * i keep it here just in case */
456 static char *effects_control[MAX_EFFECTS] = {
458 "Emboss", /* disabled */
462 "Sun Effect", /* disabled */
465 static const u8 effects_table[MAX_EFFECTS][6] = {
466 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
467 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
468 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
470 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
471 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
475 static const u8 gamma_table[GAMMA_MAX][17] = {
476 /* gamma table from cam1690.ini */
477 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
478 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
480 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
481 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
483 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
484 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
486 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
487 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
489 {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
490 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
492 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
493 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
495 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
496 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
498 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
499 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
501 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
502 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
504 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
505 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
507 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
508 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
510 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
511 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
513 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
514 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
516 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
517 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
519 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
520 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
522 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
523 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
527 static const u8 tas5130a_sensor_init[][8] = {
528 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
529 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
530 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
533 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
536 static u8 reg_r(struct gspca_dev *gspca_dev,
539 usb_control_msg(gspca_dev->dev,
540 usb_rcvctrlpipe(gspca_dev->dev, 0),
542 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
545 gspca_dev->usb_buf, 1, 500);
546 return gspca_dev->usb_buf[0];
549 static void reg_w(struct gspca_dev *gspca_dev,
552 usb_control_msg(gspca_dev->dev,
553 usb_sndctrlpipe(gspca_dev->dev, 0),
555 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
560 static void reg_w_buf(struct gspca_dev *gspca_dev,
561 const u8 *buffer, u16 len)
563 if (len <= USB_BUF_SZ) {
564 memcpy(gspca_dev->usb_buf, buffer, len);
565 usb_control_msg(gspca_dev->dev,
566 usb_sndctrlpipe(gspca_dev->dev, 0),
568 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
570 gspca_dev->usb_buf, len, 500);
574 tmpbuf = kmalloc(len, GFP_KERNEL);
576 err("Out of memory");
579 memcpy(tmpbuf, buffer, len);
580 usb_control_msg(gspca_dev->dev,
581 usb_sndctrlpipe(gspca_dev->dev, 0),
583 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
590 /* write values to consecutive registers */
591 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
593 const u8 *buffer, u16 len)
598 if (len * 2 <= USB_BUF_SZ) {
599 p = tmpbuf = gspca_dev->usb_buf;
601 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
603 err("Out of memory");
612 usb_control_msg(gspca_dev->dev,
613 usb_sndctrlpipe(gspca_dev->dev, 0),
615 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
617 tmpbuf, len * 2, 500);
618 if (len * 2 > USB_BUF_SZ)
622 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
627 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
628 static const u8 sensor_init[] = {
646 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
650 byte = reg_r(gspca_dev, 0x0060);
655 byte = reg_r(gspca_dev, 0x0063);
657 err("Bad sensor reset %02x", byte);
666 reg_w(gspca_dev, 0x3c80);
667 reg_w_buf(gspca_dev, val, sizeof val);
671 byte = reg_r(gspca_dev, 0x60);
677 reg_w(gspca_dev, 0x3c80);
680 /* this function is called at probe time */
681 static int sd_config(struct gspca_dev *gspca_dev,
682 const struct usb_device_id *id)
684 struct sd *sd = (struct sd *) gspca_dev;
687 cam = &gspca_dev->cam;
689 cam->cam_mode = vga_mode_t16;
690 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
692 sd->brightness = BRIGHTNESS_DEF;
693 sd->contrast = CONTRAST_DEF;
694 sd->colors = COLORS_DEF;
695 sd->gamma = GAMMA_DEF;
696 sd->autogain = AUTOGAIN_DEF;
697 sd->mirror = MIRROR_DEF;
700 sd->sharpness = SHARPNESS_DEF;
701 sd->effect = EFFECTS_DEF;
702 sd->red_balance = RED_BALANCE_DEF;
703 sd->blue_balance = BLUE_BALANCE_DEF;
704 sd->global_gain = global_gain_DEF;
709 static void setbrightness(struct gspca_dev *gspca_dev)
711 struct sd *sd = (struct sd *) gspca_dev;
712 unsigned int brightness;
713 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
715 brightness = sd->brightness;
716 if (brightness < 7) {
718 set6[3] = 0x70 - brightness * 0x10;
720 set6[3] = 0x00 + ((brightness - 7) * 0x10);
723 reg_w_buf(gspca_dev, set6, sizeof set6);
726 static void setcontrast(struct gspca_dev *gspca_dev)
728 struct sd *sd = (struct sd *) gspca_dev;
729 unsigned int contrast = sd->contrast;
733 reg_to_write = 0x8ea9 - contrast * 0x200;
735 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
737 reg_w(gspca_dev, reg_to_write);
740 static void setcolors(struct gspca_dev *gspca_dev)
742 struct sd *sd = (struct sd *) gspca_dev;
745 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
746 reg_w(gspca_dev, reg_to_write);
749 static void setgamma(struct gspca_dev *gspca_dev)
751 struct sd *sd = (struct sd *) gspca_dev;
753 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
754 reg_w_ixbuf(gspca_dev, 0x90,
755 gamma_table[sd->gamma], sizeof gamma_table[0]);
757 static void setglobalgain(struct gspca_dev *gspca_dev)
760 struct sd *sd = (struct sd *) gspca_dev;
761 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
762 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
763 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
766 /* Generic fnc for r/b balance, exposure and whitebalance */
767 static void setawb(struct gspca_dev *gspca_dev)
769 struct sd *sd = (struct sd *) gspca_dev;
771 /* on awb leave defaults values */
773 reg_w(gspca_dev, 0x3c80);
775 reg_w(gspca_dev, 0x3880);
776 /* shoud we wait here.. */
777 /* update and reset 'global gain' with webcam parameters */
778 sd->red_balance = reg_r(gspca_dev, 0x0087);
779 sd->blue_balance = reg_r(gspca_dev, 0x0088);
780 sd->global_gain = reg_r(gspca_dev, 0x0089);
781 setglobalgain(gspca_dev);
786 static void setsharpness(struct gspca_dev *gspca_dev)
788 struct sd *sd = (struct sd *) gspca_dev;
791 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
793 reg_w(gspca_dev, reg_to_write);
796 static void setfreq(struct gspca_dev *gspca_dev)
798 struct sd *sd = (struct sd *) gspca_dev;
800 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
802 switch (sd->sensor) {
816 case 0: /* no flicker */
825 reg_w_buf(gspca_dev, freq, sizeof freq);
828 /* this function is called at probe and resume time */
829 static int sd_init(struct gspca_dev *gspca_dev)
831 /* some of this registers are not really neded, because
832 * they are overriden by setbrigthness, setcontrast, etc,
833 * but wont hurt anyway, and can help someone with similar webcam
834 * to see the initial parameters.*/
835 struct sd *sd = (struct sd *) gspca_dev;
836 const struct additional_sensor_data *sensor;
841 static const u8 read_indexs[] =
842 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
843 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
844 static const u8 n1[] =
845 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
846 static const u8 n2[] =
849 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
850 | reg_r(gspca_dev, 0x07);
851 switch (sensor_id & 0xff0f) {
853 PDEBUG(D_PROBE, "sensor tas5130a");
854 sd->sensor = SENSOR_TAS5130A;
857 PDEBUG(D_PROBE, "sensor lt168g");
858 sd->sensor = SENSOR_LT168G;
861 PDEBUG(D_PROBE, "sensor 'other'");
862 sd->sensor = SENSOR_OTHER;
865 PDEBUG(D_PROBE, "sensor om6802");
866 sd->sensor = SENSOR_OM6802;
869 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
873 if (sd->sensor == SENSOR_OM6802) {
874 reg_w_buf(gspca_dev, n1, sizeof n1);
877 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
878 test_byte = reg_r(gspca_dev, 0x0063);
880 if (test_byte == 0x17)
884 err("Bad sensor reset %02x", test_byte);
887 reg_w_buf(gspca_dev, n2, sizeof n2);
891 while (read_indexs[i] != 0x00) {
892 test_byte = reg_r(gspca_dev, read_indexs[i]);
893 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
898 sensor = &sensor_data[sd->sensor];
899 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
900 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
902 if (sd->sensor == SENSOR_LT168G) {
903 test_byte = reg_r(gspca_dev, 0x80);
904 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
906 reg_w(gspca_dev, 0x6c80);
909 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
910 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
911 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
913 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
914 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
915 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
917 setbrightness(gspca_dev);
918 setcontrast(gspca_dev);
920 setcolors(gspca_dev);
921 setsharpness(gspca_dev);
925 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
926 reg_w(gspca_dev, 0x2088);
927 reg_w(gspca_dev, 0x2089);
929 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
930 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
931 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
932 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
934 if (sd->sensor == SENSOR_LT168G) {
935 test_byte = reg_r(gspca_dev, 0x80);
936 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
938 reg_w(gspca_dev, 0x6c80);
941 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
942 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
943 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
948 static void setmirror(struct gspca_dev *gspca_dev)
950 struct sd *sd = (struct sd *) gspca_dev;
952 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
957 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
960 static void seteffect(struct gspca_dev *gspca_dev)
962 struct sd *sd = (struct sd *) gspca_dev;
964 reg_w_buf(gspca_dev, effects_table[sd->effect],
965 sizeof effects_table[0]);
966 if (sd->effect == 1 || sd->effect == 5) {
968 "This effect have been disabled for webcam \"safety\"");
972 if (sd->effect == 1 || sd->effect == 4)
973 reg_w(gspca_dev, 0x4aa6);
975 reg_w(gspca_dev, 0xfaa6);
978 /* Is this really needed?
979 * i added some module parameters for test with some users */
980 static void poll_sensor(struct gspca_dev *gspca_dev)
982 static const u8 poll1[] =
983 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
984 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
985 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
987 static const u8 poll2[] =
988 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
989 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
990 static const u8 noise03[] = /* (some differences / ms-drv) */
991 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
992 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
993 0xc2, 0x80, 0xc3, 0x10};
995 PDEBUG(D_STREAM, "[Sensor requires polling]");
996 reg_w_buf(gspca_dev, poll1, sizeof poll1);
997 reg_w_buf(gspca_dev, poll2, sizeof poll2);
998 reg_w_buf(gspca_dev, noise03, sizeof noise03);
1001 static int sd_start(struct gspca_dev *gspca_dev)
1003 struct sd *sd = (struct sd *) gspca_dev;
1004 const struct additional_sensor_data *sensor;
1006 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1007 static const u8 t3[] =
1008 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1010 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1012 case 0: /* 640x480 (0x00) */
1014 case 1: /* 352x288 */
1017 case 2: /* 320x240 */
1020 case 3: /* 176x144 */
1024 /* case 4: * 160x120 */
1029 switch (sd->sensor) {
1031 om6802_sensor_init(gspca_dev);
1033 case SENSOR_TAS5130A:
1036 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1037 sizeof tas5130a_sensor_init[0]);
1038 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1042 reg_w(gspca_dev, 0x3c80);
1043 /* just in case and to keep sync with logs (for mine) */
1044 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1045 sizeof tas5130a_sensor_init[0]);
1046 reg_w(gspca_dev, 0x3c80);
1049 sensor = &sensor_data[sd->sensor];
1051 reg_r(gspca_dev, 0x0012);
1052 reg_w_buf(gspca_dev, t2, sizeof t2);
1053 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1054 reg_w(gspca_dev, 0x0013);
1056 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1057 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1059 if (sd->sensor == SENSOR_OM6802)
1060 poll_sensor(gspca_dev);
1065 static void sd_stopN(struct gspca_dev *gspca_dev)
1067 struct sd *sd = (struct sd *) gspca_dev;
1069 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1070 sizeof sensor_data[sd->sensor].stream);
1071 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1072 sizeof sensor_data[sd->sensor].stream);
1073 if (sd->sensor == SENSOR_OM6802) {
1075 reg_w(gspca_dev, 0x0309);
1079 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1080 u8 *data, /* isoc packet */
1081 int len) /* iso packet length */
1085 if (data[0] == 0x5a) {
1086 /* Control Packet, after this came the header again,
1087 * but extra bytes came in the packet before this,
1088 * sometimes an EOF arrives, sometimes not... */
1093 if (data[0] == 0xff && data[1] == 0xd8)
1094 pkt_type = FIRST_PACKET;
1095 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1096 pkt_type = LAST_PACKET;
1098 pkt_type = INTER_PACKET;
1099 gspca_frame_add(gspca_dev, pkt_type, data, len);
1103 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1105 struct sd *sd = (struct sd *) gspca_dev;
1107 sd->blue_balance = val;
1108 if (gspca_dev->streaming)
1109 reg_w(gspca_dev, (val << 8) + 0x88);
1113 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1115 struct sd *sd = (struct sd *) gspca_dev;
1117 *val = sd->blue_balance;
1121 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1123 struct sd *sd = (struct sd *) gspca_dev;
1125 sd->red_balance = val;
1126 if (gspca_dev->streaming)
1127 reg_w(gspca_dev, (val << 8) + 0x87);
1132 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1134 struct sd *sd = (struct sd *) gspca_dev;
1136 *val = sd->red_balance;
1142 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1144 struct sd *sd = (struct sd *) gspca_dev;
1146 sd->global_gain = val;
1147 if (gspca_dev->streaming)
1148 setglobalgain(gspca_dev);
1153 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1155 struct sd *sd = (struct sd *) gspca_dev;
1157 *val = sd->global_gain;
1161 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1163 struct sd *sd = (struct sd *) gspca_dev;
1165 sd->brightness = val;
1166 if (gspca_dev->streaming)
1167 setbrightness(gspca_dev);
1171 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1173 struct sd *sd = (struct sd *) gspca_dev;
1175 *val = sd->brightness;
1179 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1181 struct sd *sd = (struct sd *) gspca_dev;
1184 if (gspca_dev->streaming)
1189 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1191 struct sd *sd = (struct sd *) gspca_dev;
1197 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1199 struct sd *sd = (struct sd *) gspca_dev;
1202 if (gspca_dev->streaming)
1203 setmirror(gspca_dev);
1207 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1209 struct sd *sd = (struct sd *) gspca_dev;
1215 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1217 struct sd *sd = (struct sd *) gspca_dev;
1220 if (gspca_dev->streaming)
1221 seteffect(gspca_dev);
1225 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1227 struct sd *sd = (struct sd *) gspca_dev;
1233 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1235 struct sd *sd = (struct sd *) gspca_dev;
1238 if (gspca_dev->streaming)
1239 setcontrast(gspca_dev);
1243 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1245 struct sd *sd = (struct sd *) gspca_dev;
1247 *val = sd->contrast;
1251 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1253 struct sd *sd = (struct sd *) gspca_dev;
1256 if (gspca_dev->streaming)
1257 setcolors(gspca_dev);
1261 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1263 struct sd *sd = (struct sd *) gspca_dev;
1269 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1271 struct sd *sd = (struct sd *) gspca_dev;
1274 if (gspca_dev->streaming)
1275 setgamma(gspca_dev);
1279 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1281 struct sd *sd = (struct sd *) gspca_dev;
1287 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1289 struct sd *sd = (struct sd *) gspca_dev;
1292 if (gspca_dev->streaming)
1297 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1299 struct sd *sd = (struct sd *) gspca_dev;
1305 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1307 struct sd *sd = (struct sd *) gspca_dev;
1309 sd->sharpness = val;
1310 if (gspca_dev->streaming)
1311 setsharpness(gspca_dev);
1315 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1317 struct sd *sd = (struct sd *) gspca_dev;
1319 *val = sd->sharpness;
1323 /* Low Light set here......*/
1324 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1326 struct sd *sd = (struct sd *) gspca_dev;
1330 reg_w(gspca_dev, 0xf48e);
1332 reg_w(gspca_dev, 0xb48e);
1336 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1338 struct sd *sd = (struct sd *) gspca_dev;
1340 *val = sd->autogain;
1344 static int sd_querymenu(struct gspca_dev *gspca_dev,
1345 struct v4l2_querymenu *menu)
1348 case V4L2_CID_POWER_LINE_FREQUENCY:
1349 switch (menu->index) {
1350 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1351 strcpy((char *) menu->name, "50 Hz");
1353 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1354 strcpy((char *) menu->name, "60 Hz");
1358 case V4L2_CID_EFFECTS:
1359 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1360 strncpy((char *) menu->name,
1361 effects_control[menu->index],
1370 /* sub-driver description */
1371 static const struct sd_desc sd_desc = {
1372 .name = MODULE_NAME,
1374 .nctrls = ARRAY_SIZE(sd_ctrls),
1375 .config = sd_config,
1379 .pkt_scan = sd_pkt_scan,
1380 .querymenu = sd_querymenu,
1383 /* -- module initialisation -- */
1384 static const __devinitdata struct usb_device_id device_table[] = {
1385 {USB_DEVICE(0x17a1, 0x0128)},
1388 MODULE_DEVICE_TABLE(usb, device_table);
1390 /* -- device connect -- */
1391 static int sd_probe(struct usb_interface *intf,
1392 const struct usb_device_id *id)
1394 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1398 static struct usb_driver sd_driver = {
1399 .name = MODULE_NAME,
1400 .id_table = device_table,
1402 .disconnect = gspca_disconnect,
1404 .suspend = gspca_suspend,
1405 .resume = gspca_resume,
1409 /* -- module insert / remove -- */
1410 static int __init sd_mod_init(void)
1413 ret = usb_register(&sd_driver);
1416 PDEBUG(D_PROBE, "registered");
1419 static void __exit sd_mod_exit(void)
1421 usb_deregister(&sd_driver);
1422 PDEBUG(D_PROBE, "deregistered");
1425 module_init(sd_mod_init);
1426 module_exit(sd_mod_exit);