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 */
52 #define SENSOR_OM6802 0
53 #define SENSOR_OTHER 1
54 #define SENSOR_TAS5130A 2
57 /* V4L2 controls supported by the driver */
58 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
66 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
70 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
71 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
72 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
73 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
74 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
75 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
76 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
77 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
78 static int sd_querymenu(struct gspca_dev *gspca_dev,
79 struct v4l2_querymenu *menu);
81 static const struct ctrl sd_ctrls[] = {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
90 #define BRIGHTNESS_DEF 8
91 .default_value = BRIGHTNESS_DEF,
93 .set = sd_setbrightness,
94 .get = sd_getbrightness,
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
104 #define CONTRAST_DEF 0x07
105 .default_value = CONTRAST_DEF,
107 .set = sd_setcontrast,
108 .get = sd_getcontrast,
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
118 #define COLORS_DEF 0x05
119 .default_value = COLORS_DEF,
128 .id = V4L2_CID_GAMMA, /* (gamma on win) */
129 .type = V4L2_CTRL_TYPE_INTEGER,
132 .maximum = GAMMA_MAX - 1,
134 .default_value = GAMMA_DEF,
141 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
142 * some apps dont bring up the
143 * backligth_compensation control) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
149 #define AUTOGAIN_DEF 0x01
150 .default_value = AUTOGAIN_DEF,
152 .set = sd_setlowlight,
153 .get = sd_getlowlight,
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
164 .default_value = MIRROR_DEF,
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
178 .default_value = FREQ_DEF,
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
191 #define WHITE_BALANCE_DEF 0
192 .default_value = WHITE_BALANCE_DEF,
194 .set = sd_setwhitebalance,
195 .get = sd_getwhitebalance
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
205 #define SHARPNESS_DEF 0x06
206 .default_value = SHARPNESS_DEF,
208 .set = sd_setsharpness,
209 .get = sd_getsharpness,
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
219 #define EFFECTS_DEF 0
220 .default_value = EFFECTS_DEF,
227 static char *effects_control[] = {
229 "Emboss", /* disabled */
233 "Sun Effect", /* disabled */
237 static const struct v4l2_pix_format vga_mode_t16[] = {
238 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
240 .sizeimage = 160 * 120 * 4 / 8 + 590,
241 .colorspace = V4L2_COLORSPACE_JPEG,
243 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
245 .sizeimage = 176 * 144 * 3 / 8 + 590,
246 .colorspace = V4L2_COLORSPACE_JPEG,
248 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
250 .sizeimage = 320 * 240 * 3 / 8 + 590,
251 .colorspace = V4L2_COLORSPACE_JPEG,
253 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
255 .sizeimage = 352 * 288 * 3 / 8 + 590,
256 .colorspace = V4L2_COLORSPACE_JPEG,
258 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
260 .sizeimage = 640 * 480 * 3 / 8 + 590,
261 .colorspace = V4L2_COLORSPACE_JPEG,
265 /* sensor specific data */
266 struct additional_sensor_data {
269 const u8 reg80, reg8e;
279 static const u8 n4_om6802[] = {
280 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
281 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
282 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
283 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
284 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
285 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
286 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
287 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
288 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
290 static const u8 n4_other[] = {
291 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
292 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
293 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
294 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
295 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
296 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
297 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
298 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
300 static const u8 n4_tas5130a[] = {
301 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
302 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
303 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
304 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
305 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
306 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
310 static const struct additional_sensor_data sensor_data[] = {
313 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
315 .n4sz = sizeof n4_om6802,
318 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
320 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
323 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
326 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
328 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
329 {0x66, 0xca, 0xa8, 0xf0},
330 .data5 = /* this could be removed later */
331 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
333 {0x0b, 0x04, 0x0a, 0x78},
337 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
339 .n4sz = sizeof n4_other,
342 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
344 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
347 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
350 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
353 {0x66, 0x00, 0xa8, 0xa8},
355 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
357 {0x0b, 0x04, 0x0a, 0x00},
361 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
363 .n4sz = sizeof n4_tas5130a,
366 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
368 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
371 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
374 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
376 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
377 {0x66, 0x00, 0xa8, 0xe8},
379 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
381 {0x0b, 0x04, 0x0a, 0x40},
385 #define MAX_EFFECTS 7
386 /* easily done by soft, this table could be removed,
387 * i keep it here just in case */
388 static const u8 effects_table[MAX_EFFECTS][6] = {
389 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
390 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
391 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
392 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
393 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
394 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
395 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
398 static const u8 gamma_table[GAMMA_MAX][17] = {
399 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
400 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
402 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
403 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
405 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
406 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
408 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
409 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
411 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
412 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
414 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
415 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
417 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
418 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
420 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
421 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
423 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
424 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
426 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
427 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
429 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
430 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
432 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
433 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
435 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
436 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
438 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
439 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
441 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
442 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
444 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
445 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
449 static const u8 tas5130a_sensor_init[][8] = {
450 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
451 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
452 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
455 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
458 static u8 reg_r(struct gspca_dev *gspca_dev,
461 usb_control_msg(gspca_dev->dev,
462 usb_rcvctrlpipe(gspca_dev->dev, 0),
464 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
467 gspca_dev->usb_buf, 1, 500);
468 return gspca_dev->usb_buf[0];
471 static void reg_w(struct gspca_dev *gspca_dev,
474 usb_control_msg(gspca_dev->dev,
475 usb_sndctrlpipe(gspca_dev->dev, 0),
477 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
482 static void reg_w_buf(struct gspca_dev *gspca_dev,
483 const u8 *buffer, u16 len)
485 if (len <= USB_BUF_SZ) {
486 memcpy(gspca_dev->usb_buf, buffer, len);
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
492 gspca_dev->usb_buf, len, 500);
496 tmpbuf = kmalloc(len, GFP_KERNEL);
497 memcpy(tmpbuf, buffer, len);
498 usb_control_msg(gspca_dev->dev,
499 usb_sndctrlpipe(gspca_dev->dev, 0),
501 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
508 /* write values to consecutive registers */
509 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
511 const u8 *buffer, u16 len)
516 if (len * 2 <= USB_BUF_SZ)
517 p = tmpbuf = gspca_dev->usb_buf;
519 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
525 usb_control_msg(gspca_dev->dev,
526 usb_sndctrlpipe(gspca_dev->dev, 0),
528 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
530 tmpbuf, len * 2, 500);
531 if (len * 2 > USB_BUF_SZ)
535 /* Reported as OM6802*/
536 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
541 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
542 static const u8 sensor_init[] = {
560 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
564 byte = reg_r(gspca_dev, 0x0060);
569 byte = reg_r(gspca_dev, 0x0063);
571 err("Bad sensor reset %02x", byte);
580 reg_w(gspca_dev, 0x3c80);
581 reg_w_buf(gspca_dev, val, sizeof val);
585 byte = reg_r(gspca_dev, 0x60);
591 reg_w(gspca_dev, 0x3c80);
594 /* this function is called at probe time */
595 static int sd_config(struct gspca_dev *gspca_dev,
596 const struct usb_device_id *id)
598 struct sd *sd = (struct sd *) gspca_dev;
601 cam = &gspca_dev->cam;
603 cam->cam_mode = vga_mode_t16;
604 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
606 sd->brightness = BRIGHTNESS_DEF;
607 sd->contrast = CONTRAST_DEF;
608 sd->colors = COLORS_DEF;
609 sd->gamma = GAMMA_DEF;
610 sd->autogain = AUTOGAIN_DEF;
611 sd->mirror = MIRROR_DEF;
613 sd->whitebalance = WHITE_BALANCE_DEF;
614 sd->sharpness = SHARPNESS_DEF;
615 sd->effect = EFFECTS_DEF;
619 static void setbrightness(struct gspca_dev *gspca_dev)
621 struct sd *sd = (struct sd *) gspca_dev;
622 unsigned int brightness;
623 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
625 brightness = sd->brightness;
626 if (brightness < 7) {
628 set6[3] = 0x70 - brightness * 0x10;
630 set6[3] = 0x00 + ((brightness - 7) * 0x10);
633 reg_w_buf(gspca_dev, set6, sizeof set6);
636 static void setcontrast(struct gspca_dev *gspca_dev)
638 struct sd *sd = (struct sd *) gspca_dev;
639 unsigned int contrast = sd->contrast;
643 reg_to_write = 0x8ea9 - contrast * 0x200;
645 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
647 reg_w(gspca_dev, reg_to_write);
650 static void setcolors(struct gspca_dev *gspca_dev)
652 struct sd *sd = (struct sd *) gspca_dev;
655 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
656 reg_w(gspca_dev, reg_to_write);
659 static void setgamma(struct gspca_dev *gspca_dev)
661 struct sd *sd = (struct sd *) gspca_dev;
663 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
664 reg_w_ixbuf(gspca_dev, 0x90,
665 gamma_table[sd->gamma], sizeof gamma_table[0]);
668 static void setwhitebalance(struct gspca_dev *gspca_dev)
670 struct sd *sd = (struct sd *) gspca_dev;
672 u8 white_balance[8] =
673 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
675 if (sd->whitebalance)
676 white_balance[7] = 0x3c;
678 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
681 static void setsharpness(struct gspca_dev *gspca_dev)
683 struct sd *sd = (struct sd *) gspca_dev;
686 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
688 reg_w(gspca_dev, reg_to_write);
691 /* this function is called at probe and resume time */
692 static int sd_init(struct gspca_dev *gspca_dev)
694 /* some of this registers are not really neded, because
695 * they are overriden by setbrigthness, setcontrast, etc,
696 * but wont hurt anyway, and can help someone with similar webcam
697 * to see the initial parameters.*/
698 struct sd *sd = (struct sd *) gspca_dev;
699 const struct additional_sensor_data *sensor;
704 static const u8 read_indexs[] =
705 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
706 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
707 static const u8 n1[] =
708 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
709 static const u8 n2[] =
712 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
713 | reg_r(gspca_dev, 0x07);
714 switch (sensor_id & 0xff0f) {
716 PDEBUG(D_PROBE, "sensor tas5130a");
717 sd->sensor = SENSOR_TAS5130A;
720 PDEBUG(D_PROBE, "sensor 'other'");
721 sd->sensor = SENSOR_OTHER;
724 PDEBUG(D_PROBE, "sensor om6802");
725 sd->sensor = SENSOR_OM6802;
728 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
732 if (sd->sensor == SENSOR_OM6802) {
733 reg_w_buf(gspca_dev, n1, sizeof n1);
736 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
737 test_byte = reg_r(gspca_dev, 0x0063);
739 if (test_byte == 0x17)
743 err("Bad sensor reset %02x", test_byte);
746 reg_w_buf(gspca_dev, n2, sizeof n2);
750 while (read_indexs[i] != 0x00) {
751 test_byte = reg_r(gspca_dev, read_indexs[i]);
752 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
757 sensor = &sensor_data[sd->sensor];
758 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
759 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
761 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
762 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
763 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
765 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
766 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
767 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
769 setbrightness(gspca_dev);
770 setcontrast(gspca_dev);
772 setcolors(gspca_dev);
773 setsharpness(gspca_dev);
774 setwhitebalance(gspca_dev);
776 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
777 reg_w(gspca_dev, 0x2088);
778 reg_w(gspca_dev, 0x2089);
780 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
781 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
782 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
783 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
785 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
786 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
787 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
792 static void setflip(struct gspca_dev *gspca_dev)
794 struct sd *sd = (struct sd *) gspca_dev;
796 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
801 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
804 static void seteffect(struct gspca_dev *gspca_dev)
806 struct sd *sd = (struct sd *) gspca_dev;
808 reg_w_buf(gspca_dev, effects_table[sd->effect],
809 sizeof effects_table[0]);
810 if (sd->effect == 1 || sd->effect == 5) {
812 "This effect have been disabled for webcam \"safety\"");
816 if (sd->effect == 1 || sd->effect == 4)
817 reg_w(gspca_dev, 0x4aa6);
819 reg_w(gspca_dev, 0xfaa6);
822 static void setlightfreq(struct gspca_dev *gspca_dev)
824 struct sd *sd = (struct sd *) gspca_dev;
825 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
827 if (sd->freq == 2) /* 60hz */
830 reg_w_buf(gspca_dev, freq, sizeof freq);
833 /* Is this really needed?
834 * i added some module parameters for test with some users */
835 static void poll_sensor(struct gspca_dev *gspca_dev)
837 static const u8 poll1[] =
838 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
839 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
840 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
842 static const u8 poll2[] =
843 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
844 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
845 static const u8 poll3[] =
846 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
847 static const u8 poll4[] =
848 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
849 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
850 0xc2, 0x80, 0xc3, 0x10};
852 PDEBUG(D_STREAM, "[Sensor requires polling]");
853 reg_w_buf(gspca_dev, poll1, sizeof poll1);
854 reg_w_buf(gspca_dev, poll2, sizeof poll2);
855 reg_w_buf(gspca_dev, poll3, sizeof poll3);
856 reg_w_buf(gspca_dev, poll4, sizeof poll4);
859 static int sd_start(struct gspca_dev *gspca_dev)
861 struct sd *sd = (struct sd *) gspca_dev;
862 const struct additional_sensor_data *sensor;
864 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
865 static const u8 t3[] =
866 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
868 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
870 case 0: /* 640x480 (0x00) */
872 case 1: /* 352x288 */
875 case 2: /* 320x240 */
878 case 3: /* 176x144 */
882 /* case 4: * 160x120 */
887 switch (sd->sensor) {
889 om6802_sensor_init(gspca_dev);
894 /* case SENSOR_TAS5130A: */
897 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
898 sizeof tas5130a_sensor_init[0]);
899 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
903 reg_w(gspca_dev, 0x3c80);
904 /* just in case and to keep sync with logs (for mine) */
905 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
906 sizeof tas5130a_sensor_init[0]);
907 reg_w(gspca_dev, 0x3c80);
910 sensor = &sensor_data[sd->sensor];
911 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
912 reg_r(gspca_dev, 0x0012);
913 reg_w_buf(gspca_dev, t2, sizeof t2);
914 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
915 reg_w(gspca_dev, 0x0013);
917 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
918 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
920 if (sd->sensor == SENSOR_OM6802)
921 poll_sensor(gspca_dev);
926 static void sd_stopN(struct gspca_dev *gspca_dev)
928 struct sd *sd = (struct sd *) gspca_dev;
930 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
931 sizeof sensor_data[sd->sensor].stream);
932 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
933 sizeof sensor_data[sd->sensor].stream);
934 if (sd->sensor == SENSOR_OM6802) {
936 reg_w(gspca_dev, 0x0309);
940 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
941 u8 *data, /* isoc packet */
942 int len) /* iso packet length */
944 static u8 ffd9[] = { 0xff, 0xd9 };
946 if (data[0] == 0x5a) {
947 /* Control Packet, after this came the header again,
948 * but extra bytes came in the packet before this,
949 * sometimes an EOF arrives, sometimes not... */
954 if (data[0] == 0xff && data[1] == 0xd8) {
955 /* extra bytes....., could be processed too but would be
956 * a waste of time, right now leave the application and
957 * libjpeg do it for ourserlves.. */
958 gspca_frame_add(gspca_dev, LAST_PACKET,
960 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
964 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
965 /* Just in case, i have seen packets with the marker,
966 * other's do not include it... */
969 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
972 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
974 struct sd *sd = (struct sd *) gspca_dev;
976 sd->brightness = val;
977 if (gspca_dev->streaming)
978 setbrightness(gspca_dev);
982 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
984 struct sd *sd = (struct sd *) gspca_dev;
986 *val = sd->brightness;
990 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
992 struct sd *sd = (struct sd *) gspca_dev;
994 sd->whitebalance = val;
995 if (gspca_dev->streaming)
996 setwhitebalance(gspca_dev);
1000 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1002 struct sd *sd = (struct sd *) gspca_dev;
1004 *val = sd->whitebalance;
1008 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1010 struct sd *sd = (struct sd *) gspca_dev;
1013 if (gspca_dev->streaming)
1018 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1020 struct sd *sd = (struct sd *) gspca_dev;
1026 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1028 struct sd *sd = (struct sd *) gspca_dev;
1031 if (gspca_dev->streaming)
1032 seteffect(gspca_dev);
1036 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1038 struct sd *sd = (struct sd *) gspca_dev;
1044 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1046 struct sd *sd = (struct sd *) gspca_dev;
1049 if (gspca_dev->streaming)
1050 setcontrast(gspca_dev);
1054 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1056 struct sd *sd = (struct sd *) gspca_dev;
1058 *val = sd->contrast;
1062 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1064 struct sd *sd = (struct sd *) gspca_dev;
1067 if (gspca_dev->streaming)
1068 setcolors(gspca_dev);
1072 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1074 struct sd *sd = (struct sd *) gspca_dev;
1080 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1082 struct sd *sd = (struct sd *) gspca_dev;
1085 if (gspca_dev->streaming)
1086 setgamma(gspca_dev);
1090 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1092 struct sd *sd = (struct sd *) gspca_dev;
1098 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1100 struct sd *sd = (struct sd *) gspca_dev;
1103 if (gspca_dev->streaming)
1104 setlightfreq(gspca_dev);
1108 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1110 struct sd *sd = (struct sd *) gspca_dev;
1116 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1118 struct sd *sd = (struct sd *) gspca_dev;
1120 sd->sharpness = val;
1121 if (gspca_dev->streaming)
1122 setsharpness(gspca_dev);
1126 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1128 struct sd *sd = (struct sd *) gspca_dev;
1130 *val = sd->sharpness;
1134 /* Low Light set here......*/
1135 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1137 struct sd *sd = (struct sd *) gspca_dev;
1141 reg_w(gspca_dev, 0xf48e);
1143 reg_w(gspca_dev, 0xb48e);
1147 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1149 struct sd *sd = (struct sd *) gspca_dev;
1151 *val = sd->autogain;
1155 static int sd_querymenu(struct gspca_dev *gspca_dev,
1156 struct v4l2_querymenu *menu)
1159 case V4L2_CID_POWER_LINE_FREQUENCY:
1160 switch (menu->index) {
1161 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1162 strcpy((char *) menu->name, "50 Hz");
1164 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1165 strcpy((char *) menu->name, "60 Hz");
1169 case V4L2_CID_EFFECTS:
1170 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1171 strncpy((char *) menu->name,
1172 effects_control[menu->index], 32);
1180 /* sub-driver description */
1181 static const struct sd_desc sd_desc = {
1182 .name = MODULE_NAME,
1184 .nctrls = ARRAY_SIZE(sd_ctrls),
1185 .config = sd_config,
1189 .pkt_scan = sd_pkt_scan,
1190 .querymenu = sd_querymenu,
1193 /* -- module initialisation -- */
1194 static const __devinitdata struct usb_device_id device_table[] = {
1195 {USB_DEVICE(0x17a1, 0x0128)},
1198 MODULE_DEVICE_TABLE(usb, device_table);
1200 /* -- device connect -- */
1201 static int sd_probe(struct usb_interface *intf,
1202 const struct usb_device_id *id)
1204 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1208 static struct usb_driver sd_driver = {
1209 .name = MODULE_NAME,
1210 .id_table = device_table,
1212 .disconnect = gspca_disconnect,
1214 .suspend = gspca_suspend,
1215 .resume = gspca_resume,
1219 /* -- module insert / remove -- */
1220 static int __init sd_mod_init(void)
1223 ret = usb_register(&sd_driver);
1226 PDEBUG(D_PROBE, "registered");
1229 static void __exit sd_mod_exit(void)
1231 usb_deregister(&sd_driver);
1232 PDEBUG(D_PROBE, "deregistered");
1235 module_init(sd_mod_init);
1236 module_exit(sd_mod_exit);