Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/stk014.c
17628 views
1
/*
2
* Syntek DV4000 (STK014) subdriver
3
*
4
* Copyright (C) 2008 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
21
#define MODULE_NAME "stk014"
22
23
#include "gspca.h"
24
#include "jpeg.h"
25
26
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
27
MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
28
MODULE_LICENSE("GPL");
29
30
/* controls */
31
enum e_ctrl {
32
BRIGHTNESS,
33
CONTRAST,
34
COLORS,
35
LIGHTFREQ,
36
NCTRLS /* number of controls */
37
};
38
39
/* specific webcam descriptor */
40
struct sd {
41
struct gspca_dev gspca_dev; /* !! must be the first item */
42
43
struct gspca_ctrl ctrls[NCTRLS];
44
45
u8 quality;
46
#define QUALITY_MIN 70
47
#define QUALITY_MAX 95
48
#define QUALITY_DEF 88
49
50
u8 jpeg_hdr[JPEG_HDR_SZ];
51
};
52
53
/* V4L2 controls supported by the driver */
54
static void setbrightness(struct gspca_dev *gspca_dev);
55
static void setcontrast(struct gspca_dev *gspca_dev);
56
static void setcolors(struct gspca_dev *gspca_dev);
57
static void setlightfreq(struct gspca_dev *gspca_dev);
58
59
static const struct ctrl sd_ctrls[NCTRLS] = {
60
[BRIGHTNESS] = {
61
{
62
.id = V4L2_CID_BRIGHTNESS,
63
.type = V4L2_CTRL_TYPE_INTEGER,
64
.name = "Brightness",
65
.minimum = 0,
66
.maximum = 255,
67
.step = 1,
68
.default_value = 127,
69
},
70
.set_control = setbrightness
71
},
72
[CONTRAST] = {
73
{
74
.id = V4L2_CID_CONTRAST,
75
.type = V4L2_CTRL_TYPE_INTEGER,
76
.name = "Contrast",
77
.minimum = 0,
78
.maximum = 255,
79
.step = 1,
80
.default_value = 127,
81
},
82
.set_control = setcontrast
83
},
84
[COLORS] = {
85
{
86
.id = V4L2_CID_SATURATION,
87
.type = V4L2_CTRL_TYPE_INTEGER,
88
.name = "Color",
89
.minimum = 0,
90
.maximum = 255,
91
.step = 1,
92
.default_value = 127,
93
},
94
.set_control = setcolors
95
},
96
[LIGHTFREQ] = {
97
{
98
.id = V4L2_CID_POWER_LINE_FREQUENCY,
99
.type = V4L2_CTRL_TYPE_MENU,
100
.name = "Light frequency filter",
101
.minimum = 1,
102
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
103
.step = 1,
104
.default_value = 1,
105
},
106
.set_control = setlightfreq
107
},
108
};
109
110
static const struct v4l2_pix_format vga_mode[] = {
111
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
112
.bytesperline = 320,
113
.sizeimage = 320 * 240 * 3 / 8 + 590,
114
.colorspace = V4L2_COLORSPACE_JPEG,
115
.priv = 1},
116
{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117
.bytesperline = 640,
118
.sizeimage = 640 * 480 * 3 / 8 + 590,
119
.colorspace = V4L2_COLORSPACE_JPEG,
120
.priv = 0},
121
};
122
123
/* -- read a register -- */
124
static u8 reg_r(struct gspca_dev *gspca_dev,
125
__u16 index)
126
{
127
struct usb_device *dev = gspca_dev->dev;
128
int ret;
129
130
if (gspca_dev->usb_err < 0)
131
return 0;
132
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
133
0x00,
134
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
135
0x00,
136
index,
137
gspca_dev->usb_buf, 1,
138
500);
139
if (ret < 0) {
140
err("reg_r err %d", ret);
141
gspca_dev->usb_err = ret;
142
return 0;
143
}
144
return gspca_dev->usb_buf[0];
145
}
146
147
/* -- write a register -- */
148
static void reg_w(struct gspca_dev *gspca_dev,
149
__u16 index, __u16 value)
150
{
151
struct usb_device *dev = gspca_dev->dev;
152
int ret;
153
154
if (gspca_dev->usb_err < 0)
155
return;
156
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
157
0x01,
158
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159
value,
160
index,
161
NULL,
162
0,
163
500);
164
if (ret < 0) {
165
err("reg_w err %d", ret);
166
gspca_dev->usb_err = ret;
167
}
168
}
169
170
/* -- get a bulk value (4 bytes) -- */
171
static void rcv_val(struct gspca_dev *gspca_dev,
172
int ads)
173
{
174
struct usb_device *dev = gspca_dev->dev;
175
int alen, ret;
176
177
reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
178
reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
179
reg_w(gspca_dev, 0x636, ads & 0xff);
180
reg_w(gspca_dev, 0x637, 0);
181
reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
182
reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
183
reg_w(gspca_dev, 0x63a, 0);
184
reg_w(gspca_dev, 0x63b, 0);
185
reg_w(gspca_dev, 0x630, 5);
186
if (gspca_dev->usb_err < 0)
187
return;
188
ret = usb_bulk_msg(dev,
189
usb_rcvbulkpipe(dev, 0x05),
190
gspca_dev->usb_buf,
191
4, /* length */
192
&alen,
193
500); /* timeout in milliseconds */
194
if (ret < 0) {
195
err("rcv_val err %d", ret);
196
gspca_dev->usb_err = ret;
197
}
198
}
199
200
/* -- send a bulk value -- */
201
static void snd_val(struct gspca_dev *gspca_dev,
202
int ads,
203
unsigned int val)
204
{
205
struct usb_device *dev = gspca_dev->dev;
206
int alen, ret;
207
__u8 seq = 0;
208
209
if (ads == 0x003f08) {
210
reg_r(gspca_dev, 0x0704);
211
seq = reg_r(gspca_dev, 0x0705);
212
reg_r(gspca_dev, 0x0650);
213
reg_w(gspca_dev, 0x654, seq);
214
} else {
215
reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
216
}
217
reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
218
reg_w(gspca_dev, 0x656, ads & 0xff);
219
reg_w(gspca_dev, 0x657, 0);
220
reg_w(gspca_dev, 0x658, 0x04); /* size */
221
reg_w(gspca_dev, 0x659, 0);
222
reg_w(gspca_dev, 0x65a, 0);
223
reg_w(gspca_dev, 0x65b, 0);
224
reg_w(gspca_dev, 0x650, 5);
225
if (gspca_dev->usb_err < 0)
226
return;
227
gspca_dev->usb_buf[0] = val >> 24;
228
gspca_dev->usb_buf[1] = val >> 16;
229
gspca_dev->usb_buf[2] = val >> 8;
230
gspca_dev->usb_buf[3] = val;
231
ret = usb_bulk_msg(dev,
232
usb_sndbulkpipe(dev, 6),
233
gspca_dev->usb_buf,
234
4,
235
&alen,
236
500); /* timeout in milliseconds */
237
if (ret < 0) {
238
err("snd_val err %d", ret);
239
gspca_dev->usb_err = ret;
240
} else {
241
if (ads == 0x003f08) {
242
seq += 4;
243
seq &= 0x3f;
244
reg_w(gspca_dev, 0x705, seq);
245
}
246
}
247
}
248
249
/* set a camera parameter */
250
static void set_par(struct gspca_dev *gspca_dev,
251
int parval)
252
{
253
snd_val(gspca_dev, 0x003f08, parval);
254
}
255
256
static void setbrightness(struct gspca_dev *gspca_dev)
257
{
258
struct sd *sd = (struct sd *) gspca_dev;
259
int parval;
260
261
parval = 0x06000000 /* whiteness */
262
+ (sd->ctrls[BRIGHTNESS].val << 16);
263
set_par(gspca_dev, parval);
264
}
265
266
static void setcontrast(struct gspca_dev *gspca_dev)
267
{
268
struct sd *sd = (struct sd *) gspca_dev;
269
int parval;
270
271
parval = 0x07000000 /* contrast */
272
+ (sd->ctrls[CONTRAST].val << 16);
273
set_par(gspca_dev, parval);
274
}
275
276
static void setcolors(struct gspca_dev *gspca_dev)
277
{
278
struct sd *sd = (struct sd *) gspca_dev;
279
int parval;
280
281
parval = 0x08000000 /* saturation */
282
+ (sd->ctrls[COLORS].val << 16);
283
set_par(gspca_dev, parval);
284
}
285
286
static void setlightfreq(struct gspca_dev *gspca_dev)
287
{
288
struct sd *sd = (struct sd *) gspca_dev;
289
290
set_par(gspca_dev, sd->ctrls[LIGHTFREQ].val == 1
291
? 0x33640000 /* 50 Hz */
292
: 0x33780000); /* 60 Hz */
293
}
294
295
/* this function is called at probe time */
296
static int sd_config(struct gspca_dev *gspca_dev,
297
const struct usb_device_id *id)
298
{
299
struct sd *sd = (struct sd *) gspca_dev;
300
301
gspca_dev->cam.cam_mode = vga_mode;
302
gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
303
gspca_dev->cam.ctrls = sd->ctrls;
304
sd->quality = QUALITY_DEF;
305
return 0;
306
}
307
308
/* this function is called at probe and resume time */
309
static int sd_init(struct gspca_dev *gspca_dev)
310
{
311
u8 ret;
312
313
/* check if the device responds */
314
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
315
ret = reg_r(gspca_dev, 0x0740);
316
if (gspca_dev->usb_err >= 0) {
317
if (ret != 0xff) {
318
err("init reg: 0x%02x", ret);
319
gspca_dev->usb_err = -EIO;
320
}
321
}
322
return gspca_dev->usb_err;
323
}
324
325
/* -- start the camera -- */
326
static int sd_start(struct gspca_dev *gspca_dev)
327
{
328
struct sd *sd = (struct sd *) gspca_dev;
329
int ret, value;
330
331
/* create the JPEG header */
332
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
333
0x22); /* JPEG 411 */
334
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
335
336
/* work on alternate 1 */
337
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
338
339
set_par(gspca_dev, 0x10000000);
340
set_par(gspca_dev, 0x00000000);
341
set_par(gspca_dev, 0x8002e001);
342
set_par(gspca_dev, 0x14000000);
343
if (gspca_dev->width > 320)
344
value = 0x8002e001; /* 640x480 */
345
else
346
value = 0x4001f000; /* 320x240 */
347
set_par(gspca_dev, value);
348
ret = usb_set_interface(gspca_dev->dev,
349
gspca_dev->iface,
350
gspca_dev->alt);
351
if (ret < 0) {
352
err("set intf %d %d failed",
353
gspca_dev->iface, gspca_dev->alt);
354
gspca_dev->usb_err = ret;
355
goto out;
356
}
357
reg_r(gspca_dev, 0x0630);
358
rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
359
reg_r(gspca_dev, 0x0650);
360
snd_val(gspca_dev, 0x000020, 0xffffffff);
361
reg_w(gspca_dev, 0x0620, 0);
362
reg_w(gspca_dev, 0x0630, 0);
363
reg_w(gspca_dev, 0x0640, 0);
364
reg_w(gspca_dev, 0x0650, 0);
365
reg_w(gspca_dev, 0x0660, 0);
366
setbrightness(gspca_dev); /* whiteness */
367
setcontrast(gspca_dev); /* contrast */
368
setcolors(gspca_dev); /* saturation */
369
set_par(gspca_dev, 0x09800000); /* Red ? */
370
set_par(gspca_dev, 0x0a800000); /* Green ? */
371
set_par(gspca_dev, 0x0b800000); /* Blue ? */
372
set_par(gspca_dev, 0x0d030000); /* Gamma ? */
373
setlightfreq(gspca_dev);
374
375
/* start the video flow */
376
set_par(gspca_dev, 0x01000000);
377
set_par(gspca_dev, 0x01000000);
378
if (gspca_dev->usb_err >= 0)
379
PDEBUG(D_STREAM, "camera started alt: 0x%02x",
380
gspca_dev->alt);
381
out:
382
return gspca_dev->usb_err;
383
}
384
385
static void sd_stopN(struct gspca_dev *gspca_dev)
386
{
387
struct usb_device *dev = gspca_dev->dev;
388
389
set_par(gspca_dev, 0x02000000);
390
set_par(gspca_dev, 0x02000000);
391
usb_set_interface(dev, gspca_dev->iface, 1);
392
reg_r(gspca_dev, 0x0630);
393
rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
394
reg_r(gspca_dev, 0x0650);
395
snd_val(gspca_dev, 0x000020, 0xffffffff);
396
reg_w(gspca_dev, 0x0620, 0);
397
reg_w(gspca_dev, 0x0630, 0);
398
reg_w(gspca_dev, 0x0640, 0);
399
reg_w(gspca_dev, 0x0650, 0);
400
reg_w(gspca_dev, 0x0660, 0);
401
PDEBUG(D_STREAM, "camera stopped");
402
}
403
404
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
405
u8 *data, /* isoc packet */
406
int len) /* iso packet length */
407
{
408
struct sd *sd = (struct sd *) gspca_dev;
409
static unsigned char ffd9[] = {0xff, 0xd9};
410
411
/* a frame starts with:
412
* - 0xff 0xfe
413
* - 0x08 0x00 - length (little endian ?!)
414
* - 4 bytes = size of whole frame (BE - including header)
415
* - 0x00 0x0c
416
* - 0xff 0xd8
417
* - .. JPEG image with escape sequences (ff 00)
418
* (without ending - ff d9)
419
*/
420
if (data[0] == 0xff && data[1] == 0xfe) {
421
gspca_frame_add(gspca_dev, LAST_PACKET,
422
ffd9, 2);
423
424
/* put the JPEG 411 header */
425
gspca_frame_add(gspca_dev, FIRST_PACKET,
426
sd->jpeg_hdr, JPEG_HDR_SZ);
427
428
/* beginning of the frame */
429
#define STKHDRSZ 12
430
data += STKHDRSZ;
431
len -= STKHDRSZ;
432
}
433
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
434
}
435
436
static int sd_querymenu(struct gspca_dev *gspca_dev,
437
struct v4l2_querymenu *menu)
438
{
439
static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
440
441
switch (menu->id) {
442
case V4L2_CID_POWER_LINE_FREQUENCY:
443
if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
444
break;
445
strcpy((char *) menu->name, freq_nm[menu->index]);
446
return 0;
447
}
448
return -EINVAL;
449
}
450
451
static int sd_set_jcomp(struct gspca_dev *gspca_dev,
452
struct v4l2_jpegcompression *jcomp)
453
{
454
struct sd *sd = (struct sd *) gspca_dev;
455
456
if (jcomp->quality < QUALITY_MIN)
457
sd->quality = QUALITY_MIN;
458
else if (jcomp->quality > QUALITY_MAX)
459
sd->quality = QUALITY_MAX;
460
else
461
sd->quality = jcomp->quality;
462
if (gspca_dev->streaming)
463
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
464
return gspca_dev->usb_err;
465
}
466
467
static int sd_get_jcomp(struct gspca_dev *gspca_dev,
468
struct v4l2_jpegcompression *jcomp)
469
{
470
struct sd *sd = (struct sd *) gspca_dev;
471
472
memset(jcomp, 0, sizeof *jcomp);
473
jcomp->quality = sd->quality;
474
jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
475
| V4L2_JPEG_MARKER_DQT;
476
return 0;
477
}
478
479
/* sub-driver description */
480
static const struct sd_desc sd_desc = {
481
.name = MODULE_NAME,
482
.ctrls = sd_ctrls,
483
.nctrls = NCTRLS,
484
.config = sd_config,
485
.init = sd_init,
486
.start = sd_start,
487
.stopN = sd_stopN,
488
.pkt_scan = sd_pkt_scan,
489
.querymenu = sd_querymenu,
490
.get_jcomp = sd_get_jcomp,
491
.set_jcomp = sd_set_jcomp,
492
};
493
494
/* -- module initialisation -- */
495
static const struct usb_device_id device_table[] = {
496
{USB_DEVICE(0x05e1, 0x0893)},
497
{}
498
};
499
MODULE_DEVICE_TABLE(usb, device_table);
500
501
/* -- device connect -- */
502
static int sd_probe(struct usb_interface *intf,
503
const struct usb_device_id *id)
504
{
505
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
506
THIS_MODULE);
507
}
508
509
static struct usb_driver sd_driver = {
510
.name = MODULE_NAME,
511
.id_table = device_table,
512
.probe = sd_probe,
513
.disconnect = gspca_disconnect,
514
#ifdef CONFIG_PM
515
.suspend = gspca_suspend,
516
.resume = gspca_resume,
517
#endif
518
};
519
520
/* -- module insert / remove -- */
521
static int __init sd_mod_init(void)
522
{
523
return usb_register(&sd_driver);
524
}
525
static void __exit sd_mod_exit(void)
526
{
527
usb_deregister(&sd_driver);
528
}
529
530
module_init(sd_mod_init);
531
module_exit(sd_mod_exit);
532
533