GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / media / video / gspca / t613.c
blob3b3b983f2b9d8291cb1399b86c514f792f6ff537
1 /*
2 * T613 subdriver
4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *Notes: * t613 + tas5130A
21 * * Focus to light do not balance well as in win.
22 * Quality in win is not good, but its kinda better.
23 * * Fix some "extraneous bytes", most of apps will show the image anyway
24 * * Gamma table, is there, but its really doing something?
25 * * 7~8 Fps, its ok, max on win its 10.
26 * Costantino Leandro
29 #define MODULE_NAME "t613"
31 #include <linux/slab.h>
32 #include "gspca.h"
34 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
36 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
37 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
38 MODULE_LICENSE("GPL");
40 struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
43 u8 brightness;
44 u8 contrast;
45 u8 colors;
46 u8 autogain;
47 u8 gamma;
48 u8 sharpness;
49 u8 freq;
50 u8 red_gain;
51 u8 blue_gain;
52 u8 green_gain;
53 u8 awb; /* set default r/g/b and activate */
54 u8 mirror;
55 u8 effect;
57 u8 sensor;
59 enum sensors {
60 SENSOR_OM6802,
61 SENSOR_OTHER,
62 SENSOR_TAS5130A,
63 SENSOR_LT168G, /* must verify if this is the actual model */
66 /* V4L2 controls supported by the driver */
67 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
78 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
79 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
91 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
93 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
94 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
95 static int sd_querymenu(struct gspca_dev *gspca_dev,
96 struct v4l2_querymenu *menu);
98 static const struct ctrl sd_ctrls[] = {
101 .id = V4L2_CID_BRIGHTNESS,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Brightness",
104 .minimum = 0,
105 .maximum = 14,
106 .step = 1,
107 #define BRIGHTNESS_DEF 8
108 .default_value = BRIGHTNESS_DEF,
110 .set = sd_setbrightness,
111 .get = sd_getbrightness,
115 .id = V4L2_CID_CONTRAST,
116 .type = V4L2_CTRL_TYPE_INTEGER,
117 .name = "Contrast",
118 .minimum = 0,
119 .maximum = 0x0d,
120 .step = 1,
121 #define CONTRAST_DEF 0x07
122 .default_value = CONTRAST_DEF,
124 .set = sd_setcontrast,
125 .get = sd_getcontrast,
129 .id = V4L2_CID_SATURATION,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "Color",
132 .minimum = 0,
133 .maximum = 0x0f,
134 .step = 1,
135 #define COLORS_DEF 0x05
136 .default_value = COLORS_DEF,
138 .set = sd_setcolors,
139 .get = sd_getcolors,
141 #define GAMMA_MAX 16
142 #define GAMMA_DEF 10
145 .id = V4L2_CID_GAMMA, /* (gamma on win) */
146 .type = V4L2_CTRL_TYPE_INTEGER,
147 .name = "Gamma",
148 .minimum = 0,
149 .maximum = GAMMA_MAX - 1,
150 .step = 1,
151 .default_value = GAMMA_DEF,
153 .set = sd_setgamma,
154 .get = sd_getgamma,
158 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
159 * some apps dont bring up the
160 * backligth_compensation control) */
161 .type = V4L2_CTRL_TYPE_INTEGER,
162 .name = "Low Light",
163 .minimum = 0,
164 .maximum = 1,
165 .step = 1,
166 #define AUTOGAIN_DEF 0x01
167 .default_value = AUTOGAIN_DEF,
169 .set = sd_setlowlight,
170 .get = sd_getlowlight,
174 .id = V4L2_CID_HFLIP,
175 .type = V4L2_CTRL_TYPE_BOOLEAN,
176 .name = "Mirror Image",
177 .minimum = 0,
178 .maximum = 1,
179 .step = 1,
180 #define MIRROR_DEF 0
181 .default_value = MIRROR_DEF,
183 .set = sd_setmirror,
184 .get = sd_getmirror
188 .id = V4L2_CID_POWER_LINE_FREQUENCY,
189 .type = V4L2_CTRL_TYPE_MENU,
190 .name = "Light Frequency Filter",
191 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
192 .maximum = 2,
193 .step = 1,
194 #define FREQ_DEF 1
195 .default_value = FREQ_DEF,
197 .set = sd_setfreq,
198 .get = sd_getfreq},
202 .id = V4L2_CID_AUTO_WHITE_BALANCE,
203 .type = V4L2_CTRL_TYPE_INTEGER,
204 .name = "Auto White Balance",
205 .minimum = 0,
206 .maximum = 1,
207 .step = 1,
208 #define AWB_DEF 0
209 .default_value = AWB_DEF,
211 .set = sd_setawb,
212 .get = sd_getawb
216 .id = V4L2_CID_SHARPNESS,
217 .type = V4L2_CTRL_TYPE_INTEGER,
218 .name = "Sharpness",
219 .minimum = 0,
220 .maximum = 15,
221 .step = 1,
222 #define SHARPNESS_DEF 0x06
223 .default_value = SHARPNESS_DEF,
225 .set = sd_setsharpness,
226 .get = sd_getsharpness,
230 .id = V4L2_CID_EFFECTS,
231 .type = V4L2_CTRL_TYPE_MENU,
232 .name = "Webcam Effects",
233 .minimum = 0,
234 .maximum = 4,
235 .step = 1,
236 #define EFFECTS_DEF 0
237 .default_value = EFFECTS_DEF,
239 .set = sd_seteffect,
240 .get = sd_geteffect
244 .id = V4L2_CID_BLUE_BALANCE,
245 .type = V4L2_CTRL_TYPE_INTEGER,
246 .name = "Blue Balance",
247 .minimum = 0x10,
248 .maximum = 0x40,
249 .step = 1,
250 #define BLUE_GAIN_DEF 0x20
251 .default_value = BLUE_GAIN_DEF,
253 .set = sd_setblue_gain,
254 .get = sd_getblue_gain,
258 .id = V4L2_CID_RED_BALANCE,
259 .type = V4L2_CTRL_TYPE_INTEGER,
260 .name = "Red Balance",
261 .minimum = 0x10,
262 .maximum = 0x40,
263 .step = 1,
264 #define RED_GAIN_DEF 0x20
265 .default_value = RED_GAIN_DEF,
267 .set = sd_setred_gain,
268 .get = sd_getred_gain,
272 .id = V4L2_CID_GAIN,
273 .type = V4L2_CTRL_TYPE_INTEGER,
274 .name = "Gain",
275 .minimum = 0x10,
276 .maximum = 0x40,
277 .step = 1,
278 #define GAIN_DEF 0x20
279 .default_value = GAIN_DEF,
281 .set = sd_setgain,
282 .get = sd_getgain,
286 static const struct v4l2_pix_format vga_mode_t16[] = {
287 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
288 .bytesperline = 160,
289 .sizeimage = 160 * 120 * 4 / 8 + 590,
290 .colorspace = V4L2_COLORSPACE_JPEG,
291 .priv = 4},
292 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
293 .bytesperline = 176,
294 .sizeimage = 176 * 144 * 3 / 8 + 590,
295 .colorspace = V4L2_COLORSPACE_JPEG,
296 .priv = 3},
297 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
298 .bytesperline = 320,
299 .sizeimage = 320 * 240 * 3 / 8 + 590,
300 .colorspace = V4L2_COLORSPACE_JPEG,
301 .priv = 2},
302 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
303 .bytesperline = 352,
304 .sizeimage = 352 * 288 * 3 / 8 + 590,
305 .colorspace = V4L2_COLORSPACE_JPEG,
306 .priv = 1},
307 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
308 .bytesperline = 640,
309 .sizeimage = 640 * 480 * 3 / 8 + 590,
310 .colorspace = V4L2_COLORSPACE_JPEG,
311 .priv = 0},
314 /* sensor specific data */
315 struct additional_sensor_data {
316 const u8 n3[6];
317 const u8 *n4, n4sz;
318 const u8 reg80, reg8e;
319 const u8 nset8[6];
320 const u8 data1[10];
321 const u8 data2[9];
322 const u8 data3[9];
323 const u8 data5[6];
324 const u8 stream[4];
327 static const u8 n4_om6802[] = {
328 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
329 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
330 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
331 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
332 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
333 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
334 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
335 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
336 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
338 static const u8 n4_other[] = {
339 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
340 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
341 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
342 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
343 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
344 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
345 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
346 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
348 static const u8 n4_tas5130a[] = {
349 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
350 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
351 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
352 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
353 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
354 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
355 0xc6, 0xda
357 static const u8 n4_lt168g[] = {
358 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
359 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
360 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
361 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
362 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
363 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
364 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
365 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
366 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
369 static const struct additional_sensor_data sensor_data[] = {
370 [SENSOR_OM6802] = {
371 .n3 =
372 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
373 .n4 = n4_om6802,
374 .n4sz = sizeof n4_om6802,
375 .reg80 = 0x3c,
376 .reg8e = 0x33,
377 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
378 .data1 =
379 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
380 0xb3, 0xfc},
381 .data2 =
382 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
383 0xff},
384 .data3 =
385 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
386 0xff},
387 .data5 = /* this could be removed later */
388 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
389 .stream =
390 {0x0b, 0x04, 0x0a, 0x78},
392 [SENSOR_OTHER] = {
393 .n3 =
394 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
395 .n4 = n4_other,
396 .n4sz = sizeof n4_other,
397 .reg80 = 0xac,
398 .reg8e = 0xb8,
399 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
400 .data1 =
401 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
402 0xe8, 0xfc},
403 .data2 =
404 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
405 0xd9},
406 .data3 =
407 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
408 0xd9},
409 .data5 =
410 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
411 .stream =
412 {0x0b, 0x04, 0x0a, 0x00},
414 [SENSOR_TAS5130A] = {
415 .n3 =
416 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
417 .n4 = n4_tas5130a,
418 .n4sz = sizeof n4_tas5130a,
419 .reg80 = 0x3c,
420 .reg8e = 0xb4,
421 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
422 .data1 =
423 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
424 0xc8, 0xfc},
425 .data2 =
426 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
427 0xe0},
428 .data3 =
429 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
430 0xe0},
431 .data5 =
432 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
433 .stream =
434 {0x0b, 0x04, 0x0a, 0x40},
436 [SENSOR_LT168G] = {
437 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
438 .n4 = n4_lt168g,
439 .n4sz = sizeof n4_lt168g,
440 .reg80 = 0x7c,
441 .reg8e = 0xb3,
442 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
443 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
444 0xb0, 0xf4},
445 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446 0xff},
447 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
448 0xff},
449 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
450 .stream = {0x0b, 0x04, 0x0a, 0x28},
454 #define MAX_EFFECTS 7
455 /* easily done by soft, this table could be removed,
456 * i keep it here just in case */
457 static char *effects_control[MAX_EFFECTS] = {
458 "Normal",
459 "Emboss", /* disabled */
460 "Monochrome",
461 "Sepia",
462 "Sketch",
463 "Sun Effect", /* disabled */
464 "Negative",
466 static const u8 effects_table[MAX_EFFECTS][6] = {
467 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
468 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
470 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
471 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
473 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
476 static const u8 gamma_table[GAMMA_MAX][17] = {
477 /* gamma table from cam1690.ini */
478 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
479 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
480 0xff},
481 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
482 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
483 0xff},
484 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
485 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
486 0xff},
487 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
488 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
489 0xff},
490 {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
491 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
492 0xff},
493 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
494 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
495 0xff},
496 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
497 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
498 0xff},
499 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
500 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
501 0xff},
502 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
503 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
504 0xff},
505 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
506 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
507 0xff},
508 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
509 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
510 0xff},
511 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
512 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
513 0xff},
514 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
515 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
516 0xff},
517 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
518 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
519 0xff},
520 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
521 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
522 0xff},
523 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
524 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
525 0xff}
528 static const u8 tas5130a_sensor_init[][8] = {
529 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
530 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
531 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
534 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
536 /* read 1 byte */
537 static u8 reg_r(struct gspca_dev *gspca_dev,
538 u16 index)
540 usb_control_msg(gspca_dev->dev,
541 usb_rcvctrlpipe(gspca_dev->dev, 0),
542 0, /* request */
543 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
544 0, /* value */
545 index,
546 gspca_dev->usb_buf, 1, 500);
547 return gspca_dev->usb_buf[0];
550 static void reg_w(struct gspca_dev *gspca_dev,
551 u16 index)
553 usb_control_msg(gspca_dev->dev,
554 usb_sndctrlpipe(gspca_dev->dev, 0),
556 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
557 0, index,
558 NULL, 0, 500);
561 static void reg_w_buf(struct gspca_dev *gspca_dev,
562 const u8 *buffer, u16 len)
564 if (len <= USB_BUF_SZ) {
565 memcpy(gspca_dev->usb_buf, buffer, len);
566 usb_control_msg(gspca_dev->dev,
567 usb_sndctrlpipe(gspca_dev->dev, 0),
569 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
570 0x01, 0,
571 gspca_dev->usb_buf, len, 500);
572 } else {
573 u8 *tmpbuf;
575 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
576 if (!tmpbuf) {
577 err("Out of memory");
578 return;
580 usb_control_msg(gspca_dev->dev,
581 usb_sndctrlpipe(gspca_dev->dev, 0),
583 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
584 0x01, 0,
585 tmpbuf, len, 500);
586 kfree(tmpbuf);
590 /* write values to consecutive registers */
591 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
592 u8 reg,
593 const u8 *buffer, u16 len)
595 int i;
596 u8 *p, *tmpbuf;
598 if (len * 2 <= USB_BUF_SZ) {
599 p = tmpbuf = gspca_dev->usb_buf;
600 } else {
601 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
602 if (!tmpbuf) {
603 err("Out of memory");
604 return;
607 i = len;
608 while (--i >= 0) {
609 *p++ = reg++;
610 *p++ = *buffer++;
612 usb_control_msg(gspca_dev->dev,
613 usb_sndctrlpipe(gspca_dev->dev, 0),
615 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
616 0x01, 0,
617 tmpbuf, len * 2, 500);
618 if (len * 2 > USB_BUF_SZ)
619 kfree(tmpbuf);
622 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
624 int i;
625 const u8 *p;
626 u8 byte;
627 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
628 static const u8 sensor_init[] = {
629 0xdf, 0x6d,
630 0xdd, 0x18,
631 0x5a, 0xe0,
632 0x5c, 0x07,
633 0x5d, 0xb0,
634 0x5e, 0x1e,
635 0x60, 0x71,
636 0xef, 0x00,
637 0xe9, 0x00,
638 0xea, 0x00,
639 0x90, 0x24,
640 0x91, 0xb2,
641 0x82, 0x32,
642 0xfd, 0x41,
643 0x00 /* table end */
646 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
647 msleep(100);
648 i = 4;
649 while (--i > 0) {
650 byte = reg_r(gspca_dev, 0x0060);
651 if (!(byte & 0x01))
652 break;
653 msleep(100);
655 byte = reg_r(gspca_dev, 0x0063);
656 if (byte != 0x17) {
657 err("Bad sensor reset %02x", byte);
658 /* continue? */
661 p = sensor_init;
662 while (*p != 0) {
663 val[1] = *p++;
664 val[3] = *p++;
665 if (*p == 0)
666 reg_w(gspca_dev, 0x3c80);
667 reg_w_buf(gspca_dev, val, sizeof val);
668 i = 4;
669 while (--i >= 0) {
670 msleep(15);
671 byte = reg_r(gspca_dev, 0x60);
672 if (!(byte & 0x01))
673 break;
676 msleep(15);
677 reg_w(gspca_dev, 0x3c80);
680 /* this function is called at probe time */
681 static int sd_config(struct gspca_dev *gspca_dev,
682 const struct usb_device_id *id)
684 struct sd *sd = (struct sd *) gspca_dev;
685 struct cam *cam;
687 cam = &gspca_dev->cam;
689 cam->cam_mode = vga_mode_t16;
690 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
692 sd->brightness = BRIGHTNESS_DEF;
693 sd->contrast = CONTRAST_DEF;
694 sd->colors = COLORS_DEF;
695 sd->gamma = GAMMA_DEF;
696 sd->autogain = AUTOGAIN_DEF;
697 sd->mirror = MIRROR_DEF;
698 sd->freq = FREQ_DEF;
699 sd->awb = AWB_DEF;
700 sd->sharpness = SHARPNESS_DEF;
701 sd->effect = EFFECTS_DEF;
702 sd->red_gain = RED_GAIN_DEF;
703 sd->blue_gain = BLUE_GAIN_DEF;
704 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
706 return 0;
709 static void setbrightness(struct gspca_dev *gspca_dev)
711 struct sd *sd = (struct sd *) gspca_dev;
712 unsigned int brightness;
713 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
715 brightness = sd->brightness;
716 if (brightness < 7) {
717 set6[1] = 0x26;
718 set6[3] = 0x70 - brightness * 0x10;
719 } else {
720 set6[3] = 0x00 + ((brightness - 7) * 0x10);
723 reg_w_buf(gspca_dev, set6, sizeof set6);
726 static void setcontrast(struct gspca_dev *gspca_dev)
728 struct sd *sd = (struct sd *) gspca_dev;
729 unsigned int contrast = sd->contrast;
730 u16 reg_to_write;
732 if (contrast < 7)
733 reg_to_write = 0x8ea9 - contrast * 0x200;
734 else
735 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
737 reg_w(gspca_dev, reg_to_write);
740 static void setcolors(struct gspca_dev *gspca_dev)
742 struct sd *sd = (struct sd *) gspca_dev;
743 u16 reg_to_write;
745 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
746 reg_w(gspca_dev, reg_to_write);
749 static void setgamma(struct gspca_dev *gspca_dev)
751 struct sd *sd = (struct sd *) gspca_dev;
753 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
754 reg_w_ixbuf(gspca_dev, 0x90,
755 gamma_table[sd->gamma], sizeof gamma_table[0]);
758 static void setRGB(struct gspca_dev *gspca_dev)
760 struct sd *sd = (struct sd *) gspca_dev;
761 u8 all_gain_reg[6] =
762 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
764 all_gain_reg[1] = sd->red_gain;
765 all_gain_reg[3] = sd->blue_gain;
766 all_gain_reg[5] = sd->green_gain;
767 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
770 /* Generic fnc for r/b balance, exposure and awb */
771 static void setawb(struct gspca_dev *gspca_dev)
773 struct sd *sd = (struct sd *) gspca_dev;
774 u16 reg80;
776 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
778 /* on awb leave defaults values */
779 if (!sd->awb) {
780 /* shoud we wait here.. */
781 /* update and reset RGB gains with webcam values */
782 sd->red_gain = reg_r(gspca_dev, 0x0087);
783 sd->blue_gain = reg_r(gspca_dev, 0x0088);
784 sd->green_gain = reg_r(gspca_dev, 0x0089);
785 reg80 &= ~0x0400; /* AWB off */
787 reg_w(gspca_dev, reg80);
788 reg_w(gspca_dev, reg80);
791 static void init_gains(struct gspca_dev *gspca_dev)
793 struct sd *sd = (struct sd *) gspca_dev;
794 u16 reg80;
795 u8 all_gain_reg[8] =
796 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
798 all_gain_reg[1] = sd->red_gain;
799 all_gain_reg[3] = sd->blue_gain;
800 all_gain_reg[5] = sd->green_gain;
801 reg80 = sensor_data[sd->sensor].reg80;
802 if (!sd->awb)
803 reg80 &= ~0x04;
804 all_gain_reg[7] = reg80;
805 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
807 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87);
808 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
809 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89);
812 static void setsharpness(struct gspca_dev *gspca_dev)
814 struct sd *sd = (struct sd *) gspca_dev;
815 u16 reg_to_write;
817 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
819 reg_w(gspca_dev, reg_to_write);
822 static void setfreq(struct gspca_dev *gspca_dev)
824 struct sd *sd = (struct sd *) gspca_dev;
825 u8 reg66;
826 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
828 switch (sd->sensor) {
829 case SENSOR_LT168G:
830 if (sd->freq != 0)
831 freq[3] = 0xa8;
832 reg66 = 0x41;
833 break;
834 case SENSOR_OM6802:
835 reg66 = 0xca;
836 break;
837 default:
838 reg66 = 0x40;
839 break;
841 switch (sd->freq) {
842 case 0: /* no flicker */
843 freq[3] = 0xf0;
844 break;
845 case 2: /* 60Hz */
846 reg66 &= ~0x40;
847 break;
849 freq[1] = reg66;
851 reg_w_buf(gspca_dev, freq, sizeof freq);
854 /* this function is called at probe and resume time */
855 static int sd_init(struct gspca_dev *gspca_dev)
857 /* some of this registers are not really neded, because
858 * they are overriden by setbrigthness, setcontrast, etc,
859 * but wont hurt anyway, and can help someone with similar webcam
860 * to see the initial parameters.*/
861 struct sd *sd = (struct sd *) gspca_dev;
862 const struct additional_sensor_data *sensor;
863 int i;
864 u16 sensor_id;
865 u8 test_byte = 0;
867 static const u8 read_indexs[] =
868 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
869 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
870 static const u8 n1[] =
871 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
872 static const u8 n2[] =
873 {0x08, 0x00};
875 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
876 | reg_r(gspca_dev, 0x07);
877 switch (sensor_id & 0xff0f) {
878 case 0x0801:
879 PDEBUG(D_PROBE, "sensor tas5130a");
880 sd->sensor = SENSOR_TAS5130A;
881 break;
882 case 0x0802:
883 PDEBUG(D_PROBE, "sensor lt168g");
884 sd->sensor = SENSOR_LT168G;
885 break;
886 case 0x0803:
887 PDEBUG(D_PROBE, "sensor 'other'");
888 sd->sensor = SENSOR_OTHER;
889 break;
890 case 0x0807:
891 PDEBUG(D_PROBE, "sensor om6802");
892 sd->sensor = SENSOR_OM6802;
893 break;
894 default:
895 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
896 return -EINVAL;
899 if (sd->sensor == SENSOR_OM6802) {
900 reg_w_buf(gspca_dev, n1, sizeof n1);
901 i = 5;
902 while (--i >= 0) {
903 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
904 test_byte = reg_r(gspca_dev, 0x0063);
905 msleep(100);
906 if (test_byte == 0x17)
907 break; /* OK */
909 if (i < 0) {
910 err("Bad sensor reset %02x", test_byte);
911 return -EIO;
913 reg_w_buf(gspca_dev, n2, sizeof n2);
916 i = 0;
917 while (read_indexs[i] != 0x00) {
918 test_byte = reg_r(gspca_dev, read_indexs[i]);
919 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
920 test_byte);
921 i++;
924 sensor = &sensor_data[sd->sensor];
925 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
926 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
928 if (sd->sensor == SENSOR_LT168G) {
929 test_byte = reg_r(gspca_dev, 0x80);
930 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
931 test_byte);
932 reg_w(gspca_dev, 0x6c80);
935 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
936 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
937 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
939 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
940 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
941 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
943 setbrightness(gspca_dev);
944 setcontrast(gspca_dev);
945 setgamma(gspca_dev);
946 setcolors(gspca_dev);
947 setsharpness(gspca_dev);
948 init_gains(gspca_dev);
949 setfreq(gspca_dev);
951 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
952 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
953 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
955 if (sd->sensor == SENSOR_LT168G) {
956 test_byte = reg_r(gspca_dev, 0x80);
957 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
958 test_byte);
959 reg_w(gspca_dev, 0x6c80);
962 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
963 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
964 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
966 return 0;
969 static void setmirror(struct gspca_dev *gspca_dev)
971 struct sd *sd = (struct sd *) gspca_dev;
972 u8 hflipcmd[8] =
973 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
975 if (sd->mirror)
976 hflipcmd[3] = 0x01;
978 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
981 static void seteffect(struct gspca_dev *gspca_dev)
983 struct sd *sd = (struct sd *) gspca_dev;
985 reg_w_buf(gspca_dev, effects_table[sd->effect],
986 sizeof effects_table[0]);
987 if (sd->effect == 1 || sd->effect == 5) {
988 PDEBUG(D_CONF,
989 "This effect have been disabled for webcam \"safety\"");
990 return;
993 if (sd->effect == 1 || sd->effect == 4)
994 reg_w(gspca_dev, 0x4aa6);
995 else
996 reg_w(gspca_dev, 0xfaa6);
999 /* Is this really needed?
1000 * i added some module parameters for test with some users */
1001 static void poll_sensor(struct gspca_dev *gspca_dev)
1003 static const u8 poll1[] =
1004 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1005 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1006 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1007 0x60, 0x14};
1008 static const u8 poll2[] =
1009 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1010 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1011 static const u8 noise03[] = /* (some differences / ms-drv) */
1012 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1013 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1014 0xc2, 0x80, 0xc3, 0x10};
1016 PDEBUG(D_STREAM, "[Sensor requires polling]");
1017 reg_w_buf(gspca_dev, poll1, sizeof poll1);
1018 reg_w_buf(gspca_dev, poll2, sizeof poll2);
1019 reg_w_buf(gspca_dev, noise03, sizeof noise03);
1022 static int sd_start(struct gspca_dev *gspca_dev)
1024 struct sd *sd = (struct sd *) gspca_dev;
1025 const struct additional_sensor_data *sensor;
1026 int i, mode;
1027 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1028 static const u8 t3[] =
1029 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1031 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1032 switch (mode) {
1033 case 0: /* 640x480 (0x00) */
1034 break;
1035 case 1: /* 352x288 */
1036 t2[1] = 0x40;
1037 break;
1038 case 2: /* 320x240 */
1039 t2[1] = 0x10;
1040 break;
1041 case 3: /* 176x144 */
1042 t2[1] = 0x50;
1043 break;
1044 default:
1045 /* case 4: * 160x120 */
1046 t2[1] = 0x20;
1047 break;
1050 switch (sd->sensor) {
1051 case SENSOR_OM6802:
1052 om6802_sensor_init(gspca_dev);
1053 break;
1054 case SENSOR_TAS5130A:
1055 i = 0;
1056 for (;;) {
1057 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1058 sizeof tas5130a_sensor_init[0]);
1059 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1060 break;
1061 i++;
1063 reg_w(gspca_dev, 0x3c80);
1064 /* just in case and to keep sync with logs (for mine) */
1065 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1066 sizeof tas5130a_sensor_init[0]);
1067 reg_w(gspca_dev, 0x3c80);
1068 break;
1070 sensor = &sensor_data[sd->sensor];
1071 setfreq(gspca_dev);
1072 reg_r(gspca_dev, 0x0012);
1073 reg_w_buf(gspca_dev, t2, sizeof t2);
1074 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1075 reg_w(gspca_dev, 0x0013);
1076 msleep(15);
1077 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1078 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1080 if (sd->sensor == SENSOR_OM6802)
1081 poll_sensor(gspca_dev);
1083 return 0;
1086 static void sd_stopN(struct gspca_dev *gspca_dev)
1088 struct sd *sd = (struct sd *) gspca_dev;
1090 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1091 sizeof sensor_data[sd->sensor].stream);
1092 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1093 sizeof sensor_data[sd->sensor].stream);
1094 if (sd->sensor == SENSOR_OM6802) {
1095 msleep(20);
1096 reg_w(gspca_dev, 0x0309);
1100 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1101 u8 *data, /* isoc packet */
1102 int len) /* iso packet length */
1104 int pkt_type;
1106 if (data[0] == 0x5a) {
1107 /* Control Packet, after this came the header again,
1108 * but extra bytes came in the packet before this,
1109 * sometimes an EOF arrives, sometimes not... */
1110 return;
1112 data += 2;
1113 len -= 2;
1114 if (data[0] == 0xff && data[1] == 0xd8)
1115 pkt_type = FIRST_PACKET;
1116 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1117 pkt_type = LAST_PACKET;
1118 else
1119 pkt_type = INTER_PACKET;
1120 gspca_frame_add(gspca_dev, pkt_type, data, len);
1123 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1125 struct sd *sd = (struct sd *) gspca_dev;
1127 sd->blue_gain = val;
1128 if (gspca_dev->streaming)
1129 reg_w(gspca_dev, (val << 8) + 0x88);
1130 return 0;
1133 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1135 struct sd *sd = (struct sd *) gspca_dev;
1137 *val = sd->blue_gain;
1138 return 0;
1141 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1143 struct sd *sd = (struct sd *) gspca_dev;
1145 sd->red_gain = val;
1146 if (gspca_dev->streaming)
1147 reg_w(gspca_dev, (val << 8) + 0x87);
1149 return 0;
1152 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1154 struct sd *sd = (struct sd *) gspca_dev;
1156 *val = sd->red_gain;
1157 return 0;
1160 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1162 struct sd *sd = (struct sd *) gspca_dev;
1163 u16 psg, nsg;
1165 psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1166 nsg = val * 3;
1167 sd->red_gain = sd->red_gain * nsg / psg;
1168 if (sd->red_gain > 0x40)
1169 sd->red_gain = 0x40;
1170 else if (sd->red_gain < 0x10)
1171 sd->red_gain = 0x10;
1172 sd->blue_gain = sd->blue_gain * nsg / psg;
1173 if (sd->blue_gain > 0x40)
1174 sd->blue_gain = 0x40;
1175 else if (sd->blue_gain < 0x10)
1176 sd->blue_gain = 0x10;
1177 sd->green_gain = sd->green_gain * nsg / psg;
1178 if (sd->green_gain > 0x40)
1179 sd->green_gain = 0x40;
1180 else if (sd->green_gain < 0x10)
1181 sd->green_gain = 0x10;
1183 if (gspca_dev->streaming)
1184 setRGB(gspca_dev);
1185 return 0;
1188 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1190 struct sd *sd = (struct sd *) gspca_dev;
1192 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1193 return 0;
1196 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1198 struct sd *sd = (struct sd *) gspca_dev;
1200 sd->brightness = val;
1201 if (gspca_dev->streaming)
1202 setbrightness(gspca_dev);
1203 return 0;
1206 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1208 struct sd *sd = (struct sd *) gspca_dev;
1210 *val = sd->brightness;
1211 return *val;
1214 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1216 struct sd *sd = (struct sd *) gspca_dev;
1218 sd->awb = val;
1219 if (gspca_dev->streaming)
1220 setawb(gspca_dev);
1221 return 0;
1224 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1226 struct sd *sd = (struct sd *) gspca_dev;
1228 *val = sd->awb;
1229 return *val;
1232 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1234 struct sd *sd = (struct sd *) gspca_dev;
1236 sd->mirror = val;
1237 if (gspca_dev->streaming)
1238 setmirror(gspca_dev);
1239 return 0;
1242 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1244 struct sd *sd = (struct sd *) gspca_dev;
1246 *val = sd->mirror;
1247 return *val;
1250 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1252 struct sd *sd = (struct sd *) gspca_dev;
1254 sd->effect = val;
1255 if (gspca_dev->streaming)
1256 seteffect(gspca_dev);
1257 return 0;
1260 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1262 struct sd *sd = (struct sd *) gspca_dev;
1264 *val = sd->effect;
1265 return *val;
1268 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1270 struct sd *sd = (struct sd *) gspca_dev;
1272 sd->contrast = val;
1273 if (gspca_dev->streaming)
1274 setcontrast(gspca_dev);
1275 return 0;
1278 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1280 struct sd *sd = (struct sd *) gspca_dev;
1282 *val = sd->contrast;
1283 return *val;
1286 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1288 struct sd *sd = (struct sd *) gspca_dev;
1290 sd->colors = val;
1291 if (gspca_dev->streaming)
1292 setcolors(gspca_dev);
1293 return 0;
1296 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1298 struct sd *sd = (struct sd *) gspca_dev;
1300 *val = sd->colors;
1301 return 0;
1304 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1306 struct sd *sd = (struct sd *) gspca_dev;
1308 sd->gamma = val;
1309 if (gspca_dev->streaming)
1310 setgamma(gspca_dev);
1311 return 0;
1314 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1316 struct sd *sd = (struct sd *) gspca_dev;
1318 *val = sd->gamma;
1319 return 0;
1322 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1324 struct sd *sd = (struct sd *) gspca_dev;
1326 sd->freq = val;
1327 if (gspca_dev->streaming)
1328 setfreq(gspca_dev);
1329 return 0;
1332 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1334 struct sd *sd = (struct sd *) gspca_dev;
1336 *val = sd->freq;
1337 return 0;
1340 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1342 struct sd *sd = (struct sd *) gspca_dev;
1344 sd->sharpness = val;
1345 if (gspca_dev->streaming)
1346 setsharpness(gspca_dev);
1347 return 0;
1350 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1352 struct sd *sd = (struct sd *) gspca_dev;
1354 *val = sd->sharpness;
1355 return 0;
1358 /* Low Light set here......*/
1359 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1361 struct sd *sd = (struct sd *) gspca_dev;
1363 sd->autogain = val;
1364 if (val != 0)
1365 reg_w(gspca_dev, 0xf48e);
1366 else
1367 reg_w(gspca_dev, 0xb48e);
1368 return 0;
1371 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1373 struct sd *sd = (struct sd *) gspca_dev;
1375 *val = sd->autogain;
1376 return 0;
1379 static int sd_querymenu(struct gspca_dev *gspca_dev,
1380 struct v4l2_querymenu *menu)
1382 switch (menu->id) {
1383 case V4L2_CID_POWER_LINE_FREQUENCY:
1384 switch (menu->index) {
1385 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1386 strcpy((char *) menu->name, "50 Hz");
1387 return 0;
1388 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1389 strcpy((char *) menu->name, "60 Hz");
1390 return 0;
1392 break;
1393 case V4L2_CID_EFFECTS:
1394 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1395 strncpy((char *) menu->name,
1396 effects_control[menu->index],
1397 sizeof menu->name);
1398 return 0;
1400 break;
1402 return -EINVAL;
1405 /* sub-driver description */
1406 static const struct sd_desc sd_desc = {
1407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1411 .init = sd_init,
1412 .start = sd_start,
1413 .stopN = sd_stopN,
1414 .pkt_scan = sd_pkt_scan,
1415 .querymenu = sd_querymenu,
1418 /* -- module initialisation -- */
1419 static const __devinitdata struct usb_device_id device_table[] = {
1420 {USB_DEVICE(0x17a1, 0x0128)},
1423 MODULE_DEVICE_TABLE(usb, device_table);
1425 /* -- device connect -- */
1426 static int sd_probe(struct usb_interface *intf,
1427 const struct usb_device_id *id)
1429 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1430 THIS_MODULE);
1433 static struct usb_driver sd_driver = {
1434 .name = MODULE_NAME,
1435 .id_table = device_table,
1436 .probe = sd_probe,
1437 .disconnect = gspca_disconnect,
1438 #ifdef CONFIG_PM
1439 .suspend = gspca_suspend,
1440 .resume = gspca_resume,
1441 #endif
1444 /* -- module insert / remove -- */
1445 static int __init sd_mod_init(void)
1447 int ret;
1448 ret = usb_register(&sd_driver);
1449 if (ret < 0)
1450 return ret;
1451 PDEBUG(D_PROBE, "registered");
1452 return 0;
1454 static void __exit sd_mod_exit(void)
1456 usb_deregister(&sd_driver);
1457 PDEBUG(D_PROBE, "deregistered");
1460 module_init(sd_mod_init);
1461 module_exit(sd_mod_exit);