11899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/* 21899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * ngene-dvb.c: nGene PCIe bridge driver - DVB functions 31899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 41899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * Copyright (C) 2005-2007 Micronas 51899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 61899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> 71899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * Modifications for new nGene firmware, 81899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * support for EEPROM-copying, 91899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * support for new dual DVB-S2 card prototype 101899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 111899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 121899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * This program is free software; you can redistribute it and/or 131899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * modify it under the terms of the GNU General Public License 141899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * version 2 only, as published by the Free Software Foundation. 151899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 161899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 171899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * This program is distributed in the hope that it will be useful, 181899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * but WITHOUT ANY WARRANTY; without even the implied warranty of 191899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 201899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * GNU General Public License for more details. 211899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 221899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 231899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * You should have received a copy of the GNU General Public License 241899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * along with this program; if not, write to the Free Software 251899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 261899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * 02110-1301, USA 271899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 281899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller */ 291899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 301899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/module.h> 311899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/init.h> 321899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/delay.h> 331899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/slab.h> 341899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/poll.h> 351899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/io.h> 361899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <asm/div64.h> 371899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/pci.h> 381899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/timer.h> 391899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/byteorder/generic.h> 401899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/firmware.h> 411899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include <linux/vmalloc.h> 421899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 431899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller#include "ngene.h" 441899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 451899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 461899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/****************************************************************************/ 471899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/* COMMAND API interface ****************************************************/ 481899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/****************************************************************************/ 491899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 500f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzlerstatic ssize_t ts_write(struct file *file, const char *buf, 510f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler size_t count, loff_t *ppos) 520f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler{ 530f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct dvb_device *dvbdev = file->private_data; 540f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct ngene_channel *chan = dvbdev->priv; 550f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct ngene *dev = chan->dev; 560f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 570f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler if (wait_event_interruptible(dev->tsout_rbuf.queue, 580f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler dvb_ringbuffer_free 590f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler (&dev->tsout_rbuf) >= count) < 0) 600f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler return 0; 610f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 620f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); 630f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 640f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler return count; 650f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler} 660f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 670f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzlerstatic ssize_t ts_read(struct file *file, char *buf, 680f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler size_t count, loff_t *ppos) 690f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler{ 700f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct dvb_device *dvbdev = file->private_data; 710f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct ngene_channel *chan = dvbdev->priv; 720f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct ngene *dev = chan->dev; 730f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler int left, avail; 740f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 750f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler left = count; 760f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler while (left) { 770f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler if (wait_event_interruptible( 780f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler dev->tsin_rbuf.queue, 790f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0) 800f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler return -EAGAIN; 810f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler avail = dvb_ringbuffer_avail(&dev->tsin_rbuf); 820f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler if (avail > left) 830f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler avail = left; 840f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail); 850f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler left -= avail; 860f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler buf += avail; 870f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler } 880f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler return count; 890f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler} 900f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 910f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzlerstatic const struct file_operations ci_fops = { 920f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .owner = THIS_MODULE, 930f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .read = ts_read, 940f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .write = ts_write, 950f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .open = dvb_generic_open, 960f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .release = dvb_generic_release, 970f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler}; 980f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 990f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzlerstruct dvb_device ngene_dvbdev_ci = { 1000f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .priv = 0, 1010f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .readers = -1, 1020f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .writers = -1, 1030f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .users = -1, 1040f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler .fops = &ci_fops, 1050f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler}; 1060f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 1070f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler 1081899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/****************************************************************************/ 1091899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/* DVB functions and API interface ******************************************/ 1101899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller/****************************************************************************/ 1111899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1121899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellerstatic void swap_buffer(u32 *p, u32 len) 1131899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 1141899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller while (len) { 1151899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller *p = swab32(*p); 1161899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller p++; 1171899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller len -= 4; 1181899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller } 1191899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 1201899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 12136e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss/* start of filler packet */ 12236e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endrissstatic u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER }; 12336e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss 12436e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss/* #define DEBUG_CI_XFER */ 12536e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#ifdef DEBUG_CI_XFER 12636e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endrissstatic u32 ok; 12736e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endrissstatic u32 overflow; 12836e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endrissstatic u32 stripped; 12936e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#endif 13036e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss 1311899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellervoid *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 1321899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 1331899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct ngene_channel *chan = priv; 1340f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler struct ngene *dev = chan->dev; 1351899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1361899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1370f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler if (flags & DF_SWAP32) 1380f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler swap_buffer(buf, len); 13936e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss 1400f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler if (dev->ci.en && chan->number == 2) { 14136e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss while (len >= 188) { 14236e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) { 14336e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) { 14436e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188); 14536e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss wake_up(&dev->tsin_rbuf.queue); 14636e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#ifdef DEBUG_CI_XFER 14736e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss ok++; 14836e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#endif 14936e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss } 15036e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#ifdef DEBUG_CI_XFER 15136e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss else 15236e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss overflow++; 15336e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#endif 15436e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss } 15536e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#ifdef DEBUG_CI_XFER 15636e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss else 15736e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss stripped++; 15836e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss 15936e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss if (ok % 100 == 0 && overflow) 16036e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped); 16136e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss#endif 16236e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss buf += 188; 16336e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss len -= 188; 1640f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler } 16536e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss return NULL; 1660f0b270f905bbb0c8e75988ceaf10ff9a401e712Ralph Metzler } 16736e3fc8957abffa3218a6e3b61bef335eea80c03Oliver Endriss 1689143a437cc2fe329c271115903a3884950aba57dOliver Endriss if (chan->users > 0) 1691899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvb_dmx_swfilter(&chan->demux, buf, len); 1709143a437cc2fe329c271115903a3884950aba57dOliver Endriss 1711899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return NULL; 1721899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 1731899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1741899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellervoid *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 1751899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 1761899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct ngene_channel *chan = priv; 1771899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct ngene *dev = chan->dev; 1781899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller u32 alen; 1791899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1801899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); 1811899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller alen -= alen % 188; 1821899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1831899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller if (alen < len) 1841899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller FillTSBuffer(buf + alen, len - alen, flags); 1851899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller else 1861899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller alen = len; 1871899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); 1881899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller if (flags & DF_SWAP32) 1891899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller swap_buffer((u32 *)buf, alen); 1901899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller wake_up_interruptible(&dev->tsout_rbuf.queue); 1911899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return buf; 1921899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 1931899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1941899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1951899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 1961899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellerint ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) 1971899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 1981899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 1991899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct ngene_channel *chan = dvbdmx->priv; 2001899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2011899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller if (chan->users == 0) { 2025a2a1848a7d744a437f96b79a655c13b8090e74dOliver Endriss if (!chan->dev->cmd_timeout_workaround || !chan->running) 2031899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller set_transfer(chan, 1); 2041899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller } 2051899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2061899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return ++chan->users; 2071899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 2081899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2091899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellerint ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 2101899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 2111899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 2121899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct ngene_channel *chan = dvbdmx->priv; 2131899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2141899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller if (--chan->users) 2151899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return chan->users; 2161899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2175a2a1848a7d744a437f96b79a655c13b8090e74dOliver Endriss if (!chan->dev->cmd_timeout_workaround) 2185a2a1848a7d744a437f96b79a655c13b8090e74dOliver Endriss set_transfer(chan, 0); 2191899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2201899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return 0; 2211899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 2221899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2231899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellerint my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, 2241899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller int (*start_feed)(struct dvb_demux_feed *), 2251899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller int (*stop_feed)(struct dvb_demux_feed *), 2261899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller void *priv) 2271899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 2281899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->priv = priv; 2291899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2301899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->filternum = 256; 2311899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->feednum = 256; 2321899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->start_feed = start_feed; 2331899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->stop_feed = stop_feed; 2341899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->write_to_decoder = NULL; 2351899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 2361899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller DMX_SECTION_FILTERING | 2371899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller DMX_MEMORY_BASED_FILTERING); 2381899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return dvb_dmx_init(dvbdemux); 2391899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 2401899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2411899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmuellerint my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, 2421899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dvb_demux *dvbdemux, 2431899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dmx_frontend *hw_frontend, 2441899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dmx_frontend *mem_frontend, 2451899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller struct dvb_adapter *dvb_adapter) 2461899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller{ 2471899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller int ret; 2481899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2491899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dmxdev->filternum = 256; 2501899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dmxdev->demux = &dvbdemux->dmx; 2511899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dmxdev->capabilities = 0; 2521899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller ret = dvb_dmxdev_init(dmxdev, dvb_adapter); 2531899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller if (ret < 0) 2541899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return ret; 2551899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller 2561899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller hw_frontend->source = DMX_FRONTEND_0; 2571899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); 2581899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller mem_frontend->source = DMX_MEMORY_FE; 2591899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); 2601899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); 2611899e97c52b80c734ead7a98f54ed6fd6e1db96aDevin Heitmueller} 262