2 *Notes: * t613 + tas5130A
3 * * Focus to light do not balance well as in win.
4 * Quality in win is not good, but its kinda better.
5 * * Fix some "extraneous bytes", most of apps will show the image anyway
6 * * Gamma table, is there, but its really doing something?
7 * * 7~8 Fps, its ok, max on win its 10.
10 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define MODULE_NAME "t613"
29 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
30 static const char version[] = "2.1.7";
32 #define MAX_GAMMA 0x10 /* 0 to 15 */
35 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
37 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39 MODULE_LICENSE("GPL");
42 struct gspca_dev gspca_dev; /* !! must be the first item */
44 unsigned char brightness;
45 unsigned char contrast;
47 unsigned char autogain;
49 unsigned char sharpness;
51 unsigned char whitebalance;
56 /* V4L2 controls supported by the driver */
57 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
80 static struct ctrl sd_ctrls[] = {
81 #define SD_BRIGHTNESS 0
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
90 .default_value = 0x09,
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
104 .default_value = 0x07,
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
118 .default_value = 0x05,
126 .id = V4L2_CID_GAMMA, /* (gamma on win) */
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gamma (Untested)",
130 .maximum = MAX_GAMMA,
132 .default_value = 0x09,
137 #define SD_AUTOGAIN 4
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
148 .default_value = 0x01,
150 .set = sd_setlowlight,
151 .get = sd_getlowlight,
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
167 #define SD_LIGHTFREQ 6
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
181 #define SD_WHITE_BALANCE 7
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
192 .set = sd_setwhitebalance,
193 .get = sd_getwhitebalance
195 #define SD_SHARPNESS 8 /* (aka definition on win) */
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
202 .maximum = MAX_GAMMA, /* 0 to 16 */
204 .default_value = 0x06,
206 .set = sd_setsharpness,
207 .get = sd_getsharpness,
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
225 static char *effects_control[] = {
227 "Emboss", /* disabled */
231 "Sun Effect", /* disabled */
235 static struct v4l2_pix_format vga_mode_t16[] = {
236 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
238 .sizeimage = 160 * 120 * 3 / 8 + 590,
239 .colorspace = V4L2_COLORSPACE_JPEG,
241 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
243 .sizeimage = 176 * 144 * 3 / 8 + 590,
244 .colorspace = V4L2_COLORSPACE_JPEG,
246 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
248 .sizeimage = 320 * 240 * 3 / 8 + 590,
249 .colorspace = V4L2_COLORSPACE_JPEG,
251 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .sizeimage = 352 * 288 * 3 / 8 + 590,
254 .colorspace = V4L2_COLORSPACE_JPEG,
256 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
258 .sizeimage = 640 * 480 * 3 / 8 + 590,
259 .colorspace = V4L2_COLORSPACE_JPEG,
263 #define T16_OFFSET_DATA 631
264 #define MAX_EFFECTS 7
265 /* easily done by soft, this table could be removed,
266 * i keep it here just in case */
267 static const __u8 effects_table[MAX_EFFECTS][6] = {
268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
269 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
270 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
271 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
272 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
273 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
274 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
277 static const __u8 gamma_table[MAX_GAMMA][34] = {
278 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
279 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
280 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
281 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
283 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
284 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
285 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
286 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
288 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
289 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
290 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
291 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
293 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
294 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
295 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
296 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
298 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
299 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
300 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
301 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
303 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
304 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
305 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
306 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
308 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
309 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
310 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
311 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
313 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
314 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
315 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
316 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
318 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
319 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
320 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
321 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
323 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
324 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
325 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
326 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
328 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
329 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
330 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
331 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
333 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
334 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
335 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
336 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
338 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
339 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
340 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
341 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
343 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
344 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
345 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
346 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
348 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
349 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
350 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
351 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
353 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
354 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
355 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
356 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
360 static const __u8 tas5130a_sensor_init[][8] = {
361 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
362 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
363 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
364 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
369 static int reg_r_1(struct gspca_dev *gspca_dev,
372 usb_control_msg(gspca_dev->dev,
373 usb_rcvctrlpipe(gspca_dev->dev, 0),
375 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
378 gspca_dev->usb_buf, 1, 500);
379 return gspca_dev->usb_buf[0];
382 static void reg_w(struct gspca_dev *gspca_dev,
385 const __u8 *buffer, __u16 len)
387 if (buffer == NULL) {
388 usb_control_msg(gspca_dev->dev,
389 usb_sndctrlpipe(gspca_dev->dev, 0),
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
396 if (len <= sizeof gspca_dev->usb_buf) {
397 memcpy(gspca_dev->usb_buf, buffer, len);
398 usb_control_msg(gspca_dev->dev,
399 usb_sndctrlpipe(gspca_dev->dev, 0),
401 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
403 gspca_dev->usb_buf, len, 500);
407 tmpbuf = kmalloc(len, GFP_KERNEL);
408 memcpy(tmpbuf, buffer, len);
409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
419 /* this function is called at probe time */
420 static int sd_config(struct gspca_dev *gspca_dev,
421 const struct usb_device_id *id)
423 struct sd *sd = (struct sd *) gspca_dev;
426 cam = &gspca_dev->cam;
427 cam->dev_name = (char *) id->driver_info;
430 cam->cam_mode = vga_mode_t16;
431 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
433 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
434 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
435 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
436 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
437 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
438 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
439 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
440 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
441 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
445 static int init_default_parameters(struct gspca_dev *gspca_dev)
447 /* some of this registers are not really neded, because
448 * they are overriden by setbrigthness, setcontrast, etc,
449 * but wont hurt anyway, and can help someone with similar webcam
450 * to see the initial parameters.*/
454 static const __u8 read_indexs[] =
455 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
456 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
457 static const __u8 n1[6] =
458 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
459 static const __u8 n2[2] =
461 static const __u8 nset[6] =
462 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
463 static const __u8 n3[6] =
464 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
465 static const __u8 n4[0x46] =
466 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
467 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
468 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
469 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
470 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
471 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
472 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
473 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
474 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
475 static const __u8 nset4[18] = {
476 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
477 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
480 /* ojo puede ser 0xe6 en vez de 0xe9 */
481 static const __u8 nset2[20] = {
482 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
483 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
484 0xd8, 0xc8, 0xd9, 0xfc
486 static const __u8 missing[8] =
487 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
488 static const __u8 nset3[18] = {
489 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
490 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
493 static const __u8 nset5[4] =
494 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
495 static const __u8 nset6[34] = {
496 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
497 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
498 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
499 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
502 static const __u8 nset7[4] =
503 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
504 static const __u8 nset9[4] =
505 { 0x0b, 0x04, 0x0a, 0x78 };
506 static const __u8 nset8[6] =
507 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
508 static const __u8 nset10[6] =
509 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
511 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
512 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
513 reg_r_1(gspca_dev, 0x0063);
514 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
516 while (read_indexs[i] != 0x00) {
517 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
518 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
523 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
524 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
525 reg_r_1(gspca_dev, 0x0080);
526 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
527 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
528 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
529 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
530 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
531 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
532 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
534 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
535 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
536 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
537 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
539 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
541 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
542 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
543 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
545 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
546 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
547 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
548 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
550 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
551 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
552 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
553 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
558 static void setbrightness(struct gspca_dev *gspca_dev)
560 struct sd *sd = (struct sd *) gspca_dev;
561 unsigned int brightness;
562 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
563 brightness = sd->brightness;
565 if (brightness < 7) {
566 set6[3] = 0x70 - (brightness * 0xa);
569 set6[3] = 0x00 + ((brightness - 7) * 0xa);
572 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
575 static void setflip(struct gspca_dev *gspca_dev)
577 struct sd *sd = (struct sd *) gspca_dev;
580 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
585 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
588 static void seteffect(struct gspca_dev *gspca_dev)
590 struct sd *sd = (struct sd *) gspca_dev;
592 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
593 if (sd->effect == 1 || sd->effect == 5) {
595 "This effect have been disabled for webcam \"safety\"");
599 if (sd->effect == 1 || sd->effect == 4)
600 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
602 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
605 static void setwhitebalance(struct gspca_dev *gspca_dev)
607 struct sd *sd = (struct sd *) gspca_dev;
609 __u8 white_balance[8] =
610 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
612 if (sd->whitebalance == 1)
613 white_balance[7] = 0x3c;
615 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
618 static void setlightfreq(struct gspca_dev *gspca_dev)
620 struct sd *sd = (struct sd *) gspca_dev;
621 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
623 if (sd->freq == 2) /* 60hz */
626 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
629 static void setcontrast(struct gspca_dev *gspca_dev)
631 struct sd *sd = (struct sd *) gspca_dev;
632 unsigned int contrast = sd->contrast;
633 __u16 reg_to_write = 0x00;
636 reg_to_write = 0x8ea9 - (0x200 * contrast);
638 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
640 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
643 static void setcolors(struct gspca_dev *gspca_dev)
645 struct sd *sd = (struct sd *) gspca_dev;
648 reg_to_write = 0xc0bb + sd->colors * 0x100;
649 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
652 static void setgamma(struct gspca_dev *gspca_dev)
656 static void setsharpness(struct gspca_dev *gspca_dev)
658 struct sd *sd = (struct sd *) gspca_dev;
661 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
663 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
666 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
668 struct sd *sd = (struct sd *) gspca_dev;
670 sd->brightness = val;
671 if (gspca_dev->streaming)
672 setbrightness(gspca_dev);
676 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
678 struct sd *sd = (struct sd *) gspca_dev;
680 *val = sd->brightness;
684 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
686 struct sd *sd = (struct sd *) gspca_dev;
688 sd->whitebalance = val;
689 if (gspca_dev->streaming)
690 setwhitebalance(gspca_dev);
694 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
696 struct sd *sd = (struct sd *) gspca_dev;
698 *val = sd->whitebalance;
702 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
704 struct sd *sd = (struct sd *) gspca_dev;
707 if (gspca_dev->streaming)
712 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
714 struct sd *sd = (struct sd *) gspca_dev;
720 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
722 struct sd *sd = (struct sd *) gspca_dev;
725 if (gspca_dev->streaming)
726 seteffect(gspca_dev);
730 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
732 struct sd *sd = (struct sd *) gspca_dev;
738 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
740 struct sd *sd = (struct sd *) gspca_dev;
743 if (gspca_dev->streaming)
744 setcontrast(gspca_dev);
748 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
750 struct sd *sd = (struct sd *) gspca_dev;
756 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
758 struct sd *sd = (struct sd *) gspca_dev;
761 if (gspca_dev->streaming)
762 setcolors(gspca_dev);
766 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
768 struct sd *sd = (struct sd *) gspca_dev;
774 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
776 struct sd *sd = (struct sd *) gspca_dev;
779 if (gspca_dev->streaming)
784 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
786 struct sd *sd = (struct sd *) gspca_dev;
791 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
793 struct sd *sd = (struct sd *) gspca_dev;
796 if (gspca_dev->streaming)
797 setlightfreq(gspca_dev);
801 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
803 struct sd *sd = (struct sd *) gspca_dev;
809 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
811 struct sd *sd = (struct sd *) gspca_dev;
814 if (gspca_dev->streaming)
815 setsharpness(gspca_dev);
819 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
821 struct sd *sd = (struct sd *) gspca_dev;
823 *val = sd->sharpness;
827 /* Low Light set here......*/
828 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
830 struct sd *sd = (struct sd *) gspca_dev;
834 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
836 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
840 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
842 struct sd *sd = (struct sd *) gspca_dev;
848 static void sd_start(struct gspca_dev *gspca_dev)
852 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
853 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
854 static const __u8 t3[] =
855 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
856 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
857 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
859 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
861 case 1: /* 352x288 */
864 case 2: /* 320x240 */
867 case 3: /* 176x144 */
870 case 4: /* 160x120 */
873 default: /* 640x480 (0x00) */
877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
879 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
880 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
881 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
882 /* just in case and to keep sync with logs (for mine) */
883 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
884 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
885 /* just in case and to keep sync with logs (for mine) */
886 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
887 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
888 reg_r_1(gspca_dev, 0x0012);
889 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
890 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
891 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
892 /* restart on each start, just in case, sometimes regs goes wrong
893 * when using controls from app */
894 setbrightness(gspca_dev);
895 setcontrast(gspca_dev);
896 setcolors(gspca_dev);
899 static void sd_stopN(struct gspca_dev *gspca_dev)
903 static void sd_stop0(struct gspca_dev *gspca_dev)
907 static void sd_close(struct gspca_dev *gspca_dev)
911 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
912 struct gspca_frame *frame, /* target */
913 __u8 *data, /* isoc packet */
914 int len) /* iso packet length */
917 static __u8 ffd9[] = { 0xff, 0xd9 };
919 if (data[0] == 0x5a) {
920 /* Control Packet, after this came the header again,
921 * but extra bytes came in the packet before this,
922 * sometimes an EOF arrives, sometimes not... */
926 if (data[len - 1] == 0xff && data[len] == 0xd9) {
927 /* Just in case, i have seen packets with the marker,
928 * other's do not include it... */
931 } else if (data[2] == 0xff && data[3] == 0xd8) {
941 /* extra bytes....., could be processed too but would be
942 * a waste of time, right now leave the application and
943 * libjpeg do it for ourserlves.. */
944 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
946 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
950 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
953 static int sd_querymenu(struct gspca_dev *gspca_dev,
954 struct v4l2_querymenu *menu)
957 case V4L2_CID_POWER_LINE_FREQUENCY:
958 switch (menu->index) {
959 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
960 strcpy((char *) menu->name, "50 Hz");
962 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
963 strcpy((char *) menu->name, "60 Hz");
967 case V4L2_CID_EFFECTS:
968 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
969 strncpy((char *) menu->name,
970 effects_control[menu->index], 32);
978 /* this function is called at open time */
979 static int sd_open(struct gspca_dev *gspca_dev)
981 init_default_parameters(gspca_dev);
985 /* sub-driver description */
986 static const struct sd_desc sd_desc = {
989 .nctrls = ARRAY_SIZE(sd_ctrls),
996 .pkt_scan = sd_pkt_scan,
997 .querymenu = sd_querymenu,
1000 /* -- module initialisation -- */
1001 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1002 static const __devinitdata struct usb_device_id device_table[] = {
1003 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1006 MODULE_DEVICE_TABLE(usb, device_table);
1008 /* -- device connect -- */
1009 static int sd_probe(struct usb_interface *intf,
1010 const struct usb_device_id *id)
1012 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1016 static struct usb_driver sd_driver = {
1017 .name = MODULE_NAME,
1018 .id_table = device_table,
1020 .disconnect = gspca_disconnect,
1023 /* -- module insert / remove -- */
1024 static int __init sd_mod_init(void)
1026 if (usb_register(&sd_driver) < 0)
1028 PDEBUG(D_PROBE, "v%s registered", version);
1031 static void __exit sd_mod_exit(void)
1033 usb_deregister(&sd_driver);
1034 PDEBUG(D_PROBE, "deregistered");
1037 module_init(sd_mod_init);
1038 module_exit(sd_mod_exit);