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