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