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;
327 static const u8 n4_om6802[] = {
328 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
329 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
330 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
331 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
332 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
333 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
334 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
335 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
336 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
338 static const u8 n4_other[] = {
339 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
340 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
341 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
342 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
343 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
344 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
345 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
346 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
348 static const u8 n4_tas5130a[] = {
349 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
350 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
351 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
352 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
353 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
354 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
357 static const u8 n4_lt168g[] = {
358 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
359 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
360 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
361 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
362 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
363 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
364 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
365 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
366 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
369 static const struct additional_sensor_data sensor_data[] = {
372 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
374 .n4sz = sizeof n4_om6802,
377 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
379 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
382 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
385 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
387 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
388 {0x66, 0xca, 0xa8, 0xf0},
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 {0x66, 0x00, 0xa8, 0xa8},
414 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
416 {0x0b, 0x04, 0x0a, 0x00},
418 [SENSOR_TAS5130A] = {
420 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
422 .n4sz = sizeof n4_tas5130a,
425 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
427 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
430 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
433 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
435 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
436 {0x66, 0x00, 0xa8, 0xe8},
438 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
440 {0x0b, 0x04, 0x0a, 0x40},
443 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
445 .n4sz = sizeof n4_lt168g,
448 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
449 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
451 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
453 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
455 .data4 = {0x66, 0x41, 0xa8, 0xf0},
456 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
457 .stream = {0x0b, 0x04, 0x0a, 0x28},
461 #define MAX_EFFECTS 7
462 /* easily done by soft, this table could be removed,
463 * i keep it here just in case */
464 static char *effects_control[MAX_EFFECTS] = {
466 "Emboss", /* disabled */
470 "Sun Effect", /* disabled */
473 static const u8 effects_table[MAX_EFFECTS][6] = {
474 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
475 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
476 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
477 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
478 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
479 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
480 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
483 static const u8 gamma_table[GAMMA_MAX][17] = {
484 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
485 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
487 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
488 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
490 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
491 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
493 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
494 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
496 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
497 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
499 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
500 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
502 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
503 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
505 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
506 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
508 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
509 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
511 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
512 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
514 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
515 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
517 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
518 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
520 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
521 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
523 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
524 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
526 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
527 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
529 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
530 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
534 static const u8 tas5130a_sensor_init[][8] = {
535 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
536 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
537 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
540 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
543 static u8 reg_r(struct gspca_dev *gspca_dev,
546 usb_control_msg(gspca_dev->dev,
547 usb_rcvctrlpipe(gspca_dev->dev, 0),
549 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
552 gspca_dev->usb_buf, 1, 500);
553 return gspca_dev->usb_buf[0];
556 static void reg_w(struct gspca_dev *gspca_dev,
559 usb_control_msg(gspca_dev->dev,
560 usb_sndctrlpipe(gspca_dev->dev, 0),
562 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
567 static void reg_w_buf(struct gspca_dev *gspca_dev,
568 const u8 *buffer, u16 len)
570 if (len <= USB_BUF_SZ) {
571 memcpy(gspca_dev->usb_buf, buffer, len);
572 usb_control_msg(gspca_dev->dev,
573 usb_sndctrlpipe(gspca_dev->dev, 0),
575 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
577 gspca_dev->usb_buf, len, 500);
581 tmpbuf = kmalloc(len, GFP_KERNEL);
583 err("Out of memory");
586 memcpy(tmpbuf, buffer, len);
587 usb_control_msg(gspca_dev->dev,
588 usb_sndctrlpipe(gspca_dev->dev, 0),
590 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
597 /* write values to consecutive registers */
598 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
600 const u8 *buffer, u16 len)
605 if (len * 2 <= USB_BUF_SZ) {
606 p = tmpbuf = gspca_dev->usb_buf;
608 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
610 err("Out of memory");
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
624 tmpbuf, len * 2, 500);
625 if (len * 2 > USB_BUF_SZ)
629 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
634 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
635 static const u8 sensor_init[] = {
653 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
657 byte = reg_r(gspca_dev, 0x0060);
662 byte = reg_r(gspca_dev, 0x0063);
664 err("Bad sensor reset %02x", byte);
673 reg_w(gspca_dev, 0x3c80);
674 reg_w_buf(gspca_dev, val, sizeof val);
678 byte = reg_r(gspca_dev, 0x60);
684 reg_w(gspca_dev, 0x3c80);
687 /* this function is called at probe time */
688 static int sd_config(struct gspca_dev *gspca_dev,
689 const struct usb_device_id *id)
691 struct sd *sd = (struct sd *) gspca_dev;
694 cam = &gspca_dev->cam;
696 cam->cam_mode = vga_mode_t16;
697 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
699 sd->brightness = BRIGHTNESS_DEF;
700 sd->contrast = CONTRAST_DEF;
701 sd->colors = COLORS_DEF;
702 sd->gamma = GAMMA_DEF;
703 sd->autogain = AUTOGAIN_DEF;
704 sd->mirror = MIRROR_DEF;
707 sd->sharpness = SHARPNESS_DEF;
708 sd->effect = EFFECTS_DEF;
709 sd->red_balance = RED_BALANCE_DEF;
710 sd->blue_balance = BLUE_BALANCE_DEF;
711 sd->global_gain = global_gain_DEF;
716 static void setbrightness(struct gspca_dev *gspca_dev)
718 struct sd *sd = (struct sd *) gspca_dev;
719 unsigned int brightness;
720 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
722 brightness = sd->brightness;
723 if (brightness < 7) {
725 set6[3] = 0x70 - brightness * 0x10;
727 set6[3] = 0x00 + ((brightness - 7) * 0x10);
730 reg_w_buf(gspca_dev, set6, sizeof set6);
733 static void setcontrast(struct gspca_dev *gspca_dev)
735 struct sd *sd = (struct sd *) gspca_dev;
736 unsigned int contrast = sd->contrast;
740 reg_to_write = 0x8ea9 - contrast * 0x200;
742 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
744 reg_w(gspca_dev, reg_to_write);
747 static void setcolors(struct gspca_dev *gspca_dev)
749 struct sd *sd = (struct sd *) gspca_dev;
752 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
753 reg_w(gspca_dev, reg_to_write);
756 static void setgamma(struct gspca_dev *gspca_dev)
758 struct sd *sd = (struct sd *) gspca_dev;
760 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
761 reg_w_ixbuf(gspca_dev, 0x90,
762 gamma_table[sd->gamma], sizeof gamma_table[0]);
764 static void setglobalgain(struct gspca_dev *gspca_dev)
767 struct sd *sd = (struct sd *) gspca_dev;
768 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
769 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
770 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
773 /* Generic fnc for r/b balance, exposure and whitebalance */
774 static void setawb(struct gspca_dev *gspca_dev)
776 struct sd *sd = (struct sd *) gspca_dev;
778 /* on awb leave defaults values */
780 reg_w(gspca_dev, 0x3c80);
782 reg_w(gspca_dev, 0x3880);
783 /* shoud we wait here.. */
784 /* update and reset 'global gain' with webcam parameters */
785 sd->red_balance = reg_r(gspca_dev, 0x0087);
786 sd->blue_balance = reg_r(gspca_dev, 0x0088);
787 sd->global_gain = reg_r(gspca_dev, 0x0089);
788 setglobalgain(gspca_dev);
793 static void setsharpness(struct gspca_dev *gspca_dev)
795 struct sd *sd = (struct sd *) gspca_dev;
798 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
800 reg_w(gspca_dev, reg_to_write);
803 /* this function is called at probe and resume time */
804 static int sd_init(struct gspca_dev *gspca_dev)
806 /* some of this registers are not really neded, because
807 * they are overriden by setbrigthness, setcontrast, etc,
808 * but wont hurt anyway, and can help someone with similar webcam
809 * to see the initial parameters.*/
810 struct sd *sd = (struct sd *) gspca_dev;
811 const struct additional_sensor_data *sensor;
816 static const u8 read_indexs[] =
817 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
818 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
819 static const u8 n1[] =
820 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
821 static const u8 n2[] =
824 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
825 | reg_r(gspca_dev, 0x07);
826 switch (sensor_id & 0xff0f) {
828 PDEBUG(D_PROBE, "sensor tas5130a");
829 sd->sensor = SENSOR_TAS5130A;
832 PDEBUG(D_PROBE, "sensor lt168g");
833 sd->sensor = SENSOR_LT168G;
836 PDEBUG(D_PROBE, "sensor 'other'");
837 sd->sensor = SENSOR_OTHER;
840 PDEBUG(D_PROBE, "sensor om6802");
841 sd->sensor = SENSOR_OM6802;
844 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
848 if (sd->sensor == SENSOR_OM6802) {
849 reg_w_buf(gspca_dev, n1, sizeof n1);
852 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
853 test_byte = reg_r(gspca_dev, 0x0063);
855 if (test_byte == 0x17)
859 err("Bad sensor reset %02x", test_byte);
862 reg_w_buf(gspca_dev, n2, sizeof n2);
866 while (read_indexs[i] != 0x00) {
867 test_byte = reg_r(gspca_dev, read_indexs[i]);
868 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
873 sensor = &sensor_data[sd->sensor];
874 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
875 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
877 if (sd->sensor == SENSOR_LT168G) {
878 test_byte = reg_r(gspca_dev, 0x80);
879 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
881 reg_w(gspca_dev, 0x6c80);
884 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
885 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
886 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
888 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
889 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
890 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
892 setbrightness(gspca_dev);
893 setcontrast(gspca_dev);
895 setcolors(gspca_dev);
896 setsharpness(gspca_dev);
899 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
900 reg_w(gspca_dev, 0x2088);
901 reg_w(gspca_dev, 0x2089);
903 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
904 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
905 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
906 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
908 if (sd->sensor == SENSOR_LT168G) {
909 test_byte = reg_r(gspca_dev, 0x80);
910 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
912 reg_w(gspca_dev, 0x6c80);
915 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
916 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
917 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
922 static void setmirror(struct gspca_dev *gspca_dev)
924 struct sd *sd = (struct sd *) gspca_dev;
926 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
931 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
934 static void seteffect(struct gspca_dev *gspca_dev)
936 struct sd *sd = (struct sd *) gspca_dev;
938 reg_w_buf(gspca_dev, effects_table[sd->effect],
939 sizeof effects_table[0]);
940 if (sd->effect == 1 || sd->effect == 5) {
942 "This effect have been disabled for webcam \"safety\"");
946 if (sd->effect == 1 || sd->effect == 4)
947 reg_w(gspca_dev, 0x4aa6);
949 reg_w(gspca_dev, 0xfaa6);
952 static void setlightfreq(struct gspca_dev *gspca_dev)
954 struct sd *sd = (struct sd *) gspca_dev;
955 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
957 if (sd->freq == 2) /* 60hz */
960 reg_w_buf(gspca_dev, freq, sizeof freq);
963 /* Is this really needed?
964 * i added some module parameters for test with some users */
965 static void poll_sensor(struct gspca_dev *gspca_dev)
967 static const u8 poll1[] =
968 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
969 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
970 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
972 static const u8 poll2[] =
973 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
974 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
975 static const u8 poll3[] =
976 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
977 static const u8 poll4[] =
978 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
979 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
980 0xc2, 0x80, 0xc3, 0x10};
982 PDEBUG(D_STREAM, "[Sensor requires polling]");
983 reg_w_buf(gspca_dev, poll1, sizeof poll1);
984 reg_w_buf(gspca_dev, poll2, sizeof poll2);
985 reg_w_buf(gspca_dev, poll3, sizeof poll3);
986 reg_w_buf(gspca_dev, poll4, sizeof poll4);
989 static int sd_start(struct gspca_dev *gspca_dev)
991 struct sd *sd = (struct sd *) gspca_dev;
992 const struct additional_sensor_data *sensor;
994 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
995 static const u8 t3[] =
996 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
998 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1000 case 0: /* 640x480 (0x00) */
1002 case 1: /* 352x288 */
1005 case 2: /* 320x240 */
1008 case 3: /* 176x144 */
1012 /* case 4: * 160x120 */
1017 switch (sd->sensor) {
1019 om6802_sensor_init(gspca_dev);
1021 case SENSOR_TAS5130A:
1024 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1025 sizeof tas5130a_sensor_init[0]);
1026 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1030 reg_w(gspca_dev, 0x3c80);
1031 /* just in case and to keep sync with logs (for mine) */
1032 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1033 sizeof tas5130a_sensor_init[0]);
1034 reg_w(gspca_dev, 0x3c80);
1037 sensor = &sensor_data[sd->sensor];
1038 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
1039 reg_r(gspca_dev, 0x0012);
1040 reg_w_buf(gspca_dev, t2, sizeof t2);
1041 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1042 reg_w(gspca_dev, 0x0013);
1044 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1045 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1047 if (sd->sensor == SENSOR_OM6802)
1048 poll_sensor(gspca_dev);
1053 static void sd_stopN(struct gspca_dev *gspca_dev)
1055 struct sd *sd = (struct sd *) gspca_dev;
1057 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1058 sizeof sensor_data[sd->sensor].stream);
1059 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1060 sizeof sensor_data[sd->sensor].stream);
1061 if (sd->sensor == SENSOR_OM6802) {
1063 reg_w(gspca_dev, 0x0309);
1067 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1068 u8 *data, /* isoc packet */
1069 int len) /* iso packet length */
1071 static u8 ffd9[] = { 0xff, 0xd9 };
1073 if (data[0] == 0x5a) {
1074 /* Control Packet, after this came the header again,
1075 * but extra bytes came in the packet before this,
1076 * sometimes an EOF arrives, sometimes not... */
1081 if (data[0] == 0xff && data[1] == 0xd8) {
1082 /* extra bytes....., could be processed too but would be
1083 * a waste of time, right now leave the application and
1084 * libjpeg do it for ourserlves.. */
1085 gspca_frame_add(gspca_dev, LAST_PACKET,
1087 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1091 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1092 /* Just in case, i have seen packets with the marker,
1093 * other's do not include it... */
1096 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1100 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1102 struct sd *sd = (struct sd *) gspca_dev;
1104 sd->blue_balance = val;
1105 if (gspca_dev->streaming)
1106 reg_w(gspca_dev, (val << 8) + 0x88);
1110 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1112 struct sd *sd = (struct sd *) gspca_dev;
1114 *val = sd->blue_balance;
1118 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1120 struct sd *sd = (struct sd *) gspca_dev;
1122 sd->red_balance = val;
1123 if (gspca_dev->streaming)
1124 reg_w(gspca_dev, (val << 8) + 0x87);
1129 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1131 struct sd *sd = (struct sd *) gspca_dev;
1133 *val = sd->red_balance;
1139 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1141 struct sd *sd = (struct sd *) gspca_dev;
1143 sd->global_gain = val;
1144 if (gspca_dev->streaming)
1145 setglobalgain(gspca_dev);
1150 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1152 struct sd *sd = (struct sd *) gspca_dev;
1154 *val = sd->global_gain;
1158 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1160 struct sd *sd = (struct sd *) gspca_dev;
1162 sd->brightness = val;
1163 if (gspca_dev->streaming)
1164 setbrightness(gspca_dev);
1168 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1170 struct sd *sd = (struct sd *) gspca_dev;
1172 *val = sd->brightness;
1176 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1178 struct sd *sd = (struct sd *) gspca_dev;
1181 if (gspca_dev->streaming)
1186 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1188 struct sd *sd = (struct sd *) gspca_dev;
1194 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1196 struct sd *sd = (struct sd *) gspca_dev;
1199 if (gspca_dev->streaming)
1200 setmirror(gspca_dev);
1204 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1206 struct sd *sd = (struct sd *) gspca_dev;
1212 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1214 struct sd *sd = (struct sd *) gspca_dev;
1217 if (gspca_dev->streaming)
1218 seteffect(gspca_dev);
1222 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1224 struct sd *sd = (struct sd *) gspca_dev;
1230 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1232 struct sd *sd = (struct sd *) gspca_dev;
1235 if (gspca_dev->streaming)
1236 setcontrast(gspca_dev);
1240 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1242 struct sd *sd = (struct sd *) gspca_dev;
1244 *val = sd->contrast;
1248 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1250 struct sd *sd = (struct sd *) gspca_dev;
1253 if (gspca_dev->streaming)
1254 setcolors(gspca_dev);
1258 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1260 struct sd *sd = (struct sd *) gspca_dev;
1266 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1268 struct sd *sd = (struct sd *) gspca_dev;
1271 if (gspca_dev->streaming)
1272 setgamma(gspca_dev);
1276 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1278 struct sd *sd = (struct sd *) gspca_dev;
1284 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1286 struct sd *sd = (struct sd *) gspca_dev;
1289 if (gspca_dev->streaming)
1294 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1296 struct sd *sd = (struct sd *) gspca_dev;
1302 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1304 struct sd *sd = (struct sd *) gspca_dev;
1306 sd->sharpness = val;
1307 if (gspca_dev->streaming)
1308 setsharpness(gspca_dev);
1312 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1314 struct sd *sd = (struct sd *) gspca_dev;
1316 *val = sd->sharpness;
1320 /* Low Light set here......*/
1321 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1323 struct sd *sd = (struct sd *) gspca_dev;
1327 reg_w(gspca_dev, 0xf48e);
1329 reg_w(gspca_dev, 0xb48e);
1333 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1335 struct sd *sd = (struct sd *) gspca_dev;
1337 *val = sd->autogain;
1341 static int sd_querymenu(struct gspca_dev *gspca_dev,
1342 struct v4l2_querymenu *menu)
1345 case V4L2_CID_POWER_LINE_FREQUENCY:
1346 switch (menu->index) {
1347 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1348 strcpy((char *) menu->name, "50 Hz");
1350 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1351 strcpy((char *) menu->name, "60 Hz");
1355 case V4L2_CID_EFFECTS:
1356 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1357 strncpy((char *) menu->name,
1358 effects_control[menu->index],
1367 /* sub-driver description */
1368 static const struct sd_desc sd_desc = {
1369 .name = MODULE_NAME,
1371 .nctrls = ARRAY_SIZE(sd_ctrls),
1372 .config = sd_config,
1376 .pkt_scan = sd_pkt_scan,
1377 .querymenu = sd_querymenu,
1380 /* -- module initialisation -- */
1381 static const __devinitdata struct usb_device_id device_table[] = {
1382 {USB_DEVICE(0x17a1, 0x0128)},
1385 MODULE_DEVICE_TABLE(usb, device_table);
1387 /* -- device connect -- */
1388 static int sd_probe(struct usb_interface *intf,
1389 const struct usb_device_id *id)
1391 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1395 static struct usb_driver sd_driver = {
1396 .name = MODULE_NAME,
1397 .id_table = device_table,
1399 .disconnect = gspca_disconnect,
1401 .suspend = gspca_suspend,
1402 .resume = gspca_resume,
1406 /* -- module insert / remove -- */
1407 static int __init sd_mod_init(void)
1410 ret = usb_register(&sd_driver);
1413 PDEBUG(D_PROBE, "registered");
1416 static void __exit sd_mod_exit(void)
1418 usb_deregister(&sd_driver);
1419 PDEBUG(D_PROBE, "deregistered");
1422 module_init(sd_mod_init);
1423 module_exit(sd_mod_exit);