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