]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/video/gspca/t613.c
V4L/DVB: gspca - t613: Change the gamma table
[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];
82e25491
JFM
322 const u8 data5[6];
323 const u8 stream[4];
ad62fb08
LC
324};
325
78a6d74e
JFM
326static const u8 n4_om6802[] = {
327 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
328 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
329 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
330 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
331 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
332 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
333 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
334 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
335 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
336};
337static const u8 n4_other[] = {
338 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
339 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
340 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
341 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
342 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
343 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
344 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
345 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
346};
347static const u8 n4_tas5130a[] = {
348 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
349 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
350 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
351 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
352 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
353 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
354 0xc6, 0xda
355};
00e8006d
NW
356static const u8 n4_lt168g[] = {
357 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
358 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
359 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
360 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
361 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
362 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
363 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
364 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
365 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
366};
78a6d74e 367
e23b2907 368static const struct additional_sensor_data sensor_data[] = {
cd8955b8 369[SENSOR_OM6802] = {
78a6d74e
JFM
370 .n3 =
371 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
372 .n4 = n4_om6802,
373 .n4sz = sizeof n4_om6802,
374 .reg80 = 0x3c,
375 .reg8e = 0x33,
376 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
2d56f3bb
JFM
377 .data1 =
378 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
379 0xb3, 0xfc},
380 .data2 =
381 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
382 0xff},
78a6d74e
JFM
383 .data3 =
384 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
385 0xff},
2d56f3bb
JFM
386 .data5 = /* this could be removed later */
387 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
388 .stream =
389 {0x0b, 0x04, 0x0a, 0x78},
390 },
cd8955b8 391[SENSOR_OTHER] = {
78a6d74e
JFM
392 .n3 =
393 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
394 .n4 = n4_other,
395 .n4sz = sizeof n4_other,
396 .reg80 = 0xac,
397 .reg8e = 0xb8,
398 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
2d56f3bb
JFM
399 .data1 =
400 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
401 0xe8, 0xfc},
402 .data2 =
403 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
404 0xd9},
78a6d74e
JFM
405 .data3 =
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
407 0xd9},
2d56f3bb
JFM
408 .data5 =
409 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
410 .stream =
411 {0x0b, 0x04, 0x0a, 0x00},
412 },
cd8955b8 413[SENSOR_TAS5130A] = {
78a6d74e
JFM
414 .n3 =
415 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
416 .n4 = n4_tas5130a,
417 .n4sz = sizeof n4_tas5130a,
418 .reg80 = 0x3c,
419 .reg8e = 0xb4,
420 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
ad62fb08 421 .data1 =
82e25491
JFM
422 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
423 0xc8, 0xfc},
ad62fb08 424 .data2 =
82e25491
JFM
425 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
426 0xe0},
78a6d74e
JFM
427 .data3 =
428 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
429 0xe0},
ad62fb08
LC
430 .data5 =
431 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
432 .stream =
433 {0x0b, 0x04, 0x0a, 0x40},
434 },
cd8955b8 435[SENSOR_LT168G] = {
00e8006d
NW
436 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
437 .n4 = n4_lt168g,
438 .n4sz = sizeof n4_lt168g,
439 .reg80 = 0x7c,
440 .reg8e = 0xb3,
441 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
442 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
443 0xb0, 0xf4},
444 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
445 0xff},
446 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
447 0xff},
00e8006d
NW
448 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
449 .stream = {0x0b, 0x04, 0x0a, 0x28},
450 },
ad62fb08
LC
451};
452
6a7eba24
JFM
453#define MAX_EFFECTS 7
454/* easily done by soft, this table could be removed,
455 * i keep it here just in case */
cd8955b8
JFM
456static char *effects_control[MAX_EFFECTS] = {
457 "Normal",
458 "Emboss", /* disabled */
459 "Monochrome",
460 "Sepia",
461 "Sketch",
462 "Sun Effect", /* disabled */
463 "Negative",
464};
82e25491 465static const u8 effects_table[MAX_EFFECTS][6] = {
6a7eba24
JFM
466 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
467 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
468 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
470 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
471 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
473};
474
82e25491 475static const u8 gamma_table[GAMMA_MAX][17] = {
79960d39
JFM
476/* gamma table from cam1690.ini */
477 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
478 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
82e25491 479 0xff},
79960d39
JFM
480 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
481 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
82e25491 482 0xff},
79960d39
JFM
483 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
484 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
82e25491 485 0xff},
79960d39
JFM
486 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
487 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
82e25491 488 0xff},
79960d39
JFM
489 {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
490 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
82e25491 491 0xff},
79960d39
JFM
492 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
493 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
82e25491 494 0xff},
79960d39 495 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
82e25491
JFM
496 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
497 0xff},
79960d39 498 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
82e25491
JFM
499 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
500 0xff},
79960d39
JFM
501 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
502 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
82e25491 503 0xff},
79960d39
JFM
504 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
505 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
82e25491 506 0xff},
79960d39
JFM
507 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
508 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
82e25491 509 0xff},
79960d39 510 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
82e25491
JFM
511 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
512 0xff},
513 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
514 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
515 0xff},
516 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
517 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
518 0xff},
519 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
520 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
521 0xff},
522 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
523 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
524 0xff}
6a7eba24
JFM
525};
526
82e25491 527static const u8 tas5130a_sensor_init[][8] = {
6a7eba24
JFM
528 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
529 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
530 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
6a7eba24
JFM
531};
532
82e25491 533static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
392ee5a5 534
739570bb 535/* read 1 byte */
82e25491
JFM
536static u8 reg_r(struct gspca_dev *gspca_dev,
537 u16 index)
6a7eba24 538{
739570bb
JFM
539 usb_control_msg(gspca_dev->dev,
540 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
541 0, /* request */
542 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
543 0, /* value */
739570bb
JFM
544 index,
545 gspca_dev->usb_buf, 1, 500);
546 return gspca_dev->usb_buf[0];
6a7eba24
JFM
547}
548
739570bb 549static void reg_w(struct gspca_dev *gspca_dev,
82e25491 550 u16 index)
fadc7993
JFM
551{
552 usb_control_msg(gspca_dev->dev,
553 usb_sndctrlpipe(gspca_dev->dev, 0),
554 0,
0bc99b5c 555 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993
JFM
556 0, index,
557 NULL, 0, 500);
558}
559
f89be036 560static void reg_w_buf(struct gspca_dev *gspca_dev,
82e25491 561 const u8 *buffer, u16 len)
6a7eba24 562{
8295d99e 563 if (len <= USB_BUF_SZ) {
739570bb
JFM
564 memcpy(gspca_dev->usb_buf, buffer, len);
565 usb_control_msg(gspca_dev->dev,
566 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062 567 0,
0bc99b5c 568 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993 569 0x01, 0,
739570bb 570 gspca_dev->usb_buf, len, 500);
a5ae2062 571 } else {
82e25491 572 u8 *tmpbuf;
a5ae2062
JFM
573
574 tmpbuf = kmalloc(len, GFP_KERNEL);
24f222e7
JFM
575 if (!tmpbuf) {
576 err("Out of memory");
577 return;
578 }
a5ae2062 579 memcpy(tmpbuf, buffer, len);
739570bb
JFM
580 usb_control_msg(gspca_dev->dev,
581 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062 582 0,
0bc99b5c 583 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993 584 0x01, 0,
a5ae2062
JFM
585 tmpbuf, len, 500);
586 kfree(tmpbuf);
587 }
6a7eba24
JFM
588}
589
82e25491
JFM
590/* write values to consecutive registers */
591static 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
24f222e7 598 if (len * 2 <= USB_BUF_SZ) {
82e25491 599 p = tmpbuf = gspca_dev->usb_buf;
24f222e7 600 } else {
82e25491 601 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
24f222e7
JFM
602 if (!tmpbuf) {
603 err("Out of memory");
604 return;
605 }
606 }
82e25491
JFM
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
236088d2 622static void om6802_sensor_init(struct gspca_dev *gspca_dev)
fadc7993
JFM
623{
624 int i;
82e25491
JFM
625 const u8 *p;
626 u8 byte;
627 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
628 static const u8 sensor_init[] = {
fadc7993
JFM
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,
fadc7993
JFM
642 0xfd, 0x41,
643 0x00 /* table end */
644 };
645
392ee5a5 646 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
e30bdc66 647 msleep(100);
392ee5a5 648 i = 4;
97a53a0f 649 while (--i > 0) {
392ee5a5
JFM
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
fadc7993
JFM
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);
f89be036 667 reg_w_buf(gspca_dev, val, sizeof val);
fadc7993
JFM
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 }
392ee5a5
JFM
676 msleep(15);
677 reg_w(gspca_dev, 0x3c80);
fadc7993
JFM
678}
679
6a7eba24
JFM
680/* this function is called at probe time */
681static 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;
6a7eba24
JFM
688
689 cam->cam_mode = vga_mode_t16;
690 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
691
82e25491
JFM
692 sd->brightness = BRIGHTNESS_DEF;
693 sd->contrast = CONTRAST_DEF;
694 sd->colors = COLORS_DEF;
fadc7993 695 sd->gamma = GAMMA_DEF;
82e25491
JFM
696 sd->autogain = AUTOGAIN_DEF;
697 sd->mirror = MIRROR_DEF;
698 sd->freq = FREQ_DEF;
cd8955b8 699 sd->awb = AWB_DEF;
82e25491
JFM
700 sd->sharpness = SHARPNESS_DEF;
701 sd->effect = EFFECTS_DEF;
be1da9ee
CL
702 sd->red_balance = RED_BALANCE_DEF;
703 sd->blue_balance = BLUE_BALANCE_DEF;
704 sd->global_gain = global_gain_DEF;
705
6a7eba24
JFM
706 return 0;
707}
708
35480b6b
JFM
709static void setbrightness(struct gspca_dev *gspca_dev)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712 unsigned int brightness;
82e25491 713 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
35480b6b
JFM
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
726static void setcontrast(struct gspca_dev *gspca_dev)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729 unsigned int contrast = sd->contrast;
82e25491 730 u16 reg_to_write;
35480b6b
JFM
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
740static void setcolors(struct gspca_dev *gspca_dev)
741{
742 struct sd *sd = (struct sd *) gspca_dev;
82e25491 743 u16 reg_to_write;
35480b6b
JFM
744
745 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
746 reg_w(gspca_dev, reg_to_write);
747}
748
fadc7993
JFM
749static 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);
82e25491
JFM
754 reg_w_ixbuf(gspca_dev, 0x90,
755 gamma_table[sd->gamma], sizeof gamma_table[0]);
fadc7993 756}
be1da9ee
CL
757static void setglobalgain(struct gspca_dev *gspca_dev)
758{
fadc7993 759
be1da9ee
CL
760 struct sd *sd = (struct sd *) gspca_dev;
761 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
762 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
763 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
764}
765
766/* Generic fnc for r/b balance, exposure and whitebalance */
cd8955b8 767static void setawb(struct gspca_dev *gspca_dev)
35480b6b
JFM
768{
769 struct sd *sd = (struct sd *) gspca_dev;
770
cd8955b8
JFM
771 /* on awb leave defaults values */
772 if (sd->awb) {
be1da9ee
CL
773 reg_w(gspca_dev, 0x3c80);
774 } else {
775 reg_w(gspca_dev, 0x3880);
776 /* shoud we wait here.. */
777 /* update and reset 'global gain' with webcam parameters */
778 sd->red_balance = reg_r(gspca_dev, 0x0087);
779 sd->blue_balance = reg_r(gspca_dev, 0x0088);
780 sd->global_gain = reg_r(gspca_dev, 0x0089);
781 setglobalgain(gspca_dev);
782 }
783
784}
35480b6b 785
35480b6b
JFM
786static void setsharpness(struct gspca_dev *gspca_dev)
787{
788 struct sd *sd = (struct sd *) gspca_dev;
82e25491 789 u16 reg_to_write;
35480b6b
JFM
790
791 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
792
793 reg_w(gspca_dev, reg_to_write);
794}
795
78b98cb9
JFM
796static void setfreq(struct gspca_dev *gspca_dev)
797{
798 struct sd *sd = (struct sd *) gspca_dev;
799 u8 reg66;
800 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
801
802 switch (sd->sensor) {
803 case SENSOR_LT168G:
804 if (sd->freq != 0)
805 freq[3] = 0xa8;
806 reg66 = 0x41;
807 break;
808 case SENSOR_OM6802:
809 reg66 = 0xca;
810 break;
811 default:
812 reg66 = 0x40;
813 break;
814 }
815 switch (sd->freq) {
816 case 0: /* no flicker */
817 freq[3] = 0xf0;
818 break;
819 case 2: /* 60Hz */
820 reg66 &= ~0x40;
821 break;
822 }
823 freq[1] = reg66;
824
825 reg_w_buf(gspca_dev, freq, sizeof freq);
826}
827
fadc7993
JFM
828/* this function is called at probe and resume time */
829static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24 830{
6a7eba24
JFM
831 /* some of this registers are not really neded, because
832 * they are overriden by setbrigthness, setcontrast, etc,
833 * but wont hurt anyway, and can help someone with similar webcam
834 * to see the initial parameters.*/
fadc7993 835 struct sd *sd = (struct sd *) gspca_dev;
78a6d74e 836 const struct additional_sensor_data *sensor;
fadc7993 837 int i;
2d56f3bb 838 u16 sensor_id;
d9ddd3b0 839 u8 test_byte = 0;
6a7eba24 840
82e25491 841 static const u8 read_indexs[] =
249fe889 842 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
82e25491
JFM
843 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
844 static const u8 n1[] =
6a7eba24 845 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
82e25491 846 static const u8 n2[] =
6a7eba24 847 {0x08, 0x00};
6a7eba24 848
2d56f3bb
JFM
849 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
850 | reg_r(gspca_dev, 0x07);
3da37e42 851 switch (sensor_id & 0xff0f) {
2d56f3bb 852 case 0x0801:
748c0148 853 PDEBUG(D_PROBE, "sensor tas5130a");
236088d2 854 sd->sensor = SENSOR_TAS5130A;
2d56f3bb 855 break;
00e8006d
NW
856 case 0x0802:
857 PDEBUG(D_PROBE, "sensor lt168g");
858 sd->sensor = SENSOR_LT168G;
859 break;
2d56f3bb 860 case 0x0803:
748c0148 861 PDEBUG(D_PROBE, "sensor 'other'");
2d56f3bb
JFM
862 sd->sensor = SENSOR_OTHER;
863 break;
864 case 0x0807:
748c0148 865 PDEBUG(D_PROBE, "sensor om6802");
2d56f3bb
JFM
866 sd->sensor = SENSOR_OM6802;
867 break;
868 default:
748c0148 869 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
409b11dd 870 return -EINVAL;
fadc7993
JFM
871 }
872
dd72cb3e 873 if (sd->sensor == SENSOR_OM6802) {
2d56f3bb
JFM
874 reg_w_buf(gspca_dev, n1, sizeof n1);
875 i = 5;
876 while (--i >= 0) {
877 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
878 test_byte = reg_r(gspca_dev, 0x0063);
879 msleep(100);
880 if (test_byte == 0x17)
881 break; /* OK */
882 }
883 if (i < 0) {
884 err("Bad sensor reset %02x", test_byte);
78a6d74e 885 return -EIO;
2d56f3bb
JFM
886 }
887 reg_w_buf(gspca_dev, n2, sizeof n2);
fadc7993 888 }
6a7eba24 889
fadc7993 890 i = 0;
6a7eba24 891 while (read_indexs[i] != 0x00) {
fadc7993
JFM
892 test_byte = reg_r(gspca_dev, read_indexs[i]);
893 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
6a7eba24
JFM
894 test_byte);
895 i++;
896 }
897
78a6d74e
JFM
898 sensor = &sensor_data[sd->sensor];
899 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
900 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
ad62fb08 901
00e8006d
NW
902 if (sd->sensor == SENSOR_LT168G) {
903 test_byte = reg_r(gspca_dev, 0x80);
904 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
905 test_byte);
906 reg_w(gspca_dev, 0x6c80);
907 }
908
78a6d74e
JFM
909 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
910 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
911 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
ad62fb08 912
78a6d74e
JFM
913 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
914 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
915 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
ad62fb08 916
35480b6b
JFM
917 setbrightness(gspca_dev);
918 setcontrast(gspca_dev);
fadc7993 919 setgamma(gspca_dev);
35480b6b
JFM
920 setcolors(gspca_dev);
921 setsharpness(gspca_dev);
cd8955b8 922 setawb(gspca_dev);
78b98cb9 923 setfreq(gspca_dev);
fadc7993 924
35480b6b 925 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
fadc7993
JFM
926 reg_w(gspca_dev, 0x2088);
927 reg_w(gspca_dev, 0x2089);
928
78a6d74e
JFM
929 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
930 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
931 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
932 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
ad62fb08 933
00e8006d
NW
934 if (sd->sensor == SENSOR_LT168G) {
935 test_byte = reg_r(gspca_dev, 0x80);
936 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
937 test_byte);
938 reg_w(gspca_dev, 0x6c80);
939 }
940
78a6d74e
JFM
941 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
942 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
943 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
6a7eba24 944
012d6b02
JFM
945 return 0;
946}
947
cd8955b8 948static void setmirror(struct gspca_dev *gspca_dev)
6a7eba24
JFM
949{
950 struct sd *sd = (struct sd *) gspca_dev;
cd8955b8 951 u8 hflipcmd[8] =
fadc7993 952 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
6a7eba24 953
fadc7993 954 if (sd->mirror)
cd8955b8 955 hflipcmd[3] = 0x01;
6a7eba24 956
cd8955b8 957 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
6a7eba24
JFM
958}
959
960static void seteffect(struct gspca_dev *gspca_dev)
961{
962 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 963
f89be036
JFM
964 reg_w_buf(gspca_dev, effects_table[sd->effect],
965 sizeof effects_table[0]);
6a7eba24
JFM
966 if (sd->effect == 1 || sd->effect == 5) {
967 PDEBUG(D_CONF,
968 "This effect have been disabled for webcam \"safety\"");
969 return;
970 }
971
972 if (sd->effect == 1 || sd->effect == 4)
fadc7993 973 reg_w(gspca_dev, 0x4aa6);
6a7eba24 974 else
fadc7993 975 reg_w(gspca_dev, 0xfaa6);
6a7eba24
JFM
976}
977
ad62fb08
LC
978/* Is this really needed?
979 * i added some module parameters for test with some users */
980static void poll_sensor(struct gspca_dev *gspca_dev)
981{
82e25491 982 static const u8 poll1[] =
ad62fb08
LC
983 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
984 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
985 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
986 0x60, 0x14};
82e25491 987 static const u8 poll2[] =
ad62fb08
LC
988 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
989 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
82e25491 990 static const u8 poll3[] =
ad62fb08 991 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
82e25491 992 static const u8 poll4[] =
ad62fb08
LC
993 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
994 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
995 0xc2, 0x80, 0xc3, 0x10};
996
78a6d74e
JFM
997 PDEBUG(D_STREAM, "[Sensor requires polling]");
998 reg_w_buf(gspca_dev, poll1, sizeof poll1);
999 reg_w_buf(gspca_dev, poll2, sizeof poll2);
1000 reg_w_buf(gspca_dev, poll3, sizeof poll3);
1001 reg_w_buf(gspca_dev, poll4, sizeof poll4);
ad62fb08
LC
1002}
1003
fadc7993
JFM
1004static int sd_start(struct gspca_dev *gspca_dev)
1005{
1006 struct sd *sd = (struct sd *) gspca_dev;
78a6d74e 1007 const struct additional_sensor_data *sensor;
fadc7993 1008 int i, mode;
82e25491
JFM
1009 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1010 static const u8 t3[] =
1011 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
fadc7993 1012
78a6d74e 1013 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
fadc7993 1014 switch (mode) {
82e25491
JFM
1015 case 0: /* 640x480 (0x00) */
1016 break;
fadc7993
JFM
1017 case 1: /* 352x288 */
1018 t2[1] = 0x40;
1019 break;
1020 case 2: /* 320x240 */
1021 t2[1] = 0x10;
1022 break;
1023 case 3: /* 176x144 */
1024 t2[1] = 0x50;
1025 break;
82e25491
JFM
1026 default:
1027/* case 4: * 160x120 */
fadc7993
JFM
1028 t2[1] = 0x20;
1029 break;
fadc7993
JFM
1030 }
1031
2d56f3bb
JFM
1032 switch (sd->sensor) {
1033 case SENSOR_OM6802:
1034 om6802_sensor_init(gspca_dev);
1035 break;
cd8955b8 1036 case SENSOR_TAS5130A:
fadc7993 1037 i = 0;
78a6d74e 1038 for (;;) {
f89be036 1039 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
fadc7993 1040 sizeof tas5130a_sensor_init[0]);
78a6d74e
JFM
1041 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1042 break;
fadc7993
JFM
1043 i++;
1044 }
1045 reg_w(gspca_dev, 0x3c80);
1046 /* just in case and to keep sync with logs (for mine) */
78a6d74e 1047 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
fadc7993
JFM
1048 sizeof tas5130a_sensor_init[0]);
1049 reg_w(gspca_dev, 0x3c80);
2d56f3bb 1050 break;
fadc7993 1051 }
78a6d74e 1052 sensor = &sensor_data[sd->sensor];
78b98cb9 1053 setfreq(gspca_dev);
fadc7993 1054 reg_r(gspca_dev, 0x0012);
ad62fb08 1055 reg_w_buf(gspca_dev, t2, sizeof t2);
82e25491 1056 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
fadc7993 1057 reg_w(gspca_dev, 0x0013);
ad62fb08 1058 msleep(15);
78a6d74e
JFM
1059 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1060 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1061
1062 if (sd->sensor == SENSOR_OM6802)
1063 poll_sensor(gspca_dev);
ad62fb08 1064
fadc7993
JFM
1065 return 0;
1066}
1067
eb229b22
JFM
1068static void sd_stopN(struct gspca_dev *gspca_dev)
1069{
1070 struct sd *sd = (struct sd *) gspca_dev;
1071
1072 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1073 sizeof sensor_data[sd->sensor].stream);
eb229b22
JFM
1074 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1075 sizeof sensor_data[sd->sensor].stream);
78a6d74e 1076 if (sd->sensor == SENSOR_OM6802) {
2d56f3bb
JFM
1077 msleep(20);
1078 reg_w(gspca_dev, 0x0309);
1079 }
eb229b22
JFM
1080}
1081
fadc7993 1082static void sd_pkt_scan(struct gspca_dev *gspca_dev,
82e25491 1083 u8 *data, /* isoc packet */
fadc7993
JFM
1084 int len) /* iso packet length */
1085{
82e25491 1086 static u8 ffd9[] = { 0xff, 0xd9 };
fadc7993
JFM
1087
1088 if (data[0] == 0x5a) {
1089 /* Control Packet, after this came the header again,
1090 * but extra bytes came in the packet before this,
1091 * sometimes an EOF arrives, sometimes not... */
1092 return;
1093 }
1094 data += 2;
1095 len -= 2;
1096 if (data[0] == 0xff && data[1] == 0xd8) {
1097 /* extra bytes....., could be processed too but would be
1098 * a waste of time, right now leave the application and
1099 * libjpeg do it for ourserlves.. */
76dd272b 1100 gspca_frame_add(gspca_dev, LAST_PACKET,
fadc7993 1101 ffd9, 2);
76dd272b 1102 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
fadc7993
JFM
1103 return;
1104 }
1105
1106 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1107 /* Just in case, i have seen packets with the marker,
1108 * other's do not include it... */
1109 len -= 2;
1110 }
76dd272b 1111 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
1112}
1113
be1da9ee
CL
1114
1115static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1116{
1117 struct sd *sd = (struct sd *) gspca_dev;
1118
1119 sd->blue_balance = val;
1120 if (gspca_dev->streaming)
1121 reg_w(gspca_dev, (val << 8) + 0x88);
1122 return 0;
1123}
1124
1125static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1126{
1127 struct sd *sd = (struct sd *) gspca_dev;
1128
1129 *val = sd->blue_balance;
1130 return 0;
1131}
1132
1133static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136
1137 sd->red_balance = val;
1138 if (gspca_dev->streaming)
1139 reg_w(gspca_dev, (val << 8) + 0x87);
1140
1141 return 0;
1142}
1143
1144static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1145{
1146 struct sd *sd = (struct sd *) gspca_dev;
1147
1148 *val = sd->red_balance;
1149 return 0;
1150}
1151
1152
1153
1154static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1155{
1156 struct sd *sd = (struct sd *) gspca_dev;
1157
1158 sd->global_gain = val;
1159 if (gspca_dev->streaming)
1160 setglobalgain(gspca_dev);
1161
1162 return 0;
1163}
1164
1165static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1166{
1167 struct sd *sd = (struct sd *) gspca_dev;
1168
1169 *val = sd->global_gain;
1170 return 0;
1171}
1172
6a7eba24
JFM
1173static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1174{
1175 struct sd *sd = (struct sd *) gspca_dev;
1176
1177 sd->brightness = val;
1178 if (gspca_dev->streaming)
1179 setbrightness(gspca_dev);
1180 return 0;
1181}
1182
1183static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1184{
1185 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1186
6a7eba24
JFM
1187 *val = sd->brightness;
1188 return *val;
1189}
1190
cd8955b8 1191static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
6a7eba24
JFM
1192{
1193 struct sd *sd = (struct sd *) gspca_dev;
1194
cd8955b8 1195 sd->awb = val;
6a7eba24 1196 if (gspca_dev->streaming)
cd8955b8 1197 setawb(gspca_dev);
6a7eba24
JFM
1198 return 0;
1199}
1200
cd8955b8 1201static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
6a7eba24
JFM
1202{
1203 struct sd *sd = (struct sd *) gspca_dev;
1204
cd8955b8 1205 *val = sd->awb;
6a7eba24
JFM
1206 return *val;
1207}
1208
cd8955b8 1209static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
6a7eba24
JFM
1210{
1211 struct sd *sd = (struct sd *) gspca_dev;
1212
1213 sd->mirror = val;
1214 if (gspca_dev->streaming)
cd8955b8 1215 setmirror(gspca_dev);
6a7eba24
JFM
1216 return 0;
1217}
1218
cd8955b8 1219static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
6a7eba24
JFM
1220{
1221 struct sd *sd = (struct sd *) gspca_dev;
1222
1223 *val = sd->mirror;
1224 return *val;
1225}
1226
1227static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1228{
1229 struct sd *sd = (struct sd *) gspca_dev;
1230
1231 sd->effect = val;
1232 if (gspca_dev->streaming)
1233 seteffect(gspca_dev);
1234 return 0;
1235}
1236
1237static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1238{
1239 struct sd *sd = (struct sd *) gspca_dev;
1240
1241 *val = sd->effect;
1242 return *val;
1243}
1244
1245static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1246{
1247 struct sd *sd = (struct sd *) gspca_dev;
1248
1249 sd->contrast = val;
1250 if (gspca_dev->streaming)
1251 setcontrast(gspca_dev);
1252 return 0;
1253}
1254
1255static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1256{
1257 struct sd *sd = (struct sd *) gspca_dev;
1258
1259 *val = sd->contrast;
1260 return *val;
1261}
1262
1263static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1264{
1265 struct sd *sd = (struct sd *) gspca_dev;
1266
1267 sd->colors = val;
1268 if (gspca_dev->streaming)
1269 setcolors(gspca_dev);
1270 return 0;
1271}
1272
1273static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1274{
1275 struct sd *sd = (struct sd *) gspca_dev;
1276
1277 *val = sd->colors;
1278 return 0;
1279}
1280
1281static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1282{
1283 struct sd *sd = (struct sd *) gspca_dev;
1284
1285 sd->gamma = val;
1286 if (gspca_dev->streaming)
1287 setgamma(gspca_dev);
1288 return 0;
1289}
1290
1291static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1292{
1293 struct sd *sd = (struct sd *) gspca_dev;
fadc7993 1294
6a7eba24
JFM
1295 *val = sd->gamma;
1296 return 0;
1297}
1298
1299static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1300{
1301 struct sd *sd = (struct sd *) gspca_dev;
1302
1303 sd->freq = val;
1304 if (gspca_dev->streaming)
cd8955b8 1305 setfreq(gspca_dev);
6a7eba24
JFM
1306 return 0;
1307}
1308
1309static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1310{
1311 struct sd *sd = (struct sd *) gspca_dev;
1312
1313 *val = sd->freq;
1314 return 0;
1315}
1316
1317static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1318{
1319 struct sd *sd = (struct sd *) gspca_dev;
1320
1321 sd->sharpness = val;
1322 if (gspca_dev->streaming)
1323 setsharpness(gspca_dev);
1324 return 0;
1325}
1326
1327static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1328{
1329 struct sd *sd = (struct sd *) gspca_dev;
1330
1331 *val = sd->sharpness;
1332 return 0;
1333}
1334
1335/* Low Light set here......*/
1336static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1337{
1338 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
1339
1340 sd->autogain = val;
1341 if (val != 0)
fadc7993 1342 reg_w(gspca_dev, 0xf48e);
6a7eba24 1343 else
fadc7993 1344 reg_w(gspca_dev, 0xb48e);
6a7eba24
JFM
1345 return 0;
1346}
1347
1348static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1349{
1350 struct sd *sd = (struct sd *) gspca_dev;
1351
1352 *val = sd->autogain;
1353 return 0;
1354}
1355
6a7eba24
JFM
1356static int sd_querymenu(struct gspca_dev *gspca_dev,
1357 struct v4l2_querymenu *menu)
1358{
6a7eba24
JFM
1359 switch (menu->id) {
1360 case V4L2_CID_POWER_LINE_FREQUENCY:
1361 switch (menu->index) {
1362 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
a5ae2062 1363 strcpy((char *) menu->name, "50 Hz");
6a7eba24
JFM
1364 return 0;
1365 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
a5ae2062 1366 strcpy((char *) menu->name, "60 Hz");
6a7eba24
JFM
1367 return 0;
1368 }
1369 break;
1370 case V4L2_CID_EFFECTS:
a5ae2062
JFM
1371 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1372 strncpy((char *) menu->name,
cd8955b8
JFM
1373 effects_control[menu->index],
1374 sizeof menu->name);
a5ae2062
JFM
1375 return 0;
1376 }
6a7eba24
JFM
1377 break;
1378 }
a5ae2062 1379 return -EINVAL;
6a7eba24
JFM
1380}
1381
6a7eba24 1382/* sub-driver description */
a5ae2062 1383static const struct sd_desc sd_desc = {
6a7eba24
JFM
1384 .name = MODULE_NAME,
1385 .ctrls = sd_ctrls,
1386 .nctrls = ARRAY_SIZE(sd_ctrls),
1387 .config = sd_config,
012d6b02 1388 .init = sd_init,
6a7eba24 1389 .start = sd_start,
eb229b22 1390 .stopN = sd_stopN,
6a7eba24
JFM
1391 .pkt_scan = sd_pkt_scan,
1392 .querymenu = sd_querymenu,
1393};
1394
1395/* -- module initialisation -- */
a5ae2062 1396static const __devinitdata struct usb_device_id device_table[] = {
9d64fdb1 1397 {USB_DEVICE(0x17a1, 0x0128)},
6a7eba24
JFM
1398 {}
1399};
6a7eba24
JFM
1400MODULE_DEVICE_TABLE(usb, device_table);
1401
1402/* -- device connect -- */
1403static int sd_probe(struct usb_interface *intf,
1404 const struct usb_device_id *id)
1405{
1406 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1407 THIS_MODULE);
1408}
1409
1410static struct usb_driver sd_driver = {
1411 .name = MODULE_NAME,
1412 .id_table = device_table,
1413 .probe = sd_probe,
1414 .disconnect = gspca_disconnect,
6a709749
JFM
1415#ifdef CONFIG_PM
1416 .suspend = gspca_suspend,
1417 .resume = gspca_resume,
1418#endif
6a7eba24
JFM
1419};
1420
1421/* -- module insert / remove -- */
1422static int __init sd_mod_init(void)
1423{
f69e9529
AK
1424 int ret;
1425 ret = usb_register(&sd_driver);
1426 if (ret < 0)
e6b14849 1427 return ret;
10b0e96e 1428 PDEBUG(D_PROBE, "registered");
6a7eba24
JFM
1429 return 0;
1430}
1431static void __exit sd_mod_exit(void)
1432{
1433 usb_deregister(&sd_driver);
1434 PDEBUG(D_PROBE, "deregistered");
1435}
1436
1437module_init(sd_mod_init);
1438module_exit(sd_mod_exit);