• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/tm6000/
1/*
2   tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
3
4   Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
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 version 2
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/usb.h>
23
24#include "tm6000.h"
25#include "tm6000-regs.h"
26
27#include "zl10353.h"
28
29#include <media/tuner.h>
30
31#include "tuner-xc2028.h"
32#include "xc5000.h"
33
34MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
35MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
36MODULE_LICENSE("GPL");
37
38MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
39			"{{Trident, tm6000},"
40			"{{Trident, tm6010}");
41
42static int debug;
43
44module_param(debug, int, 0644);
45MODULE_PARM_DESC(debug, "enable debug message");
46
47static inline void print_err_status(struct tm6000_core *dev,
48				    int packet, int status)
49{
50	char *errmsg = "Unknown";
51
52	switch (status) {
53	case -ENOENT:
54		errmsg = "unlinked synchronuously";
55		break;
56	case -ECONNRESET:
57		errmsg = "unlinked asynchronuously";
58		break;
59	case -ENOSR:
60		errmsg = "Buffer error (overrun)";
61		break;
62	case -EPIPE:
63		errmsg = "Stalled (device not responding)";
64		break;
65	case -EOVERFLOW:
66		errmsg = "Babble (bad cable?)";
67		break;
68	case -EPROTO:
69		errmsg = "Bit-stuff error (bad cable?)";
70		break;
71	case -EILSEQ:
72		errmsg = "CRC/Timeout (could be anything)";
73		break;
74	case -ETIME:
75		errmsg = "Device does not respond";
76		break;
77	}
78	if (packet < 0) {
79		dprintk(dev, 1, "URB status %d [%s].\n",
80			status, errmsg);
81	} else {
82		dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
83			packet, status, errmsg);
84	}
85}
86
87static void tm6000_urb_received(struct urb *urb)
88{
89	int ret;
90	struct tm6000_core *dev = urb->context;
91
92	if (urb->status != 0)
93		print_err_status(dev, 0, urb->status);
94	else if (urb->actual_length > 0)
95		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
96						   urb->actual_length);
97
98	if (dev->dvb->streams > 0) {
99		ret = usb_submit_urb(urb, GFP_ATOMIC);
100		if (ret < 0) {
101			printk(KERN_ERR "tm6000:  error %s\n", __FUNCTION__);
102			kfree(urb->transfer_buffer);
103			usb_free_urb(urb);
104		}
105	}
106}
107
108int tm6000_start_stream(struct tm6000_core *dev)
109{
110	int ret;
111	unsigned int pipe, size;
112	struct tm6000_dvb *dvb = dev->dvb;
113
114	printk(KERN_INFO "tm6000: got start stream request %s\n", __FUNCTION__);
115
116	if (dev->mode != TM6000_MODE_DIGITAL) {
117		tm6000_init_digital_mode(dev);
118		dev->mode = TM6000_MODE_DIGITAL;
119	}
120
121	dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
122	if (dvb->bulk_urb == NULL) {
123		printk(KERN_ERR "tm6000: couldn't allocate urb\n");
124		return -ENOMEM;
125	}
126
127	pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
128							  & USB_ENDPOINT_NUMBER_MASK);
129
130	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
131	size = size * 15; /* 512 x 8 or 12 or 15 */
132
133	dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
134	if (dvb->bulk_urb->transfer_buffer == NULL) {
135		usb_free_urb(dvb->bulk_urb);
136		printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
137		return -ENOMEM;
138	}
139
140	usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
141						 dvb->bulk_urb->transfer_buffer,
142						 size,
143						 tm6000_urb_received, dev);
144
145	ret = usb_clear_halt(dev->udev, pipe);
146	if (ret < 0) {
147		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
148							ret, __FUNCTION__);
149		return ret;
150	} else
151		printk(KERN_ERR "tm6000: pipe resetted\n");
152
153/*	mutex_lock(&tm6000_driver.open_close_mutex); */
154	ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
155
156/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
157	if (ret) {
158		printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
159									ret);
160
161		kfree(dvb->bulk_urb->transfer_buffer);
162		usb_free_urb(dvb->bulk_urb);
163		return ret;
164	}
165
166	return 0;
167}
168
169void tm6000_stop_stream(struct tm6000_core *dev)
170{
171	struct tm6000_dvb *dvb = dev->dvb;
172
173	if (dvb->bulk_urb) {
174		printk(KERN_INFO "urb killing\n");
175		usb_kill_urb(dvb->bulk_urb);
176		printk(KERN_INFO "urb buffer free\n");
177		kfree(dvb->bulk_urb->transfer_buffer);
178		usb_free_urb(dvb->bulk_urb);
179		dvb->bulk_urb = NULL;
180	}
181}
182
183int tm6000_start_feed(struct dvb_demux_feed *feed)
184{
185	struct dvb_demux *demux = feed->demux;
186	struct tm6000_core *dev = demux->priv;
187	struct tm6000_dvb *dvb = dev->dvb;
188	printk(KERN_INFO "tm6000: got start feed request %s\n", __FUNCTION__);
189
190	mutex_lock(&dvb->mutex);
191	if (dvb->streams == 0) {
192		dvb->streams = 1;
193/*		mutex_init(&tm6000_dev->streming_mutex); */
194		tm6000_start_stream(dev);
195	} else
196		++(dvb->streams);
197	mutex_unlock(&dvb->mutex);
198
199	return 0;
200}
201
202int tm6000_stop_feed(struct dvb_demux_feed *feed)
203{
204	struct dvb_demux *demux = feed->demux;
205	struct tm6000_core *dev = demux->priv;
206	struct tm6000_dvb *dvb = dev->dvb;
207
208	printk(KERN_INFO "tm6000: got stop feed request %s\n", __FUNCTION__);
209
210	mutex_lock(&dvb->mutex);
211
212	printk(KERN_INFO "stream %#x\n", dvb->streams);
213	--(dvb->streams);
214	if (dvb->streams == 0) {
215		printk(KERN_INFO "stop stream\n");
216		tm6000_stop_stream(dev);
217/*		mutex_destroy(&tm6000_dev->streaming_mutex); */
218	}
219	mutex_unlock(&dvb->mutex);
220/*	mutex_destroy(&tm6000_dev->streaming_mutex); */
221
222	return 0;
223}
224
225int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
226{
227	struct tm6000_dvb *dvb = dev->dvb;
228
229	if (dev->caps.has_zl10353) {
230		struct zl10353_config config = {
231				     .demod_address = dev->demod_addr,
232				     .no_tuner = 1,
233				     .parallel_ts = 1,
234				     .if2 = 45700,
235				     .disable_i2c_gate_ctrl = 1,
236				    };
237
238		dvb->frontend = dvb_attach(zl10353_attach, &config,
239							   &dev->i2c_adap);
240	} else {
241		printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
242		return -1;
243	}
244
245	return (!dvb->frontend) ? -1 : 0;
246}
247
248DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
249
250int register_dvb(struct tm6000_core *dev)
251{
252	int ret = -1;
253	struct tm6000_dvb *dvb = dev->dvb;
254
255	mutex_init(&dvb->mutex);
256
257	dvb->streams = 0;
258
259	/* attach the frontend */
260	ret = tm6000_dvb_attach_frontend(dev);
261	if (ret < 0) {
262		printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
263		goto err;
264	}
265
266	ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
267					THIS_MODULE, &dev->udev->dev, adapter_nr);
268	dvb->adapter.priv = dev;
269
270	if (dvb->frontend) {
271		switch (dev->tuner_type) {
272		case TUNER_XC2028: {
273			struct xc2028_config cfg = {
274				.i2c_adap = &dev->i2c_adap,
275				.i2c_addr = dev->tuner_addr,
276			};
277
278			dvb->frontend->callback = tm6000_tuner_callback;
279			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
280			if (ret < 0) {
281				printk(KERN_ERR
282					"tm6000: couldn't register frontend\n");
283				goto adapter_err;
284			}
285
286			if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
287				printk(KERN_ERR "tm6000: couldn't register "
288						"frontend (xc3028)\n");
289				ret = -EINVAL;
290				goto frontend_err;
291			}
292			printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
293					 "attached to frontend!\n");
294			break;
295			}
296		case TUNER_XC5000: {
297			struct xc5000_config cfg = {
298				.i2c_address = dev->tuner_addr,
299			};
300
301			dvb->frontend->callback = tm6000_xc5000_callback;
302			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
303			if (ret < 0) {
304				printk(KERN_ERR
305					"tm6000: couldn't register frontend\n");
306				goto adapter_err;
307			}
308
309			if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
310				printk(KERN_ERR "tm6000: couldn't register "
311						"frontend (xc5000)\n");
312				ret = -EINVAL;
313				goto frontend_err;
314			}
315			printk(KERN_INFO "tm6000: XC5000 asked to be "
316					 "attached to frontend!\n");
317			break;
318			}
319		}
320	} else
321		printk(KERN_ERR "tm6000: no frontend found\n");
322
323	dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
324							    | DMX_MEMORY_BASED_FILTERING;
325	dvb->demux.priv = dev;
326	dvb->demux.filternum = 8;
327	dvb->demux.feednum = 8;
328	dvb->demux.start_feed = tm6000_start_feed;
329	dvb->demux.stop_feed = tm6000_stop_feed;
330	dvb->demux.write_to_decoder = NULL;
331	ret = dvb_dmx_init(&dvb->demux);
332	if (ret < 0) {
333		printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
334		goto frontend_err;
335	}
336
337	dvb->dmxdev.filternum = dev->dvb->demux.filternum;
338	dvb->dmxdev.demux = &dev->dvb->demux.dmx;
339	dvb->dmxdev.capabilities = 0;
340
341	ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
342	if (ret < 0) {
343		printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
344		goto dvb_dmx_err;
345	}
346
347	return 0;
348
349dvb_dmx_err:
350	dvb_dmx_release(&dvb->demux);
351frontend_err:
352	if (dvb->frontend) {
353		dvb_frontend_detach(dvb->frontend);
354		dvb_unregister_frontend(dvb->frontend);
355	}
356adapter_err:
357	dvb_unregister_adapter(&dvb->adapter);
358err:
359	return ret;
360}
361
362void unregister_dvb(struct tm6000_core *dev)
363{
364	struct tm6000_dvb *dvb = dev->dvb;
365
366	if (dvb->bulk_urb != NULL) {
367		struct urb *bulk_urb = dvb->bulk_urb;
368
369		kfree(bulk_urb->transfer_buffer);
370		bulk_urb->transfer_buffer = NULL;
371		usb_unlink_urb(bulk_urb);
372		usb_free_urb(bulk_urb);
373	}
374
375/*	mutex_lock(&tm6000_driver.open_close_mutex); */
376	if (dvb->frontend) {
377		dvb_frontend_detach(dvb->frontend);
378		dvb_unregister_frontend(dvb->frontend);
379	}
380
381	dvb_dmxdev_release(&dvb->dmxdev);
382	dvb_dmx_release(&dvb->demux);
383	dvb_unregister_adapter(&dvb->adapter);
384	mutex_destroy(&dvb->mutex);
385/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
386}
387
388static int dvb_init(struct tm6000_core *dev)
389{
390	struct tm6000_dvb *dvb;
391	int rc;
392
393	if (!dev)
394		return 0;
395
396	if (!dev->caps.has_dvb)
397		return 0;
398
399	dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
400	if (!dvb) {
401		printk(KERN_INFO "Cannot allocate memory\n");
402		return -ENOMEM;
403	}
404
405	dev->dvb = dvb;
406
407	rc = register_dvb(dev);
408	if (rc < 0) {
409		kfree(dvb);
410		dev->dvb = NULL;
411		return 0;
412	}
413
414	return 0;
415}
416
417static int dvb_fini(struct tm6000_core *dev)
418{
419	if (!dev)
420		return 0;
421
422	if (!dev->caps.has_dvb)
423		return 0;
424
425	if (dev->dvb) {
426		unregister_dvb(dev);
427		kfree(dev->dvb);
428		dev->dvb = NULL;
429	}
430
431	return 0;
432}
433
434static struct tm6000_ops dvb_ops = {
435	.type	= TM6000_DVB,
436	.name	= "TM6000 dvb Extension",
437	.init	= dvb_init,
438	.fini	= dvb_fini,
439};
440
441static int __init tm6000_dvb_register(void)
442{
443	return tm6000_register_extension(&dvb_ops);
444}
445
446static void __exit tm6000_dvb_unregister(void)
447{
448	tm6000_unregister_extension(&dvb_ops);
449}
450
451module_init(tm6000_dvb_register);
452module_exit(tm6000_dvb_unregister);
453