em28xx-dvb.c revision a84f79aed688a94197387830df3a2f2068f49dc0
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 9e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 10bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller 113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton (c) 2008 Aidan Thornton <makosoft@googlemail.com> 123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: 143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> 153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify 183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab it under the terms of the GNU General Public License as published by 193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab the Free Software Foundation; either version 2 of the License. 203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab */ 213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/kernel.h> 233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/usb.h> 243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "em28xx.h" 263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/v4l2-common.h> 273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/videobuf-vmalloc.h> 28d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng#include <media/tuner.h> 29d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng#include "tuner-simple.h" 303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "lgdt330x.h" 327e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton#include "zl10353.h" 336e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora#include "s5h1409.h" 344fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller#include "mt352.h" 354fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller#include "mt352_priv.h" /* FIXME */ 363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards"); 383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL"); 403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug; 423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644); 433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do { \ 483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) \ 493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ 503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0) 513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_NUM_BUFS 5 533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETS 64 543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstruct em28xx_dvb { 563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_frontend *frontend; 573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* feed count management */ 593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct mutex lock; 603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int nfeeds; 613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* general boilerplate stuff */ 633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_adapter adapter; 643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux demux; 653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmxdev dmxdev; 663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_hw; 673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_mem; 683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_net net; 693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}; 703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline void print_err_status(struct em28xx *dev, 733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int packet, int status) 743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton char *errmsg = "Unknown"; 763aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton switch (status) { 783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOENT: 793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked synchronuously"; 803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ECONNRESET: 823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked asynchronuously"; 833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOSR: 853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Buffer error (overrun)"; 863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPIPE: 883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Stalled (device not responding)"; 893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EOVERFLOW: 913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Babble (bad cable?)"; 923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPROTO: 943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Bit-stuff error (bad cable?)"; 953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EILSEQ: 973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "CRC/Timeout (could be anything)"; 983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ETIME: 1003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Device does not respond"; 1013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 1023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (packet < 0) { 1043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dprintk(1, "URB status %d [%s].\n", status, errmsg); 1053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } else { 1066ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk(1, "URB packet %d, status %d [%s].\n", 1076ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf packet, status, errmsg); 1083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) 1123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int i; 1143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev) 1163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) 1193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status < 0) { 1223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, -1, urb->status); 1233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status == -ENOENT) 1243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton for (i = 0; i < urb->number_of_packets; i++) { 1283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int status = urb->iso_frame_desc[i].status; 1293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (status < 0) { 1313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, i, status); 1323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->iso_frame_desc[i].status != -EPROTO) 1333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton continue; 1343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + 1373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].offset, 1383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].actual_length); 1393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1446ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int start_streaming(struct em28xx_dvb *dvb) 1456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 146c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab int rc; 1473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 148d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller int max_dvb_packet_size; 1493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton usb_set_interface(dev->udev, 0, 1); 151c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 152c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab if (rc < 0) 153c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab return rc; 1543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 155d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); 156d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller 1573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, 158d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, 159c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab dvb_isoc_copy); 1603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1626ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int stop_streaming(struct em28xx_dvb *dvb) 1636ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 1643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton em28xx_uninit_isoc(dev); 167c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1682fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 169c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 1713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 1723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int start_feed(struct dvb_demux_feed *feed) 1743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int rc, ret; 1783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!demux->dmx.frontend) 1803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -EINVAL; 1813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds++; 1843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton rc = dvb->nfeeds; 1853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dvb->nfeeds == 1) { 1873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton ret = start_streaming(dvb); 1886ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (ret < 0) 1896ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf rc = ret; 1903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 1933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return rc; 1943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int stop_feed(struct dvb_demux_feed *feed) 1973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 2003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int err = 0; 2013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 2033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds--; 2046ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2056ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (0 == dvb->nfeeds) 2063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton err = stop_streaming(dvb); 2076ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 2093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return err; 2103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 2113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 213e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 214e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 215e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehabstatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 216e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab{ 217e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab struct em28xx *dev = fe->dvb->priv; 218e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 219e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab if (acquire) 220e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 221e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab else 2222fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_SUSPEND); 223e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab} 224e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 227227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = { 228227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_address = 0x0e, 229227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_chip = LGDT3303, 230227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab}; 2313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2327e6388a1b97cca57a1906df6104feb4001721576Aidan Thorntonstatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 2337e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .demod_address = (0x1e >> 1), 2347e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .no_tuner = 1, 2357e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .parallel_ts = 1, 2367e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .if2 = 45600, 2377e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton}; 2387e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton 2396e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakorastatic struct s5h1409_config em28xx_s5h1409_with_xc3028 = { 2406e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .demod_address = 0x32 >> 1, 2416e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .output_mode = S5H1409_PARALLEL_OUTPUT, 2426e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .gpio = S5H1409_GPIO_OFF, 2436e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .inversion = S5H1409_INVERSION_OFF, 2446e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .status_mode = S5H1409_DEMODLOCKING, 2456e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 2466e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora}; 2476e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora 248a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmuellerstatic struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { 249f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .demod_address = (0x1e >> 1), 250f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .no_tuner = 1, 251f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .disable_i2c_gate_ctrl = 1, 252f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .parallel_ts = 1, 253f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .if2 = 45600, 254f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller}; 255f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller 25617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 25717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller/* [TODO] djh - not sure yet what the device config needs to contain */ 25817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmuellerstatic struct drx397xD_config em28xx_drx397xD_with_xc3028 = { 25917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller .demod_address = (0xe0 >> 1), 26017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller}; 26117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 26217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller 2634fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmuellerstatic int mt352_terratec_xs_init(struct dvb_frontend *fe) 2644fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller{ 2654fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller /* Values extracted from a USB trace of the Terratec Windows driver */ 2664fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; 2674fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 reset[] = { RESET, 0x80 }; 2684fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 2694fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; 2704fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; 2714fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; 2724fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 2734fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; 2744fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; 275ff69786b4ccd0d5b99a60ba0be98237f9b7d8f52Devin Heitmueller static u8 tuner_go[] = { TUNER_GO, 0x01}; 2764fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 2774fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, clock_config, sizeof(clock_config)); 2784fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller udelay(200); 2794fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, reset, sizeof(reset)); 2804fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 2814fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 2824fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); 2834fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); 2844fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 2854fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); 2864fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); 2874fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, tuner_go, sizeof(tuner_go)); 2884fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller return 0; 2894fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller} 2904fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 2914fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmuellerstatic struct mt352_config terratec_xs_mt352_cfg = { 2924fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .demod_address = (0x1e >> 1), 2934fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .no_tuner = 1, 2944fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .if2 = 45600, 2954fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .demod_init = mt352_terratec_xs_init, 2964fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller}; 2974fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 2983aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2993aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3003aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int attach_xc3028(u8 addr, struct em28xx *dev) 3013aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 3023aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab struct dvb_frontend *fe; 3033ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab struct xc2028_config cfg; 3043ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 3056ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf memset(&cfg, 0, sizeof(cfg)); 3063ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_adap = &dev->i2c_adap; 3073ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_addr = addr; 3083ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 3093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev->dvb->frontend) { 3103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: dvb frontend not attached. " 3113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "Can't attach xc3028\n", 3123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 3133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 3143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 3153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); 3173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab if (!fe) { 3183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: xc3028 attach failed\n", 3193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 3203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dev->dvb->frontend); 3213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb->frontend = NULL; 3223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 3233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 3243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); 3263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 3283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 3293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton/* ------------------------------------------------------------------ */ 3313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 332d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuilstatic int register_dvb(struct em28xx_dvb *dvb, 3333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct module *module, 3343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev, 3353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct device *device) 3363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 3373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result; 3383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_init(&dvb->lock); 3403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register adapter */ 3423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, 3433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton adapter_nr); 3443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", 3463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_adapter; 3483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 349e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 350e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab /* Ensure all frontends negotiate bus access */ 351e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 352e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->adapter.priv = dev; 3543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register frontend */ 3563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_frontend(&dvb->adapter, dvb->frontend); 3573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", 3593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_frontend; 3613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register demux stuff */ 3643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.capabilities = 3653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_TS_FILTERING | DMX_SECTION_FILTERING | 3663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_MEMORY_BASED_FILTERING; 3673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.priv = dvb; 3683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.filternum = 256; 3693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.feednum = 256; 3703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.start_feed = start_feed; 3713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.stop_feed = stop_feed; 372e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmx_init(&dvb->demux); 3743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", 3763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmx; 3783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.filternum = 256; 3813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.demux = &dvb->demux.dmx; 3823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.capabilities = 0; 3833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 3843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", 3863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmxdev; 3883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 38952284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab 3903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_hw.source = DMX_FRONTEND_0; 3913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 3943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_hw; 3963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_mem.source = DMX_MEMORY_FE; 3993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 4013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 4023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 4033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_mem; 4043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 4083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", 4093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 4103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_conn; 4113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register network adapter */ 4143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 4153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 4163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_conn: 4183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_mem: 4203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_hw: 4223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 4233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmxdev: 4243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 4253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmx: 4263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 4273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_frontend: 4283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 4293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 4303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_adapter: 4313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 4323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 4333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic void unregister_dvb(struct em28xx_dvb *dvb) 4353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 4363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_release(&dvb->net); 4373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 4403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 4413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 4423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 4433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 4443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 4453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int dvb_init(struct em28xx *dev) 4483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 4493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result = 0; 4503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb; 4513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 452505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (!dev->board.has_dvb) { 453df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 454df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 455df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 456df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 4573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); 4586ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 4596ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (dvb == NULL) { 4606ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); 4613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -ENOMEM; 4623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = dvb; 4643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 465c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 4663aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* init frontend */ 4673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab switch (dev->model) { 468f89bc32974a4376e8393001484af28d8c3350ab4Douglas Schilling Landgraf case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 46910ac6603613d46a43a4544fbbe9581e50879bd45Mauro Carvalho Chehab case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 4704fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 471e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 4723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(lgdt330x_attach, 4733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em2880_lgdt3303_dev, 4743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 479227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab break; 48046510b56ca56a25ce973d6a6e8490c1109ff94efThierry MERLE case EM2880_BOARD_KWORLD_DVB_310U: 481e5db5d44432abc82b1250dd05bd0a4b011392d9dDouglas Schilling Landgraf case EM2880_BOARD_EMPIRE_DUAL_TV: 4823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(zl10353_attach, 4833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em28xx_zl10353_with_xc3028, 4843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4897e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton break; 490a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 491a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller dvb->frontend = dvb_attach(zl10353_attach, 492a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &em28xx_zl10353_xc3028_no_i2c_gate, 493a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &dev->i2c_adap); 494a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 495a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller result = -EINVAL; 496a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller goto out_free; 497a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller } 498a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller break; 499f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller case EM2880_BOARD_TERRATEC_HYBRID_XS: 500d5b3ba9cb375620a109d79f2e3a7bc21e9b75d8fDevin Heitmueller case EM2881_BOARD_PINNACLE_HYBRID_PRO: 501f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller dvb->frontend = dvb_attach(zl10353_attach, 502a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &em28xx_zl10353_xc3028_no_i2c_gate, 503f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller &dev->i2c_adap); 504f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller if (dvb->frontend == NULL) { 505f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller /* This board could have either a zl10353 or a mt352. 506f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller If the chip id isn't for zl10353, try mt352 */ 5074fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller dvb->frontend = dvb_attach(mt352_attach, 5084fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller &terratec_xs_mt352_cfg, 5094fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller &dev->i2c_adap); 510f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller } 5114fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 512f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 513f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller result = -EINVAL; 514f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller goto out_free; 515f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller } 516f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller break; 5176e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora case EM2883_BOARD_KWORLD_HYBRID_330U: 51819859229d7d98bc2d582ff45045dd7f73d649383Devin Heitmueller case EM2882_BOARD_EVGA_INDTUBE: 5196e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora dvb->frontend = dvb_attach(s5h1409_attach, 5206e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora &em28xx_s5h1409_with_xc3028, 5216e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora &dev->i2c_adap); 5226e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora if (attach_xc3028(0x61, dev) < 0) { 5236e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora result = -EINVAL; 5246e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora goto out_free; 5256e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora } 5266e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora break; 527d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng case EM2882_BOARD_KWORLD_ATSC_315U: 528d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng dvb->frontend = dvb_attach(lgdt330x_attach, 529d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &em2880_lgdt3303_dev, 530d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &dev->i2c_adap); 531d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng if (dvb->frontend != NULL) { 532d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng if (!dvb_attach(simple_tuner_attach, dvb->frontend, 533d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { 534d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng result = -EINVAL; 535d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng goto out_free; 536d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng } 537d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng } 538d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng break; 53917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 54017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 54117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller /* We don't have the config structure properly populated, so 54217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller this is commented out for now */ 54317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller dvb->frontend = dvb_attach(drx397xD_attach, 54417d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &em28xx_drx397xD_with_xc3028, 54517d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &dev->i2c_adap); 54617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 54717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller result = -EINVAL; 54817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller goto out_free; 54917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller } 55017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller break; 55117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 5523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab default: 5533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" 5543aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab " isn't supported yet\n", 5553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 5563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab break; 5573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 5583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (NULL == dvb->frontend) { 5593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR 5603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "%s/2: frontend initialization failed\n", 5613aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 5623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 5633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 5643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 565d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky /* define general-purpose callback pointer */ 566d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky dvb->frontend->callback = em28xx_tuner_callback; 5673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* register everything */ 5693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); 5703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5716ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (result < 0) 5723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 5733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5742fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 575102a0b0879a01a413ed5f667f7db9c2085ca8474Mauro Carvalho Chehab printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); 5763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 5773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonout_free: 5792fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 5803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton kfree(dvb); 5813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 5823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 5833aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 5843aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_fini(struct em28xx *dev) 5863aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 587505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (!dev->board.has_dvb) { 588df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 589df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 590df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 591df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 5923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dev->dvb) { 5933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton unregister_dvb(dev->dvb); 5943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 5953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 5963aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5973aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 5983aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 5993aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6003aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = { 6013aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .id = EM28XX_DVB, 6023aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .name = "Em28xx dvb Extension", 6033aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .init = dvb_init, 6043aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .fini = dvb_fini, 6053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}; 6063aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6073aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void) 6083aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 6093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return em28xx_register_extension(&dvb_ops); 6103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void) 6133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 6143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab em28xx_unregister_extension(&dvb_ops); 6153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register); 6183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister); 619