Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  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", __func__);
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", __func__);
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, __func__);
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", __func__);
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", __func__);
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);