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