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 
36 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
37 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
38 MODULE_LICENSE("GPL");
39 
40 struct 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 };
59 enum 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 */
67 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
78 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
79 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
81 
82 static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
90 
91 static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92 static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
93 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
94 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
95 static int sd_querymenu(struct gspca_dev *gspca_dev,
96 			struct v4l2_querymenu *menu);
97 
98 static 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 
286 static 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 */
315 struct 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 
327 static 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 };
338 static 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 };
348 static 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 };
357 static 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 
369 static 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 */
457 static char *effects_control[MAX_EFFECTS] = {
458 	"Normal",
459 	"Emboss",		/* disabled */
460 	"Monochrome",
461 	"Sepia",
462 	"Sketch",
463 	"Sun Effect",		/* disabled */
464 	"Negative",
465 };
466 static 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 
476 static 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 
528 static 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 
534 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
535 
536 /* read 1 byte */
reg_r(struct gspca_dev * gspca_dev,u16 index)537 static 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 
reg_w(struct gspca_dev * gspca_dev,u16 index)550 static 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 
reg_w_buf(struct gspca_dev * gspca_dev,const u8 * buffer,u16 len)561 static 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 */
reg_w_ixbuf(struct gspca_dev * gspca_dev,u8 reg,const u8 * buffer,u16 len)591 static 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 
om6802_sensor_init(struct gspca_dev * gspca_dev)622 static 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 */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)681 static 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 
setbrightness(struct gspca_dev * gspca_dev)709 static 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 
setcontrast(struct gspca_dev * gspca_dev)726 static 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 
setcolors(struct gspca_dev * gspca_dev)740 static 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 
setgamma(struct gspca_dev * gspca_dev)749 static 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 
setRGB(struct gspca_dev * gspca_dev)758 static 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 */
setawb(struct gspca_dev * gspca_dev)771 static 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 
init_gains(struct gspca_dev * gspca_dev)791 static 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 
setsharpness(struct gspca_dev * gspca_dev)812 static 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 
setfreq(struct gspca_dev * gspca_dev)822 static 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 */
sd_init(struct gspca_dev * gspca_dev)855 static 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 		err("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 
setmirror(struct gspca_dev * gspca_dev)969 static 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 
seteffect(struct gspca_dev * gspca_dev)981 static 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 */
poll_sensor(struct gspca_dev * gspca_dev)1001 static 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 
sd_start(struct gspca_dev * gspca_dev)1022 static 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 
sd_stopN(struct gspca_dev * gspca_dev)1086 static 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 
sd_pkt_scan(struct gspca_dev * gspca_dev,u8 * data,int len)1100 static 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 
sd_setblue_gain(struct gspca_dev * gspca_dev,__s32 val)1123 static 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 
sd_getblue_gain(struct gspca_dev * gspca_dev,__s32 * val)1133 static 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 
sd_setred_gain(struct gspca_dev * gspca_dev,__s32 val)1141 static 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 
sd_getred_gain(struct gspca_dev * gspca_dev,__s32 * val)1152 static 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 
sd_setgain(struct gspca_dev * gspca_dev,__s32 val)1160 static 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 
sd_getgain(struct gspca_dev * gspca_dev,__s32 * val)1188 static 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 
sd_setbrightness(struct gspca_dev * gspca_dev,__s32 val)1196 static 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 
sd_getbrightness(struct gspca_dev * gspca_dev,__s32 * val)1206 static 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 
sd_setawb(struct gspca_dev * gspca_dev,__s32 val)1214 static 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 
sd_getawb(struct gspca_dev * gspca_dev,__s32 * val)1224 static 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 
sd_setmirror(struct gspca_dev * gspca_dev,__s32 val)1232 static 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 
sd_getmirror(struct gspca_dev * gspca_dev,__s32 * val)1242 static 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 
sd_seteffect(struct gspca_dev * gspca_dev,__s32 val)1250 static 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 
sd_geteffect(struct gspca_dev * gspca_dev,__s32 * val)1260 static 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 
sd_setcontrast(struct gspca_dev * gspca_dev,__s32 val)1268 static 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 
sd_getcontrast(struct gspca_dev * gspca_dev,__s32 * val)1278 static 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 
sd_setcolors(struct gspca_dev * gspca_dev,__s32 val)1286 static 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 
sd_getcolors(struct gspca_dev * gspca_dev,__s32 * val)1296 static 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 
sd_setgamma(struct gspca_dev * gspca_dev,__s32 val)1304 static 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 
sd_getgamma(struct gspca_dev * gspca_dev,__s32 * val)1314 static 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 
sd_setfreq(struct gspca_dev * gspca_dev,__s32 val)1322 static 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 
sd_getfreq(struct gspca_dev * gspca_dev,__s32 * val)1332 static 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 
sd_setsharpness(struct gspca_dev * gspca_dev,__s32 val)1340 static 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 
sd_getsharpness(struct gspca_dev * gspca_dev,__s32 * val)1350 static 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......*/
sd_setlowlight(struct gspca_dev * gspca_dev,__s32 val)1359 static 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 
sd_getlowlight(struct gspca_dev * gspca_dev,__s32 * val)1371 static 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 
sd_querymenu(struct gspca_dev * gspca_dev,struct v4l2_querymenu * menu)1379 static 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 */
1406 static 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 -- */
1419 static const struct usb_device_id device_table[] = {
1420 	{USB_DEVICE(0x17a1, 0x0128)},
1421 	{}
1422 };
1423 MODULE_DEVICE_TABLE(usb, device_table);
1424 
1425 /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)1426 static 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 
1433 static 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 -- */
sd_mod_init(void)1445 static int __init sd_mod_init(void)
1446 {
1447 	return usb_register(&sd_driver);
1448 }
sd_mod_exit(void)1449 static void __exit sd_mod_exit(void)
1450 {
1451 	usb_deregister(&sd_driver);
1452 }
1453 
1454 module_init(sd_mod_init);
1455 module_exit(sd_mod_exit);
1456