linux/drivers/media/dvb/ngene/ngene-dvb.c
<<
>>
Prefs
   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/timer.h>
  39#include <linux/byteorder/generic.h>
  40#include <linux/firmware.h>
  41#include <linux/vmalloc.h>
  42
  43#include "ngene.h"
  44
  45
  46/****************************************************************************/
  47/* COMMAND API interface ****************************************************/
  48/****************************************************************************/
  49
  50/****************************************************************************/
  51/* DVB functions and API interface ******************************************/
  52/****************************************************************************/
  53
  54static void swap_buffer(u32 *p, u32 len)
  55{
  56        while (len) {
  57                *p = swab32(*p);
  58                p++;
  59                len -= 4;
  60        }
  61}
  62
  63void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
  64{
  65        struct ngene_channel *chan = priv;
  66
  67
  68        if (chan->users > 0)
  69                dvb_dmx_swfilter(&chan->demux, buf, len);
  70        return NULL;
  71}
  72
  73u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 };
  74
  75void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
  76{
  77        struct ngene_channel *chan = priv;
  78        struct ngene *dev = chan->dev;
  79        u32 alen;
  80
  81        alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
  82        alen -= alen % 188;
  83
  84        if (alen < len)
  85                FillTSBuffer(buf + alen, len - alen, flags);
  86        else
  87                alen = len;
  88        dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
  89        if (flags & DF_SWAP32)
  90                swap_buffer((u32 *)buf, alen);
  91        wake_up_interruptible(&dev->tsout_rbuf.queue);
  92        return buf;
  93}
  94
  95
  96
  97int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
  98{
  99        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 100        struct ngene_channel *chan = dvbdmx->priv;
 101
 102        if (chan->users == 0) {
 103                if (!chan->dev->cmd_timeout_workaround || !chan->running)
 104                        set_transfer(chan, 1);
 105        }
 106
 107        return ++chan->users;
 108}
 109
 110int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 111{
 112        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 113        struct ngene_channel *chan = dvbdmx->priv;
 114
 115        if (--chan->users)
 116                return chan->users;
 117
 118        if (!chan->dev->cmd_timeout_workaround)
 119                set_transfer(chan, 0);
 120
 121        return 0;
 122}
 123
 124int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
 125                            int (*start_feed)(struct dvb_demux_feed *),
 126                            int (*stop_feed)(struct dvb_demux_feed *),
 127                            void *priv)
 128{
 129        dvbdemux->priv = priv;
 130
 131        dvbdemux->filternum = 256;
 132        dvbdemux->feednum = 256;
 133        dvbdemux->start_feed = start_feed;
 134        dvbdemux->stop_feed = stop_feed;
 135        dvbdemux->write_to_decoder = NULL;
 136        dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
 137                                      DMX_SECTION_FILTERING |
 138                                      DMX_MEMORY_BASED_FILTERING);
 139        return dvb_dmx_init(dvbdemux);
 140}
 141
 142int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
 143                               struct dvb_demux *dvbdemux,
 144                               struct dmx_frontend *hw_frontend,
 145                               struct dmx_frontend *mem_frontend,
 146                               struct dvb_adapter *dvb_adapter)
 147{
 148        int ret;
 149
 150        dmxdev->filternum = 256;
 151        dmxdev->demux = &dvbdemux->dmx;
 152        dmxdev->capabilities = 0;
 153        ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
 154        if (ret < 0)
 155                return ret;
 156
 157        hw_frontend->source = DMX_FRONTEND_0;
 158        dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
 159        mem_frontend->source = DMX_MEMORY_FE;
 160        dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
 161        return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
 162}
 163