tm6000-dvb.c 10.5 KB
Newer Older
1
/*
2 3 4 5 6 7 8 9 10 11 12 13
 *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
 *
 *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation version 2
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
14 15
 */

16
#include <linux/kernel.h>
T
Tejun Heo 已提交
17
#include <linux/slab.h>
18 19 20 21 22 23 24 25 26
#include <linux/usb.h>

#include "tm6000.h"
#include "tm6000-regs.h"

#include "zl10353.h"

#include <media/tuner.h>

27
#include "tuner-xc2028.h"
28
#include "xc5000.h"
29

30
MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
31
MODULE_AUTHOR("Mauro Carvalho Chehab");
32 33
MODULE_LICENSE("GPL");

34
MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},{{Trident, tm6000},{{Trident, tm6010}");
35 36 37 38 39 40

static int debug;

module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug message");

41 42
static inline void print_err_status(struct tm6000_core *dev,
				    int packet, int status)
43 44 45
{
	char *errmsg = "Unknown";

46
	switch (status) {
47
	case -ENOENT:
48
		errmsg = "unlinked synchronously";
49 50
		break;
	case -ECONNRESET:
51
		errmsg = "unlinked asynchronously";
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
		break;
	case -ENOSR:
		errmsg = "Buffer error (overrun)";
		break;
	case -EPIPE:
		errmsg = "Stalled (device not responding)";
		break;
	case -EOVERFLOW:
		errmsg = "Babble (bad cable?)";
		break;
	case -EPROTO:
		errmsg = "Bit-stuff error (bad cable?)";
		break;
	case -EILSEQ:
		errmsg = "CRC/Timeout (could be anything)";
		break;
	case -ETIME:
		errmsg = "Device does not respond";
		break;
	}
72
	if (packet < 0) {
73 74 75 76 77 78 79 80
		dprintk(dev, 1, "URB status %d [%s].\n",
			status, errmsg);
	} else {
		dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
			packet, status, errmsg);
	}
}

81 82 83
static void tm6000_urb_received(struct urb *urb)
{
	int ret;
84
	struct tm6000_core *dev = urb->context;
85

86 87 88 89 90 91 92 93 94
	switch (urb->status) {
	case 0:
	case -ETIMEDOUT:
		break;
	case -ENOENT:
	case -ECONNRESET:
	case -ESHUTDOWN:
		return;
	default:
95
		print_err_status(dev, 0, urb->status);
96 97 98
	}

	if (urb->actual_length > 0)
99 100 101
		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
						   urb->actual_length);

102
	if (dev->dvb->streams > 0) {
103
		ret = usb_submit_urb(urb, GFP_ATOMIC);
104
		if (ret < 0) {
105
			printk(KERN_ERR "tm6000:  error %s\n", __func__);
106 107
			kfree(urb->transfer_buffer);
			usb_free_urb(urb);
108
			dev->dvb->bulk_urb = NULL;
109 110 111 112
		}
	}
}

113
static int tm6000_start_stream(struct tm6000_core *dev)
114 115
{
	int ret;
116
	unsigned int pipe, size;
117 118
	struct tm6000_dvb *dvb = dev->dvb;

119
	printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
120

121 122 123 124
	if (dev->mode != TM6000_MODE_DIGITAL) {
		tm6000_init_digital_mode(dev);
		dev->mode = TM6000_MODE_DIGITAL;
	}
125 126

	dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
127
	if (!dvb->bulk_urb)
128 129
		return -ENOMEM;

130
	pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
131 132 133 134
							  & USB_ENDPOINT_NUMBER_MASK);

	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
	size = size * 15; /* 512 x 8 or 12 or 15 */
135

136
	dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
137
	if (!dvb->bulk_urb->transfer_buffer) {
138
		usb_free_urb(dvb->bulk_urb);
139
		dvb->bulk_urb = NULL;
140 141 142 143 144
		return -ENOMEM;
	}

	usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
						 dvb->bulk_urb->transfer_buffer,
145
						 size,
146
						 tm6000_urb_received, dev);
147

148
	ret = usb_clear_halt(dev->udev, pipe);
149 150
	if (ret < 0) {
		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
151
							ret, __func__);
152
		return ret;
153
	} else
154 155
		printk(KERN_ERR "tm6000: pipe resetted\n");

156
/*	mutex_lock(&tm6000_driver.open_close_mutex); */
157
	ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
158

159
/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
160
	if (ret) {
161 162
		printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
									ret);
163 164 165

		kfree(dvb->bulk_urb->transfer_buffer);
		usb_free_urb(dvb->bulk_urb);
