2 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
27 #define MODULE_NAME "t613"
31 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
33 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35 MODULE_LICENSE("GPL");
38 struct gspca_dev gspca_dev; /* !! must be the first item */
47 u8 red_balance; /* split balance */
49 u8 global_gain; /* aka gain */
50 u8 whitebalance; /* set default r/g/b and activate */
55 #define SENSOR_OM6802 0
56 #define SENSOR_OTHER 1
57 #define SENSOR_TAS5130A 2
58 #define SENSOR_LT168G 3 /* must verify if this is the actual model */
61 /* V4L2 controls supported by the driver */
62 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
66 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
70 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
71 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
72 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
73 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
74 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
75 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
78 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
79 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
80 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
91 static int sd_querymenu(struct gspca_dev *gspca_dev,
92 struct v4l2_querymenu *menu);
95 static const struct ctrl sd_ctrls[] = {
98 .id = V4L2_CID_BRIGHTNESS,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Brightness",
104 #define BRIGHTNESS_DEF 8
105 .default_value = BRIGHTNESS_DEF,
107 .set = sd_setbrightness,
108 .get = sd_getbrightness,
112 .id = V4L2_CID_CONTRAST,
113 .type = V4L2_CTRL_TYPE_INTEGER,
118 #define CONTRAST_DEF 0x07
119 .default_value = CONTRAST_DEF,
121 .set = sd_setcontrast,
122 .get = sd_getcontrast,
126 .id = V4L2_CID_SATURATION,
127 .type = V4L2_CTRL_TYPE_INTEGER,
132 #define COLORS_DEF 0x05
133 .default_value = COLORS_DEF,
142 .id = V4L2_CID_GAMMA, /* (gamma on win) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
146 .maximum = GAMMA_MAX - 1,
148 .default_value = GAMMA_DEF,
155 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
156 * some apps dont bring up the
157 * backligth_compensation control) */
158 .type = V4L2_CTRL_TYPE_INTEGER,
163 #define AUTOGAIN_DEF 0x01
164 .default_value = AUTOGAIN_DEF,
166 .set = sd_setlowlight,
167 .get = sd_getlowlight,
171 .id = V4L2_CID_HFLIP,
172 .type = V4L2_CTRL_TYPE_BOOLEAN,
173 .name = "Mirror Image",
178 .default_value = MIRROR_DEF,
185 .id = V4L2_CID_POWER_LINE_FREQUENCY,
186 .type = V4L2_CTRL_TYPE_MENU,
187 .name = "Light Frequency Filter",
188 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
192 .default_value = FREQ_DEF,
199 .id = V4L2_CID_AUTO_WHITE_BALANCE,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "White Balance",
205 #define WHITE_BALANCE_DEF 0
206 .default_value = WHITE_BALANCE_DEF,
208 .set = sd_setwhitebalance,
209 .get = sd_getwhitebalance
213 .id = V4L2_CID_SHARPNESS,
214 .type = V4L2_CTRL_TYPE_INTEGER,
219 #define SHARPNESS_DEF 0x06
220 .default_value = SHARPNESS_DEF,
222 .set = sd_setsharpness,
223 .get = sd_getsharpness,
227 .id = V4L2_CID_EFFECTS,
228 .type = V4L2_CTRL_TYPE_MENU,
229 .name = "Webcam Effects",
233 #define EFFECTS_DEF 0
234 .default_value = EFFECTS_DEF,
241 .id = V4L2_CID_BLUE_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Blue Balance",
247 #define BLUE_BALANCE_DEF 0x20
248 .default_value = BLUE_BALANCE_DEF,
250 .set = sd_setblue_balance,
251 .get = sd_getblue_balance,
255 .id = V4L2_CID_RED_BALANCE,
256 .type = V4L2_CTRL_TYPE_INTEGER,
257 .name = "Red Balance",
261 #define RED_BALANCE_DEF 0x20
262 .default_value = RED_BALANCE_DEF,
264 .set = sd_setred_balance,
265 .get = sd_getred_balance,
270 .type = V4L2_CTRL_TYPE_INTEGER,
275 #define global_gain_DEF 0x20
276 .default_value = global_gain_DEF,
278 .set = sd_setglobal_gain,
279 .get = sd_getglobal_gain,
283 static char *effects_control[] = {
285 "Emboss", /* disabled */
289 "Sun Effect", /* disabled */
293 static const struct v4l2_pix_format vga_mode_t16[] = {
294 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
296 .sizeimage = 160 * 120 * 4 / 8 + 590,
297 .colorspace = V4L2_COLORSPACE_JPEG,
299 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
301 .sizeimage = 176 * 144 * 3 / 8 + 590,
302 .colorspace = V4L2_COLORSPACE_JPEG,
304 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
306 .sizeimage = 320 * 240 * 3 / 8 + 590,
307 .colorspace = V4L2_COLORSPACE_JPEG,
309 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
311 .sizeimage = 352 * 288 * 3 / 8 + 590,
312 .colorspace = V4L2_COLORSPACE_JPEG,
314 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
316 .sizeimage = 640 * 480 * 3 / 8 + 590,
317 .colorspace = V4L2_COLORSPACE_JPEG,
321 /* sensor specific data */
322 struct additional_sensor_data {
325 const u8 reg80, reg8e;
335 static const u8 n4_om6802[] = {
336 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
337 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
338 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
339 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
340 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
341 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
342 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
343 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
344 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
346 static const u8 n4_other[] = {
347 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
348 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
349 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
350 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
351 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
352 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
353 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
354 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
356 static const u8 n4_tas5130a[] = {
357 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
358 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
359 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
360 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
361 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
362 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
365 static const u8 n4_lt168g[] = {
366 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
367 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
368 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
369 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
370 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
371 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
372 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
373 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
374 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
377 static const struct additional_sensor_data sensor_data[] = {
380 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
382 .n4sz = sizeof n4_om6802,
385 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
387 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
390 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
393 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
395 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
396 {0x66, 0xca, 0xa8, 0xf0},
397 .data5 = /* this could be removed later */
398 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
400 {0x0b, 0x04, 0x0a, 0x78},
404 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
406 .n4sz = sizeof n4_other,
409 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
411 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
414 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
417 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
420 {0x66, 0x00, 0xa8, 0xa8},
422 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
424 {0x0b, 0x04, 0x0a, 0x00},
428 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
430 .n4sz = sizeof n4_tas5130a,
433 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
435 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
438 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
441 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
443 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
444 {0x66, 0x00, 0xa8, 0xe8},
446 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
448 {0x0b, 0x04, 0x0a, 0x40},
451 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
453 .n4sz = sizeof n4_lt168g,
456 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
457 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
459 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
461 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
463 .data4 = {0x66, 0x41, 0xa8, 0xf0},
464 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
465 .stream = {0x0b, 0x04, 0x0a, 0x28},
469 #define MAX_EFFECTS 7
470 /* easily done by soft, this table could be removed,
471 * i keep it here just in case */
472 static const u8 effects_table[MAX_EFFECTS][6] = {
473 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
474 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
475 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
476 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
477 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
478 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
479 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
482 static const u8 gamma_table[GAMMA_MAX][17] = {
483 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
484 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
486 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
487 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
489 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
490 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
492 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
493 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
495 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
496 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
498 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
499 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
501 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
502 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
504 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
505 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
507 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
508 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
510 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
511 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
513 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
514 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
516 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
517 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
519 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
520 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
522 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
523 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
525 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
526 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
528 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
529 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
533 static const u8 tas5130a_sensor_init[][8] = {
534 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
535 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
536 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
539 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
542 static u8 reg_r(struct gspca_dev *gspca_dev,
545 usb_control_msg(gspca_dev->dev,
546 usb_rcvctrlpipe(gspca_dev->dev, 0),
548 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
551 gspca_dev->usb_buf, 1, 500);
552 return gspca_dev->usb_buf[0];
555 static void reg_w(struct gspca_dev *gspca_dev,
558 usb_control_msg(gspca_dev->dev,
559 usb_sndctrlpipe(gspca_dev->dev, 0),
561 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
566 static void reg_w_buf(struct gspca_dev *gspca_dev,
567 const u8 *buffer, u16 len)
569 if (len <= USB_BUF_SZ) {
570 memcpy(gspca_dev->usb_buf, buffer, len);
571 usb_control_msg(gspca_dev->dev,
572 usb_sndctrlpipe(gspca_dev->dev, 0),
574 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
576 gspca_dev->usb_buf, len, 500);
580 tmpbuf = kmalloc(len, GFP_KERNEL);
582 err("Out of memory");
585 memcpy(tmpbuf, buffer, len);
586 usb_control_msg(gspca_dev->dev,
587 usb_sndctrlpipe(gspca_dev->dev, 0),
589 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
596 /* write values to consecutive registers */
597 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
599 const u8 *buffer, u16 len)
604 if (len * 2 <= USB_BUF_SZ) {
605 p = tmpbuf = gspca_dev->usb_buf;
607 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
609 err("Out of memory");
618 usb_control_msg(gspca_dev->dev,
619 usb_sndctrlpipe(gspca_dev->dev, 0),
621 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
623 tmpbuf, len * 2, 500);
624 if (len * 2 > USB_BUF_SZ)
628 /* Reported as OM6802*/
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;
706 sd->whitebalance = WHITE_BALANCE_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 setbalance(struct gspca_dev *gspca_dev)
776 struct sd *sd = (struct sd *) gspca_dev;
778 /* on whitebalance leave defaults values */
779 if (sd->whitebalance) {
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);
795 static void setwhitebalance(struct gspca_dev *gspca_dev)
797 setbalance(gspca_dev);
800 static void setsharpness(struct gspca_dev *gspca_dev)
802 struct sd *sd = (struct sd *) gspca_dev;
805 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
807 reg_w(gspca_dev, reg_to_write);
810 /* this function is called at probe and resume time */
811 static int sd_init(struct gspca_dev *gspca_dev)
813 /* some of this registers are not really neded, because
814 * they are overriden by setbrigthness, setcontrast, etc,
815 * but wont hurt anyway, and can help someone with similar webcam
816 * to see the initial parameters.*/
817 struct sd *sd = (struct sd *) gspca_dev;
818 const struct additional_sensor_data *sensor;
823 static const u8 read_indexs[] =
824 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
825 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
826 static const u8 n1[] =
827 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
828 static const u8 n2[] =
831 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
832 | reg_r(gspca_dev, 0x07);
833 switch (sensor_id & 0xff0f) {
835 PDEBUG(D_PROBE, "sensor tas5130a");
836 sd->sensor = SENSOR_TAS5130A;
839 PDEBUG(D_PROBE, "sensor lt168g");
840 sd->sensor = SENSOR_LT168G;
843 PDEBUG(D_PROBE, "sensor 'other'");
844 sd->sensor = SENSOR_OTHER;
847 PDEBUG(D_PROBE, "sensor om6802");
848 sd->sensor = SENSOR_OM6802;
851 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
855 if (sd->sensor == SENSOR_OM6802) {
856 reg_w_buf(gspca_dev, n1, sizeof n1);
859 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
860 test_byte = reg_r(gspca_dev, 0x0063);
862 if (test_byte == 0x17)
866 err("Bad sensor reset %02x", test_byte);
869 reg_w_buf(gspca_dev, n2, sizeof n2);
873 while (read_indexs[i] != 0x00) {
874 test_byte = reg_r(gspca_dev, read_indexs[i]);
875 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
880 sensor = &sensor_data[sd->sensor];
881 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
882 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
884 if (sd->sensor == SENSOR_LT168G) {
885 test_byte = reg_r(gspca_dev, 0x80);
886 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
888 reg_w(gspca_dev, 0x6c80);
891 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
892 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
893 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
895 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
896 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
897 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
899 setbrightness(gspca_dev);
900 setcontrast(gspca_dev);
902 setcolors(gspca_dev);
903 setsharpness(gspca_dev);
904 setwhitebalance(gspca_dev);
906 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
907 reg_w(gspca_dev, 0x2088);
908 reg_w(gspca_dev, 0x2089);
910 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
911 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
912 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
913 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
915 if (sd->sensor == SENSOR_LT168G) {
916 test_byte = reg_r(gspca_dev, 0x80);
917 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
919 reg_w(gspca_dev, 0x6c80);
922 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
923 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
924 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
929 static void setflip(struct gspca_dev *gspca_dev)
931 struct sd *sd = (struct sd *) gspca_dev;
933 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
938 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
941 static void seteffect(struct gspca_dev *gspca_dev)
943 struct sd *sd = (struct sd *) gspca_dev;
945 reg_w_buf(gspca_dev, effects_table[sd->effect],
946 sizeof effects_table[0]);
947 if (sd->effect == 1 || sd->effect == 5) {
949 "This effect have been disabled for webcam \"safety\"");
953 if (sd->effect == 1 || sd->effect == 4)
954 reg_w(gspca_dev, 0x4aa6);
956 reg_w(gspca_dev, 0xfaa6);
959 static void setlightfreq(struct gspca_dev *gspca_dev)
961 struct sd *sd = (struct sd *) gspca_dev;
962 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
964 if (sd->freq == 2) /* 60hz */
967 reg_w_buf(gspca_dev, freq, sizeof freq);
970 /* Is this really needed?
971 * i added some module parameters for test with some users */
972 static void poll_sensor(struct gspca_dev *gspca_dev)
974 static const u8 poll1[] =
975 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
976 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
977 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
979 static const u8 poll2[] =
980 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
981 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
982 static const u8 poll3[] =
983 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
984 static const u8 poll4[] =
985 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
986 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
987 0xc2, 0x80, 0xc3, 0x10};
989 PDEBUG(D_STREAM, "[Sensor requires polling]");
990 reg_w_buf(gspca_dev, poll1, sizeof poll1);
991 reg_w_buf(gspca_dev, poll2, sizeof poll2);
992 reg_w_buf(gspca_dev, poll3, sizeof poll3);
993 reg_w_buf(gspca_dev, poll4, sizeof poll4);
996 static int sd_start(struct gspca_dev *gspca_dev)
998 struct sd *sd = (struct sd *) gspca_dev;
999 const struct additional_sensor_data *sensor;
1001 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1002 static const u8 t3[] =
1003 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1005 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1007 case 0: /* 640x480 (0x00) */
1009 case 1: /* 352x288 */
1012 case 2: /* 320x240 */
1015 case 3: /* 176x144 */
1019 /* case 4: * 160x120 */
1024 switch (sd->sensor) {
1026 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];
1050 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
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 */
1083 static u8 ffd9[] = { 0xff, 0xd9 };
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 /* extra bytes....., could be processed too but would be
1095 * a waste of time, right now leave the application and
1096 * libjpeg do it for ourserlves.. */
1097 gspca_frame_add(gspca_dev, LAST_PACKET,
1099 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1103 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1104 /* Just in case, i have seen packets with the marker,
1105 * other's do not include it... */
1108 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1112 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1114 struct sd *sd = (struct sd *) gspca_dev;
1116 sd->blue_balance = val;
1117 if (gspca_dev->streaming)
1118 reg_w(gspca_dev, (val << 8) + 0x88);
1122 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1124 struct sd *sd = (struct sd *) gspca_dev;
1126 *val = sd->blue_balance;
1130 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1132 struct sd *sd = (struct sd *) gspca_dev;
1134 sd->red_balance = val;
1135 if (gspca_dev->streaming)
1136 reg_w(gspca_dev, (val << 8) + 0x87);
1141 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1143 struct sd *sd = (struct sd *) gspca_dev;
1145 *val = sd->red_balance;
1151 static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1153 struct sd *sd = (struct sd *) gspca_dev;
1155 sd->global_gain = val;
1156 if (gspca_dev->streaming)
1157 setglobalgain(gspca_dev);
1162 static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1164 struct sd *sd = (struct sd *) gspca_dev;
1166 *val = sd->global_gain;
1171 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1173 struct sd *sd = (struct sd *) gspca_dev;
1175 sd->brightness = val;
1176 if (gspca_dev->streaming)
1177 setbrightness(gspca_dev);
1181 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1183 struct sd *sd = (struct sd *) gspca_dev;
1185 *val = sd->brightness;
1189 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
1191 struct sd *sd = (struct sd *) gspca_dev;
1193 sd->whitebalance = val;
1194 if (gspca_dev->streaming)
1195 setwhitebalance(gspca_dev);
1199 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1201 struct sd *sd = (struct sd *) gspca_dev;
1203 *val = sd->whitebalance;
1207 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1209 struct sd *sd = (struct sd *) gspca_dev;
1212 if (gspca_dev->streaming)
1217 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1219 struct sd *sd = (struct sd *) gspca_dev;
1225 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1227 struct sd *sd = (struct sd *) gspca_dev;
1230 if (gspca_dev->streaming)
1231 seteffect(gspca_dev);
1235 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1237 struct sd *sd = (struct sd *) gspca_dev;
1243 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1245 struct sd *sd = (struct sd *) gspca_dev;
1248 if (gspca_dev->streaming)
1249 setcontrast(gspca_dev);
1253 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1255 struct sd *sd = (struct sd *) gspca_dev;
1257 *val = sd->contrast;
1261 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1263 struct sd *sd = (struct sd *) gspca_dev;
1266 if (gspca_dev->streaming)
1267 setcolors(gspca_dev);
1271 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1273 struct sd *sd = (struct sd *) gspca_dev;
1279 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1281 struct sd *sd = (struct sd *) gspca_dev;
1284 if (gspca_dev->streaming)
1285 setgamma(gspca_dev);
1289 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1291 struct sd *sd = (struct sd *) gspca_dev;
1297 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1299 struct sd *sd = (struct sd *) gspca_dev;
1302 if (gspca_dev->streaming)
1303 setlightfreq(gspca_dev);
1307 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1309 struct sd *sd = (struct sd *) gspca_dev;
1315 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1317 struct sd *sd = (struct sd *) gspca_dev;
1319 sd->sharpness = val;
1320 if (gspca_dev->streaming)
1321 setsharpness(gspca_dev);
1325 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1327 struct sd *sd = (struct sd *) gspca_dev;
1329 *val = sd->sharpness;
1333 /* Low Light set here......*/
1334 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1336 struct sd *sd = (struct sd *) gspca_dev;
1340 reg_w(gspca_dev, 0xf48e);
1342 reg_w(gspca_dev, 0xb48e);
1346 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1348 struct sd *sd = (struct sd *) gspca_dev;
1350 *val = sd->autogain;
1354 static int sd_querymenu(struct gspca_dev *gspca_dev,
1355 struct v4l2_querymenu *menu)
1358 case V4L2_CID_POWER_LINE_FREQUENCY:
1359 switch (menu->index) {
1360 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1361 strcpy((char *) menu->name, "50 Hz");
1363 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1364 strcpy((char *) menu->name, "60 Hz");
1368 case V4L2_CID_EFFECTS:
1369 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1370 strncpy((char *) menu->name,
1371 effects_control[menu->index], 32);
1379 /* sub-driver description */
1380 static const struct sd_desc sd_desc = {
1381 .name = MODULE_NAME,
1383 .nctrls = ARRAY_SIZE(sd_ctrls),
1384 .config = sd_config,
1388 .pkt_scan = sd_pkt_scan,
1389 .querymenu = sd_querymenu,
1392 /* -- module initialisation -- */
1393 static const __devinitdata struct usb_device_id device_table[] = {
1394 {USB_DEVICE(0x17a1, 0x0128)},
1397 MODULE_DEVICE_TABLE(usb, device_table);
1399 /* -- device connect -- */
1400 static int sd_probe(struct usb_interface *intf,
1401 const struct usb_device_id *id)
1403 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1407 static struct usb_driver sd_driver = {
1408 .name = MODULE_NAME,
1409 .id_table = device_table,
1411 .disconnect = gspca_disconnect,
1413 .suspend = gspca_suspend,
1414 .resume = gspca_resume,
1418 /* -- module insert / remove -- */
1419 static int __init sd_mod_init(void)
1422 ret = usb_register(&sd_driver);
1425 PDEBUG(D_PROBE, "registered");
1428 static void __exit sd_mod_exit(void)
1430 usb_deregister(&sd_driver);
1431 PDEBUG(D_PROBE, "deregistered");
1434 module_init(sd_mod_init);
1435 module_exit(sd_mod_exit);