em28xx-dvb.c revision ec994d0505fc3dde5f46203602c76b527e2ac69d
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 */ 36285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari#include "tda1002x.h" 373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards"); 393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL"); 413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug; 433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644); 443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do { \ 493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) \ 503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ 513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0) 523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_NUM_BUFS 5 543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETS 64 553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstruct em28xx_dvb { 573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_frontend *frontend; 583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* feed count management */ 603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct mutex lock; 613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int nfeeds; 623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* general boilerplate stuff */ 643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_adapter adapter; 653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux demux; 663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmxdev dmxdev; 673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_hw; 683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_mem; 693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_net net; 703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}; 713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline void print_err_status(struct em28xx *dev, 743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int packet, int status) 753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton char *errmsg = "Unknown"; 773aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton switch (status) { 793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOENT: 803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked synchronuously"; 813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ECONNRESET: 833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked asynchronuously"; 843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOSR: 863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Buffer error (overrun)"; 873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPIPE: 893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Stalled (device not responding)"; 903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EOVERFLOW: 923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Babble (bad cable?)"; 933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPROTO: 953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Bit-stuff error (bad cable?)"; 963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EILSEQ: 983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "CRC/Timeout (could be anything)"; 993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 1003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ETIME: 1013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Device does not respond"; 1023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 1033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (packet < 0) { 1053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dprintk(1, "URB status %d [%s].\n", status, errmsg); 1063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } else { 1076ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk(1, "URB packet %d, status %d [%s].\n", 1086ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf packet, status, errmsg); 1093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) 1133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int i; 1153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev) 1173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) 1203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status < 0) { 1233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, -1, urb->status); 1243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status == -ENOENT) 1253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton for (i = 0; i < urb->number_of_packets; i++) { 1293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int status = urb->iso_frame_desc[i].status; 1303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (status < 0) { 1323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, i, status); 1333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->iso_frame_desc[i].status != -EPROTO) 1343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton continue; 1353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + 1383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].offset, 1393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].actual_length); 1403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int start_streaming(struct em28xx_dvb *dvb) 1466ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 147c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab int rc; 1483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 149d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller int max_dvb_packet_size; 1503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton usb_set_interface(dev->udev, 0, 1); 152c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 153c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab if (rc < 0) 154c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab return rc; 1553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 156d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); 157d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller 1583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, 159d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, 160c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab dvb_isoc_copy); 1613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1636ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int stop_streaming(struct em28xx_dvb *dvb) 1646ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 1653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton em28xx_uninit_isoc(dev); 168c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1692fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 170c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 1723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 1733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int start_feed(struct dvb_demux_feed *feed) 1753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int rc, ret; 1793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!demux->dmx.frontend) 1813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -EINVAL; 1823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds++; 1853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton rc = dvb->nfeeds; 1863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dvb->nfeeds == 1) { 1883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton ret = start_streaming(dvb); 1896ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (ret < 0) 1906ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf rc = ret; 1913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 1943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return rc; 1953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int stop_feed(struct dvb_demux_feed *feed) 1983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 2003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 2013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int err = 0; 2023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 2043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds--; 2056ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2066ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (0 == dvb->nfeeds) 2073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton err = stop_streaming(dvb); 2086ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 2103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return err; 2113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 2123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 214e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 215e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 216e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehabstatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 217e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab{ 218e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab struct em28xx *dev = fe->dvb->priv; 219e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 220e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab if (acquire) 221e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 222e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab else 2232fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_SUSPEND); 224e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab} 225e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 228227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = { 229227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_address = 0x0e, 230227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_chip = LGDT3303, 231227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab}; 2323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2337e6388a1b97cca57a1906df6104feb4001721576Aidan Thorntonstatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 2347e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .demod_address = (0x1e >> 1), 2357e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .no_tuner = 1, 2367e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .parallel_ts = 1, 2377e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .if2 = 45600, 2387e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton}; 2397e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton 2406e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakorastatic struct s5h1409_config em28xx_s5h1409_with_xc3028 = { 2416e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .demod_address = 0x32 >> 1, 2426e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .output_mode = S5H1409_PARALLEL_OUTPUT, 2436e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .gpio = S5H1409_GPIO_OFF, 2446e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .inversion = S5H1409_INVERSION_OFF, 2456e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .status_mode = S5H1409_DEMODLOCKING, 2466e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 2476e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora}; 2486e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora 249a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmuellerstatic struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { 250f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .demod_address = (0x1e >> 1), 251f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .no_tuner = 1, 252f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .disable_i2c_gate_ctrl = 1, 253f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .parallel_ts = 1, 254f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller .if2 = 45600, 255f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller}; 256f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller 25717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 25817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller/* [TODO] djh - not sure yet what the device config needs to contain */ 25917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmuellerstatic struct drx397xD_config em28xx_drx397xD_with_xc3028 = { 26017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller .demod_address = (0xe0 >> 1), 26117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller}; 26217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 26317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller 2644fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmuellerstatic int mt352_terratec_xs_init(struct dvb_frontend *fe) 2654fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller{ 2664fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller /* Values extracted from a USB trace of the Terratec Windows driver */ 2674fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; 2684fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 reset[] = { RESET, 0x80 }; 2694fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 2704fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; 2714fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; 2724fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; 2734fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 2744fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; 2754fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; 276ff69786b4ccd0d5b99a60ba0be98237f9b7d8f52Devin Heitmueller static u8 tuner_go[] = { TUNER_GO, 0x01}; 2774fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 2784fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, clock_config, sizeof(clock_config)); 2794fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller udelay(200); 2804fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, reset, sizeof(reset)); 2814fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 2824fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 2834fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); 2844fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); 2854fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 2864fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); 2874fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); 2884fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller mt352_write(fe, tuner_go, sizeof(tuner_go)); 2894fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller return 0; 2904fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller} 2914fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 2924fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmuellerstatic struct mt352_config terratec_xs_mt352_cfg = { 2934fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .demod_address = (0x1e >> 1), 2944fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .no_tuner = 1, 2954fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .if2 = 45600, 2964fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller .demod_init = mt352_terratec_xs_init, 2974fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller}; 2984fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 299285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaaristatic struct tda10023_config em28xx_tda10023_config = { 300285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari .demod_address = 0x0c, 301285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari .invert = 1, 302285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari}; 303285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari 3043aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 3053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3063aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int attach_xc3028(u8 addr, struct em28xx *dev) 3073aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 3083aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab struct dvb_frontend *fe; 3093ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab struct xc2028_config cfg; 3103ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 3116ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf memset(&cfg, 0, sizeof(cfg)); 3123ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_adap = &dev->i2c_adap; 3133ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_addr = addr; 3143ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 3153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev->dvb->frontend) { 3163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: dvb frontend not attached. " 3173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "Can't attach xc3028\n", 3183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 3193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 3203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 3213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); 3233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab if (!fe) { 3243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: xc3028 attach failed\n", 3253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 3263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dev->dvb->frontend); 3273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb->frontend = NULL; 3283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 3293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 3303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); 3323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 3343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 3353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton/* ------------------------------------------------------------------ */ 3373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 338d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuilstatic int register_dvb(struct em28xx_dvb *dvb, 3393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct module *module, 3403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev, 3413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct device *device) 3423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 3433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result; 3443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_init(&dvb->lock); 3463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 3473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register adapter */ 3483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, 3493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton adapter_nr); 3503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", 3523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_adapter; 3543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 355e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 356e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab /* Ensure all frontends negotiate bus access */ 357e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 358e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->adapter.priv = dev; 3603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register frontend */ 3623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_frontend(&dvb->adapter, dvb->frontend); 3633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", 3653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_frontend; 3673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register demux stuff */ 3703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.capabilities = 3713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_TS_FILTERING | DMX_SECTION_FILTERING | 3723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_MEMORY_BASED_FILTERING; 3733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.priv = dvb; 3743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.filternum = 256; 3753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.feednum = 256; 3763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.start_feed = start_feed; 3773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.stop_feed = stop_feed; 378e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmx_init(&dvb->demux); 3803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", 3823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmx; 3843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.filternum = 256; 3873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.demux = &dvb->demux.dmx; 3883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.capabilities = 0; 3893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 3903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", 3923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmxdev; 3943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 39552284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab 3963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_hw.source = DMX_FRONTEND_0; 3973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 4003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 4013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_hw; 4023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_mem.source = DMX_MEMORY_FE; 4053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 4073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 4083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 4093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_mem; 4103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 4143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", 4153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 4163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_conn; 4173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register network adapter */ 4203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 4213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 4223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_conn: 4243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_mem: 4263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_hw: 4283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 4293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmxdev: 4303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 4313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmx: 4323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 4333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_frontend: 4343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 4353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 4363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_adapter: 4373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 4383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 4393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic void unregister_dvb(struct em28xx_dvb *dvb) 4413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 4423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_release(&dvb->net); 4433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 4443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 4453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 4463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 4473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 4483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 4493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 4503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 4513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int dvb_init(struct em28xx *dev) 4543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 4553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result = 0; 4563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb; 4573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 458505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (!dev->board.has_dvb) { 459df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 460df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 461df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 462df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 4633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); 4646ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 4656ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (dvb == NULL) { 4666ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); 4673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -ENOMEM; 4683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = dvb; 4703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 471c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 4723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* init frontend */ 4733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab switch (dev->model) { 474f89bc32974a4376e8393001484af28d8c3350ab4Douglas Schilling Landgraf case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 47510ac6603613d46a43a4544fbbe9581e50879bd45Mauro Carvalho Chehab case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 4764fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 477e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 4783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(lgdt330x_attach, 4793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em2880_lgdt3303_dev, 4803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 485227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab break; 48646510b56ca56a25ce973d6a6e8490c1109ff94efThierry MERLE case EM2880_BOARD_KWORLD_DVB_310U: 4873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(zl10353_attach, 4883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em28xx_zl10353_with_xc3028, 4893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4947e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton break; 495a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 496ec994d0505fc3dde5f46203602c76b527e2ac69dUroš Vampl case EM2882_BOARD_TERRATEC_HYBRID_XS: 49701a5fd6ff3fbae9a599d3334a8cca0f00865e360Devin Heitmueller case EM2880_BOARD_EMPIRE_DUAL_TV: 498a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller dvb->frontend = dvb_attach(zl10353_attach, 499a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &em28xx_zl10353_xc3028_no_i2c_gate, 500a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &dev->i2c_adap); 501a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 502a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller result = -EINVAL; 503a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller goto out_free; 504a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller } 505a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller break; 506f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller case EM2880_BOARD_TERRATEC_HYBRID_XS: 507d5b3ba9cb375620a109d79f2e3a7bc21e9b75d8fDevin Heitmueller case EM2881_BOARD_PINNACLE_HYBRID_PRO: 508f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller dvb->frontend = dvb_attach(zl10353_attach, 509a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller &em28xx_zl10353_xc3028_no_i2c_gate, 510f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller &dev->i2c_adap); 511f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller if (dvb->frontend == NULL) { 512f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller /* This board could have either a zl10353 or a mt352. 513f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller If the chip id isn't for zl10353, try mt352 */ 5144fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller dvb->frontend = dvb_attach(mt352_attach, 5154fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller &terratec_xs_mt352_cfg, 5164fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller &dev->i2c_adap); 517f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller } 5184fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller 519f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 520f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller result = -EINVAL; 521f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller goto out_free; 522f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller } 523f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller break; 5246e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora case EM2883_BOARD_KWORLD_HYBRID_330U: 52519859229d7d98bc2d582ff45045dd7f73d649383Devin Heitmueller case EM2882_BOARD_EVGA_INDTUBE: 5266e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora dvb->frontend = dvb_attach(s5h1409_attach, 5276e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora &em28xx_s5h1409_with_xc3028, 5286e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora &dev->i2c_adap); 5296e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora if (attach_xc3028(0x61, dev) < 0) { 5306e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora result = -EINVAL; 5316e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora goto out_free; 5326e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora } 5336e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora break; 534d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng case EM2882_BOARD_KWORLD_ATSC_315U: 535d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng dvb->frontend = dvb_attach(lgdt330x_attach, 536d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &em2880_lgdt3303_dev, 537d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &dev->i2c_adap); 538d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng if (dvb->frontend != NULL) { 539d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng if (!dvb_attach(simple_tuner_attach, dvb->frontend, 540d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { 541d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng result = -EINVAL; 542d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng goto out_free; 543d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng } 544d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng } 545d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng break; 54617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 54717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 54817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller /* We don't have the config structure properly populated, so 54917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller this is commented out for now */ 55017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller dvb->frontend = dvb_attach(drx397xD_attach, 55117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &em28xx_drx397xD_with_xc3028, 55217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &dev->i2c_adap); 55317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 55417d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller result = -EINVAL; 55517d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller goto out_free; 55617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller } 55717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller break; 55817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 559285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari case EM2870_BOARD_REDDO_DVB_C_USB_BOX: 560285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ 561285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari dvb->frontend = dvb_attach(tda10023_attach, 562285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari &em28xx_tda10023_config, 563285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari &dev->i2c_adap, 0x48); 564285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari if (dvb->frontend) { 565285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari if (!dvb_attach(simple_tuner_attach, dvb->frontend, 566285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { 567285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari result = -EINVAL; 568285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari goto out_free; 569285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari } 570285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari } 571285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari break; 5723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab default: 5733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" 5743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab " isn't supported yet\n", 5753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 5763aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab break; 5773aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 5783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (NULL == dvb->frontend) { 5793aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR 5803aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "%s/2: frontend initialization failed\n", 5813aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 5823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 5833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 5843aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 585d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky /* define general-purpose callback pointer */ 586d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky dvb->frontend->callback = em28xx_tuner_callback; 5873aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5883aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* register everything */ 5893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); 5903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5916ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (result < 0) 5923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 5933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5942fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 595102a0b0879a01a413ed5f667f7db9c2085ca8474Mauro Carvalho Chehab printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); 5963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 5973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 5983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonout_free: 5992fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_SUSPEND); 6003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton kfree(dvb); 6013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 6023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 6033aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6043aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_fini(struct em28xx *dev) 6063aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 607505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (!dev->board.has_dvb) { 608df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 609df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 610df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 611df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 6123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dev->dvb) { 6133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton unregister_dvb(dev->dvb); 6143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 6153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 6163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 6183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = { 6213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .id = EM28XX_DVB, 6223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .name = "Em28xx dvb Extension", 6233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .init = dvb_init, 6243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .fini = dvb_fini, 6253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}; 6263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void) 6283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 6293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return em28xx_register_extension(&dvb_ops); 6303aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void) 6333aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 6343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab em28xx_unregister_extension(&dvb_ops); 6353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 6363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 6373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register); 6383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister); 639