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