166
		dvb->bulk_urb = NULL;
167 168 169 170 171 172
		return ret;
	}

	return 0;
}

173
static void tm6000_stop_stream(struct tm6000_core *dev)
174 175 176
{
	struct tm6000_dvb *dvb = dev->dvb;

177 178
	if (dvb->bulk_urb) {
		printk(KERN_INFO "urb killing\n");
179
		usb_kill_urb(dvb->bulk_urb);
180
		printk(KERN_INFO "urb buffer free\n");
181 182 183 184 185 186
		kfree(dvb->bulk_urb->transfer_buffer);
		usb_free_urb(dvb->bulk_urb);
		dvb->bulk_urb = NULL;
	}
}

187
static int tm6000_start_feed(struct dvb_demux_feed *feed)
188 189 190 191
{
	struct dvb_demux *demux = feed->demux;
	struct tm6000_core *dev = demux->priv;
	struct tm6000_dvb *dvb = dev->dvb;
192
	printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
193 194

	mutex_lock(&dvb->mutex);
195
	if (dvb->streams == 0) {
196
		dvb->streams = 1;
197
/*		mutex_init(&tm6000_dev->streming_mutex); */
198
		tm6000_start_stream(dev);
199
	} else
200 201 202 203 204 205
		++(dvb->streams);
	mutex_unlock(&dvb->mutex);

	return 0;
}

206
static int tm6000_stop_feed(struct dvb_demux_feed *feed)
207
{
208 209 210 211
	struct dvb_demux *demux = feed->demux;
	struct tm6000_core *dev = demux->priv;
	struct tm6000_dvb *dvb = dev->dvb;

212
	printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
213 214 215

	mutex_lock(&dvb->mutex);

216
	printk(KERN_INFO "stream %#x\n", dvb->streams);
217
	--(dvb->streams);
218 219
	if (dvb->streams == 0) {
		printk(KERN_INFO "stop stream\n");
220
		tm6000_stop_stream(dev);
221
/*		mutex_destroy(&tm6000_dev->streaming_mutex); */
222 223
	}
	mutex_unlock(&dvb->mutex);
224
/*	mutex_destroy(&tm6000_dev->streaming_mutex); */
225 226 227 228

	return 0;
}

229
static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
230 231 232
{
	struct tm6000_dvb *dvb = dev->dvb;

233 234 235
	if (dev->caps.has_zl10353) {
		struct zl10353_config config = {
				     .demod_address = dev->demod_addr,
236
				     .no_tuner = 1,
237 238 239
				     .parallel_ts = 1,
				     .if2 = 45700,
				     .disable_i2c_gate_ctrl = 1,
240 241
				    };

242
		dvb->frontend = dvb_attach(zl10353_attach, &config,
243
							   &dev->i2c_adap);
244
	} else {
245 246 247 248
		printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
		return -1;
	}

249
	return (!dvb->frontend) ? -1 : 0;
250 251
}

252 253
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

254
static int register_dvb(struct tm6000_core *dev)
255 256 257 258 259 260 261 262 263 264
{
	int ret = -1;
	struct tm6000_dvb *dvb = dev->dvb;

	mutex_init(&dvb->mutex);

	dvb->streams = 0;

	/* attach the frontend */
	ret = tm6000_dvb_attach_frontend(dev);
265
	if (ret < 0) {
266
		printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
267
		goto err;
268 269 270
	}

	ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
271
					THIS_MODULE, &dev->udev->dev, adapter_nr);
272 273 274 275 276
	if (ret < 0) {
		pr_err("tm6000: couldn't register the adapter!\n");
		goto err;
	}

277 278
	dvb->adapter.priv = dev;

279
	if (dvb->frontend) {
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
		switch (dev->tuner_type) {
		case TUNER_XC2028: {
			struct xc2028_config cfg = {
				.i2c_adap = &dev->i2c_adap,
				.i2c_addr = dev->tuner_addr,
			};

			dvb->frontend->callback = tm6000_tuner_callback;
			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
			if (ret < 0) {
				printk(KERN_ERR
					"tm6000: couldn't register frontend\n");
				goto adapter_err;
			}

			if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
296
				printk(KERN_ERR "tm6000: couldn't register frontend (xc3028)\n");
297 298 299
				ret = -EINVAL;
				goto frontend_err;
			}
300
			printk(KERN_INFO "tm6000: XC2028/3028 asked to be attached to frontend!\n");
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
			break;
			}
		case TUNER_XC5000: {
			struct xc5000_config cfg = {
				.i2c_address = dev->tuner_addr,
			};

			dvb->frontend->callback = tm6000_xc5000_callback;
			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
			if (ret < 0) {
				printk(KERN_ERR
					"tm6000: couldn't register frontend\n");
				goto adapter_err;
			}

			if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
317
				printk(KERN_ERR "tm6000: couldn't register frontend (xc5000)\n");
318 319 320
				ret = -EINVAL;
				goto frontend_err;
			}
321
			printk(KERN_INFO "tm6000: XC5000 asked to be attached to frontend!\n");
322 323
			break;
			}
