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