em28xx-dvb.c revision 52284c3e47bf502aaff72ab2ede509193b628b1b
13aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/*
23aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab DVB device driver for em28xx
33aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
43aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
53aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
6bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
7bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller	- Fixes for the driver to properly work with HVR-950
8bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller
93aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab Based on cx88-dvb and saa7134-dvb originally written by:
103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	(c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify
143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab it under the terms of the GNU General Public License as published by
153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab the Free Software Foundation; either version 2 of the License.
163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab */
173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/kernel.h>
193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/usb.h>
203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "em28xx.h"
223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/v4l2-common.h>
233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/videobuf-vmalloc.h>
243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "lgdt330x.h"
263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards");
283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL");
303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug;
323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644);
333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]");
343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do {			\
383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) 						\
393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg)	\
403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0)
413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int
433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabbuffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	struct em28xx_fh *fh = vq->priv_data;
463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	struct em28xx        *dev = fh->dev;
473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
4852284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab	/* FIXME: The better would be to allocate a smaller buffer */
493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	*size = 16 * fh->dev->width * fh->dev->height >> 3;
503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (0 == *count)
513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		*count = EM28XX_DEF_BUF;
523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (*count < EM28XX_MIN_BUF)
543aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		*count = EM28XX_MIN_BUF;
553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	dev->mode = EM28XX_DIGITAL_MODE;
573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
613aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */
623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
63227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = {
64227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab	.demod_address = 0x0e,
65227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab	.demod_chip = LGDT3303,
66227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab};
673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */
693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int attach_xc3028(u8 addr, struct em28xx *dev)
713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	struct dvb_frontend *fe;
733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	struct xc2028_ctrl ctl;
743ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	struct xc2028_config cfg;
753ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab
763ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	memset (&cfg, 0, sizeof(cfg));
773ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.i2c_adap  = &dev->i2c_adap;
783ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.i2c_addr  = addr;
793ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.ctrl      = &ctl;
803ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.callback  = em28xx_tuner_callback;
813ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab
823ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	em28xx_setup_xc3028(dev, &ctl);
833aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
843aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (!dev->dvb.frontend) {
853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		printk(KERN_ERR "%s/2: dvb frontend not attached. "
863aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab				"Can't attach xc3028\n",
873aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		       dev->name);
883aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		return -EINVAL;
893aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
903aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
913aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
923aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (!fe) {
933aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
943aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		       dev->name);
953aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		dvb_frontend_detach(dev->dvb.frontend);
963aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		dvb_unregister_frontend(dev->dvb.frontend);
973aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		dev->dvb.frontend = NULL;
983aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		return -EINVAL;
993aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
1003aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1013aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
1023aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1033aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
1043aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1063aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_init(struct em28xx *dev)
1073aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
1083aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	/* init struct videobuf_dvb */
1093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	dev->dvb.name = dev->name;
1103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	dev->qops->buf_setup = buffer_setup;
1123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
11352284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab	/* FIXME: Do we need more initialization here? */
11452284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab	memset(&dev->dvb_fh, 0, sizeof (dev->dvb_fh));
11552284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab	dev->dvb_fh.dev = dev;
11652284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab	dev->dvb_fh.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
11752284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab
1183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	videobuf_queue_vmalloc_init(&dev->dvb.dvbq, dev->qops,
1193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab			&dev->udev->dev, &dev->slock,
1203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab			V4L2_BUF_TYPE_VIDEO_CAPTURE,
1213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab			V4L2_FIELD_ALTERNATE,
12252284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab			sizeof(struct em28xx_buffer), &dev->dvb_fh);
1233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	/* init frontend */
1253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	switch (dev->model) {
126227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
127227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		/* Enable lgdt330x */
128bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller		dev->mode = EM28XX_DIGITAL_MODE;
129227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0);
130227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab
131227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
132227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab					       &em2880_lgdt3303_dev,
133227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab					       &dev->i2c_adap);
134227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		if (attach_xc3028(0x61, dev) < 0)
135227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab			return -EINVAL;
136227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		break;
1373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	default:
1383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
1393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab				" isn't supported yet\n",
1403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		       dev->name);
1413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		break;
1423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
1433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (NULL == dev->dvb.frontend) {
1443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		printk(KERN_ERR
1453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		       "%s/2: frontend initialization failed\n",
1463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		       dev->name);
1473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		return -EINVAL;
1483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
1493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	/* register everything */
1513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
1523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab				     &dev->udev->dev,
1533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab				     adapter_nr);
1543aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_fini(struct em28xx *dev)
1573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
1583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (dev->dvb.frontend)
1593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		videobuf_dvb_unregister(&dev->dvb);
1603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1613aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
1623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = {
1653aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.id   = EM28XX_DVB,
1663aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.name = "Em28xx dvb Extension",
1673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.init = dvb_init,
1683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.fini = dvb_fini,
1693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab};
1703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void)
1723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
1733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return em28xx_register_extension(&dvb_ops);
1743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1763aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void)
1773aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
1783aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	em28xx_unregister_extension(&dvb_ops);
1793aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1803aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1813aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register);
1823aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister);
183