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