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