• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/gspca/
1/*
2 * T613 subdriver
3 *
4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 *Notes: * t613  + tas5130A
21 *	* Focus to light do not balance well as in win.
22 *	  Quality in win is not good, but its kinda better.
23 *	 * Fix some "extraneous bytes", most of apps will show the image anyway
24 *	 * Gamma table, is there, but its really doing something?
25 *	 * 7~8 Fps, its ok, max on win its 10.
26 *			Costantino Leandro
27 */
28
29#define MODULE_NAME "t613"
30
31#include <linux/slab.h>
32#include "gspca.h"
33
34#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
35
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
43	u8 brightness;
44	u8 contrast;
45	u8 colors;
46	u8 autogain;
47	u8 gamma;
48	u8 sharpness;
49	u8 freq;
50	u8 red_gain;
51	u8 blue_gain;
52	u8 green_gain;
53	u8 awb; /* set default r/g/b and activate */
54	u8 mirror;
55	u8 effect;
56
57	u8 sensor;
58};
59enum sensors {
60	SENSOR_OM6802,
61	SENSOR_OTHER,
62	SENSOR_TAS5130A,
63	SENSOR_LT168G,		/* must verify if this is the actual model */
64};
65
66/* V4L2 controls supported by the driver */
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);
81
82static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
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);
90
91static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
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
98static const struct ctrl sd_ctrls[] = {
99	{
100	 {
101	  .id = V4L2_CID_BRIGHTNESS,
102	  .type = V4L2_CTRL_TYPE_INTEGER,
103	  .name = "Brightness",
104	  .minimum = 0,
105	  .maximum = 14,
106	  .step = 1,
107#define BRIGHTNESS_DEF 8
108	  .default_value = BRIGHTNESS_DEF,
109	  },
110	 .set = sd_setbrightness,
111	 .get = sd_getbrightness,
112	 },
113	{
114	 {
115	  .id = V4L2_CID_CONTRAST,
116	  .type = V4L2_CTRL_TYPE_INTEGER,
117	  .name = "Contrast",
118	  .minimum = 0,
119	  .maximum = 0x0d,
120	  .step = 1,
121#define CONTRAST_DEF 0x07
122	  .default_value = CONTRAST_DEF,
123	  },
124	 .set = sd_setcontrast,
125	 .get = sd_getcontrast,
126	 },
127	{
128	 {
129	  .id = V4L2_CID_SATURATION,
130	  .type = V4L2_CTRL_TYPE_INTEGER,
131	  .name = "Color",
132	  .minimum = 0,
133	  .maximum = 0x0f,
134	  .step = 1,
135#define COLORS_DEF 0x05
136	  .default_value = COLORS_DEF,
137	  },
138	 .set = sd_setcolors,
139	 .get = sd_getcolors,
140	 },
141#define GAMMA_MAX 16
142#define GAMMA_DEF 10
143	{
144	 {
145	  .id = V4L2_CID_GAMMA,	/* (gamma on win) */
146	  .type = V4L2_CTRL_TYPE_INTEGER,
147	  .name = "Gamma",
148	  .minimum = 0,
149	  .maximum = GAMMA_MAX - 1,
150	  .step = 1,
151	  .default_value = GAMMA_DEF,
152	  },
153	 .set = sd_setgamma,
154	 .get = sd_getgamma,
155	 },
156	{
157	 {
158	  .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
159				 * some apps dont bring up the
160				 * backligth_compensation control) */
161	  .type = V4L2_CTRL_TYPE_INTEGER,
162	  .name = "Low Light",
163	  .minimum = 0,
164	  .maximum = 1,
165	  .step = 1,
166#define AUTOGAIN_DEF 0x01
167	  .default_value = AUTOGAIN_DEF,
168	  },
169	 .set = sd_setlowlight,
170	 .get = sd_getlowlight,
171	 },
172	{
173	 {
174	  .id = V4L2_CID_HFLIP,
175	  .type = V4L2_CTRL_TYPE_BOOLEAN,
176	  .name = "Mirror Image",
177	  .minimum = 0,
178	  .maximum = 1,
179	  .step = 1,
180#define MIRROR_DEF 0
181	  .default_value = MIRROR_DEF,
182	  },
183	 .set = sd_setmirror,
184	 .get = sd_getmirror
185	},
186	{
187	 {
188	  .id = V4L2_CID_POWER_LINE_FREQUENCY,
189	  .type = V4L2_CTRL_TYPE_MENU,
190	  .name = "Light Frequency Filter",
191	  .minimum = 1,		/* 1 -> 0x50, 2->0x60 */
192	  .maximum = 2,
193	  .step = 1,
194#define FREQ_DEF 1
195	  .default_value = FREQ_DEF,
196	  },
197	 .set = sd_setfreq,
198	 .get = sd_getfreq},
199
200	{
201	 {
202	  .id =  V4L2_CID_AUTO_WHITE_BALANCE,
203	  .type = V4L2_CTRL_TYPE_INTEGER,
204	  .name = "Auto White Balance",
205	  .minimum = 0,
206	  .maximum = 1,
207	  .step = 1,
208#define AWB_DEF 0
209	  .default_value = AWB_DEF,
210	  },
211	 .set = sd_setawb,
212	 .get = sd_getawb
213	},
214	{
215	 {
216	  .id = V4L2_CID_SHARPNESS,
217	  .type = V4L2_CTRL_TYPE_INTEGER,
218	  .name = "Sharpness",
219	  .minimum = 0,
220	  .maximum = 15,
221	  .step = 1,
222#define SHARPNESS_DEF 0x06
223	  .default_value = SHARPNESS_DEF,
224	  },
225	 .set = sd_setsharpness,
226	 .get = sd_getsharpness,
227	 },
228	{
229	 {
230	  .id = V4L2_CID_EFFECTS,
231	  .type = V4L2_CTRL_TYPE_MENU,
232	  .name = "Webcam Effects",
233	  .minimum = 0,
234	  .maximum = 4,
235	  .step = 1,
236#define EFFECTS_DEF 0
237	  .default_value = EFFECTS_DEF,
238	  },
239	 .set = sd_seteffect,
240	 .get = sd_geteffect
241	},
242	{
243	 {
244	    .id      = V4L2_CID_BLUE_BALANCE,
245	    .type    = V4L2_CTRL_TYPE_INTEGER,
246	    .name    = "Blue Balance",
247	    .minimum = 0x10,
248	    .maximum = 0x40,
249	    .step    = 1,
250#define BLUE_GAIN_DEF 0x20
251	    .default_value = BLUE_GAIN_DEF,
252	 },
253	.set = sd_setblue_gain,
254	.get = sd_getblue_gain,
255	},
256	{
257	 {
258	    .id      = V4L2_CID_RED_BALANCE,
259	    .type    = V4L2_CTRL_TYPE_INTEGER,
260	    .name    = "Red Balance",
261	    .minimum = 0x10,
262	    .maximum = 0x40,
263	    .step    = 1,
264#define RED_GAIN_DEF 0x20
265	    .default_value = RED_GAIN_DEF,
266	 },
267	.set = sd_setred_gain,
268	.get = sd_getred_gain,
269	},
270	{
271	 {
272	    .id      = V4L2_CID_GAIN,
273	    .type    = V4L2_CTRL_TYPE_INTEGER,
274	    .name    = "Gain",
275	    .minimum = 0x10,
276	    .maximum = 0x40,
277	    .step    = 1,
278#define GAIN_DEF  0x20
279	    .default_value = GAIN_DEF,
280	 },
281	.set = sd_setgain,
282	.get = sd_getgain,
283	},
284};
285
286static const struct v4l2_pix_format vga_mode_t16[] = {
287	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
288		.bytesperline = 160,
289		.sizeimage = 160 * 120 * 4 / 8 + 590,
290		.colorspace = V4L2_COLORSPACE_JPEG,
291		.priv = 4},
292	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
293		.bytesperline = 176,
294		.sizeimage = 176 * 144 * 3 / 8 + 590,
295		.colorspace = V4L2_COLORSPACE_JPEG,
296		.priv = 3},
297	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
298		.bytesperline = 320,
299		.sizeimage = 320 * 240 * 3 / 8 + 590,
300		.colorspace = V4L2_COLORSPACE_JPEG,
301		.priv = 2},
302	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
303		.bytesperline = 352,
304		.sizeimage = 352 * 288 * 3 / 8 + 590,
305		.colorspace = V4L2_COLORSPACE_JPEG,
306		.priv = 1},
307	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
308		.bytesperline = 640,
309		.sizeimage = 640 * 480 * 3 / 8 + 590,
310		.colorspace = V4L2_COLORSPACE_JPEG,
311		.priv = 0},
312};
313
314/* sensor specific data */
315struct additional_sensor_data {
316	const u8 n3[6];
317	const u8 *n4, n4sz;
318	const u8 reg80, reg8e;
319	const u8 nset8[6];
320	const u8 data1[10];
321	const u8 data2[9];
322	const u8 data3[9];
323	const u8 data5[6];
324	const u8 stream[4];
325};
326
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};
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};
368
369static const struct additional_sensor_data sensor_data[] = {
370[SENSOR_OM6802] = {
371	.n3 =
372		{0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
373	.n4 = n4_om6802,
374	.n4sz = sizeof n4_om6802,
375	.reg80 = 0x3c,
376	.reg8e = 0x33,
377	.nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
378	.data1 =
379		{0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
380		 0xb3, 0xfc},
381	.data2 =
382		{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
383		 0xff},
384	.data3 =
385		{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
386		 0xff},
387	.data5 =	/* this could be removed later */
388		{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
389	.stream =
390		{0x0b, 0x04, 0x0a, 0x78},
391    },
392[SENSOR_OTHER] = {
393	.n3 =
394		{0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
395	.n4 = n4_other,
396	.n4sz = sizeof n4_other,
397	.reg80 = 0xac,
398	.reg8e = 0xb8,
399	.nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
400	.data1 =
401		{0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
402		 0xe8, 0xfc},
403	.data2 =
404		{0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
405		 0xd9},
406	.data3 =
407		{0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
408		 0xd9},
409	.data5 =
410		{0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
411	.stream =
412		{0x0b, 0x04, 0x0a, 0x00},
413    },
414[SENSOR_TAS5130A] = {
415	.n3 =
416		{0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
417	.n4 = n4_tas5130a,
418	.n4sz = sizeof n4_tas5130a,
419	.reg80 = 0x3c,
420	.reg8e = 0xb4,
421	.nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
422	.data1 =
423		{0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
424		 0xc8, 0xfc},
425	.data2 =
426		{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
427		 0xe0},
428	.data3 =
429		{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
430		 0xe0},
431	.data5 =
432		{0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
433	.stream =
434		{0x0b, 0x04, 0x0a, 0x40},
435    },
436[SENSOR_LT168G] = {
437	.n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
438	.n4 = n4_lt168g,
439	.n4sz = sizeof n4_lt168g,
440	.reg80 = 0x7c,
441	.reg8e = 0xb3,
442	.nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
443	.data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
444		 0xb0, 0xf4},
445	.data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446		 0xff},
447	.data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
448		 0xff},
449	.data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
450	.stream = {0x0b, 0x04, 0x0a, 0x28},
451    },
452};
453
454#define MAX_EFFECTS 7
455/* easily done by soft, this table could be removed,
456 * i keep it here just in case */
457static char *effects_control[MAX_EFFECTS] = {
458	"Normal",
459	"Emboss",		/* disabled */
460	"Monochrome",
461	"Sepia",
462	"Sketch",
463	"Sun Effect",		/* disabled */
464	"Negative",
465};
466static const u8 effects_table[MAX_EFFECTS][6] = {
467	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},	/* Normal */
468	{0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},	/* Repujar */
469	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},	/* Monochrome */
470	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},	/* Sepia */
471	{0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},	/* Croquis */
472	{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},	/* Sun Effect */
473	{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},	/* Negative */
474};
475
476static const u8 gamma_table[GAMMA_MAX][17] = {
477/* gamma table from cam1690.ini */
478	{0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,	/* 0 */
479	 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
480	 0xff},
481	{0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,	/* 1 */
482	 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
483	 0xff},
484	{0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,	/* 2 */
485	 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
486	 0xff},
487	{0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,	/* 3 */
488	 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
489	 0xff},
490	{0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a,	/* 4 */
491	 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
492	 0xff},
493	{0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,	/* 5 */
494	 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
495	 0xff},
496	{0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,	/* 6 */
497	 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
498	 0xff},
499	{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,	/* 7 */
500	 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
501	 0xff},
502	{0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,	/* 8 */
503	 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
504	 0xff},
505	{0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,	/* 9 */
506	 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
507	 0xff},
508	{0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,	/* 10 */
509	 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
510	 0xff},
511	{0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,	/* 11 */
512	 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
513	 0xff},
514	{0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,	/* 12 */
515	 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
516	 0xff},
517	{0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,	/* 13 */
518	 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
519	 0xff},
520	{0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,	/* 14 */
521	 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
522	 0xff},
523	{0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,	/* 15 */
524	 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
525	 0xff}
526};
527
528static const u8 tas5130a_sensor_init[][8] = {
529	{0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
530	{0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
531	{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
532};
533
534static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
535
536/* read 1 byte */
537static u8 reg_r(struct gspca_dev *gspca_dev,
538		   u16 index)
539{
540	usb_control_msg(gspca_dev->dev,
541			usb_rcvctrlpipe(gspca_dev->dev, 0),
542			0,		/* request */
543			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
544			0,		/* value */
545			index,
546			gspca_dev->usb_buf, 1, 500);
547	return gspca_dev->usb_buf[0];
548}
549
550static void reg_w(struct gspca_dev *gspca_dev,
551		  u16 index)
552{
553	usb_control_msg(gspca_dev->dev,
554			usb_sndctrlpipe(gspca_dev->dev, 0),
555			0,
556			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
557			0, index,
558			NULL, 0, 500);
559}
560
561static void reg_w_buf(struct gspca_dev *gspca_dev,
562		  const u8 *buffer, u16 len)
563{
564	if (len <= USB_BUF_SZ) {
565		memcpy(gspca_dev->usb_buf, buffer, len);
566		usb_control_msg(gspca_dev->dev,
567				usb_sndctrlpipe(gspca_dev->dev, 0),
568				0,
569			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
570				0x01, 0,
571				gspca_dev->usb_buf, len, 500);
572	} else {
573		u8 *tmpbuf;
574
575		tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
576		if (!tmpbuf) {
577			err("Out of memory");
578			return;
579		}
580		usb_control_msg(gspca_dev->dev,
581				usb_sndctrlpipe(gspca_dev->dev, 0),
582				0,
583			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
584				0x01, 0,
585				tmpbuf, len, 500);
586		kfree(tmpbuf);
587	}
588}
589
590/* write values to consecutive registers */
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
598	if (len * 2 <= USB_BUF_SZ) {
599		p = tmpbuf = gspca_dev->usb_buf;
600	} else {
601		p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
602		if (!tmpbuf) {
603			err("Out of memory");
604			return;
605		}
606	}
607	i = len;
608	while (--i >= 0) {
609		*p++ = reg++;
610		*p++ = *buffer++;
611	}
612	usb_control_msg(gspca_dev->dev,
613			usb_sndctrlpipe(gspca_dev->dev, 0),
614			0,
615			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
616			0x01, 0,
617			tmpbuf, len * 2, 500);
618	if (len * 2 > USB_BUF_SZ)
619		kfree(tmpbuf);
620}
621
622static void om6802_sensor_init(struct gspca_dev *gspca_dev)
623{
624	int i;
625	const u8 *p;
626	u8 byte;
627	u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
628	static const u8 sensor_init[] = {
629		0xdf, 0x6d,
630		0xdd, 0x18,
631		0x5a, 0xe0,
632		0x5c, 0x07,
633		0x5d, 0xb0,
634		0x5e, 0x1e,
635		0x60, 0x71,
636		0xef, 0x00,
637		0xe9, 0x00,
638		0xea, 0x00,
639		0x90, 0x24,
640		0x91, 0xb2,
641		0x82, 0x32,
642		0xfd, 0x41,
643		0x00			/* table end */
644	};
645
646	reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
647	msleep(100);
648	i = 4;
649	while (--i > 0) {
650		byte = reg_r(gspca_dev, 0x0060);
651		if (!(byte & 0x01))
652			break;
653		msleep(100);
654	}
655	byte = reg_r(gspca_dev, 0x0063);
656	if (byte != 0x17) {
657		err("Bad sensor reset %02x", byte);
658		/* continue? */
659	}
660
661	p = sensor_init;
662	while (*p != 0) {
663		val[1] = *p++;
664		val[3] = *p++;
665		if (*p == 0)
666			reg_w(gspca_dev, 0x3c80);
667		reg_w_buf(gspca_dev, val, sizeof val);
668		i = 4;
669		while (--i >= 0) {
670			msleep(15);
671			byte = reg_r(gspca_dev, 0x60);
672			if (!(byte & 0x01))
673				break;
674		}
675	}
676	msleep(15);
677	reg_w(gspca_dev, 0x3c80);
678}
679
680/* this function is called at probe time */
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;
688
689	cam->cam_mode = vga_mode_t16;
690	cam->nmodes = ARRAY_SIZE(vga_mode_t16);
691
692	sd->brightness = BRIGHTNESS_DEF;
693	sd->contrast = CONTRAST_DEF;
694	sd->colors = COLORS_DEF;
695	sd->gamma = GAMMA_DEF;
696	sd->autogain = AUTOGAIN_DEF;
697	sd->mirror = MIRROR_DEF;
698	sd->freq = FREQ_DEF;
699	sd->awb = AWB_DEF;
700	sd->sharpness = SHARPNESS_DEF;
701	sd->effect = EFFECTS_DEF;
702	sd->red_gain = RED_GAIN_DEF;
703	sd->blue_gain = BLUE_GAIN_DEF;
704	sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
705
706	return 0;
707}
708
709static void setbrightness(struct gspca_dev *gspca_dev)
710{
711	struct sd *sd = (struct sd *) gspca_dev;
712	unsigned int brightness;
713	u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
714
715	brightness = sd->brightness;
716	if (brightness < 7) {
717		set6[1] = 0x26;
718		set6[3] = 0x70 - brightness * 0x10;
719	} else {
720		set6[3] = 0x00 + ((brightness - 7) * 0x10);
721	}
722
723	reg_w_buf(gspca_dev, set6, sizeof set6);
724}
725
726static void setcontrast(struct gspca_dev *gspca_dev)
727{
728	struct sd *sd = (struct sd *) gspca_dev;
729	unsigned int contrast = sd->contrast;
730	u16 reg_to_write;
731
732	if (contrast < 7)
733		reg_to_write = 0x8ea9 - contrast * 0x200;
734	else
735		reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
736
737	reg_w(gspca_dev, reg_to_write);
738}
739
740static void setcolors(struct gspca_dev *gspca_dev)
741{
742	struct sd *sd = (struct sd *) gspca_dev;
743	u16 reg_to_write;
744
745	reg_to_write = 0x80bb + sd->colors * 0x100;	/* was 0xc0 */
746	reg_w(gspca_dev, reg_to_write);
747}
748
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);
754	reg_w_ixbuf(gspca_dev, 0x90,
755		gamma_table[sd->gamma], sizeof gamma_table[0]);
756}
757
758static void setRGB(struct gspca_dev *gspca_dev)
759{
760	struct sd *sd = (struct sd *) gspca_dev;
761	u8 all_gain_reg[6] =
762		{0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
763
764	all_gain_reg[1] = sd->red_gain;
765	all_gain_reg[3] = sd->blue_gain;
766	all_gain_reg[5] = sd->green_gain;
767	reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
768}
769
770/* Generic fnc for r/b balance, exposure and awb */
771static void setawb(struct gspca_dev *gspca_dev)
772{
773	struct sd *sd = (struct sd *) gspca_dev;
774	u16 reg80;
775
776	reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
777
778	/* on awb leave defaults values */
779	if (!sd->awb) {
780		/* shoud we wait here.. */
781		/* update and reset RGB gains with webcam values */
782		sd->red_gain = reg_r(gspca_dev, 0x0087);
783		sd->blue_gain = reg_r(gspca_dev, 0x0088);
784		sd->green_gain = reg_r(gspca_dev, 0x0089);
785		reg80 &= ~0x0400;		/* AWB off */
786	}
787	reg_w(gspca_dev, reg80);
788	reg_w(gspca_dev, reg80);
789}
790
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);
810}
811
812static void setsharpness(struct gspca_dev *gspca_dev)
813{
814	struct sd *sd = (struct sd *) gspca_dev;
815	u16 reg_to_write;
816
817	reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
818
819	reg_w(gspca_dev, reg_to_write);
820}
821
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
854/* this function is called at probe and resume time */
855static int sd_init(struct gspca_dev *gspca_dev)
856{
857	/* some of this registers are not really neded, because
858	 * they are overriden by setbrigthness, setcontrast, etc,
859	 * but wont hurt anyway, and can help someone with similar webcam
860	 * to see the initial parameters.*/
861	struct sd *sd = (struct sd *) gspca_dev;
862	const struct additional_sensor_data *sensor;
863	int i;
864	u16 sensor_id;
865	u8 test_byte = 0;
866
867	static const u8 read_indexs[] =
868		{ 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
869		  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
870	static const u8 n1[] =
871			{0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
872	static const u8 n2[] =
873			{0x08, 0x00};
874
875	sensor_id = (reg_r(gspca_dev, 0x06) << 8)
876			| reg_r(gspca_dev, 0x07);
877	switch (sensor_id & 0xff0f) {
878	case 0x0801:
879		PDEBUG(D_PROBE, "sensor tas5130a");
880		sd->sensor = SENSOR_TAS5130A;
881		break;
882	case 0x0802:
883		PDEBUG(D_PROBE, "sensor lt168g");
884		sd->sensor = SENSOR_LT168G;
885		break;
886	case 0x0803:
887		PDEBUG(D_PROBE, "sensor 'other'");
888		sd->sensor = SENSOR_OTHER;
889		break;
890	case 0x0807:
891		PDEBUG(D_PROBE, "sensor om6802");
892		sd->sensor = SENSOR_OM6802;
893		break;
894	default:
895		PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
896		return -EINVAL;
897	}
898
899	if (sd->sensor == SENSOR_OM6802) {
900		reg_w_buf(gspca_dev, n1, sizeof n1);
901		i = 5;
902		while (--i >= 0) {
903			reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
904			test_byte = reg_r(gspca_dev, 0x0063);
905			msleep(100);
906			if (test_byte == 0x17)
907				break;		/* OK */
908		}
909		if (i < 0) {
910			err("Bad sensor reset %02x", test_byte);
911			return -EIO;
912		}
913		reg_w_buf(gspca_dev, n2, sizeof n2);
914	}
915
916	i = 0;
917	while (read_indexs[i] != 0x00) {
918		test_byte = reg_r(gspca_dev, read_indexs[i]);
919		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
920		       test_byte);
921		i++;
922	}
923
924	sensor = &sensor_data[sd->sensor];
925	reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
926	reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
927
928	if (sd->sensor == SENSOR_LT168G) {
929		test_byte = reg_r(gspca_dev, 0x80);
930		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
931		       test_byte);
932		reg_w(gspca_dev, 0x6c80);
933	}
934
935	reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
936	reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
937	reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
938
939	reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
940	reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
941	reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
942
943	setbrightness(gspca_dev);
944	setcontrast(gspca_dev);
945	setgamma(gspca_dev);
946	setcolors(gspca_dev);
947	setsharpness(gspca_dev);
948	init_gains(gspca_dev);
949	setfreq(gspca_dev);
950
951	reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
952	reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
953	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
954
955	if (sd->sensor == SENSOR_LT168G) {
956		test_byte = reg_r(gspca_dev, 0x80);
957		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
958		       test_byte);
959		reg_w(gspca_dev, 0x6c80);
960	}
961
962	reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
963	reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
964	reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
965
966	return 0;
967}
968
969static void setmirror(struct gspca_dev *gspca_dev)
970{
971	struct sd *sd = (struct sd *) gspca_dev;
972	u8 hflipcmd[8] =
973		{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
974
975	if (sd->mirror)
976		hflipcmd[3] = 0x01;
977
978	reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
979}
980
981static void seteffect(struct gspca_dev *gspca_dev)
982{
983	struct sd *sd = (struct sd *) gspca_dev;
984
985	reg_w_buf(gspca_dev, effects_table[sd->effect],
986				sizeof effects_table[0]);
987	if (sd->effect == 1 || sd->effect == 5) {
988		PDEBUG(D_CONF,
989		       "This effect have been disabled for webcam \"safety\"");
990		return;
991	}
992
993	if (sd->effect == 1 || sd->effect == 4)
994		reg_w(gspca_dev, 0x4aa6);
995	else
996		reg_w(gspca_dev, 0xfaa6);
997}
998
999/* Is this really needed?
1000 * i added some module parameters for test with some users */
1001static void poll_sensor(struct gspca_dev *gspca_dev)
1002{
1003	static const u8 poll1[] =
1004		{0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1005		 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1006		 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1007		 0x60, 0x14};
1008	static const u8 poll2[] =
1009		{0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1010		 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1011	static const u8 noise03[] =	/* (some differences / ms-drv) */
1012		{0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1013		 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1014		 0xc2, 0x80, 0xc3, 0x10};
1015
1016	PDEBUG(D_STREAM, "[Sensor requires polling]");
1017	reg_w_buf(gspca_dev, poll1, sizeof poll1);
1018	reg_w_buf(gspca_dev, poll2, sizeof poll2);
1019	reg_w_buf(gspca_dev, noise03, sizeof noise03);
1020}
1021
1022static int sd_start(struct gspca_dev *gspca_dev)
1023{
1024	struct sd *sd = (struct sd *) gspca_dev;
1025	const struct additional_sensor_data *sensor;
1026	int i, mode;
1027	u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1028	static const u8 t3[] =
1029		{ 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1030
1031	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1032	switch (mode) {
1033	case 0:		/* 640x480 (0x00) */
1034		break;
1035	case 1:		/* 352x288 */
1036		t2[1] = 0x40;
1037		break;
1038	case 2:		/* 320x240 */
1039		t2[1] = 0x10;
1040		break;
1041	case 3:		/* 176x144 */
1042		t2[1] = 0x50;
1043		break;
1044	default:
1045/*	case 4:		 * 160x120 */
1046		t2[1] = 0x20;
1047		break;
1048	}
1049
1050	switch (sd->sensor) {
1051	case SENSOR_OM6802:
1052		om6802_sensor_init(gspca_dev);
1053		break;
1054	case SENSOR_TAS5130A:
1055		i = 0;
1056		for (;;) {
1057			reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1058					 sizeof tas5130a_sensor_init[0]);
1059			if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1060				break;
1061			i++;
1062		}
1063		reg_w(gspca_dev, 0x3c80);
1064		/* just in case and to keep sync with logs (for mine) */
1065		reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1066				 sizeof tas5130a_sensor_init[0]);
1067		reg_w(gspca_dev, 0x3c80);
1068		break;
1069	}
1070	sensor = &sensor_data[sd->sensor];
1071	setfreq(gspca_dev);
1072	reg_r(gspca_dev, 0x0012);
1073	reg_w_buf(gspca_dev, t2, sizeof t2);
1074	reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1075	reg_w(gspca_dev, 0x0013);
1076	msleep(15);
1077	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1078	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1079
1080	if (sd->sensor == SENSOR_OM6802)
1081		poll_sensor(gspca_dev);
1082
1083	return 0;
1084}
1085
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);
1092	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1093			sizeof sensor_data[sd->sensor].stream);
1094	if (sd->sensor == SENSOR_OM6802) {
1095		msleep(20);
1096		reg_w(gspca_dev, 0x0309);
1097	}
1098}
1099
1100static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1101			u8 *data,			/* isoc packet */
1102			int len)			/* iso packet length */
1103{
1104	int pkt_type;
1105
1106	if (data[0] == 0x5a) {
1107		/* Control Packet, after this came the header again,
1108		 * but extra bytes came in the packet before this,
1109		 * sometimes an EOF arrives, sometimes not... */
1110		return;
1111	}
1112	data += 2;
1113	len -= 2;
1114	if (data[0] == 0xff && data[1] == 0xd8)
1115		pkt_type = FIRST_PACKET;
1116	else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1117		pkt_type = LAST_PACKET;
1118	else
1119		pkt_type = INTER_PACKET;
1120	gspca_frame_add(gspca_dev, pkt_type, data, len);
1121}
1122
1123static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1124{
1125	struct sd *sd = (struct sd *) gspca_dev;
1126
1127	sd->blue_gain = val;
1128	if (gspca_dev->streaming)
1129		reg_w(gspca_dev, (val << 8) + 0x88);
1130	return 0;
1131}
1132
1133static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1134{
1135	struct sd *sd = (struct sd *) gspca_dev;
1136
1137	*val = sd->blue_gain;
1138	return 0;
1139}
1140
1141static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1142{
1143	struct sd *sd = (struct sd *) gspca_dev;
1144
1145	sd->red_gain = val;
1146	if (gspca_dev->streaming)
1147		reg_w(gspca_dev, (val << 8) + 0x87);
1148
1149	return 0;
1150}
1151
1152static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1153{
1154	struct sd *sd = (struct sd *) gspca_dev;
1155
1156	*val = sd->red_gain;
1157	return 0;
1158}
1159
1160static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1161{
1162	struct sd *sd = (struct sd *) gspca_dev;
1163	u16 psg, nsg;
1164
1165	psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1166	nsg = val * 3;
1167	sd->red_gain = sd->red_gain * nsg / psg;
1168	if (sd->red_gain > 0x40)
1169		sd->red_gain = 0x40;
1170	else if (sd->red_gain < 0x10)
1171		sd->red_gain = 0x10;
1172	sd->blue_gain = sd->blue_gain * nsg / psg;
1173	if (sd->blue_gain > 0x40)
1174		sd->blue_gain = 0x40;
1175	else if (sd->blue_gain < 0x10)
1176		sd->blue_gain = 0x10;
1177	sd->green_gain = sd->green_gain * nsg / psg;
1178	if (sd->green_gain > 0x40)
1179		sd->green_gain = 0x40;
1180	else if (sd->green_gain < 0x10)
1181		sd->green_gain = 0x10;
1182
1183	if (gspca_dev->streaming)
1184		setRGB(gspca_dev);
1185	return 0;
1186}
1187
1188static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1189{
1190	struct sd *sd = (struct sd *) gspca_dev;
1191
1192	*val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1193	return 0;
1194}
1195
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;
1209
1210	*val = sd->brightness;
1211	return *val;
1212}
1213
1214static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1215{
1216	struct sd *sd = (struct sd *) gspca_dev;
1217
1218	sd->awb = val;
1219	if (gspca_dev->streaming)
1220		setawb(gspca_dev);
1221	return 0;
1222}
1223
1224static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1225{
1226	struct sd *sd = (struct sd *) gspca_dev;
1227
1228	*val = sd->awb;
1229	return *val;
1230}
1231
1232static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1233{
1234	struct sd *sd = (struct sd *) gspca_dev;
1235
1236	sd->mirror = val;
1237	if (gspca_dev->streaming)
1238		setmirror(gspca_dev);
1239	return 0;
1240}
1241
1242static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1243{
1244	struct sd *sd = (struct sd *) gspca_dev;
1245
1246	*val = sd->mirror;
1247	return *val;
1248}
1249
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;
1317
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)
1328		setfreq(gspca_dev);
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;
1362
1363	sd->autogain = val;
1364	if (val != 0)
1365		reg_w(gspca_dev, 0xf48e);
1366	else
1367		reg_w(gspca_dev, 0xb48e);
1368	return 0;
1369}
1370
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
1379static int sd_querymenu(struct gspca_dev *gspca_dev,
1380			struct v4l2_querymenu *menu)
1381{
1382	switch (menu->id) {
1383	case V4L2_CID_POWER_LINE_FREQUENCY:
1384		switch (menu->index) {
1385		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1386			strcpy((char *) menu->name, "50 Hz");
1387			return 0;
1388		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1389			strcpy((char *) menu->name, "60 Hz");
1390			return 0;
1391		}
1392		break;
1393	case V4L2_CID_EFFECTS:
1394		if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1395			strncpy((char *) menu->name,
1396				effects_control[menu->index],
1397				sizeof menu->name);
1398			return 0;
1399		}
1400		break;
1401	}
1402	return -EINVAL;
1403}
1404
1405/* sub-driver description */
1406static const struct sd_desc sd_desc = {
1407	.name = MODULE_NAME,
1408	.ctrls = sd_ctrls,
1409	.nctrls = ARRAY_SIZE(sd_ctrls),
1410	.config = sd_config,
1411	.init = sd_init,
1412	.start = sd_start,
1413	.stopN = sd_stopN,
1414	.pkt_scan = sd_pkt_scan,
1415	.querymenu = sd_querymenu,
1416};
1417
1418/* -- module initialisation -- */
1419static const __devinitdata struct usb_device_id device_table[] = {
1420	{USB_DEVICE(0x17a1, 0x0128)},
1421	{}
1422};
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,
1438#ifdef CONFIG_PM
1439	.suspend = gspca_suspend,
1440	.resume = gspca_resume,
1441#endif
1442};
1443
1444/* -- module insert / remove -- */
1445static int __init sd_mod_init(void)
1446{
1447	int ret;
1448	ret = usb_register(&sd_driver);
1449	if (ret < 0)
1450		return ret;
1451	PDEBUG(D_PROBE, "registered");
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);
1462