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