em28xx-dvb.c revision e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7
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> 283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "lgdt330x.h" 307e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton#include "zl10353.h" 3117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 3217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#include "drx397xD.h" 3317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 353aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards"); 363aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 373aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL"); 383aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 393aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug; 403aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644); 413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do { \ 463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) \ 473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ 483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0) 493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_NUM_BUFS 5 513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETSIZE 564 523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETS 64 533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstruct em28xx_dvb { 553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_frontend *frontend; 563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* feed count management */ 583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct mutex lock; 593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int nfeeds; 603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* general boilerplate stuff */ 623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_adapter adapter; 633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux demux; 643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmxdev dmxdev; 653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_hw; 663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dmx_frontend fe_mem; 673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_net net; 683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}; 693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline void print_err_status(struct em28xx *dev, 723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int packet, int status) 733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton char *errmsg = "Unknown"; 753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton switch (status) { 773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOENT: 783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked synchronuously"; 793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ECONNRESET: 813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "unlinked asynchronuously"; 823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ENOSR: 843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Buffer error (overrun)"; 853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPIPE: 873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Stalled (device not responding)"; 883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EOVERFLOW: 903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Babble (bad cable?)"; 913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EPROTO: 933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Bit-stuff error (bad cable?)"; 943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -EILSEQ: 963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "CRC/Timeout (could be anything)"; 973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton case -ETIME: 993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton errmsg = "Device does not respond"; 1003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton break; 1013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (packet < 0) { 1033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dprintk(1, "URB status %d [%s].\n", status, errmsg); 1043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } else { 1056ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk(1, "URB packet %d, status %d [%s].\n", 1066ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf packet, status, errmsg); 1073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) 1113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int i; 1133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev) 1153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) 1183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status < 0) { 1213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, -1, urb->status); 1223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->status == -ENOENT) 1233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton for (i = 0; i < urb->number_of_packets; i++) { 1273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int status = urb->iso_frame_desc[i].status; 1283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (status < 0) { 1303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton print_err_status(dev, i, status); 1313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (urb->iso_frame_desc[i].status != -EPROTO) 1323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton continue; 1333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + 1363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].offset, 1373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton urb->iso_frame_desc[i].actual_length); 1383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 1413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1436ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int start_streaming(struct em28xx_dvb *dvb) 1446ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 145c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab int rc; 1463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton usb_set_interface(dev->udev, 0, 1); 149c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 150c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab if (rc < 0) 151c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab return rc; 1523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, 1543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, 155c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab dvb_isoc_copy); 1563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1586ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafstatic int stop_streaming(struct em28xx_dvb *dvb) 1596ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{ 1603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev = dvb->adapter.priv; 1613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton em28xx_uninit_isoc(dev); 163c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 164c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 165c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab 1663aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 1673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 1683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 1693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int start_feed(struct dvb_demux_feed *feed) 1703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int rc, ret; 1743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!demux->dmx.frontend) 1763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -EINVAL; 1773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds++; 1803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton rc = dvb->nfeeds; 1813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dvb->nfeeds == 1) { 1833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton ret = start_streaming(dvb); 1846ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (ret < 0) 1856ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf rc = ret; 1863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 1873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 1893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return rc; 1903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 1913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int stop_feed(struct dvb_demux_feed *feed) 1933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 1943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct dvb_demux *demux = feed->demux; 1953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb = demux->priv; 1963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int err = 0; 1973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 1983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_lock(&dvb->lock); 1993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->nfeeds--; 2006ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2016ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (0 == dvb->nfeeds) 2023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton err = stop_streaming(dvb); 2036ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 2043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_unlock(&dvb->lock); 2053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return err; 2063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 2073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 209e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 210e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 211e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehabstatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 212e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab{ 213e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab struct em28xx *dev = fe->dvb->priv; 214e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 215e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab if (acquire) 216e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 217e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab else 218e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 219e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab} 220e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 223227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = { 224227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_address = 0x0e, 225227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab .demod_chip = LGDT3303, 226227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab}; 2273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2287e6388a1b97cca57a1906df6104feb4001721576Aidan Thorntonstatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 2297e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .demod_address = (0x1e >> 1), 2307e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .no_tuner = 1, 2317e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .parallel_ts = 1, 2327e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton .if2 = 45600, 2337e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton}; 2347e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton 23517d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 23617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller/* [TODO] djh - not sure yet what the device config needs to contain */ 23717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmuellerstatic struct drx397xD_config em28xx_drx397xD_with_xc3028 = { 23817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller .demod_address = (0xe0 >> 1), 23917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller}; 24017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 24117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller 2423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */ 2433aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int attach_xc3028(u8 addr, struct em28xx *dev) 2453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 2463aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab struct dvb_frontend *fe; 2473ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab struct xc2028_config cfg; 2483ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 2496ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf memset(&cfg, 0, sizeof(cfg)); 2503ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_adap = &dev->i2c_adap; 2513ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.i2c_addr = addr; 2523ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab cfg.callback = em28xx_tuner_callback; 2533ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab 2543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (!dev->dvb->frontend) { 2553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: dvb frontend not attached. " 2563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "Can't attach xc3028\n", 2573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 2583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 2593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 2603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); 2623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab if (!fe) { 2633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: xc3028 attach failed\n", 2643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 2653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dev->dvb->frontend); 2663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb->frontend = NULL; 2673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return -EINVAL; 2683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 2693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); 2713aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2723aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 2733aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 2743aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton/* ------------------------------------------------------------------ */ 2763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 2773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonint register_dvb(struct em28xx_dvb *dvb, 2783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct module *module, 2793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx *dev, 2803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct device *device) 2813aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 2823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result; 2833aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton mutex_init(&dvb->lock); 2853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 2863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register adapter */ 2873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, 2883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton adapter_nr); 2893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 2903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", 2913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 2923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_adapter; 2933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 294e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 295e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab /* Ensure all frontends negotiate bus access */ 296e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 297e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 2983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->adapter.priv = dev; 2993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register frontend */ 3013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_register_frontend(&dvb->adapter, dvb->frontend); 3023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", 3043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_frontend; 3063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register demux stuff */ 3093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.capabilities = 3103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_TS_FILTERING | DMX_SECTION_FILTERING | 3113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton DMX_MEMORY_BASED_FILTERING; 3123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.priv = dvb; 3133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.filternum = 256; 3143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.feednum = 256; 3153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.start_feed = start_feed; 3163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.stop_feed = stop_feed; 317e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab 3183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmx_init(&dvb->demux); 3193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", 3213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmx; 3233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.filternum = 256; 3263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.demux = &dvb->demux.dmx; 3273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->dmxdev.capabilities = 0; 3283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 3293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", 3313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_dmxdev; 3333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 33452284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab 3353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_hw.source = DMX_FRONTEND_0; 3363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 3393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_hw; 3413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->fe_mem.source = DMX_MEMORY_FE; 3443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 3473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_mem; 3493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (result < 0) { 3533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", 3543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->name, result); 3553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto fail_fe_conn; 3563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 3573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton /* register network adapter */ 3593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 3603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 3613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_conn: 3633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_mem: 3653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_hw: 3673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 3683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmxdev: 3693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 3703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmx: 3713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 3723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_frontend: 3733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 3743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 3753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_adapter: 3763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 3773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 3783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic void unregister_dvb(struct em28xx_dvb *dvb) 3803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 3813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_net_release(&dvb->net); 3823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 3833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 3843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmxdev_release(&dvb->dmxdev); 3853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_dmx_release(&dvb->demux); 3863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_frontend(dvb->frontend); 3873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_frontend_detach(dvb->frontend); 3883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb_unregister_adapter(&dvb->adapter); 3893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton} 3903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 3923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic int dvb_init(struct em28xx *dev) 3933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{ 3943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton int result = 0; 3953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton struct em28xx_dvb *dvb; 3963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 397df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller if (!dev->has_dvb) { 398df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 399df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 400df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 401df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 4023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); 4036ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 4046ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (dvb == NULL) { 4056ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); 4063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return -ENOMEM; 4073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = dvb; 4093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 410c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 4113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* init frontend */ 4123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab switch (dev->model) { 413227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 4144fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 415e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 4163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(lgdt330x_attach, 4173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em2880_lgdt3303_dev, 4183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 423227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab break; 4247e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 4253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dvb->frontend = dvb_attach(zl10353_attach, 4263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &em28xx_zl10353_with_xc3028, 4273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton &dev->i2c_adap); 4283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (attach_xc3028(0x61, dev) < 0) { 4293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4327e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton break; 43317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 43417d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#ifdef EM28XX_DRX397XD_SUPPORT 43517d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller /* We don't have the config structure properly populated, so 43617d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller this is commented out for now */ 43717d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller dvb->frontend = dvb_attach(drx397xD_attach, 43817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &em28xx_drx397xD_with_xc3028, 43917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller &dev->i2c_adap); 44017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller if (attach_xc3028(0x61, dev) < 0) { 44117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller result = -EINVAL; 44217d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller goto out_free; 44317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller } 44417d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller break; 44517d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller#endif 446655b8408557d586212d0797d423babdc464c587freinhard schwab case EM2880_BOARD_TERRATEC_HYBRID_XS: 447655b8408557d586212d0797d423babdc464c587freinhard schwab dvb->frontend = dvb_attach(zl10353_attach, 448655b8408557d586212d0797d423babdc464c587freinhard schwab &em28xx_zl10353_with_xc3028, 449655b8408557d586212d0797d423babdc464c587freinhard schwab &dev->i2c_adap); 450655b8408557d586212d0797d423babdc464c587freinhard schwab if (attach_xc3028(0x61, dev) < 0) { 451655b8408557d586212d0797d423babdc464c587freinhard schwab result = -EINVAL; 452655b8408557d586212d0797d423babdc464c587freinhard schwab goto out_free; 453655b8408557d586212d0797d423babdc464c587freinhard schwab } 454655b8408557d586212d0797d423babdc464c587freinhard schwab break; 4553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab default: 4563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" 4573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab " isn't supported yet\n", 4583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 4593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab break; 4603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 4613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (NULL == dvb->frontend) { 4623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab printk(KERN_ERR 4633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab "%s/2: frontend initialization failed\n", 4643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab dev->name); 4653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = -EINVAL; 4663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab } 4683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab /* register everything */ 4703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); 4713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4726ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (result < 0) 4733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton goto out_free; 4743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 475c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 476102a0b0879a01a413ed5f667f7db9c2085ca8474Mauro Carvalho Chehab printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); 4773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return 0; 4783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton 4793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonout_free: 480c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); 4813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton kfree(dvb); 4823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 4833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton return result; 4843aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 4853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4863aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int dvb_fini(struct em28xx *dev) 4873aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 488df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller if (!dev->has_dvb) { 489df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller /* This device does not support the extension */ 490df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller return 0; 491df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller } 492df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller 4933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton if (dev->dvb) { 4943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton unregister_dvb(dev->dvb); 4953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton dev->dvb = NULL; 4963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton } 4973aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 4983aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return 0; 4993aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 5003aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5013aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = { 5023aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .id = EM28XX_DVB, 5033aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .name = "Em28xx dvb Extension", 5043aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .init = dvb_init, 5053aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab .fini = dvb_fini, 5063aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}; 5073aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5083aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void) 5093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 5103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab return em28xx_register_extension(&dvb_ops); 5113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 5123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void) 5143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{ 5153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab em28xx_unregister_extension(&dvb_ops); 5163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} 5173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab 5183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register); 5193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister); 520