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