aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/t613.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/gspca/t613.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/gspca/t613.c')
-rw-r--r--drivers/media/video/gspca/t613.c1450
1 files changed, 1450 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
new file mode 100644
index 00000000000..d1d733b9359
--- /dev/null
+++ b/drivers/media/video/gspca/t613.c
@@ -0,0 +1,1450 @@
1/*
2 * T613 subdriver
3 *
4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
5 *
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.
10 *
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.
15 *
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
19 *
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
27 */
28
29#define MODULE_NAME "t613"
30
31#include <linux/slab.h>
32#include "gspca.h"
33
34#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
35
36MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
37MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
42
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;
56
57 u8 sensor;
58};
59enum sensors {
60 SENSOR_OM6802,
61 SENSOR_OTHER,
62 SENSOR_TAS5130A,
63 SENSOR_LT168G, /* must verify if this is the actual model */
64};
65
66/* V4L2 controls supported by the driver */
67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
81
82static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
90
91static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
95
96static const struct ctrl sd_ctrls[] = {
97 {
98 {
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,
107 },
108 .set = sd_setbrightness,
109 .get = sd_getbrightness,
110 },
111 {
112 {
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,
121 },
122 .set = sd_setcontrast,
123 .get = sd_getcontrast,
124 },
125 {
126 {
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,
135 },
136 .set = sd_setcolors,
137 .get = sd_getcolors,
138 },
139#define GAMMA_MAX 16
140#define GAMMA_DEF 10
141 {
142 {
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,
150 },
151 .set = sd_setgamma,
152 .get = sd_getgamma,
153 },
154 {
155 {
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,
166 },
167 .set = sd_setlowlight,
168 .get = sd_getlowlight,
169 },
170 {
171 {
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,
180 },
181 .set = sd_setmirror,
182 .get = sd_getmirror
183 },
184 {
185 {
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,
194 },
195 .set = sd_setfreq,
196 .get = sd_getfreq},
197
198 {
199 {
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,
208 },
209 .set = sd_setawb,
210 .get = sd_getawb
211 },
212 {
213 {
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,
222 },
223 .set = sd_setsharpness,
224 .get = sd_getsharpness,
225 },
226 {
227 {
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,
236 },
237 .set = sd_seteffect,
238 .get = sd_geteffect
239 },
240 {
241 {
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,
250 },
251 .set = sd_setblue_gain,
252 .get = sd_getblue_gain,
253 },
254 {
255 {
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,
264 },
265 .set = sd_setred_gain,
266 .get = sd_getred_gain,
267 },
268 {
269 {
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,
278 },
279 .set = sd_setgain,
280 .get = sd_getgain,
281 },
282};
283
284static 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},
310};
311
312/* sensor specific data */
313struct 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];
323};
324
325static 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
335};
336static 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
345};
346static 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
354};
355static 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
365};
366
367static 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},
389 },
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},
411 },
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},
433 },
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},
449 },
450};
451
452#define MAX_EFFECTS 7
453/* easily done by soft, this table could be removed,
454 * i keep it here just in case */
455static char *effects_control[MAX_EFFECTS] = {
456 "Normal",
457 "Emboss", /* disabled */
458 "Monochrome",
459 "Sepia",
460 "Sketch",
461 "Sun Effect", /* disabled */
462 "Negative",
463};
464static 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 */
472};
473
474static 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}
524};
525
526static 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},
530};
531
532static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
533
534/* read 1 byte */
535static u8 reg_r(struct gspca_dev *gspca_dev,
536 u16 index)
537{
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];
546}
547
548static void reg_w(struct gspca_dev *gspca_dev,
549 u16 index)
550{
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0,
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
555 0, index,
556 NULL, 0, 500);
557}
558
559static void reg_w_buf(struct gspca_dev *gspca_dev,
560 const u8 *buffer, u16 len)
561{
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),
566 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;
572
573 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
574 if (!tmpbuf) {
575 err("Out of memory");
576 return;
577 }
578 usb_control_msg(gspca_dev->dev,
579 usb_sndctrlpipe(gspca_dev->dev, 0),
580 0,
581 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
582 0x01, 0,
583 tmpbuf, len, 500);
584 kfree(tmpbuf);
585 }
586}
587
588/* write values to consecutive registers */
589static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
590 u8 reg,
591 const u8 *buffer, u16 len)
592{
593 int i;
594 u8 *p, *tmpbuf;
595
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;
603 }
604 }
605 i = len;
606 while (--i >= 0) {
607 *p++ = reg++;
608 *p++ = *buffer++;
609 }
610 usb_control_msg(gspca_dev->dev,
611 usb_sndctrlpipe(gspca_dev->dev, 0),
612 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);
618}
619
620static void om6802_sensor_init(struct gspca_dev *gspca_dev)
621{
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 */
642 };
643
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);
652 }
653 byte = reg_r(gspca_dev, 0x0063);
654 if (byte != 0x17) {
655 err("Bad sensor reset %02x", byte);
656 /* continue? */
657 }
658
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;
672 }
673 }
674 msleep(15);
675 reg_w(gspca_dev, 0x3c80);
676}
677
678/* this function is called at probe time */
679static int sd_config(struct gspca_dev *gspca_dev,
680 const struct usb_device_id *id)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct cam *cam;
684
685 cam = &gspca_dev->cam;
686
687 cam->cam_mode = vga_mode_t16;
688 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
689
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;
703
704 return 0;
705}
706
707static void setbrightness(struct gspca_dev *gspca_dev)
708{
709 struct sd *sd = (struct sd *) gspca_dev;
710 unsigned int brightness;
711 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
712
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);
719 }
720
721 reg_w_buf(gspca_dev, set6, sizeof set6);
722}
723
724static void setcontrast(struct gspca_dev *gspca_dev)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727 unsigned int contrast = sd->contrast;
728 u16 reg_to_write;
729
730 if (contrast < 7)
731 reg_to_write = 0x8ea9 - contrast * 0x200;
732 else
733 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
734
735 reg_w(gspca_dev, reg_to_write);
736}
737
738static void setcolors(struct gspca_dev *gspca_dev)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741 u16 reg_to_write;
742
743 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
744 reg_w(gspca_dev, reg_to_write);
745}
746
747static void setgamma(struct gspca_dev *gspca_dev)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750
751 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
752 reg_w_ixbuf(gspca_dev, 0x90,
753 gamma_table[sd->gamma], sizeof gamma_table[0]);
754}
755
756static void setRGB(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759 u8 all_gain_reg[6] =
760 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
761
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);
766}
767
768/* Generic fnc for r/b balance, exposure and awb */
769static void setawb(struct gspca_dev *gspca_dev)
770{
771 struct sd *sd = (struct sd *) gspca_dev;
772 u16 reg80;
773
774 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
775
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 */
784 }
785 reg_w(gspca_dev, reg80);
786 reg_w(gspca_dev, reg80);
787}
788
789static void init_gains(struct gspca_dev *gspca_dev)
790{
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};
795
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);
804
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);
808}
809
810static void setsharpness(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813 u16 reg_to_write;
814
815 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
816
817 reg_w(gspca_dev, reg_to_write);
818}
819
820static void setfreq(struct gspca_dev *gspca_dev)
821{
822 struct sd *sd = (struct sd *) gspca_dev;
823 u8 reg66;
824 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
825
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;
838 }
839 switch (sd->freq) {
840 case 0: /* no flicker */
841 freq[3] = 0xf0;
842 break;
843 case 2: /* 60Hz */
844 reg66 &= ~0x40;
845 break;
846 }
847 freq[1] = reg66;
848
849 reg_w_buf(gspca_dev, freq, sizeof freq);
850}
851
852/* this function is called at probe and resume time */
853static int sd_init(struct gspca_dev *gspca_dev)
854{
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;
864
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};
872
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;
895 }
896
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 */
906 }
907 if (i < 0) {
908 err("Bad sensor reset %02x", test_byte);
909 return -EIO;
910 }
911 reg_w_buf(gspca_dev, n2, sizeof n2);
912 }
913
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++;
920 }
921
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);
925
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);
931 }
932
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);
936
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);
940
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);
948
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);
952
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);
958 }
959
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);
963
964 return 0;
965}
966
967static void setmirror(struct gspca_dev *gspca_dev)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970 u8 hflipcmd[8] =
971 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
972
973 if (sd->mirror)
974 hflipcmd[3] = 0x01;
975
976 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
977}
978
979static void seteffect(struct gspca_dev *gspca_dev)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
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;
989 }
990
991 if (sd->effect == 1 || sd->effect == 4)
992 reg_w(gspca_dev, 0x4aa6);
993 else
994 reg_w(gspca_dev, 0xfaa6);
995}
996
997/* Is this really needed?
998 * i added some module parameters for test with some users */
999static void poll_sensor(struct gspca_dev *gspca_dev)
1000{
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};
1013
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);
1018}
1019
1020static int sd_start(struct gspca_dev *gspca_dev)
1021{
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 };
1028
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;
1046 }
1047
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++;
1060 }
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;
1067 }
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);
1077
1078 if (sd->sensor == SENSOR_OM6802)
1079 poll_sensor(gspca_dev);
1080
1081 return 0;
1082}
1083
1084static void sd_stopN(struct gspca_dev *gspca_dev)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
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);
1095 }
1096}
1097
1098static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1099 u8 *data, /* isoc packet */
1100 int len) /* iso packet length */
1101{
1102 int pkt_type;
1103
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;
1109 }
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);
1119}
1120
1121static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1122{
1123 struct sd *sd = (struct sd *) gspca_dev;
1124
1125 sd->blue_gain = val;
1126 if (gspca_dev->streaming)
1127 reg_w(gspca_dev, (val << 8) + 0x88);
1128 return 0;
1129}
1130
1131static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134
1135 *val = sd->blue_gain;
1136 return 0;
1137}
1138
1139static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142
1143 sd->red_gain = val;
1144 if (gspca_dev->streaming)
1145 reg_w(gspca_dev, (val << 8) + 0x87);
1146
1147 return 0;
1148}
1149
1150static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153
1154 *val = sd->red_gain;
1155 return 0;
1156}
1157
1158static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 u16 psg, nsg;
1162
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;
1180
1181 if (gspca_dev->streaming)
1182 setRGB(gspca_dev);
1183 return 0;
1184}
1185
1186static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1187{
1188 struct sd *sd = (struct sd *) gspca_dev;
1189
1190 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1191 return 0;
1192}
1193
1194static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197
1198 sd->brightness = val;
1199 if (gspca_dev->streaming)
1200 setbrightness(gspca_dev);
1201 return 0;
1202}
1203
1204static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1205{
1206 struct sd *sd = (struct sd *) gspca_dev;
1207
1208 *val = sd->brightness;
1209 return *val;
1210}
1211
1212static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1213{
1214 struct sd *sd = (struct sd *) gspca_dev;
1215
1216 sd->awb = val;
1217 if (gspca_dev->streaming)
1218 setawb(gspca_dev);
1219 return 0;
1220}
1221
1222static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1223{
1224 struct sd *sd = (struct sd *) gspca_dev;
1225
1226 *val = sd->awb;
1227 return *val;
1228}
1229
1230static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1231{
1232 struct sd *sd = (struct sd *) gspca_dev;
1233
1234 sd->mirror = val;
1235 if (gspca_dev->streaming)
1236 setmirror(gspca_dev);
1237 return 0;
1238}
1239
1240static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1241{
1242 struct sd *sd = (struct sd *) gspca_dev;
1243
1244 *val = sd->mirror;
1245 return *val;
1246}
1247
1248static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1249{
1250 struct sd *sd = (struct sd *) gspca_dev;
1251
1252 sd->effect = val;
1253 if (gspca_dev->streaming)
1254 seteffect(gspca_dev);
1255 return 0;
1256}
1257
1258static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1259{
1260 struct sd *sd = (struct sd *) gspca_dev;
1261
1262 *val = sd->effect;
1263 return *val;
1264}
1265
1266static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1267{
1268 struct sd *sd = (struct sd *) gspca_dev;
1269
1270 sd->contrast = val;
1271 if (gspca_dev->streaming)
1272 setcontrast(gspca_dev);
1273 return 0;
1274}
1275
1276static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1277{
1278 struct sd *sd = (struct sd *) gspca_dev;
1279
1280 *val = sd->contrast;
1281 return *val;
1282}
1283
1284static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 sd->colors = val;
1289 if (gspca_dev->streaming)
1290 setcolors(gspca_dev);
1291 return 0;
1292}
1293
1294static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297
1298 *val = sd->colors;
1299 return 0;
1300}
1301
1302static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1303{
1304 struct sd *sd = (struct sd *) gspca_dev;
1305
1306 sd->gamma = val;
1307 if (gspca_dev->streaming)
1308 setgamma(gspca_dev);
1309 return 0;
1310}
1311
1312static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1313{
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 *val = sd->gamma;
1317 return 0;
1318}
1319
1320static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1321{
1322 struct sd *sd = (struct sd *) gspca_dev;
1323
1324 sd->freq = val;
1325 if (gspca_dev->streaming)
1326 setfreq(gspca_dev);
1327 return 0;
1328}
1329
1330static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 *val = sd->freq;
1335 return 0;
1336}
1337
1338static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1339{
1340 struct sd *sd = (struct sd *) gspca_dev;
1341
1342 sd->sharpness = val;
1343 if (gspca_dev->streaming)
1344 setsharpness(gspca_dev);
1345 return 0;
1346}
1347
1348static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1349{
1350 struct sd *sd = (struct sd *) gspca_dev;
1351
1352 *val = sd->sharpness;
1353 return 0;
1354}
1355
1356/* Low Light set here......*/
1357static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1358{
1359 struct sd *sd = (struct sd *) gspca_dev;
1360
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;
1367}
1368
1369static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1370{
1371 struct sd *sd = (struct sd *) gspca_dev;
1372
1373 *val = sd->autogain;
1374 return 0;
1375}
1376
1377static int sd_querymenu(struct gspca_dev *gspca_dev,
1378 struct v4l2_querymenu *menu)
1379{
1380 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
1381
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;
1394 }
1395 break;
1396 }
1397 return -EINVAL;
1398}
1399
1400/* sub-driver description */
1401static 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,
1411};
1412
1413/* -- module initialisation -- */
1414static const struct usb_device_id device_table[] = {
1415 {USB_DEVICE(0x17a1, 0x0128)},
1416 {}
1417};
1418MODULE_DEVICE_TABLE(usb, device_table);
1419
1420/* -- device connect -- */
1421static int sd_probe(struct usb_interface *intf,
1422 const struct usb_device_id *id)
1423{
1424 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1425 THIS_MODULE);
1426}
1427
1428static 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
1437};
1438
1439/* -- module insert / remove -- */
1440static int __init sd_mod_init(void)
1441{
1442 return usb_register(&sd_driver);
1443}
1444static void __exit sd_mod_exit(void)
1445{
1446 usb_deregister(&sd_driver);
1447}
1448
1449module_init(sd_mod_init);
1450module_exit(sd_mod_exit);