1/* 2 * ngene-dvb.c: nGene PCIe bridge driver - DVB functions 3 * 4 * Copyright (C) 2005-2007 Micronas 5 * 6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> 7 * Modifications for new nGene firmware, 8 * support for EEPROM-copying, 9 * support for new dual DVB-S2 card prototype 10 * 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * version 2 only, as published by the Free Software Foundation. 15 * 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 * 02110-1301, USA 27 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 28 */ 29 30#include <linux/module.h> 31#include <linux/init.h> 32#include <linux/delay.h> 33#include <linux/slab.h> 34#include <linux/poll.h> 35#include <linux/io.h> 36#include <asm/div64.h> 37#include <linux/pci.h> 38#include <linux/smp_lock.h> 39#include <linux/timer.h> 40#include <linux/byteorder/generic.h> 41#include <linux/firmware.h> 42#include <linux/vmalloc.h> 43 44#include "ngene.h" 45 46 47/****************************************************************************/ 48/* COMMAND API interface ****************************************************/ 49/****************************************************************************/ 50 51/****************************************************************************/ 52/* DVB functions and API interface ******************************************/ 53/****************************************************************************/ 54 55static void swap_buffer(u32 *p, u32 len) 56{ 57 while (len) { 58 *p = swab32(*p); 59 p++; 60 len -= 4; 61 } 62} 63 64void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 65{ 66 struct ngene_channel *chan = priv; 67 68 69 if (chan->users > 0) 70 dvb_dmx_swfilter(&chan->demux, buf, len); 71 return NULL; 72} 73 74u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; 75 76void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 77{ 78 struct ngene_channel *chan = priv; 79 struct ngene *dev = chan->dev; 80 u32 alen; 81 82 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); 83 alen -= alen % 188; 84 85 if (alen < len) 86 FillTSBuffer(buf + alen, len - alen, flags); 87 else 88 alen = len; 89 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); 90 if (flags & DF_SWAP32) 91 swap_buffer((u32 *)buf, alen); 92 wake_up_interruptible(&dev->tsout_rbuf.queue); 93 return buf; 94} 95 96 97 98int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) 99{ 100 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 101 struct ngene_channel *chan = dvbdmx->priv; 102 103 if (chan->users == 0) { 104 if (!chan->dev->cmd_timeout_workaround || !chan->running) 105 set_transfer(chan, 1); 106 } 107 108 return ++chan->users; 109} 110 111int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 112{ 113 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 114 struct ngene_channel *chan = dvbdmx->priv; 115 116 if (--chan->users) 117 return chan->users; 118 119 if (!chan->dev->cmd_timeout_workaround) 120 set_transfer(chan, 0); 121 122 return 0; 123} 124 125int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, 126 int (*start_feed)(struct dvb_demux_feed *), 127 int (*stop_feed)(struct dvb_demux_feed *), 128 void *priv) 129{ 130 dvbdemux->priv = priv; 131 132 dvbdemux->filternum = 256; 133 dvbdemux->feednum = 256; 134 dvbdemux->start_feed = start_feed; 135 dvbdemux->stop_feed = stop_feed; 136 dvbdemux->write_to_decoder = NULL; 137 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 138 DMX_SECTION_FILTERING | 139 DMX_MEMORY_BASED_FILTERING); 140 return dvb_dmx_init(dvbdemux); 141} 142 143int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, 144 struct dvb_demux *dvbdemux, 145 struct dmx_frontend *hw_frontend, 146 struct dmx_frontend *mem_frontend, 147 struct dvb_adapter *dvb_adapter) 148{ 149 int ret; 150 151 dmxdev->filternum = 256; 152 dmxdev->demux = &dvbdemux->dmx; 153 dmxdev->capabilities = 0; 154 ret = dvb_dmxdev_init(dmxdev, dvb_adapter); 155 if (ret < 0) 156 return ret; 157 158 hw_frontend->source = DMX_FRONTEND_0; 159 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); 160 mem_frontend->source = DMX_MEMORY_FE; 161 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); 162 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); 163} 164