324
		}
325
	} else
326
		printk(KERN_ERR "tm6000: no frontend found\n");
327 328 329 330

	dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
							    | DMX_MEMORY_BASED_FILTERING;
	dvb->demux.priv = dev;
331 332
	dvb->demux.filternum = 8;
	dvb->demux.feednum = 8;
333 334 335 336
	dvb->demux.start_feed = tm6000_start_feed;
	dvb->demux.stop_feed = tm6000_stop_feed;
	dvb->demux.write_to_decoder = NULL;
	ret = dvb_dmx_init(&dvb->demux);
337
	if (ret < 0) {
338
		printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
339 340 341 342 343 344 345 346
		goto frontend_err;
	}

	dvb->dmxdev.filternum = dev->dvb->demux.filternum;
	dvb->dmxdev.demux = &dev->dvb->demux.dmx;
	dvb->dmxdev.capabilities = 0;

	ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
347
	if (ret < 0) {
348
		printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
349 350 351 352 353 354 355 356
		goto dvb_dmx_err;
	}

	return 0;

dvb_dmx_err:
	dvb_dmx_release(&dvb->demux);
frontend_err:
357
	if (dvb->frontend) {
358
		dvb_unregister_frontend(dvb->frontend);
359
		dvb_frontend_detach(dvb->frontend);
360 361 362 363 364 365 366
	}
adapter_err:
	dvb_unregister_adapter(&dvb->adapter);
err:
	return ret;
}

367
static void unregister_dvb(struct tm6000_core *dev)
368 369 370
{
	struct tm6000_dvb *dvb = dev->dvb;

371
	if (dvb->bulk_urb) {
372 373 374 375 376 377 378 379
		struct urb *bulk_urb = dvb->bulk_urb;

		kfree(bulk_urb->transfer_buffer);
		bulk_urb->transfer_buffer = NULL;
		usb_unlink_urb(bulk_urb);
		usb_free_urb(bulk_urb);
	}

380
/*	mutex_lock(&tm6000_driver.open_close_mutex); */
381
	if (dvb->frontend) {
382
		dvb_unregister_frontend(dvb->frontend);
383
		dvb_frontend_detach(dvb->frontend);
384 385 386 387 388 389
	}

	dvb_dmxdev_release(&dvb->dmxdev);
	dvb_dmx_release(&dvb->demux);
	dvb_unregister_adapter(&dvb->adapter);
	mutex_destroy(&dvb->mutex);
390
/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
391
}
392 393 394 395 396 397 398 399 400 401 402 403

static int dvb_init(struct tm6000_core *dev)
{
	struct tm6000_dvb *dvb;
	int rc;

	if (!dev)
		return 0;

	if (!dev->caps.has_dvb)
		return 0;

404 405 406 407 408
	if (dev->udev->speed == USB_SPEED_FULL) {
		printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
		return 0;
	}

409
	dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
410
	if (!dvb)
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
		return -ENOMEM;

	dev->dvb = dvb;

	rc = register_dvb(dev);
	if (rc < 0) {
		kfree(dvb);
		dev->dvb = NULL;
		return 0;
	}

	return 0;
}

static int dvb_fini(struct tm6000_core *dev)
{
	if (!dev)
		return 0;

	if (!dev->caps.has_dvb)
		return 0;

	if (dev->dvb) {
		unregister_dvb(dev);
		kfree(dev->dvb);
		dev->dvb = NULL;
	}

	return 0;
}

static struct tm6000_ops dvb_ops = {
443
	.type	= TM6000_DVB,
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
	.name	= "TM6000 dvb Extension",
	.init	= dvb_init,
	.fini	= dvb_fini,
};

static int __init tm6000_dvb_register(void)
{
	return tm6000_register_extension(&dvb_ops);
}

static void __exit tm6000_dvb_unregister(void)
{
	tm6000_unregister_extension(&dvb_ops);
}

module_init(tm6000_dvb_register);
module_exit(tm6000_dvb_unregister);