Avoid beyond bounds copy while caching ACL
[zen-stable.git] / drivers / media / video / gspca / t613.c
blob9b9f85a8e60e750f9d2fba5cb4a0deab8e4f3b63
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31 #define MODULE_NAME "t613"
33 #include <linux/input.h>
34 #include <linux/slab.h>
35 #include "gspca.h"
37 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
39 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
40 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
41 MODULE_LICENSE("GPL");
43 struct sd {
44 struct gspca_dev gspca_dev; /* !! must be the first item */
46 u8 brightness;
47 u8 contrast;
48 u8 colors;
49 u8 autogain;
50 u8 gamma;
51 u8 sharpness;
52 u8 freq;
53 u8 red_gain;
54 u8 blue_gain;
55 u8 green_gain;
56 u8 awb; /* set default r/g/b and activate */
57 u8 mirror;
58 u8 effect;
60 u8 sensor;
61 u8 button_pressed;
63 enum sensors {
64 SENSOR_OM6802,
65 SENSOR_OTHER,
66 SENSOR_TAS5130A,
67 SENSOR_LT168G, /* must verify if this is the actual model */
70 /* V4L2 controls supported by the driver */
71 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
78 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
79 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
81 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
82 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
83 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
95 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
96 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
97 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
98 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
100 static const struct ctrl sd_ctrls[] = {
103 .id = V4L2_CID_BRIGHTNESS,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Brightness",
106 .minimum = 0,
107 .maximum = 14,
108 .step = 1,
109 #define BRIGHTNESS_DEF 8
110 .default_value = BRIGHTNESS_DEF,
112 .set = sd_setbrightness,
113 .get = sd_getbrightness,
117 .id = V4L2_CID_CONTRAST,
118 .type = V4L2_CTRL_TYPE_INTEGER,
119 .name = "Contrast",
120 .minimum = 0,
121 .maximum = 0x0d,
122 .step = 1,
123 #define CONTRAST_DEF 0x07
124 .default_value = CONTRAST_DEF,
126 .set = sd_setcontrast,
127 .get = sd_getcontrast,
131 .id = V4L2_CID_SATURATION,
132 .type = V4L2_CTRL_TYPE_INTEGER,
133 .name = "Color",
134 .minimum = 0,
135 .maximum = 0x0f,
136 .step = 1,
137 #define COLORS_DEF 0x05
138 .default_value = COLORS_DEF,
140 .set = sd_setcolors,
141 .get = sd_getcolors,
143 #define GAMMA_MAX 16
144 #define GAMMA_DEF 10
147 .id = V4L2_CID_GAMMA, /* (gamma on win) */
148 .type = V4L2_CTRL_TYPE_INTEGER,
149 .name = "Gamma",
150 .minimum = 0,
151 .maximum = GAMMA_MAX - 1,
152 .step = 1,
153 .default_value = GAMMA_DEF,
155 .set = sd_setgamma,
156 .get = sd_getgamma,
160 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
161 * some apps dont bring up the
162 * backligth_compensation control) */
163 .type = V4L2_CTRL_TYPE_INTEGER,
164 .name = "Low Light",
165 .minimum = 0,
166 .maximum = 1,
167 .step = 1,
168 #define AUTOGAIN_DEF 0x01
169 .default_value = AUTOGAIN_DEF,
171 .set = sd_setlowlight,
172 .get = sd_getlowlight,
176 .id = V4L2_CID_HFLIP,
177 .type = V4L2_CTRL_TYPE_BOOLEAN,
178 .name = "Mirror Image",
179 .minimum = 0,
180 .maximum = 1,
181 .step = 1,
182 #define MIRROR_DEF 0
183 .default_value = MIRROR_DEF,
185 .set = sd_setmirror,
186 .get = sd_getmirror
190 .id = V4L2_CID_POWER_LINE_FREQUENCY,
191 .type = V4L2_CTRL_TYPE_MENU,
192 .name = "Light Frequency Filter",
193 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
194 .maximum = 2,
195 .step = 1,
196 #define FREQ_DEF 1
197 .default_value = FREQ_DEF,
199 .set = sd_setfreq,
200 .get = sd_getfreq},
204 .id = V4L2_CID_AUTO_WHITE_BALANCE,
205 .type = V4L2_CTRL_TYPE_INTEGER,
206 .name = "Auto White Balance",
207 .minimum = 0,
208 .maximum = 1,
209 .step = 1,
210 #define AWB_DEF 0
211 .default_value = AWB_DEF,
213 .set = sd_setawb,
214 .get = sd_getawb
218 .id = V4L2_CID_SHARPNESS,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "Sharpness",
221 .minimum = 0,
222 .maximum = 15,
223 .step = 1,
224 #define SHARPNESS_DEF 0x06
225 .default_value = SHARPNESS_DEF,
227 .set = sd_setsharpness,
228 .get = sd_getsharpness,
232 .id = V4L2_CID_EFFECTS,
233 .type = V4L2_CTRL_TYPE_MENU,
234 .name = "Webcam Effects",
235 .minimum = 0,
236 .maximum = 4,
237 .step = 1,
238 #define EFFECTS_DEF 0
239 .default_value = EFFECTS_DEF,
241 .set = sd_seteffect,
242 .get = sd_geteffect
246 .id = V4L2_CID_BLUE_BALANCE,
247 .type = V4L2_CTRL_TYPE_INTEGER,
248 .name = "Blue Balance",
249 .minimum = 0x10,
250 .maximum = 0x40,
251 .step = 1,
252 #define BLUE_GAIN_DEF 0x20
253 .default_value = BLUE_GAIN_DEF,
255 .set = sd_setblue_gain,
256 .get = sd_getblue_gain,
260 .id = V4L2_CID_RED_BALANCE,
261 .type = V4L2_CTRL_TYPE_INTEGER,
262 .name = "Red Balance",
263 .minimum = 0x10,
264 .maximum = 0x40,
265 .step = 1,
266 #define RED_GAIN_DEF 0x20
267 .default_value = RED_GAIN_DEF,
269 .set = sd_setred_gain,
270 .get = sd_getred_gain,
274 .id = V4L2_CID_GAIN,
275 .type = V4L2_CTRL_TYPE_INTEGER,
276 .name = "Gain",
277 .minimum = 0x10,
278 .maximum = 0x40,
279 .step = 1,
280 #define GAIN_DEF 0x20
281 .default_value = GAIN_DEF,
283 .set = sd_setgain,
284 .get = sd_getgain,
288 static const struct v4l2_pix_format vga_mode_t16[] = {
289 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
290 .bytesperline = 160,
291 .sizeimage = 160 * 120 * 4 / 8 + 590,
292 .colorspace = V4L2_COLORSPACE_JPEG,
293 .priv = 4},
294 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
295 .bytesperline = 176,
296 .sizeimage = 176 * 144 * 3 / 8 + 590,
297 .colorspace = V4L2_COLORSPACE_JPEG,
298 .priv = 3},
299 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
300 .bytesperline = 320,
301 .sizeimage = 320 * 240 * 3 / 8 + 590,
302 .colorspace = V4L2_COLORSPACE_JPEG,
303 .priv = 2},
304 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
305 .bytesperline = 352,
306 .sizeimage = 352 * 288 * 3 / 8 + 590,
307 .colorspace = V4L2_COLORSPACE_JPEG,
308 .priv = 1},
309 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
310 .bytesperline = 640,
311 .sizeimage = 640 * 480 * 3 / 8 + 590,
312 .colorspace = V4L2_COLORSPACE_JPEG,
313 .priv = 0},
316 /* sensor specific data */
317 struct additional_sensor_data {
318 const u8 n3[6];
319 const u8 *n4, n4sz;
320 const u8 reg80, reg8e;
321 const u8 nset8[6];
322 const u8 data1[10];
323 const u8 data2[9];
324 const u8 data3[9];
325 const u8 data5[6];
326 const u8 stream[4];
329 static const u8 n4_om6802[] = {
330 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
331 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
332 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
333 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
334 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
335 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
336 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
337 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
338 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
340 static const u8 n4_other[] = {
341 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
342 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
343 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
344 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
345 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
346 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
347 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
348 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
350 static const u8 n4_tas5130a[] = {
351 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
352 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
353 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
354 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
355 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
356 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
357 0xc6, 0xda
359 static const u8 n4_lt168g[] = {
360 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
361 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
362 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
363 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
364 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
365 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
366 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
367 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
368 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
371 static const struct additional_sensor_data sensor_data[] = {
372 [SENSOR_OM6802] = {
373 .n3 =
374 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
375 .n4 = n4_om6802,
376 .n4sz = sizeof n4_om6802,
377 .reg80 = 0x3c,
378 .reg8e = 0x33,
379 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
380 .data1 =
381 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
382 0xb3, 0xfc},
383 .data2 =
384 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
385 0xff},
386 .data3 =
387 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
388 0xff},
389 .data5 = /* this could be removed later */
390 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
391 .stream =
392 {0x0b, 0x04, 0x0a, 0x78},
394 [SENSOR_OTHER] = {
395 .n3 =
396 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
397 .n4 = n4_other,
398 .n4sz = sizeof n4_other,
399 .reg80 = 0xac,
400 .reg8e = 0xb8,
401 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
402 .data1 =
403 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
404 0xe8, 0xfc},
405 .data2 =
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
407 0xd9},
408 .data3 =
409 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
410 0xd9},
411 .data5 =
412 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
413 .stream =
414 {0x0b, 0x04, 0x0a, 0x00},
416 [SENSOR_TAS5130A] = {
417 .n3 =
418 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
419 .n4 = n4_tas5130a,
420 .n4sz = sizeof n4_tas5130a,
421 .reg80 = 0x3c,
422 .reg8e = 0xb4,
423 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
424 .data1 =
425 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
426 0xc8, 0xfc},
427 .data2 =
428 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
429 0xe0},
430 .data3 =
431 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
432 0xe0},
433 .data5 =
434 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
435 .stream =
436 {0x0b, 0x04, 0x0a, 0x40},
438 [SENSOR_LT168G] = {
439 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
440 .n4 = n4_lt168g,
441 .n4sz = sizeof n4_lt168g,
442 .reg80 = 0x7c,
443 .reg8e = 0xb3,
444 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
445 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
446 0xb0, 0xf4},
447 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
448 0xff},
449 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
450 0xff},
451 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
452 .stream = {0x0b, 0x04, 0x0a, 0x28},
456 #define MAX_EFFECTS 7
457 /* easily done by soft, this table could be removed,
458 * i keep it here just in case */
459 static char *effects_control[MAX_EFFECTS] = {
460 "Normal",
461 "Emboss", /* disabled */
462 "Monochrome",
463 "Sepia",
464 "Sketch",
465 "Sun Effect", /* disabled */
466 "Negative",
468 static const u8 effects_table[MAX_EFFECTS][6] = {
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
470 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
471 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
472 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
473 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
474 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
475 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
478 static const u8 gamma_table[GAMMA_MAX][17] = {
479 /* gamma table from cam1690.ini */
480 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
481 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
482 0xff},
483 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
484 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
485 0xff},
486 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
487 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
488 0xff},
489 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
490 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
491 0xff},
492 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
493 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
494 0xff},
495 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
496 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
497 0xff},
498 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
499 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
500 0xff},
501 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
502 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
503 0xff},
504 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
505 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
506 0xff},
507 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
508 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
509 0xff},
510 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
511 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
512 0xff},
513 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
514 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
515 0xff},
516 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
517 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
518 0xff},
519 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
520 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
521 0xff},
522 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
523 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
524 0xff},
525 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
526 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
527 0xff}
530 static const u8 tas5130a_sensor_init[][8] = {
531 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
532 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
533 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
536 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
538 /* read 1 byte */
539 static u8 reg_r(struct gspca_dev *gspca_dev,
540 u16 index)
542 usb_control_msg(gspca_dev->dev,
543 usb_rcvctrlpipe(gspca_dev->dev, 0),
544 0, /* request */
545 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
546 0, /* value */
547 index,
548 gspca_dev->usb_buf, 1, 500);
549 return gspca_dev->usb_buf[0];
552 static void reg_w(struct gspca_dev *gspca_dev,
553 u16 index)
555 usb_control_msg(gspca_dev->dev,
556 usb_sndctrlpipe(gspca_dev->dev, 0),
558 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
559 0, index,
560 NULL, 0, 500);
563 static void reg_w_buf(struct gspca_dev *gspca_dev,
564 const u8 *buffer, u16 len)
566 if (len <= USB_BUF_SZ) {
567 memcpy(gspca_dev->usb_buf, buffer, len);
568 usb_control_msg(gspca_dev->dev,
569 usb_sndctrlpipe(gspca_dev->dev, 0),
571 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
572 0x01, 0,
573 gspca_dev->usb_buf, len, 500);
574 } else {
575 u8 *tmpbuf;
577 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
578 if (!tmpbuf) {
579 pr_err("Out of memory\n");
580 return;
582 usb_control_msg(gspca_dev->dev,
583 usb_sndctrlpipe(gspca_dev->dev, 0),
585 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
586 0x01, 0,
587 tmpbuf, len, 500);
588 kfree(tmpbuf);
592 /* write values to consecutive registers */
593 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
594 u8 reg,
595 const u8 *buffer, u16 len)
597 int i;
598 u8 *p, *tmpbuf;
600 if (len * 2 <= USB_BUF_SZ) {
601 p = tmpbuf = gspca_dev->usb_buf;
602 } else {
603 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
604 if (!tmpbuf) {
605 pr_err("Out of memory\n");
606 return;
609 i = len;
610 while (--i >= 0) {
611 *p++ = reg++;
612 *p++ = *buffer++;
614 usb_control_msg(gspca_dev->dev,
615 usb_sndctrlpipe(gspca_dev->dev, 0),
617 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
618 0x01, 0,
619 tmpbuf, len * 2, 500);
620 if (len * 2 > USB_BUF_SZ)
621 kfree(tmpbuf);
624 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
626 int i;
627 const u8 *p;
628 u8 byte;
629 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
630 static const u8 sensor_init[] = {
631 0xdf, 0x6d,
632 0xdd, 0x18,
633 0x5a, 0xe0,
634 0x5c, 0x07,
635 0x5d, 0xb0,
636 0x5e, 0x1e,
637 0x60, 0x71,
638 0xef, 0x00,
639 0xe9, 0x00,
640 0xea, 0x00,
641 0x90, 0x24,
642 0x91, 0xb2,
643 0x82, 0x32,
644 0xfd, 0x41,
645 0x00 /* table end */
648 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
649 msleep(100);
650 i = 4;
651 while (--i > 0) {
652 byte = reg_r(gspca_dev, 0x0060);
653 if (!(byte & 0x01))
654 break;
655 msleep(100);
657 byte = reg_r(gspca_dev, 0x0063);
658 if (byte != 0x17) {
659 pr_err("Bad sensor reset %02x\n", byte);
660 /* continue? */
663 p = sensor_init;
664 while (*p != 0) {
665 val[1] = *p++;
666 val[3] = *p++;
667 if (*p == 0)
668 reg_w(gspca_dev, 0x3c80);
669 reg_w_buf(gspca_dev, val, sizeof val);
670 i = 4;
671 while (--i >= 0) {
672 msleep(15);
673 byte = reg_r(gspca_dev, 0x60);
674 if (!(byte & 0x01))
675 break;
678 msleep(15);
679 reg_w(gspca_dev, 0x3c80);
682 /* this function is called at probe time */
683 static int sd_config(struct gspca_dev *gspca_dev,
684 const struct usb_device_id *id)
686 struct sd *sd = (struct sd *) gspca_dev;
687 struct cam *cam;
689 cam = &gspca_dev->cam;
691 cam->cam_mode = vga_mode_t16;
692 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
694 sd->brightness = BRIGHTNESS_DEF;
695 sd->contrast = CONTRAST_DEF;
696 sd->colors = COLORS_DEF;
697 sd->gamma = GAMMA_DEF;
698 sd->autogain = AUTOGAIN_DEF;
699 sd->mirror = MIRROR_DEF;
700 sd->freq = FREQ_DEF;
701 sd->awb = AWB_DEF;
702 sd->sharpness = SHARPNESS_DEF;
703 sd->effect = EFFECTS_DEF;
704 sd->red_gain = RED_GAIN_DEF;
705 sd->blue_gain = BLUE_GAIN_DEF;
706 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
708 return 0;
711 static void setbrightness(struct gspca_dev *gspca_dev)
713 struct sd *sd = (struct sd *) gspca_dev;
714 unsigned int brightness;
715 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
717 brightness = sd->brightness;
718 if (brightness < 7) {
719 set6[1] = 0x26;
720 set6[3] = 0x70 - brightness * 0x10;
721 } else {
722 set6[3] = 0x00 + ((brightness - 7) * 0x10);
725 reg_w_buf(gspca_dev, set6, sizeof set6);
728 static void setcontrast(struct gspca_dev *gspca_dev)
730 struct sd *sd = (struct sd *) gspca_dev;
731 unsigned int contrast = sd->contrast;
732 u16 reg_to_write;
734 if (contrast < 7)
735 reg_to_write = 0x8ea9 - contrast * 0x200;
736 else
737 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
739 reg_w(gspca_dev, reg_to_write);
742 static void setcolors(struct gspca_dev *gspca_dev)
744 struct sd *sd = (struct sd *) gspca_dev;
745 u16 reg_to_write;
747 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
748 reg_w(gspca_dev, reg_to_write);
751 static void setgamma(struct gspca_dev *gspca_dev)
753 struct sd *sd = (struct sd *) gspca_dev;
755 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
756 reg_w_ixbuf(gspca_dev, 0x90,
757 gamma_table[sd->gamma], sizeof gamma_table[0]);
760 static void setRGB(struct gspca_dev *gspca_dev)
762 struct sd *sd = (struct sd *) gspca_dev;
763 u8 all_gain_reg[6] =
764 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
766 all_gain_reg[1] = sd->red_gain;
767 all_gain_reg[3] = sd->blue_gain;
768 all_gain_reg[5] = sd->green_gain;
769 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
772 /* Generic fnc for r/b balance, exposure and awb */
773 static void setawb(struct gspca_dev *gspca_dev)
775 struct sd *sd = (struct sd *) gspca_dev;
776 u16 reg80;
778 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
780 /* on awb leave defaults values */
781 if (!sd->awb) {
782 /* shoud we wait here.. */
783 /* update and reset RGB gains with webcam values */
784 sd->red_gain = reg_r(gspca_dev, 0x0087);
785 sd->blue_gain = reg_r(gspca_dev, 0x0088);
786 sd->green_gain = reg_r(gspca_dev, 0x0089);
787 reg80 &= ~0x0400; /* AWB off */
789 reg_w(gspca_dev, reg80);
790 reg_w(gspca_dev, reg80);
793 static void init_gains(struct gspca_dev *gspca_dev)
795 struct sd *sd = (struct sd *) gspca_dev;
796 u16 reg80;
797 u8 all_gain_reg[8] =
798 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
800 all_gain_reg[1] = sd->red_gain;
801 all_gain_reg[3] = sd->blue_gain;
802 all_gain_reg[5] = sd->green_gain;
803 reg80 = sensor_data[sd->sensor].reg80;
804 if (!sd->awb)
805 reg80 &= ~0x04;
806 all_gain_reg[7] = reg80;
807 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
809 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87);
810 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
811 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89);
814 static void setsharpness(struct gspca_dev *gspca_dev)
816 struct sd *sd = (struct sd *) gspca_dev;
817 u16 reg_to_write;
819 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
821 reg_w(gspca_dev, reg_to_write);
824 static void setfreq(struct gspca_dev *gspca_dev)
826 struct sd *sd = (struct sd *) gspca_dev;
827 u8 reg66;
828 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
830 switch (sd->sensor) {
831 case SENSOR_LT168G:
832 if (sd->freq != 0)
833 freq[3] = 0xa8;
834 reg66 = 0x41;
835 break;
836 case SENSOR_OM6802:
837 reg66 = 0xca;
838 break;
839 default:
840 reg66 = 0x40;
841 break;
843 switch (sd->freq) {
844 case 0: /* no flicker */
845 freq[3] = 0xf0;
846 break;
847 case 2: /* 60Hz */
848 reg66 &= ~0x40;
849 break;
851 freq[1] = reg66;
853 reg_w_buf(gspca_dev, freq, sizeof freq);
856 /* this function is called at probe and resume time */
857 static int sd_init(struct gspca_dev *gspca_dev)
859 /* some of this registers are not really neded, because
860 * they are overriden by setbrigthness, setcontrast, etc,
861 * but wont hurt anyway, and can help someone with similar webcam
862 * to see the initial parameters.*/
863 struct sd *sd = (struct sd *) gspca_dev;
864 const struct additional_sensor_data *sensor;
865 int i;
866 u16 sensor_id;
867 u8 test_byte = 0;
869 static const u8 read_indexs[] =
870 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
871 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
872 static const u8 n1[] =
873 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
874 static const u8 n2[] =
875 {0x08, 0x00};
877 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
878 | reg_r(gspca_dev, 0x07);
879 switch (sensor_id & 0xff0f) {
880 case 0x0801:
881 PDEBUG(D_PROBE, "sensor tas5130a");
882 sd->sensor = SENSOR_TAS5130A;
883 break;
884 case 0x0802:
885 PDEBUG(D_PROBE, "sensor lt168g");
886 sd->sensor = SENSOR_LT168G;
887 break;
888 case 0x0803:
889 PDEBUG(D_PROBE, "sensor 'other'");
890 sd->sensor = SENSOR_OTHER;
891 break;
892 case 0x0807:
893 PDEBUG(D_PROBE, "sensor om6802");
894 sd->sensor = SENSOR_OM6802;
895 break;
896 default:
897 pr_err("unknown sensor %04x\n", sensor_id);
898 return -EINVAL;
901 if (sd->sensor == SENSOR_OM6802) {
902 reg_w_buf(gspca_dev, n1, sizeof n1);
903 i = 5;
904 while (--i >= 0) {
905 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
906 test_byte = reg_r(gspca_dev, 0x0063);
907 msleep(100);
908 if (test_byte == 0x17)
909 break; /* OK */
911 if (i < 0) {
912 pr_err("Bad sensor reset %02x\n", test_byte);
913 return -EIO;
915 reg_w_buf(gspca_dev, n2, sizeof n2);
918 i = 0;
919 while (read_indexs[i] != 0x00) {
920 test_byte = reg_r(gspca_dev, read_indexs[i]);
921 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
922 test_byte);
923 i++;
926 sensor = &sensor_data[sd->sensor];
927 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
928 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
930 if (sd->sensor == SENSOR_LT168G) {
931 test_byte = reg_r(gspca_dev, 0x80);
932 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
933 test_byte);
934 reg_w(gspca_dev, 0x6c80);
937 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
938 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
939 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
941 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
942 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
943 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
945 setbrightness(gspca_dev);
946 setcontrast(gspca_dev);
947 setgamma(gspca_dev);
948 setcolors(gspca_dev);
949 setsharpness(gspca_dev);
950 init_gains(gspca_dev);
951 setfreq(gspca_dev);
953 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
954 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
955 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
957 if (sd->sensor == SENSOR_LT168G) {
958 test_byte = reg_r(gspca_dev, 0x80);
959 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
960 test_byte);
961 reg_w(gspca_dev, 0x6c80);
964 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
965 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
966 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
968 return 0;
971 static void setmirror(struct gspca_dev *gspca_dev)
973 struct sd *sd = (struct sd *) gspca_dev;
974 u8 hflipcmd[8] =
975 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
977 if (sd->mirror)
978 hflipcmd[3] = 0x01;
980 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
983 static void seteffect(struct gspca_dev *gspca_dev)
985 struct sd *sd = (struct sd *) gspca_dev;
987 reg_w_buf(gspca_dev, effects_table[sd->effect],
988 sizeof effects_table[0]);
989 if (sd->effect == 1 || sd->effect == 5) {
990 PDEBUG(D_CONF,
991 "This effect have been disabled for webcam \"safety\"");
992 return;
995 if (sd->effect == 1 || sd->effect == 4)
996 reg_w(gspca_dev, 0x4aa6);
997 else
998 reg_w(gspca_dev, 0xfaa6);
1001 /* Is this really needed?
1002 * i added some module parameters for test with some users */
1003 static void poll_sensor(struct gspca_dev *gspca_dev)
1005 static const u8 poll1[] =
1006 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1007 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1008 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1009 0x60, 0x14};
1010 static const u8 poll2[] =
1011 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1012 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1013 static const u8 noise03[] = /* (some differences / ms-drv) */
1014 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1015 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1016 0xc2, 0x80, 0xc3, 0x10};
1018 PDEBUG(D_STREAM, "[Sensor requires polling]");
1019 reg_w_buf(gspca_dev, poll1, sizeof poll1);
1020 reg_w_buf(gspca_dev, poll2, sizeof poll2);
1021 reg_w_buf(gspca_dev, noise03, sizeof noise03);
1024 static int sd_start(struct gspca_dev *gspca_dev)
1026 struct sd *sd = (struct sd *) gspca_dev;
1027 const struct additional_sensor_data *sensor;
1028 int i, mode;
1029 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1030 static const u8 t3[] =
1031 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1033 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1034 switch (mode) {
1035 case 0: /* 640x480 (0x00) */
1036 break;
1037 case 1: /* 352x288 */
1038 t2[1] = 0x40;
1039 break;
1040 case 2: /* 320x240 */
1041 t2[1] = 0x10;
1042 break;
1043 case 3: /* 176x144 */
1044 t2[1] = 0x50;
1045 break;
1046 default:
1047 /* case 4: * 160x120 */
1048 t2[1] = 0x20;
1049 break;
1052 switch (sd->sensor) {
1053 case SENSOR_OM6802:
1054 om6802_sensor_init(gspca_dev);
1055 break;
1056 case SENSOR_TAS5130A:
1057 i = 0;
1058 for (;;) {
1059 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1060 sizeof tas5130a_sensor_init[0]);
1061 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1062 break;
1063 i++;
1065 reg_w(gspca_dev, 0x3c80);
1066 /* just in case and to keep sync with logs (for mine) */
1067 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1068 sizeof tas5130a_sensor_init[0]);
1069 reg_w(gspca_dev, 0x3c80);
1070 break;
1072 sensor = &sensor_data[sd->sensor];
1073 setfreq(gspca_dev);
1074 reg_r(gspca_dev, 0x0012);
1075 reg_w_buf(gspca_dev, t2, sizeof t2);
1076 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1077 reg_w(gspca_dev, 0x0013);
1078 msleep(15);
1079 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1080 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1082 if (sd->sensor == SENSOR_OM6802)
1083 poll_sensor(gspca_dev);
1085 return 0;
1088 static void sd_stopN(struct gspca_dev *gspca_dev)
1090 struct sd *sd = (struct sd *) gspca_dev;
1092 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1093 sizeof sensor_data[sd->sensor].stream);
1094 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1095 sizeof sensor_data[sd->sensor].stream);
1096 if (sd->sensor == SENSOR_OM6802) {
1097 msleep(20);
1098 reg_w(gspca_dev, 0x0309);
1100 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1101 /* If the last button state is pressed, release it now! */
1102 if (sd->button_pressed) {
1103 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1104 input_sync(gspca_dev->input_dev);
1105 sd->button_pressed = 0;
1107 #endif
1110 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1111 u8 *data, /* isoc packet */
1112 int len) /* iso packet length */
1114 struct sd *sd = (struct sd *) gspca_dev;
1115 int pkt_type;
1117 if (data[0] == 0x5a) {
1118 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1119 if (len > 20) {
1120 u8 state = (data[20] & 0x80) ? 1 : 0;
1121 if (sd->button_pressed != state) {
1122 input_report_key(gspca_dev->input_dev,
1123 KEY_CAMERA, state);
1124 input_sync(gspca_dev->input_dev);
1125 sd->button_pressed = state;
1128 #endif
1129 /* Control Packet, after this came the header again,
1130 * but extra bytes came in the packet before this,
1131 * sometimes an EOF arrives, sometimes not... */
1132 return;
1134 data += 2;
1135 len -= 2;
1136 if (data[0] == 0xff && data[1] == 0xd8)
1137 pkt_type = FIRST_PACKET;
1138 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1139 pkt_type = LAST_PACKET;
1140 else
1141 pkt_type = INTER_PACKET;
1142 gspca_frame_add(gspca_dev, pkt_type, data, len);
1145 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1147 struct sd *sd = (struct sd *) gspca_dev;
1149 sd->blue_gain = val;
1150 if (gspca_dev->streaming)
1151 reg_w(gspca_dev, (val << 8) + 0x88);
1152 return 0;
1155 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1157 struct sd *sd = (struct sd *) gspca_dev;
1159 *val = sd->blue_gain;
1160 return 0;
1163 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1165 struct sd *sd = (struct sd *) gspca_dev;
1167 sd->red_gain = val;
1168 if (gspca_dev->streaming)
1169 reg_w(gspca_dev, (val << 8) + 0x87);
1171 return 0;
1174 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1176 struct sd *sd = (struct sd *) gspca_dev;
1178 *val = sd->red_gain;
1179 return 0;
1182 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1184 struct sd *sd = (struct sd *) gspca_dev;
1185 u16 psg, nsg;
1187 psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1188 nsg = val * 3;
1189 sd->red_gain = sd->red_gain * nsg / psg;
1190 if (sd->red_gain > 0x40)
1191 sd->red_gain = 0x40;
1192 else if (sd->red_gain < 0x10)
1193 sd->red_gain = 0x10;
1194 sd->blue_gain = sd->blue_gain * nsg / psg;
1195 if (sd->blue_gain > 0x40)
1196 sd->blue_gain = 0x40;
1197 else if (sd->blue_gain < 0x10)
1198 sd->blue_gain = 0x10;
1199 sd->green_gain = sd->green_gain * nsg / psg;
1200 if (sd->green_gain > 0x40)
1201 sd->green_gain = 0x40;
1202 else if (sd->green_gain < 0x10)
1203 sd->green_gain = 0x10;
1205 if (gspca_dev->streaming)
1206 setRGB(gspca_dev);
1207 return 0;
1210 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1212 struct sd *sd = (struct sd *) gspca_dev;
1214 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1215 return 0;
1218 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1220 struct sd *sd = (struct sd *) gspca_dev;
1222 sd->brightness = val;
1223 if (gspca_dev->streaming)
1224 setbrightness(gspca_dev);
1225 return 0;
1228 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1230 struct sd *sd = (struct sd *) gspca_dev;
1232 *val = sd->brightness;
1233 return *val;
1236 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1238 struct sd *sd = (struct sd *) gspca_dev;
1240 sd->awb = val;
1241 if (gspca_dev->streaming)
1242 setawb(gspca_dev);
1243 return 0;
1246 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1248 struct sd *sd = (struct sd *) gspca_dev;
1250 *val = sd->awb;
1251 return *val;
1254 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1256 struct sd *sd = (struct sd *) gspca_dev;
1258 sd->mirror = val;
1259 if (gspca_dev->streaming)
1260 setmirror(gspca_dev);
1261 return 0;
1264 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1266 struct sd *sd = (struct sd *) gspca_dev;
1268 *val = sd->mirror;
1269 return *val;
1272 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1274 struct sd *sd = (struct sd *) gspca_dev;
1276 sd->effect = val;
1277 if (gspca_dev->streaming)
1278 seteffect(gspca_dev);
1279 return 0;
1282 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1284 struct sd *sd = (struct sd *) gspca_dev;
1286 *val = sd->effect;
1287 return *val;
1290 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1292 struct sd *sd = (struct sd *) gspca_dev;
1294 sd->contrast = val;
1295 if (gspca_dev->streaming)
1296 setcontrast(gspca_dev);
1297 return 0;
1300 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1302 struct sd *sd = (struct sd *) gspca_dev;
1304 *val = sd->contrast;
1305 return *val;
1308 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1310 struct sd *sd = (struct sd *) gspca_dev;
1312 sd->colors = val;
1313 if (gspca_dev->streaming)
1314 setcolors(gspca_dev);
1315 return 0;
1318 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1320 struct sd *sd = (struct sd *) gspca_dev;
1322 *val = sd->colors;
1323 return 0;
1326 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1328 struct sd *sd = (struct sd *) gspca_dev;
1330 sd->gamma = val;
1331 if (gspca_dev->streaming)
1332 setgamma(gspca_dev);
1333 return 0;
1336 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1338 struct sd *sd = (struct sd *) gspca_dev;
1340 *val = sd->gamma;
1341 return 0;
1344 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1346 struct sd *sd = (struct sd *) gspca_dev;
1348 sd->freq = val;
1349 if (gspca_dev->streaming)
1350 setfreq(gspca_dev);
1351 return 0;
1354 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1356 struct sd *sd = (struct sd *) gspca_dev;
1358 *val = sd->freq;
1359 return 0;
1362 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1364 struct sd *sd = (struct sd *) gspca_dev;
1366 sd->sharpness = val;
1367 if (gspca_dev->streaming)
1368 setsharpness(gspca_dev);
1369 return 0;
1372 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1374 struct sd *sd = (struct sd *) gspca_dev;
1376 *val = sd->sharpness;
1377 return 0;
1380 /* Low Light set here......*/
1381 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1383 struct sd *sd = (struct sd *) gspca_dev;
1385 sd->autogain = val;
1386 if (val != 0)
1387 reg_w(gspca_dev, 0xf48e);
1388 else
1389 reg_w(gspca_dev, 0xb48e);
1390 return 0;
1393 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1395 struct sd *sd = (struct sd *) gspca_dev;
1397 *val = sd->autogain;
1398 return 0;
1401 static int sd_querymenu(struct gspca_dev *gspca_dev,
1402 struct v4l2_querymenu *menu)
1404 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
1406 switch (menu->id) {
1407 case V4L2_CID_POWER_LINE_FREQUENCY:
1408 if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
1409 break;
1410 strcpy((char *) menu->name, freq_nm[menu->index]);
1411 return 0;
1412 case V4L2_CID_EFFECTS:
1413 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1414 strlcpy((char *) menu->name,
1415 effects_control[menu->index],
1416 sizeof menu->name);
1417 return 0;
1419 break;
1421 return -EINVAL;
1424 /* sub-driver description */
1425 static const struct sd_desc sd_desc = {
1426 .name = MODULE_NAME,
1427 .ctrls = sd_ctrls,
1428 .nctrls = ARRAY_SIZE(sd_ctrls),
1429 .config = sd_config,
1430 .init = sd_init,
1431 .start = sd_start,
1432 .stopN = sd_stopN,
1433 .pkt_scan = sd_pkt_scan,
1434 .querymenu = sd_querymenu,
1435 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1436 .other_input = 1,
1437 #endif
1440 /* -- module initialisation -- */
1441 static const struct usb_device_id device_table[] = {
1442 {USB_DEVICE(0x17a1, 0x0128)},
1445 MODULE_DEVICE_TABLE(usb, device_table);
1447 /* -- device connect -- */
1448 static int sd_probe(struct usb_interface *intf,
1449 const struct usb_device_id *id)
1451 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1452 THIS_MODULE);
1455 static struct usb_driver sd_driver = {
1456 .name = MODULE_NAME,
1457 .id_table = device_table,
1458 .probe = sd_probe,
1459 .disconnect = gspca_disconnect,
1460 #ifdef CONFIG_PM
1461 .suspend = gspca_suspend,
1462 .resume = gspca_resume,
1463 #endif
1466 module_usb_driver(sd_driver);