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 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
477 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
479 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
480 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
482 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
483 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
485 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
486 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
488 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
489 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
491 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
492 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
494 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
495 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
497 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
498 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
500 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
501 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
503 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
504 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
506 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
507 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
509 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
510 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
512 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
513 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
515 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
516 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
518 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
519 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
521 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
522 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
526 static const u8 tas5130a_sensor_init[][8] = {
527 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
528 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
529 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
532 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
535 static u8 reg_r(struct gspca_dev *gspca_dev,
538 usb_control_msg(gspca_dev->dev,
539 usb_rcvctrlpipe(gspca_dev->dev, 0),
541 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
544 gspca_dev->usb_buf, 1, 500);
545 return gspca_dev->usb_buf[0];
548 static void reg_w(struct gspca_dev *gspca_dev,
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
559 static void reg_w_buf(struct gspca_dev *gspca_dev,
560 const u8 *buffer, u16 len)
562 if (len <= USB_BUF_SZ) {
563 memcpy(gspca_dev->usb_buf, buffer, len);
564 usb_control_msg(gspca_dev->dev,
565 usb_sndctrlpipe(gspca_dev->dev, 0),
567 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
569 gspca_dev->usb_buf, len, 500);
573 tmpbuf = kmalloc(len, GFP_KERNEL);
575 err("Out of memory");
578 memcpy(tmpbuf, buffer, len);
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
589 /* write values to consecutive registers */
590 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
592 const u8 *buffer, u16 len)
597 if (len * 2 <= USB_BUF_SZ) {
598 p = tmpbuf = gspca_dev->usb_buf;
600 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
602 err("Out of memory");
611 usb_control_msg(gspca_dev->dev,
612 usb_sndctrlpipe(gspca_dev->dev, 0),
614 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
616 tmpbuf, len * 2, 500);
617 if (len * 2 > USB_BUF_SZ)
621 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
626 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
627 static const u8 sensor_init[] = {
645 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
649 byte = reg_r(gspca_dev, 0x0060);
654 byte = reg_r(gspca_dev, 0x0063);
656 err("Bad sensor reset %02x", byte);
665 reg_w(gspca_dev, 0x3c80);
666 reg_w_buf(gspca_dev, val, sizeof val);
670 byte = reg_r(gspca_dev, 0x60);
676 reg_w(gspca_dev, 0x3c80);
679 /* this function is called at probe time */
680 static int sd_config(struct gspca_dev *gspca_dev,
681 const struct usb_device_id *id)
683 struct sd *sd = (struct sd *) gspca_dev;
686 cam = &gspca_dev->cam;
688 cam->cam_mode = vga_mode_t16;
689 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
691 sd->brightness = BRIGHTNESS_DEF;
692 sd->contrast = CONTRAST_DEF;
693 sd->colors = COLORS_DEF;
694 sd->gamma = GAMMA_DEF;
695 sd->autogain = AUTOGAIN_DEF;
696 sd->mirror = MIRROR_DEF;
699 sd->sharpness = SHARPNESS_DEF;
700 sd->effect = EFFECTS_DEF;
701 sd->red_balance = RED_BALANCE_DEF;
702 sd->blue_balance = BLUE_BALANCE_DEF;
703 sd->global_gain = global_gain_DEF;
708 static void setbrightness(struct gspca_dev *gspca_dev)
710 struct sd *sd = (struct sd *) gspca_dev;
711 unsigned int brightness;
712 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
714 brightness = sd->brightness;
715 if (brightness < 7) {
717 set6[3] = 0x70 - brightness * 0x10;
719 set6[3] = 0x00 + ((brightness - 7) * 0x10);
722 reg_w_buf(gspca_dev, set6, sizeof set6);
725 static void setcontrast(struct gspca_dev *gspca_dev)
727 struct sd *sd = (struct sd *) gspca_dev;
728 unsigned int contrast = sd->contrast;
732 reg_to_write = 0x8ea9 - contrast * 0x200;
734 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
736 reg_w(gspca_dev, reg_to_write);
739 static void setcolors(struct gspca_dev *gspca_dev)
741 struct sd *sd = (struct sd *) gspca_dev;
744 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
745 reg_w(gspca_dev, reg_to_write);
748 static void setgamma(struct gspca_dev *gspca_dev)
750 struct sd *sd = (struct sd *) gspca_dev;
752 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
753 reg_w_ixbuf(gspca_dev, 0x90,
754 gamma_table[sd->gamma], sizeof gamma_table[0]);
756 static void setglobalgain(struct gspca_dev *gspca_dev)
759 struct sd *sd = (struct sd *) gspca_dev;
760 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
761 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
762 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
765 /* Generic fnc for r/b balance, exposure and whitebalance */
766 static void setawb(struct gspca_dev *gspca_dev)
768 struct sd *sd = (struct sd *) gspca_dev;
770 /* on awb leave defaults values */
772 reg_w(gspca_dev, 0x3c80);
774 reg_w(gspca_dev, 0x3880);
775 /* shoud we wait here.. */
776 /* update and reset 'global gain' with webcam parameters */
777 sd->red_balance = reg_r(gspca_dev, 0x0087);
778 sd->blue_balance = reg_r(gspca_dev, 0x0088);
779 sd->global_gain = reg_r(gspca_dev, 0x0089);
780 setglobalgain(gspca_dev);
785 static void setsharpness(struct gspca_dev *gspca_dev)
787 struct sd *sd = (struct sd *) gspca_dev;
790 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
792 reg_w(gspca_dev, reg_to_write);
795 static void setfreq(struct gspca_dev *gspca_dev)
797 struct sd *sd = (struct sd *) gspca_dev;
799 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
801 switch (sd->sensor) {
815 case 0: /* no flicker */
824 reg_w_buf(gspca_dev, freq, sizeof freq);
827 /* this function is called at probe and resume time */
828 static int sd_init(struct gspca_dev *gspca_dev)
830 /* some of this registers are not really neded, because
831 * they are overriden by setbrigthness, setcontrast, etc,
832 * but wont hurt anyway, and can help someone with similar webcam
833 * to see the initial parameters.*/
834 struct sd *sd = (struct sd *) gspca_dev;
835 const struct additional_sensor_data *sensor;
840 static const u8 read_indexs[] =
841 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
842 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
843 static const u8 n1[] =
844 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
845 static const u8 n2[] =
848 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
849 | reg_r(gspca_dev, 0x07);
850 switch (sensor_id & 0xff0f) {
852 PDEBUG(D_PROBE, "sensor tas5130a");
853 sd->sensor = SENSOR_TAS5130A;
856 PDEBUG(D_PROBE, "sensor lt168g");
857 sd->sensor = SENSOR_LT168G;
860 PDEBUG(D_PROBE, "sensor 'other'");
861 sd->sensor = SENSOR_OTHER;
864 PDEBUG(D_PROBE, "sensor om6802");
865 sd->sensor = SENSOR_OM6802;
868 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
872 if (sd->sensor == SENSOR_OM6802) {
873 reg_w_buf(gspca_dev, n1, sizeof n1);
876 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
877 test_byte = reg_r(gspca_dev, 0x0063);
879 if (test_byte == 0x17)
883 err("Bad sensor reset %02x", test_byte);
886 reg_w_buf(gspca_dev, n2, sizeof n2);
890 while (read_indexs[i] != 0x00) {
891 test_byte = reg_r(gspca_dev, read_indexs[i]);
892 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
897 sensor = &sensor_data[sd->sensor];
898 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
899 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
901 if (sd->sensor == SENSOR_LT168G) {
902 test_byte = reg_r(gspca_dev, 0x80);
903 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
905 reg_w(gspca_dev, 0x6c80);
908 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
909 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
910 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
912 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
913 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
914 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
916 setbrightness(gspca_dev);
917 setcontrast(gspca_dev);
919 setcolors(gspca_dev);
920 setsharpness(gspca_dev);
924 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
925 reg_w(gspca_dev, 0x2088);
926 reg_w(gspca_dev, 0x2089);
928 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
929 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
930 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
931 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
933 if (sd->sensor == SENSOR_LT168G) {
934 test_byte = reg_r(gspca_dev, 0x80);
935 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
937 reg_w(gspca_dev, 0x6c80);
940 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
941 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
942 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
947 static void setmirror(struct gspca_dev *gspca_dev)
949 struct sd *sd = (struct sd *) gspca_dev;
951 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
956 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
959 static void seteffect(struct gspca_dev *gspca_dev)
961 struct sd *sd = (struct sd *) gspca_dev;
963 reg_w_buf(gspca_dev, effects_table[sd->effect],
964 sizeof effects_table[0]);
965 if (sd->effect == 1 || sd->effect == 5) {
967 "This effect have been disabled for webcam \"safety\"");
971 if (sd->effect == 1 || sd->effect == 4)
972 reg_w(gspca_dev, 0x4aa6);
974 reg_w(gspca_dev, 0xfaa6);
977 /* Is this really needed?
978 * i added some module parameters for test with some users */
979 static void poll_sensor(struct gspca_dev *gspca_dev)
981 static const u8 poll1[] =
982 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
983 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
984 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
986 static const u8 poll2[] =
987 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
988 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
989 static const u8 poll3[] =
990 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
991 static const u8 poll4[] =
992 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
993 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
994 0xc2, 0x80, 0xc3, 0x10};
996 PDEBUG(D_STREAM, "[Sensor requires polling]");
997 reg_w_buf(gspca_dev, poll1, sizeof poll1);
998 reg_w_buf(gspca_dev, poll2, sizeof poll2);
999 reg_w_buf(gspca_dev, poll3, sizeof poll3);
1000 reg_w_buf(gspca_dev, poll4, sizeof poll4);
1003 static int sd_start(struct gspca_dev *gspca_dev)
1005 struct sd *sd = (struct sd *) gspca_dev;
1006 const struct additional_sensor_data *sensor;
1008 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1009 static const u8 t3[] =
1010 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1012 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1014 case 0: /* 640x480 (0x00) */
1016 case 1: /* 352x288 */
1019 case 2: /* 320x240 */
1022 case 3: /* 176x144 */
1026 /* case 4: * 160x120 */
1031 switch (sd->sensor) {
1033 om6802_sensor_init(gspca_dev);
1035 case SENSOR_TAS5130A:
1038 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1039 sizeof tas5130a_sensor_init[0]);
1040 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1044 reg_w(gspca_dev, 0x3c80);
1045 /* just in case and to keep sync with logs (for mine) */
1046 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1047 sizeof tas5130a_sensor_init[0]);
1048 reg_w(gspca_dev, 0x3c80);
1051 sensor = &sensor_data[sd->sensor];
1053 reg_r(gspca_dev, 0x0012);
1054 reg_w_buf(gspca_dev, t2, sizeof t2);
1055 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1056 reg_w(gspca_dev, 0x0013);
1058 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1059 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1061 if (sd->sensor == SENSOR_OM6802)
1062 poll_sensor(gspca_dev);
1067 static void sd_stopN(struct gspca_dev *gspca_dev)
1069 struct sd *sd = (struct sd *) gspca_dev;
1071 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1072 sizeof sensor_data[sd->sensor].stream);
1073 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1074 sizeof sensor_data[sd->sensor].stream);
1075 if (sd->sensor == SENSOR_OM6802) {
1077 reg_w(gspca_dev, 0x0309);
1081 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1082 u8 *data, /* isoc packet */
1083 int len) /* iso packet length */
1085 static u8 ffd9[] = { 0xff, 0xd9 };
1087 if (data[0] == 0x5a) {
1088 /* Control Packet, after this came the header again,
1089 * but extra bytes came in the packet before this,
1090 * sometimes an EOF arrives, sometimes not... */
1095 if (data[0] == 0xff && data[1] == 0xd8) {
1096 /* extra bytes....., could be processed too but would be
1097 * a waste of time, right now leave the application and
1098 * libjpeg do it for ourserlves.. */
1099 gspca_frame_add(gspca_dev, LAST_PACKET,
1101 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1105 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1106 /* Just in case, i have seen packets with the marker,
1107 * other's do not include it... */
1110 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1114 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1116 struct sd *sd = (struct sd *) gspca_dev;
1118 sd->blue_balance = val;
1119 if (gspca_dev->streaming)
1120 reg_w(gspca_dev, (val << 8) + 0x88);
1124 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1126 struct sd *sd = (struct sd *) gspca_dev;
1128 *val = sd->blue_balance;
1132 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1134 struct sd *sd = (struct sd *) gspca_dev;
1136 sd->red_balance = val;
1137 if (gspca_dev->streaming)
1138 reg_w(gspca_dev, (val << 8) + 0x87);
1143 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1145 struct sd *sd = (struct sd *) gspca_dev;
1147 *val = sd->red_balance;
1153 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1155 struct sd *sd = (struct sd *) gspca_dev;
1157 sd->global_gain = val;
1158 if (gspca_dev->streaming)
1159 setglobalgain(gspca_dev);
1164 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1166 struct sd *sd = (struct sd *) gspca_dev;
1168 *val = sd->global_gain;
1172 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1174 struct sd *sd = (struct sd *) gspca_dev;
1176 sd->brightness = val;
1177 if (gspca_dev->streaming)
1178 setbrightness(gspca_dev);
1182 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1184 struct sd *sd = (struct sd *) gspca_dev;
1186 *val = sd->brightness;
1190 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1192 struct sd *sd = (struct sd *) gspca_dev;
1195 if (gspca_dev->streaming)
1200 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1202 struct sd *sd = (struct sd *) gspca_dev;
1208 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1210 struct sd *sd = (struct sd *) gspca_dev;
1213 if (gspca_dev->streaming)
1214 setmirror(gspca_dev);
1218 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1220 struct sd *sd = (struct sd *) gspca_dev;
1226 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1228 struct sd *sd = (struct sd *) gspca_dev;
1231 if (gspca_dev->streaming)
1232 seteffect(gspca_dev);
1236 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1238 struct sd *sd = (struct sd *) gspca_dev;
1244 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1246 struct sd *sd = (struct sd *) gspca_dev;
1249 if (gspca_dev->streaming)
1250 setcontrast(gspca_dev);
1254 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1256 struct sd *sd = (struct sd *) gspca_dev;
1258 *val = sd->contrast;
1262 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1264 struct sd *sd = (struct sd *) gspca_dev;
1267 if (gspca_dev->streaming)
1268 setcolors(gspca_dev);
1272 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1274 struct sd *sd = (struct sd *) gspca_dev;
1280 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1282 struct sd *sd = (struct sd *) gspca_dev;
1285 if (gspca_dev->streaming)
1286 setgamma(gspca_dev);
1290 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1292 struct sd *sd = (struct sd *) gspca_dev;
1298 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1300 struct sd *sd = (struct sd *) gspca_dev;
1303 if (gspca_dev->streaming)
1308 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1310 struct sd *sd = (struct sd *) gspca_dev;
1316 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1318 struct sd *sd = (struct sd *) gspca_dev;
1320 sd->sharpness = val;
1321 if (gspca_dev->streaming)
1322 setsharpness(gspca_dev);
1326 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1328 struct sd *sd = (struct sd *) gspca_dev;
1330 *val = sd->sharpness;
1334 /* Low Light set here......*/
1335 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1337 struct sd *sd = (struct sd *) gspca_dev;
1341 reg_w(gspca_dev, 0xf48e);
1343 reg_w(gspca_dev, 0xb48e);
1347 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1349 struct sd *sd = (struct sd *) gspca_dev;
1351 *val = sd->autogain;
1355 static int sd_querymenu(struct gspca_dev *gspca_dev,
1356 struct v4l2_querymenu *menu)
1359 case V4L2_CID_POWER_LINE_FREQUENCY:
1360 switch (menu->index) {
1361 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1362 strcpy((char *) menu->name, "50 Hz");
1364 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1365 strcpy((char *) menu->name, "60 Hz");
1369 case V4L2_CID_EFFECTS:
1370 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1371 strncpy((char *) menu->name,
1372 effects_control[menu->index],
1381 /* sub-driver description */
1382 static const struct sd_desc sd_desc = {
1383 .name = MODULE_NAME,
1385 .nctrls = ARRAY_SIZE(sd_ctrls),
1386 .config = sd_config,
1390 .pkt_scan = sd_pkt_scan,
1391 .querymenu = sd_querymenu,
1394 /* -- module initialisation -- */
1395 static const __devinitdata struct usb_device_id device_table[] = {
1396 {USB_DEVICE(0x17a1, 0x0128)},
1399 MODULE_DEVICE_TABLE(usb, device_table);
1401 /* -- device connect -- */
1402 static int sd_probe(struct usb_interface *intf,
1403 const struct usb_device_id *id)
1405 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1409 static struct usb_driver sd_driver = {
1410 .name = MODULE_NAME,
1411 .id_table = device_table,
1413 .disconnect = gspca_disconnect,
1415 .suspend = gspca_suspend,
1416 .resume = gspca_resume,
1420 /* -- module insert / remove -- */
1421 static int __init sd_mod_init(void)
1424 ret = usb_register(&sd_driver);
1427 PDEBUG(D_PROBE, "registered");
1430 static void __exit sd_mod_exit(void)
1432 usb_deregister(&sd_driver);
1433 PDEBUG(D_PROBE, "deregistered");
1436 module_init(sd_mod_init);
1437 module_exit(sd_mod_exit);