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