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 MAX_GAMMA 0x10 /* 0 to 15 */
33 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
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 */
42 unsigned char brightness;
43 unsigned char contrast;
45 unsigned char autogain;
47 unsigned char sharpness;
49 unsigned char whitebalance;
54 /* V4L2 controls supported by the driver */
55 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
56 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
57 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
58 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
59 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
60 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
61 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_querymenu(struct gspca_dev *gspca_dev,
76 struct v4l2_querymenu *menu);
78 static struct ctrl sd_ctrls[] = {
79 #define SD_BRIGHTNESS 0
82 .id = V4L2_CID_BRIGHTNESS,
83 .type = V4L2_CTRL_TYPE_INTEGER,
88 .default_value = 0x09,
90 .set = sd_setbrightness,
91 .get = sd_getbrightness,
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
102 .default_value = 0x07,
104 .set = sd_setcontrast,
105 .get = sd_getcontrast,
110 .id = V4L2_CID_SATURATION,
111 .type = V4L2_CTRL_TYPE_INTEGER,
116 .default_value = 0x05,
124 .id = V4L2_CID_GAMMA, /* (gamma on win) */
125 .type = V4L2_CTRL_TYPE_INTEGER,
126 .name = "Gamma (Untested)",
128 .maximum = MAX_GAMMA,
130 .default_value = 0x09,
135 #define SD_AUTOGAIN 4
138 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
139 * some apps dont bring up the
140 * backligth_compensation control) */
141 .type = V4L2_CTRL_TYPE_INTEGER,
146 .default_value = 0x01,
148 .set = sd_setlowlight,
149 .get = sd_getlowlight,
154 .id = V4L2_CID_HFLIP,
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .name = "Mirror Image",
165 #define SD_LIGHTFREQ 6
168 .id = V4L2_CID_POWER_LINE_FREQUENCY,
169 .type = V4L2_CTRL_TYPE_MENU,
170 .name = "Light Frequency Filter",
171 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
179 #define SD_WHITE_BALANCE 7
182 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "White Balance",
190 .set = sd_setwhitebalance,
191 .get = sd_getwhitebalance
193 #define SD_SHARPNESS 8 /* (aka definition on win) */
196 .id = V4L2_CID_SHARPNESS,
197 .type = V4L2_CTRL_TYPE_INTEGER,
200 .maximum = MAX_GAMMA, /* 0 to 16 */
202 .default_value = 0x06,
204 .set = sd_setsharpness,
205 .get = sd_getsharpness,
210 .id = V4L2_CID_EFFECTS,
211 .type = V4L2_CTRL_TYPE_MENU,
212 .name = "Webcam Effects",
223 static char *effects_control[] = {
225 "Emboss", /* disabled */
229 "Sun Effect", /* disabled */
233 static struct v4l2_pix_format vga_mode_t16[] = {
234 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
236 .sizeimage = 160 * 120 * 3 / 8 + 590,
237 .colorspace = V4L2_COLORSPACE_JPEG,
239 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
241 .sizeimage = 176 * 144 * 3 / 8 + 590,
242 .colorspace = V4L2_COLORSPACE_JPEG,
244 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
246 .sizeimage = 320 * 240 * 3 / 8 + 590,
247 .colorspace = V4L2_COLORSPACE_JPEG,
249 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
251 .sizeimage = 352 * 288 * 3 / 8 + 590,
252 .colorspace = V4L2_COLORSPACE_JPEG,
254 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
256 .sizeimage = 640 * 480 * 3 / 8 + 590,
257 .colorspace = V4L2_COLORSPACE_JPEG,
261 #define T16_OFFSET_DATA 631
262 #define MAX_EFFECTS 7
263 /* easily done by soft, this table could be removed,
264 * i keep it here just in case */
265 static const __u8 effects_table[MAX_EFFECTS][6] = {
266 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
267 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
269 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
270 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
271 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
272 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
275 static const __u8 gamma_table[MAX_GAMMA][34] = {
276 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
277 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
278 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
279 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
281 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
282 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
283 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
284 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
286 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
287 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
288 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
289 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
291 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
292 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
293 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
294 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
296 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
297 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
298 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
299 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
301 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
302 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
303 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
304 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
306 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
307 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
308 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
309 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
311 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
312 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
313 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
314 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
316 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
317 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
318 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
319 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
321 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
322 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
323 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
324 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
326 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
327 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
328 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
329 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
331 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
332 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
333 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
334 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
336 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
337 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
338 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
339 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
341 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
342 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
343 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
344 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
346 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
347 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
348 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
349 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
351 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
352 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
353 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
354 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
358 static const __u8 tas5130a_sensor_init[][8] = {
359 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
360 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
361 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
362 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
367 static int reg_r_1(struct gspca_dev *gspca_dev,
370 usb_control_msg(gspca_dev->dev,
371 usb_rcvctrlpipe(gspca_dev->dev, 0),
373 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 gspca_dev->usb_buf, 1, 500);
377 return gspca_dev->usb_buf[0];
380 static void reg_w(struct gspca_dev *gspca_dev,
383 const __u8 *buffer, __u16 len)
385 if (buffer == NULL) {
386 usb_control_msg(gspca_dev->dev,
387 usb_sndctrlpipe(gspca_dev->dev, 0),
389 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
394 if (len <= sizeof gspca_dev->usb_buf) {
395 memcpy(gspca_dev->usb_buf, buffer, len);
396 usb_control_msg(gspca_dev->dev,
397 usb_sndctrlpipe(gspca_dev->dev, 0),
399 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
401 gspca_dev->usb_buf, len, 500);
405 tmpbuf = kmalloc(len, GFP_KERNEL);
406 memcpy(tmpbuf, buffer, len);
407 usb_control_msg(gspca_dev->dev,
408 usb_sndctrlpipe(gspca_dev->dev, 0),
410 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
417 /* this function is called at probe time */
418 static int sd_config(struct gspca_dev *gspca_dev,
419 const struct usb_device_id *id)
421 struct sd *sd = (struct sd *) gspca_dev;
424 cam = &gspca_dev->cam;
425 cam->dev_name = (char *) id->driver_info;
428 cam->cam_mode = vga_mode_t16;
429 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
431 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
432 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
433 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
434 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
435 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
436 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
437 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
438 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
439 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
443 static int init_default_parameters(struct gspca_dev *gspca_dev)
445 /* some of this registers are not really neded, because
446 * they are overriden by setbrigthness, setcontrast, etc,
447 * but wont hurt anyway, and can help someone with similar webcam
448 * to see the initial parameters.*/
452 static const __u8 read_indexs[] =
453 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
454 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
455 static const __u8 n1[6] =
456 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
457 static const __u8 n2[2] =
459 static const __u8 nset[6] =
460 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
461 static const __u8 n3[6] =
462 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
463 static const __u8 n4[0x46] =
464 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
465 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
466 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
467 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
468 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
469 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
470 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
471 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
472 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
473 static const __u8 nset4[18] = {
474 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
475 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
478 /* ojo puede ser 0xe6 en vez de 0xe9 */
479 static const __u8 nset2[20] = {
480 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
481 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
482 0xd8, 0xc8, 0xd9, 0xfc
484 static const __u8 missing[8] =
485 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
486 static const __u8 nset3[18] = {
487 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
488 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
491 static const __u8 nset5[4] =
492 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
493 static const __u8 nset6[34] = {
494 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
495 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
496 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
497 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
500 static const __u8 nset7[4] =
501 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
502 static const __u8 nset9[4] =
503 { 0x0b, 0x04, 0x0a, 0x78 };
504 static const __u8 nset8[6] =
505 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
506 static const __u8 nset10[6] =
507 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
509 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
510 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
511 reg_r_1(gspca_dev, 0x0063);
512 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
514 while (read_indexs[i] != 0x00) {
515 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
516 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
521 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
522 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
523 reg_r_1(gspca_dev, 0x0080);
524 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
525 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
526 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
527 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
528 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
529 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
530 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
531 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
532 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
534 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
535 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
537 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
539 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
540 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
541 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
543 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
544 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
545 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
546 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
548 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
549 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
550 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
551 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
556 static void setbrightness(struct gspca_dev *gspca_dev)
558 struct sd *sd = (struct sd *) gspca_dev;
559 unsigned int brightness;
560 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
561 brightness = sd->brightness;
563 if (brightness < 7) {
564 set6[3] = 0x70 - (brightness * 0xa);
567 set6[3] = 0x00 + ((brightness - 7) * 0xa);
570 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
573 static void setflip(struct gspca_dev *gspca_dev)
575 struct sd *sd = (struct sd *) gspca_dev;
578 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
583 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
586 static void seteffect(struct gspca_dev *gspca_dev)
588 struct sd *sd = (struct sd *) gspca_dev;
590 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
591 if (sd->effect == 1 || sd->effect == 5) {
593 "This effect have been disabled for webcam \"safety\"");
597 if (sd->effect == 1 || sd->effect == 4)
598 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
600 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
603 static void setwhitebalance(struct gspca_dev *gspca_dev)
605 struct sd *sd = (struct sd *) gspca_dev;
607 __u8 white_balance[8] =
608 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
610 if (sd->whitebalance == 1)
611 white_balance[7] = 0x3c;
613 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
616 static void setlightfreq(struct gspca_dev *gspca_dev)
618 struct sd *sd = (struct sd *) gspca_dev;
619 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
621 if (sd->freq == 2) /* 60hz */
624 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
627 static void setcontrast(struct gspca_dev *gspca_dev)
629 struct sd *sd = (struct sd *) gspca_dev;
630 unsigned int contrast = sd->contrast;
631 __u16 reg_to_write = 0x00;
634 reg_to_write = 0x8ea9 - (0x200 * contrast);
636 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
638 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
641 static void setcolors(struct gspca_dev *gspca_dev)
643 struct sd *sd = (struct sd *) gspca_dev;
646 reg_to_write = 0xc0bb + sd->colors * 0x100;
647 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
650 static void setgamma(struct gspca_dev *gspca_dev)
654 static void setsharpness(struct gspca_dev *gspca_dev)
656 struct sd *sd = (struct sd *) gspca_dev;
659 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
661 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
664 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
666 struct sd *sd = (struct sd *) gspca_dev;
668 sd->brightness = val;
669 if (gspca_dev->streaming)
670 setbrightness(gspca_dev);
674 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
676 struct sd *sd = (struct sd *) gspca_dev;
678 *val = sd->brightness;
682 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
684 struct sd *sd = (struct sd *) gspca_dev;
686 sd->whitebalance = val;
687 if (gspca_dev->streaming)
688 setwhitebalance(gspca_dev);
692 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
694 struct sd *sd = (struct sd *) gspca_dev;
696 *val = sd->whitebalance;
700 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
702 struct sd *sd = (struct sd *) gspca_dev;
705 if (gspca_dev->streaming)
710 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
712 struct sd *sd = (struct sd *) gspca_dev;
718 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
720 struct sd *sd = (struct sd *) gspca_dev;
723 if (gspca_dev->streaming)
724 seteffect(gspca_dev);
728 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
730 struct sd *sd = (struct sd *) gspca_dev;
736 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
738 struct sd *sd = (struct sd *) gspca_dev;
741 if (gspca_dev->streaming)
742 setcontrast(gspca_dev);
746 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
748 struct sd *sd = (struct sd *) gspca_dev;
754 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
756 struct sd *sd = (struct sd *) gspca_dev;
759 if (gspca_dev->streaming)
760 setcolors(gspca_dev);
764 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
766 struct sd *sd = (struct sd *) gspca_dev;
772 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
774 struct sd *sd = (struct sd *) gspca_dev;
777 if (gspca_dev->streaming)
782 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
784 struct sd *sd = (struct sd *) gspca_dev;
789 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
791 struct sd *sd = (struct sd *) gspca_dev;
794 if (gspca_dev->streaming)
795 setlightfreq(gspca_dev);
799 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
801 struct sd *sd = (struct sd *) gspca_dev;
807 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
809 struct sd *sd = (struct sd *) gspca_dev;
812 if (gspca_dev->streaming)
813 setsharpness(gspca_dev);
817 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
819 struct sd *sd = (struct sd *) gspca_dev;
821 *val = sd->sharpness;
825 /* Low Light set here......*/
826 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
828 struct sd *sd = (struct sd *) gspca_dev;
832 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
834 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
838 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
840 struct sd *sd = (struct sd *) gspca_dev;
846 static void sd_start(struct gspca_dev *gspca_dev)
850 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
851 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
852 static const __u8 t3[] =
853 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
854 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
855 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
857 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
859 case 1: /* 352x288 */
862 case 2: /* 320x240 */
865 case 3: /* 176x144 */
868 case 4: /* 160x120 */
871 default: /* 640x480 (0x00) */
875 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
876 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
879 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
880 /* just in case and to keep sync with logs (for mine) */
881 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
882 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
883 /* just in case and to keep sync with logs (for mine) */
884 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
885 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
886 reg_r_1(gspca_dev, 0x0012);
887 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
888 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
889 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
890 /* restart on each start, just in case, sometimes regs goes wrong
891 * when using controls from app */
892 setbrightness(gspca_dev);
893 setcontrast(gspca_dev);
894 setcolors(gspca_dev);
897 static void sd_stopN(struct gspca_dev *gspca_dev)
901 static void sd_stop0(struct gspca_dev *gspca_dev)
905 static void sd_close(struct gspca_dev *gspca_dev)
909 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
910 struct gspca_frame *frame, /* target */
911 __u8 *data, /* isoc packet */
912 int len) /* iso packet length */
915 static __u8 ffd9[] = { 0xff, 0xd9 };
917 if (data[0] == 0x5a) {
918 /* Control Packet, after this came the header again,
919 * but extra bytes came in the packet before this,
920 * sometimes an EOF arrives, sometimes not... */
924 if (data[len - 1] == 0xff && data[len] == 0xd9) {
925 /* Just in case, i have seen packets with the marker,
926 * other's do not include it... */
929 } else if (data[2] == 0xff && data[3] == 0xd8) {
939 /* extra bytes....., could be processed too but would be
940 * a waste of time, right now leave the application and
941 * libjpeg do it for ourserlves.. */
942 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
944 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
948 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
951 static int sd_querymenu(struct gspca_dev *gspca_dev,
952 struct v4l2_querymenu *menu)
955 case V4L2_CID_POWER_LINE_FREQUENCY:
956 switch (menu->index) {
957 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
958 strcpy((char *) menu->name, "50 Hz");
960 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
961 strcpy((char *) menu->name, "60 Hz");
965 case V4L2_CID_EFFECTS:
966 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
967 strncpy((char *) menu->name,
968 effects_control[menu->index], 32);
976 /* this function is called at open time */
977 static int sd_open(struct gspca_dev *gspca_dev)
979 init_default_parameters(gspca_dev);
983 /* sub-driver description */
984 static const struct sd_desc sd_desc = {
987 .nctrls = ARRAY_SIZE(sd_ctrls),
994 .pkt_scan = sd_pkt_scan,
995 .querymenu = sd_querymenu,
998 /* -- module initialisation -- */
999 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1000 static const __devinitdata struct usb_device_id device_table[] = {
1001 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1004 MODULE_DEVICE_TABLE(usb, device_table);
1006 /* -- device connect -- */
1007 static int sd_probe(struct usb_interface *intf,
1008 const struct usb_device_id *id)
1010 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1014 static struct usb_driver sd_driver = {
1015 .name = MODULE_NAME,
1016 .id_table = device_table,
1018 .disconnect = gspca_disconnect,
1021 /* -- module insert / remove -- */
1022 static int __init sd_mod_init(void)
1024 if (usb_register(&sd_driver) < 0)
1026 PDEBUG(D_PROBE, "registered");
1029 static void __exit sd_mod_exit(void)
1031 usb_deregister(&sd_driver);
1032 PDEBUG(D_PROBE, "deregistered");
1035 module_init(sd_mod_init);
1036 module_exit(sd_mod_exit);