em28xx-dvb.c revision 4fd305b2a2c4d16e8d4ebc95c84f946edd3385c5
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 84fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick 9bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller 103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton (c) 2008 Aidan Thornton <makosoft@googlemail.com> 113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: 133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> 143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify 173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab it under the terms of the GNU General Public License as published by 183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab the Free Software Foundation; either version 2 of the License. 193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab */ 203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/kernel.h> 223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/usb.h> 233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "em28xx.h" 253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/v4l2-common.h> 263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/videobuf-vmalloc.h> 273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "lgdt330x.h" 297e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton#include "zl10353.h" 303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards"); 323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL"); 343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug; 363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644); 373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do { \ 423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) \ 433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ 443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0) 453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_NUM_BUFS 5 473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETSIZE 564 483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETS 64 493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstruct em28xx_dvb { 513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_frontend *frontend; 523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* feed count management */ 543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct mutex lock; 553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int nfeeds; 563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* general boilerplate stuff */ 583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_adapter adapter; 593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux demux; 603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmxdev dmxdev; 613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_hw; 623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_mem; 633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_net net; 643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}; 653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline void print_err_status(struct em28xx *dev, 683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int packet, int status) 693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton char *errmsg = "Unknown"; 713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton switch (status) { 733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOENT: 743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked synchronuously"; 753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ECONNRESET: 773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked asynchronuously"; 783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOSR: 803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Buffer error (overrun)"; 813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPIPE: 833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Stalled (device not responding)"; 843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EOVERFLOW: 863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Babble (bad cable?)"; 873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPROTO: 893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Bit-stuff error (bad cable?)"; 903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EILSEQ: 923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "CRC/Timeout (could be anything)"; 933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ETIME: 953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Device does not respond"; 963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (packet < 0) { 993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dprintk(1, "URB status %d [%s].\n", status, errmsg); 1003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } else { 1016ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk(1, "URB packet %d, status %d [%s].\n", 1026ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf packet, status, errmsg); 1033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) 1073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int i; 1093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev) 1113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) 1143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status < 0) { 1173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, -1, urb->status); 1183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status == -ENOENT) 1193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton for (i = 0; i < urb->number_of_packets; i++) { 1233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int status = urb->iso_frame_desc[i].status; 1243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (status < 0) { 1263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, i, status); 1273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->iso_frame_desc[i].status != -EPROTO) 1283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton continue; 1293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + 1323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].offset, 1333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].actual_length); 1343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1396ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int start_streaming(struct em28xx_dvb *dvb) 1406ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 141c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab int rc; 1423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton usb_set_interface(dev->udev, 0, 1); 145c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 146c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab if (rc < 0) 147c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab return rc; 1483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, 1503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, 151c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab dvb_isoc_copy); 1523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1546ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int stop_streaming(struct em28xx_dvb *dvb) 1556ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 1563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton em28xx_uninit_isoc(dev); 159c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 160c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 161c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 1633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 1643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int start_feed(struct dvb_demux_feed *feed) 1663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int rc, ret; 1703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!demux->dmx.frontend) 1723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -EINVAL; 1733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds++; 1763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton rc = dvb->nfeeds; 1773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dvb->nfeeds == 1) { 1793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton ret = start_streaming(dvb); 1806ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (ret < 0) 1816ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf rc = ret; 1823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 1853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return rc; 1863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int stop_feed(struct dvb_demux_feed *feed) 1893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int err = 0; 1933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds--; 1966ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 1976ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (0 == dvb->nfeeds) 1983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton err = stop_streaming(dvb); 1996ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 2013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return err; 2023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 2033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 205e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 206e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 207e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehabstatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 208e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab{ 209e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab struct em28xx *dev = fe->dvb->priv; 210e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 211e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab if (acquire) 212e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 213e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab else 214e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 215e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab} 216e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 219227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = { 220227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_address = 0x0e, 221227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_chip = LGDT3303, 222227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab}; 2233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2247e6388a1b97cca57a1906df6104feb4001721576Aidan Thorntonstatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 2257e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .demod_address = (0x1e >> 1), 2267e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .no_tuner = 1, 2277e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .parallel_ts = 1, 2287e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .if2 = 45600, 2297e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton}; 2307e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton 2313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int attach_xc3028(u8 addr, struct em28xx *dev) 2343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 2353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab struct dvb_frontend *fe; 2363ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab struct xc2028_config cfg; 2373ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 2386ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf memset(&cfg, 0, sizeof(cfg)); 2393ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_adap = &dev->i2c_adap; 2403ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_addr = addr; 2413ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.callback = em28xx_tuner_callback; 2423ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 2433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev->dvb->frontend) { 2443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: dvb frontend not attached. " 2453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "Can't attach xc3028\n", 2463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 2473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 2483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 2493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); 2513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab if (!fe) { 2523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: xc3028 attach failed\n", 2533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 2543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dev->dvb->frontend); 2553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb->frontend = NULL; 2563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 2573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 2583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); 2603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2613aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 2623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 2633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton/* ------------------------------------------------------------------ */ 2653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonint register_dvb(struct em28xx_dvb *dvb, 2673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct module *module, 2683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev, 2693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct device *device) 2703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 2713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result; 2723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_init(&dvb->lock); 2743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register adapter */ 2763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, 2773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton adapter_nr); 2783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 2793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", 2803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 2813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_adapter; 2823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 283e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 284e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab /* Ensure all frontends negotiate bus access */ 285e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 286e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->adapter.priv = dev; 2883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register frontend */ 2903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_frontend(&dvb->adapter, dvb->frontend); 2913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 2923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", 2933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 2943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_frontend; 2953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 2963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register demux stuff */ 2983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.capabilities = 2993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_TS_FILTERING | DMX_SECTION_FILTERING | 3003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_MEMORY_BASED_FILTERING; 3013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.priv = dvb; 3023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.filternum = 256; 3033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.feednum = 256; 3043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.start_feed = start_feed; 3053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.stop_feed = stop_feed; 306e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmx_init(&dvb->demux); 3083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", 3103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmx; 3123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.filternum = 256; 3153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.demux = &dvb->demux.dmx; 3163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.capabilities = 0; 3173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 3183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", 3203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmxdev; 3223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 32352284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab 3243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_hw.source = DMX_FRONTEND_0; 3253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 3283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_hw; 3303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_mem.source = DMX_MEMORY_FE; 3333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 3363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_mem; 3383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", 3433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_conn; 3453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register network adapter */ 3483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 3493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 3503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_conn: 3523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_mem: 3543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_hw: 3563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 3573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmxdev: 3583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 3593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmx: 3603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 3613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_frontend: 3623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 3633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 3643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_adapter: 3653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 3663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 3673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic void unregister_dvb(struct em28xx_dvb *dvb) 3693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 3703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_release(&dvb->net); 3713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 3743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 3753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 3763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 3773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 3783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 3793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int dvb_init(struct em28xx *dev) 3823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 3833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result = 0; 3843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb; 3853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 386df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller if (!dev->has_dvb) { 387df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 388df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 389df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 390df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 3913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); 3926ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 3936ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (dvb == NULL) { 3946ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); 3953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -ENOMEM; 3963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = dvb; 3983aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 399c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 4003aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* init frontend */ 4013aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab switch (dev->model) { 402227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 4034fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 4043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(lgdt330x_attach, 4053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em2880_lgdt3303_dev, 4063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 411227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab break; 4127e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 4133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(zl10353_attach, 4143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em28xx_zl10353_with_xc3028, 4153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4207e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton break; 4213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab default: 4223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" 4233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab " isn't supported yet\n", 4243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 4253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab break; 4263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 4273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (NULL == dvb->frontend) { 4283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR 4293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "%s/2: frontend initialization failed\n", 4303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 4313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 4343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* register everything */ 4363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); 4373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4386ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (result < 0) 4393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 441c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 442102a0b0879a01a413ed5f667f7db9c2085ca8474Mauro Carvalho Chehab printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); 4433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 4443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonout_free: 446c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 4473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton kfree(dvb); 4483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 4493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 4503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 4513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_fini(struct em28xx *dev) 4533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 454df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller if (!dev->has_dvb) { 455df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 456df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 457df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 458df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 4593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dev->dvb) { 4603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton unregister_dvb(dev->dvb); 4613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 4623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 4653aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 4663aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = { 4683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .id = EM28XX_DVB, 4693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .name = "Em28xx dvb Extension", 4703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .init = dvb_init, 4713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .fini = dvb_fini, 4723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}; 4733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void) 4753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 4763aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return em28xx_register_extension(&dvb_ops); 4773aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 4783aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4793aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void) 4803aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 4813aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab em28xx_unregister_extension(&dvb_ops); 4823aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 4833aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4843aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register); 4853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister); 486