Merge remote-tracking branch 'moduleh/module.h-split'
[linux-2.6/next.git] / drivers / media / video / gspca / t613.c
blobd1d733b9359b41e9f012a6d6b651d2f4b2597a3b
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);
96 static const struct ctrl sd_ctrls[] = {
99 .id = V4L2_CID_BRIGHTNESS,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Brightness",
102 .minimum = 0,
103 .maximum = 14,
104 .step = 1,
105 #define BRIGHTNESS_DEF 8
106 .default_value = BRIGHTNESS_DEF,
108 .set = sd_setbrightness,
109 .get = sd_getbrightness,
113 .id = V4L2_CID_CONTRAST,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Contrast",
116 .minimum = 0,
117 .maximum = 0x0d,
118 .step = 1,
119 #define CONTRAST_DEF 0x07
120 .default_value = CONTRAST_DEF,
122 .set = sd_setcontrast,
123 .get = sd_getcontrast,
127 .id = V4L2_CID_SATURATION,
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "Color",
130 .minimum = 0,
131 .maximum = 0x0f,
132 .step = 1,
133 #define COLORS_DEF 0x05
134 .default_value = COLORS_DEF,
136 .set = sd_setcolors,
137 .get = sd_getcolors,
139 #define GAMMA_MAX 16
140 #define GAMMA_DEF 10
143 .id = V4L2_CID_GAMMA, /* (gamma on win) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Gamma",
146 .minimum = 0,
147 .maximum = GAMMA_MAX - 1,
148 .step = 1,
149 .default_value = GAMMA_DEF,
151 .set = sd_setgamma,
152 .get = sd_getgamma,
156 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
157 * some apps dont bring up the
158 * backligth_compensation control) */
159 .type = V4L2_CTRL_TYPE_INTEGER,
160 .name = "Low Light",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164 #define AUTOGAIN_DEF 0x01
165 .default_value = AUTOGAIN_DEF,
167 .set = sd_setlowlight,
168 .get = sd_getlowlight,
172 .id = V4L2_CID_HFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Mirror Image",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178 #define MIRROR_DEF 0
179 .default_value = MIRROR_DEF,
181 .set = sd_setmirror,
182 .get = sd_getmirror
186 .id = V4L2_CID_POWER_LINE_FREQUENCY,
187 .type = V4L2_CTRL_TYPE_MENU,
188 .name = "Light Frequency Filter",
189 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
190 .maximum = 2,
191 .step = 1,
192 #define FREQ_DEF 1
193 .default_value = FREQ_DEF,
195 .set = sd_setfreq,
196 .get = sd_getfreq},
200 .id = V4L2_CID_AUTO_WHITE_BALANCE,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 .name = "Auto White Balance",
203 .minimum = 0,
204 .maximum = 1,
205 .step = 1,
206 #define AWB_DEF 0
207 .default_value = AWB_DEF,
209 .set = sd_setawb,
210 .get = sd_getawb
214 .id = V4L2_CID_SHARPNESS,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "Sharpness",
217 .minimum = 0,
218 .maximum = 15,
219 .step = 1,
220 #define SHARPNESS_DEF 0x06
221 .default_value = SHARPNESS_DEF,
223 .set = sd_setsharpness,
224 .get = sd_getsharpness,
228 .id = V4L2_CID_EFFECTS,
229 .type = V4L2_CTRL_TYPE_MENU,
230 .name = "Webcam Effects",
231 .minimum = 0,
232 .maximum = 4,
233 .step = 1,
234 #define EFFECTS_DEF 0
235 .default_value = EFFECTS_DEF,
237 .set = sd_seteffect,
238 .get = sd_geteffect
242 .id = V4L2_CID_BLUE_BALANCE,
243 .type = V4L2_CTRL_TYPE_INTEGER,
244 .name = "Blue Balance",
245 .minimum = 0x10,
246 .maximum = 0x40,
247 .step = 1,
248 #define BLUE_GAIN_DEF 0x20
249 .default_value = BLUE_GAIN_DEF,
251 .set = sd_setblue_gain,
252 .get = sd_getblue_gain,
256 .id = V4L2_CID_RED_BALANCE,
257 .type = V4L2_CTRL_TYPE_INTEGER,
258 .name = "Red Balance",
259 .minimum = 0x10,
260 .maximum = 0x40,
261 .step = 1,
262 #define RED_GAIN_DEF 0x20
263 .default_value = RED_GAIN_DEF,
265 .set = sd_setred_gain,
266 .get = sd_getred_gain,
270 .id = V4L2_CID_GAIN,
271 .type = V4L2_CTRL_TYPE_INTEGER,
272 .name = "Gain",
273 .minimum = 0x10,
274 .maximum = 0x40,
275 .step = 1,
276 #define GAIN_DEF 0x20
277 .default_value = GAIN_DEF,
279 .set = sd_setgain,
280 .get = sd_getgain,
284 static const struct v4l2_pix_format vga_mode_t16[] = {
285 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
286 .bytesperline = 160,
287 .sizeimage = 160 * 120 * 4 / 8 + 590,
288 .colorspace = V4L2_COLORSPACE_JPEG,
289 .priv = 4},
290 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
291 .bytesperline = 176,
292 .sizeimage = 176 * 144 * 3 / 8 + 590,
293 .colorspace = V4L2_COLORSPACE_JPEG,
294 .priv = 3},
295 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
296 .bytesperline = 320,
297 .sizeimage = 320 * 240 * 3 / 8 + 590,
298 .colorspace = V4L2_COLORSPACE_JPEG,
299 .priv = 2},
300 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
301 .bytesperline = 352,
302 .sizeimage = 352 * 288 * 3 / 8 + 590,
303 .colorspace = V4L2_COLORSPACE_JPEG,
304 .priv = 1},
305 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
306 .bytesperline = 640,
307 .sizeimage = 640 * 480 * 3 / 8 + 590,
308 .colorspace = V4L2_COLORSPACE_JPEG,
309 .priv = 0},
312 /* sensor specific data */
313 struct additional_sensor_data {
314 const u8 n3[6];
315 const u8 *n4, n4sz;
316 const u8 reg80, reg8e;
317 const u8 nset8[6];
318 const u8 data1[10];
319 const u8 data2[9];
320 const u8 data3[9];
321 const u8 data5[6];
322 const u8 stream[4];
325 static const u8 n4_om6802[] = {
326 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
327 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
328 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
329 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
330 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
331 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
332 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
333 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
334 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
336 static const u8 n4_other[] = {
337 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
338 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
339 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
340 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
341 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
342 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
343 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
344 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
346 static const u8 n4_tas5130a[] = {
347 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
348 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
349 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
350 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
351 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
352 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
353 0xc6, 0xda
355 static const u8 n4_lt168g[] = {
356 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
357 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
358 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
359 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
360 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
361 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
362 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
363 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
364 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
367 static const struct additional_sensor_data sensor_data[] = {
368 [SENSOR_OM6802] = {
369 .n3 =
370 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
371 .n4 = n4_om6802,
372 .n4sz = sizeof n4_om6802,
373 .reg80 = 0x3c,
374 .reg8e = 0x33,
375 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
376 .data1 =
377 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
378 0xb3, 0xfc},
379 .data2 =
380 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
381 0xff},
382 .data3 =
383 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
384 0xff},
385 .data5 = /* this could be removed later */
386 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
387 .stream =
388 {0x0b, 0x04, 0x0a, 0x78},
390 [SENSOR_OTHER] = {
391 .n3 =
392 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
393 .n4 = n4_other,
394 .n4sz = sizeof n4_other,
395 .reg80 = 0xac,
396 .reg8e = 0xb8,
397 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
398 .data1 =
399 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
400 0xe8, 0xfc},
401 .data2 =
402 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
403 0xd9},
404 .data3 =
405 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
406 0xd9},
407 .data5 =
408 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
409 .stream =
410 {0x0b, 0x04, 0x0a, 0x00},
412 [SENSOR_TAS5130A] = {
413 .n3 =
414 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
415 .n4 = n4_tas5130a,
416 .n4sz = sizeof n4_tas5130a,
417 .reg80 = 0x3c,
418 .reg8e = 0xb4,
419 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
420 .data1 =
421 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
422 0xc8, 0xfc},
423 .data2 =
424 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
425 0xe0},
426 .data3 =
427 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
428 0xe0},
429 .data5 =
430 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
431 .stream =
432 {0x0b, 0x04, 0x0a, 0x40},
434 [SENSOR_LT168G] = {
435 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
436 .n4 = n4_lt168g,
437 .n4sz = sizeof n4_lt168g,
438 .reg80 = 0x7c,
439 .reg8e = 0xb3,
440 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
441 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
442 0xb0, 0xf4},
443 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
444 0xff},
445 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446 0xff},
447 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
448 .stream = {0x0b, 0x04, 0x0a, 0x28},
452 #define MAX_EFFECTS 7
453 /* easily done by soft, this table could be removed,
454 * i keep it here just in case */
455 static char *effects_control[MAX_EFFECTS] = {
456 "Normal",
457 "Emboss", /* disabled */
458 "Monochrome",
459 "Sepia",
460 "Sketch",
461 "Sun Effect", /* disabled */
462 "Negative",
464 static const u8 effects_table[MAX_EFFECTS][6] = {
465 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
466 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
467 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
468 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
469 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
470 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
471 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
474 static const u8 gamma_table[GAMMA_MAX][17] = {
475 /* gamma table from cam1690.ini */
476 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
477 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
478 0xff},
479 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
480 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
481 0xff},
482 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
483 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
484 0xff},
485 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
486 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
487 0xff},
488 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
489 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
490 0xff},
491 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
492 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
493 0xff},
494 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
495 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
496 0xff},
497 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
498 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
499 0xff},
500 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
501 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
502 0xff},
503 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
504 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
505 0xff},
506 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
507 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
508 0xff},
509 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
510 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
511 0xff},
512 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
513 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
514 0xff},
515 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
516 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
517 0xff},
518 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
519 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
520 0xff},
521 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
522 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
523 0xff}
526 static const u8 tas5130a_sensor_init[][8] = {
527 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
528 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
529 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
532 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
534 /* read 1 byte */
535 static u8 reg_r(struct gspca_dev *gspca_dev,
536 u16 index)
538 usb_control_msg(gspca_dev->dev,
539 usb_rcvctrlpipe(gspca_dev->dev, 0),
540 0, /* request */
541 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
542 0, /* value */
543 index,
544 gspca_dev->usb_buf, 1, 500);
545 return gspca_dev->usb_buf[0];
548 static void reg_w(struct gspca_dev *gspca_dev,
549 u16 index)
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
555 0, index,
556 NULL, 0, 500);
559 static void reg_w_buf(struct gspca_dev *gspca_dev,
560 const u8 *buffer, u16 len)
562 if (len <= USB_BUF_SZ) {
563 memcpy(gspca_dev->usb_buf, buffer, len);
564 usb_control_msg(gspca_dev->dev,
565 usb_sndctrlpipe(gspca_dev->dev, 0),
567 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
568 0x01, 0,
569 gspca_dev->usb_buf, len, 500);
570 } else {
571 u8 *tmpbuf;
573 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
574 if (!tmpbuf) {
575 err("Out of memory");
576 return;
578 usb_control_msg(gspca_dev->dev,
579 usb_sndctrlpipe(gspca_dev->dev, 0),
581 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
582 0x01, 0,
583 tmpbuf, len, 500);
584 kfree(tmpbuf);
588 /* write values to consecutive registers */
589 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
590 u8 reg,
591 const u8 *buffer, u16 len)
593 int i;
594 u8 *p, *tmpbuf;
596 if (len * 2 <= USB_BUF_SZ) {
597 p = tmpbuf = gspca_dev->usb_buf;
598 } else {
599 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
600 if (!tmpbuf) {
601 err("Out of memory");
602 return;
605 i = len;
606 while (--i >= 0) {
607 *p++ = reg++;
608 *p++ = *buffer++;
610 usb_control_msg(gspca_dev->dev,
611 usb_sndctrlpipe(gspca_dev->dev, 0),
613 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
614 0x01, 0,
615 tmpbuf, len * 2, 500);
616 if (len * 2 > USB_BUF_SZ)
617 kfree(tmpbuf);
620 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
622 int i;
623 const u8 *p;
624 u8 byte;
625 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
626 static const u8 sensor_init[] = {
627 0xdf, 0x6d,
628 0xdd, 0x18,
629 0x5a, 0xe0,
630 0x5c, 0x07,
631 0x5d, 0xb0,
632 0x5e, 0x1e,
633 0x60, 0x71,
634 0xef, 0x00,
635 0xe9, 0x00,
636 0xea, 0x00,
637 0x90, 0x24,
638 0x91, 0xb2,
639 0x82, 0x32,
640 0xfd, 0x41,
641 0x00 /* table end */
644 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
645 msleep(100);
646 i = 4;
647 while (--i > 0) {
648 byte = reg_r(gspca_dev, 0x0060);
649 if (!(byte & 0x01))
650 break;
651 msleep(100);
653 byte = reg_r(gspca_dev, 0x0063);
654 if (byte != 0x17) {
655 err("Bad sensor reset %02x", byte);
656 /* continue? */
659 p = sensor_init;
660 while (*p != 0) {
661 val[1] = *p++;
662 val[3] = *p++;
663 if (*p == 0)
664 reg_w(gspca_dev, 0x3c80);
665 reg_w_buf(gspca_dev, val, sizeof val);
666 i = 4;
667 while (--i >= 0) {
668 msleep(15);
669 byte = reg_r(gspca_dev, 0x60);
670 if (!(byte & 0x01))
671 break;
674 msleep(15);
675 reg_w(gspca_dev, 0x3c80);
678 /* this function is called at probe time */
679 static int sd_config(struct gspca_dev *gspca_dev,
680 const struct usb_device_id *id)
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct cam *cam;
685 cam = &gspca_dev->cam;
687 cam->cam_mode = vga_mode_t16;
688 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
690 sd->brightness = BRIGHTNESS_DEF;
691 sd->contrast = CONTRAST_DEF;
692 sd->colors = COLORS_DEF;
693 sd->gamma = GAMMA_DEF;
694 sd->autogain = AUTOGAIN_DEF;
695 sd->mirror = MIRROR_DEF;
696 sd->freq = FREQ_DEF;
697 sd->awb = AWB_DEF;
698 sd->sharpness = SHARPNESS_DEF;
699 sd->effect = EFFECTS_DEF;
700 sd->red_gain = RED_GAIN_DEF;
701 sd->blue_gain = BLUE_GAIN_DEF;
702 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
704 return 0;
707 static void setbrightness(struct gspca_dev *gspca_dev)
709 struct sd *sd = (struct sd *) gspca_dev;
710 unsigned int brightness;
711 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
713 brightness = sd->brightness;
714 if (brightness < 7) {
715 set6[1] = 0x26;
716 set6[3] = 0x70 - brightness * 0x10;
717 } else {
718 set6[3] = 0x00 + ((brightness - 7) * 0x10);
721 reg_w_buf(gspca_dev, set6, sizeof set6);
724 static void setcontrast(struct gspca_dev *gspca_dev)
726 struct sd *sd = (struct sd *) gspca_dev;
727 unsigned int contrast = sd->contrast;
728 u16 reg_to_write;
730 if (contrast < 7)
731 reg_to_write = 0x8ea9 - contrast * 0x200;
732 else
733 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
735 reg_w(gspca_dev, reg_to_write);
738 static void setcolors(struct gspca_dev *gspca_dev)
740 struct sd *sd = (struct sd *) gspca_dev;
741 u16 reg_to_write;
743 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
744 reg_w(gspca_dev, reg_to_write);
747 static void setgamma(struct gspca_dev *gspca_dev)
749 struct sd *sd = (struct sd *) gspca_dev;
751 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
752 reg_w_ixbuf(gspca_dev, 0x90,
753 gamma_table[sd->gamma], sizeof gamma_table[0]);
756 static void setRGB(struct gspca_dev *gspca_dev)
758 struct sd *sd = (struct sd *) gspca_dev;
759 u8 all_gain_reg[6] =
760 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
762 all_gain_reg[1] = sd->red_gain;
763 all_gain_reg[3] = sd->blue_gain;
764 all_gain_reg[5] = sd->green_gain;
765 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
768 /* Generic fnc for r/b balance, exposure and awb */
769 static void setawb(struct gspca_dev *gspca_dev)
771 struct sd *sd = (struct sd *) gspca_dev;
772 u16 reg80;
774 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
776 /* on awb leave defaults values */
777 if (!sd->awb) {
778 /* shoud we wait here.. */
779 /* update and reset RGB gains with webcam values */
780 sd->red_gain = reg_r(gspca_dev, 0x0087);
781 sd->blue_gain = reg_r(gspca_dev, 0x0088);
782 sd->green_gain = reg_r(gspca_dev, 0x0089);
783 reg80 &= ~0x0400; /* AWB off */
785 reg_w(gspca_dev, reg80);
786 reg_w(gspca_dev, reg80);
789 static void init_gains(struct gspca_dev *gspca_dev)
791 struct sd *sd = (struct sd *) gspca_dev;
792 u16 reg80;
793 u8 all_gain_reg[8] =
794 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
796 all_gain_reg[1] = sd->red_gain;
797 all_gain_reg[3] = sd->blue_gain;
798 all_gain_reg[5] = sd->green_gain;
799 reg80 = sensor_data[sd->sensor].reg80;
800 if (!sd->awb)
801 reg80 &= ~0x04;
802 all_gain_reg[7] = reg80;
803 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
805 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87);
806 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
807 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89);
810 static void setsharpness(struct gspca_dev *gspca_dev)
812 struct sd *sd = (struct sd *) gspca_dev;
813 u16 reg_to_write;
815 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
817 reg_w(gspca_dev, reg_to_write);
820 static void setfreq(struct gspca_dev *gspca_dev)
822 struct sd *sd = (struct sd *) gspca_dev;
823 u8 reg66;
824 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
826 switch (sd->sensor) {
827 case SENSOR_LT168G:
828 if (sd->freq != 0)
829 freq[3] = 0xa8;
830 reg66 = 0x41;
831 break;
832 case SENSOR_OM6802:
833 reg66 = 0xca;
834 break;
835 default:
836 reg66 = 0x40;
837 break;
839 switch (sd->freq) {
840 case 0: /* no flicker */
841 freq[3] = 0xf0;
842 break;
843 case 2: /* 60Hz */
844 reg66 &= ~0x40;
845 break;
847 freq[1] = reg66;
849 reg_w_buf(gspca_dev, freq, sizeof freq);
852 /* this function is called at probe and resume time */
853 static int sd_init(struct gspca_dev *gspca_dev)
855 /* some of this registers are not really neded, because
856 * they are overriden by setbrigthness, setcontrast, etc,
857 * but wont hurt anyway, and can help someone with similar webcam
858 * to see the initial parameters.*/
859 struct sd *sd = (struct sd *) gspca_dev;
860 const struct additional_sensor_data *sensor;
861 int i;
862 u16 sensor_id;
863 u8 test_byte = 0;
865 static const u8 read_indexs[] =
866 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
867 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
868 static const u8 n1[] =
869 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
870 static const u8 n2[] =
871 {0x08, 0x00};
873 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
874 | reg_r(gspca_dev, 0x07);
875 switch (sensor_id & 0xff0f) {
876 case 0x0801:
877 PDEBUG(D_PROBE, "sensor tas5130a");
878 sd->sensor = SENSOR_TAS5130A;
879 break;
880 case 0x0802:
881 PDEBUG(D_PROBE, "sensor lt168g");
882 sd->sensor = SENSOR_LT168G;
883 break;
884 case 0x0803:
885 PDEBUG(D_PROBE, "sensor 'other'");
886 sd->sensor = SENSOR_OTHER;
887 break;
888 case 0x0807:
889 PDEBUG(D_PROBE, "sensor om6802");
890 sd->sensor = SENSOR_OM6802;
891 break;
892 default:
893 err("unknown sensor %04x", sensor_id);
894 return -EINVAL;
897 if (sd->sensor == SENSOR_OM6802) {
898 reg_w_buf(gspca_dev, n1, sizeof n1);
899 i = 5;
900 while (--i >= 0) {
901 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
902 test_byte = reg_r(gspca_dev, 0x0063);
903 msleep(100);
904 if (test_byte == 0x17)
905 break; /* OK */
907 if (i < 0) {
908 err("Bad sensor reset %02x", test_byte);
909 return -EIO;
911 reg_w_buf(gspca_dev, n2, sizeof n2);
914 i = 0;
915 while (read_indexs[i] != 0x00) {
916 test_byte = reg_r(gspca_dev, read_indexs[i]);
917 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
918 test_byte);
919 i++;
922 sensor = &sensor_data[sd->sensor];
923 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
924 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
926 if (sd->sensor == SENSOR_LT168G) {
927 test_byte = reg_r(gspca_dev, 0x80);
928 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
929 test_byte);
930 reg_w(gspca_dev, 0x6c80);
933 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
934 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
935 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
937 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
938 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
939 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
941 setbrightness(gspca_dev);
942 setcontrast(gspca_dev);
943 setgamma(gspca_dev);
944 setcolors(gspca_dev);
945 setsharpness(gspca_dev);
946 init_gains(gspca_dev);
947 setfreq(gspca_dev);
949 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
950 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
951 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
953 if (sd->sensor == SENSOR_LT168G) {
954 test_byte = reg_r(gspca_dev, 0x80);
955 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
956 test_byte);
957 reg_w(gspca_dev, 0x6c80);
960 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
961 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
962 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
964 return 0;
967 static void setmirror(struct gspca_dev *gspca_dev)
969 struct sd *sd = (struct sd *) gspca_dev;
970 u8 hflipcmd[8] =
971 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
973 if (sd->mirror)
974 hflipcmd[3] = 0x01;
976 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
979 static void seteffect(struct gspca_dev *gspca_dev)
981 struct sd *sd = (struct sd *) gspca_dev;
983 reg_w_buf(gspca_dev, effects_table[sd->effect],
984 sizeof effects_table[0]);
985 if (sd->effect == 1 || sd->effect == 5) {
986 PDEBUG(D_CONF,
987 "This effect have been disabled for webcam \"safety\"");
988 return;
991 if (sd->effect == 1 || sd->effect == 4)
992 reg_w(gspca_dev, 0x4aa6);
993 else
994 reg_w(gspca_dev, 0xfaa6);
997 /* Is this really needed?
998 * i added some module parameters for test with some users */
999 static void poll_sensor(struct gspca_dev *gspca_dev)
1001 static const u8 poll1[] =
1002 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1003 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1004 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1005 0x60, 0x14};
1006 static const u8 poll2[] =
1007 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1008 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1009 static const u8 noise03[] = /* (some differences / ms-drv) */
1010 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1011 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1012 0xc2, 0x80, 0xc3, 0x10};
1014 PDEBUG(D_STREAM, "[Sensor requires polling]");
1015 reg_w_buf(gspca_dev, poll1, sizeof poll1);
1016 reg_w_buf(gspca_dev, poll2, sizeof poll2);
1017 reg_w_buf(gspca_dev, noise03, sizeof noise03);
1020 static int sd_start(struct gspca_dev *gspca_dev)
1022 struct sd *sd = (struct sd *) gspca_dev;
1023 const struct additional_sensor_data *sensor;
1024 int i, mode;
1025 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1026 static const u8 t3[] =
1027 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1029 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1030 switch (mode) {
1031 case 0: /* 640x480 (0x00) */
1032 break;
1033 case 1: /* 352x288 */
1034 t2[1] = 0x40;
1035 break;
1036 case 2: /* 320x240 */
1037 t2[1] = 0x10;
1038 break;
1039 case 3: /* 176x144 */
1040 t2[1] = 0x50;
1041 break;
1042 default:
1043 /* case 4: * 160x120 */
1044 t2[1] = 0x20;
1045 break;
1048 switch (sd->sensor) {
1049 case SENSOR_OM6802:
1050 om6802_sensor_init(gspca_dev);
1051 break;
1052 case SENSOR_TAS5130A:
1053 i = 0;
1054 for (;;) {
1055 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1056 sizeof tas5130a_sensor_init[0]);
1057 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1058 break;
1059 i++;
1061 reg_w(gspca_dev, 0x3c80);
1062 /* just in case and to keep sync with logs (for mine) */
1063 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1064 sizeof tas5130a_sensor_init[0]);
1065 reg_w(gspca_dev, 0x3c80);
1066 break;
1068 sensor = &sensor_data[sd->sensor];
1069 setfreq(gspca_dev);
1070 reg_r(gspca_dev, 0x0012);
1071 reg_w_buf(gspca_dev, t2, sizeof t2);
1072 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1073 reg_w(gspca_dev, 0x0013);
1074 msleep(15);
1075 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1076 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1078 if (sd->sensor == SENSOR_OM6802)
1079 poll_sensor(gspca_dev);
1081 return 0;
1084 static void sd_stopN(struct gspca_dev *gspca_dev)
1086 struct sd *sd = (struct sd *) gspca_dev;
1088 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1089 sizeof sensor_data[sd->sensor].stream);
1090 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1091 sizeof sensor_data[sd->sensor].stream);
1092 if (sd->sensor == SENSOR_OM6802) {
1093 msleep(20);
1094 reg_w(gspca_dev, 0x0309);
1098 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1099 u8 *data, /* isoc packet */
1100 int len) /* iso packet length */
1102 int pkt_type;
1104 if (data[0] == 0x5a) {
1105 /* Control Packet, after this came the header again,
1106 * but extra bytes came in the packet before this,
1107 * sometimes an EOF arrives, sometimes not... */
1108 return;
1110 data += 2;
1111 len -= 2;
1112 if (data[0] == 0xff && data[1] == 0xd8)
1113 pkt_type = FIRST_PACKET;
1114 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1115 pkt_type = LAST_PACKET;
1116 else
1117 pkt_type = INTER_PACKET;
1118 gspca_frame_add(gspca_dev, pkt_type, data, len);
1121 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1123 struct sd *sd = (struct sd *) gspca_dev;
1125 sd->blue_gain = val;
1126 if (gspca_dev->streaming)
1127 reg_w(gspca_dev, (val << 8) + 0x88);
1128 return 0;
1131 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1133 struct sd *sd = (struct sd *) gspca_dev;
1135 *val = sd->blue_gain;
1136 return 0;
1139 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1141 struct sd *sd = (struct sd *) gspca_dev;
1143 sd->red_gain = val;
1144 if (gspca_dev->streaming)
1145 reg_w(gspca_dev, (val << 8) + 0x87);
1147 return 0;
1150 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1152 struct sd *sd = (struct sd *) gspca_dev;
1154 *val = sd->red_gain;
1155 return 0;
1158 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 u16 psg, nsg;
1163 psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1164 nsg = val * 3;
1165 sd->red_gain = sd->red_gain * nsg / psg;
1166 if (sd->red_gain > 0x40)
1167 sd->red_gain = 0x40;
1168 else if (sd->red_gain < 0x10)
1169 sd->red_gain = 0x10;
1170 sd->blue_gain = sd->blue_gain * nsg / psg;
1171 if (sd->blue_gain > 0x40)
1172 sd->blue_gain = 0x40;
1173 else if (sd->blue_gain < 0x10)
1174 sd->blue_gain = 0x10;
1175 sd->green_gain = sd->green_gain * nsg / psg;
1176 if (sd->green_gain > 0x40)
1177 sd->green_gain = 0x40;
1178 else if (sd->green_gain < 0x10)
1179 sd->green_gain = 0x10;
1181 if (gspca_dev->streaming)
1182 setRGB(gspca_dev);
1183 return 0;
1186 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1188 struct sd *sd = (struct sd *) gspca_dev;
1190 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1191 return 0;
1194 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1196 struct sd *sd = (struct sd *) gspca_dev;
1198 sd->brightness = val;
1199 if (gspca_dev->streaming)
1200 setbrightness(gspca_dev);
1201 return 0;
1204 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1206 struct sd *sd = (struct sd *) gspca_dev;
1208 *val = sd->brightness;
1209 return *val;
1212 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1214 struct sd *sd = (struct sd *) gspca_dev;
1216 sd->awb = val;
1217 if (gspca_dev->streaming)
1218 setawb(gspca_dev);
1219 return 0;
1222 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1224 struct sd *sd = (struct sd *) gspca_dev;
1226 *val = sd->awb;
1227 return *val;
1230 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1232 struct sd *sd = (struct sd *) gspca_dev;
1234 sd->mirror = val;
1235 if (gspca_dev->streaming)
1236 setmirror(gspca_dev);
1237 return 0;
1240 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1242 struct sd *sd = (struct sd *) gspca_dev;
1244 *val = sd->mirror;
1245 return *val;
1248 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1250 struct sd *sd = (struct sd *) gspca_dev;
1252 sd->effect = val;
1253 if (gspca_dev->streaming)
1254 seteffect(gspca_dev);
1255 return 0;
1258 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1260 struct sd *sd = (struct sd *) gspca_dev;
1262 *val = sd->effect;
1263 return *val;
1266 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1268 struct sd *sd = (struct sd *) gspca_dev;
1270 sd->contrast = val;
1271 if (gspca_dev->streaming)
1272 setcontrast(gspca_dev);
1273 return 0;
1276 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1278 struct sd *sd = (struct sd *) gspca_dev;
1280 *val = sd->contrast;
1281 return *val;
1284 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1286 struct sd *sd = (struct sd *) gspca_dev;
1288 sd->colors = val;
1289 if (gspca_dev->streaming)
1290 setcolors(gspca_dev);
1291 return 0;
1294 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1296 struct sd *sd = (struct sd *) gspca_dev;
1298 *val = sd->colors;
1299 return 0;
1302 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1304 struct sd *sd = (struct sd *) gspca_dev;
1306 sd->gamma = val;
1307 if (gspca_dev->streaming)
1308 setgamma(gspca_dev);
1309 return 0;
1312 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1314 struct sd *sd = (struct sd *) gspca_dev;
1316 *val = sd->gamma;
1317 return 0;
1320 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1322 struct sd *sd = (struct sd *) gspca_dev;
1324 sd->freq = val;
1325 if (gspca_dev->streaming)
1326 setfreq(gspca_dev);
1327 return 0;
1330 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1332 struct sd *sd = (struct sd *) gspca_dev;
1334 *val = sd->freq;
1335 return 0;
1338 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1340 struct sd *sd = (struct sd *) gspca_dev;
1342 sd->sharpness = val;
1343 if (gspca_dev->streaming)
1344 setsharpness(gspca_dev);
1345 return 0;
1348 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1350 struct sd *sd = (struct sd *) gspca_dev;
1352 *val = sd->sharpness;
1353 return 0;
1356 /* Low Light set here......*/
1357 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1359 struct sd *sd = (struct sd *) gspca_dev;
1361 sd->autogain = val;
1362 if (val != 0)
1363 reg_w(gspca_dev, 0xf48e);
1364 else
1365 reg_w(gspca_dev, 0xb48e);
1366 return 0;
1369 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1371 struct sd *sd = (struct sd *) gspca_dev;
1373 *val = sd->autogain;
1374 return 0;
1377 static int sd_querymenu(struct gspca_dev *gspca_dev,
1378 struct v4l2_querymenu *menu)
1380 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
1382 switch (menu->id) {
1383 case V4L2_CID_POWER_LINE_FREQUENCY:
1384 if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
1385 break;
1386 strcpy((char *) menu->name, freq_nm[menu->index]);
1387 return 0;
1388 case V4L2_CID_EFFECTS:
1389 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1390 strlcpy((char *) menu->name,
1391 effects_control[menu->index],
1392 sizeof menu->name);
1393 return 0;
1395 break;
1397 return -EINVAL;
1400 /* sub-driver description */
1401 static const struct sd_desc sd_desc = {
1402 .name = MODULE_NAME,
1403 .ctrls = sd_ctrls,
1404 .nctrls = ARRAY_SIZE(sd_ctrls),
1405 .config = sd_config,
1406 .init = sd_init,
1407 .start = sd_start,
1408 .stopN = sd_stopN,
1409 .pkt_scan = sd_pkt_scan,
1410 .querymenu = sd_querymenu,
1413 /* -- module initialisation -- */
1414 static const struct usb_device_id device_table[] = {
1415 {USB_DEVICE(0x17a1, 0x0128)},
1418 MODULE_DEVICE_TABLE(usb, device_table);
1420 /* -- device connect -- */
1421 static int sd_probe(struct usb_interface *intf,
1422 const struct usb_device_id *id)
1424 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1425 THIS_MODULE);
1428 static struct usb_driver sd_driver = {
1429 .name = MODULE_NAME,
1430 .id_table = device_table,
1431 .probe = sd_probe,
1432 .disconnect = gspca_disconnect,
1433 #ifdef CONFIG_PM
1434 .suspend = gspca_suspend,
1435 .resume = gspca_resume,
1436 #endif
1439 /* -- module insert / remove -- */
1440 static int __init sd_mod_init(void)
1442 return usb_register(&sd_driver);
1444 static void __exit sd_mod_exit(void)
1446 usb_deregister(&sd_driver);
1449 module_init(sd_mod_init);
1450 module_exit(sd_mod_exit);