Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / media / pci / ngene / ngene-dvb.c
blob03fc218a45e95e2e742eb1ba8a55a4bdf3e09f7e
1 /*
2 * ngene-dvb.c: nGene PCIe bridge driver - DVB functions
4 * Copyright (C) 2005-2007 Micronas
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
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.
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.
22 * To obtain the license, point your browser to
23 * http://www.gnu.org/copyleft/gpl.html
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/slab.h>
30 #include <linux/poll.h>
31 #include <linux/io.h>
32 #include <asm/div64.h>
33 #include <linux/pci.h>
34 #include <linux/timer.h>
35 #include <linux/byteorder/generic.h>
36 #include <linux/firmware.h>
37 #include <linux/vmalloc.h>
39 #include "ngene.h"
42 /****************************************************************************/
43 /* COMMAND API interface ****************************************************/
44 /****************************************************************************/
46 static ssize_t ts_write(struct file *file, const char __user *buf,
47 size_t count, loff_t *ppos)
49 struct dvb_device *dvbdev = file->private_data;
50 struct ngene_channel *chan = dvbdev->priv;
51 struct ngene *dev = chan->dev;
53 if (wait_event_interruptible(dev->tsout_rbuf.queue,
54 dvb_ringbuffer_free
55 (&dev->tsout_rbuf) >= count) < 0)
56 return 0;
58 dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count);
60 return count;
63 static ssize_t ts_read(struct file *file, char __user *buf,
64 size_t count, loff_t *ppos)
66 struct dvb_device *dvbdev = file->private_data;
67 struct ngene_channel *chan = dvbdev->priv;
68 struct ngene *dev = chan->dev;
69 int left, avail;
71 left = count;
72 while (left) {
73 if (wait_event_interruptible(
74 dev->tsin_rbuf.queue,
75 dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
76 return -EAGAIN;
77 avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
78 if (avail > left)
79 avail = left;
80 dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
81 left -= avail;
82 buf += avail;
84 return count;
87 static const struct file_operations ci_fops = {
88 .owner = THIS_MODULE,
89 .read = ts_read,
90 .write = ts_write,
91 .open = dvb_generic_open,
92 .release = dvb_generic_release,
95 struct dvb_device ngene_dvbdev_ci = {
96 .readers = -1,
97 .writers = -1,
98 .users = -1,
99 .fops = &ci_fops,
103 /****************************************************************************/
104 /* DVB functions and API interface ******************************************/
105 /****************************************************************************/
107 static void swap_buffer(u32 *p, u32 len)
109 while (len) {
110 *p = swab32(*p);
111 p++;
112 len -= 4;
116 /* start of filler packet */
117 static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
119 /* #define DEBUG_CI_XFER */
120 #ifdef DEBUG_CI_XFER
121 static u32 ok;
122 static u32 overflow;
123 static u32 stripped;
124 #endif
126 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
128 struct ngene_channel *chan = priv;
129 struct ngene *dev = chan->dev;
132 if (flags & DF_SWAP32)
133 swap_buffer(buf, len);
135 if (dev->ci.en && chan->number == 2) {
136 while (len >= 188) {
137 if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
138 if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
139 dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
140 wake_up(&dev->tsin_rbuf.queue);
141 #ifdef DEBUG_CI_XFER
142 ok++;
143 #endif
145 #ifdef DEBUG_CI_XFER
146 else
147 overflow++;
148 #endif
150 #ifdef DEBUG_CI_XFER
151 else
152 stripped++;
154 if (ok % 100 == 0 && overflow)
155 printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
156 #endif
157 buf += 188;
158 len -= 188;
160 return NULL;
163 if (chan->users > 0)
164 dvb_dmx_swfilter(&chan->demux, buf, len);
166 return NULL;
169 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
171 struct ngene_channel *chan = priv;
172 struct ngene *dev = chan->dev;
173 u32 alen;
175 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
176 alen -= alen % 188;
178 if (alen < len)
179 FillTSBuffer(buf + alen, len - alen, flags);
180 else
181 alen = len;
182 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
183 if (flags & DF_SWAP32)
184 swap_buffer((u32 *)buf, alen);
185 wake_up_interruptible(&dev->tsout_rbuf.queue);
186 return buf;
191 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
193 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
194 struct ngene_channel *chan = dvbdmx->priv;
196 if (chan->users == 0) {
197 if (!chan->dev->cmd_timeout_workaround || !chan->running)
198 set_transfer(chan, 1);
201 return ++chan->users;
204 int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
206 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
207 struct ngene_channel *chan = dvbdmx->priv;
209 if (--chan->users)
210 return chan->users;
212 if (!chan->dev->cmd_timeout_workaround)
213 set_transfer(chan, 0);
215 return 0;
218 int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
219 int (*start_feed)(struct dvb_demux_feed *),
220 int (*stop_feed)(struct dvb_demux_feed *),
221 void *priv)
223 dvbdemux->priv = priv;
225 dvbdemux->filternum = 256;
226 dvbdemux->feednum = 256;
227 dvbdemux->start_feed = start_feed;
228 dvbdemux->stop_feed = stop_feed;
229 dvbdemux->write_to_decoder = NULL;
230 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
231 DMX_SECTION_FILTERING |
232 DMX_MEMORY_BASED_FILTERING);
233 return dvb_dmx_init(dvbdemux);
236 int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
237 struct dvb_demux *dvbdemux,
238 struct dmx_frontend *hw_frontend,
239 struct dmx_frontend *mem_frontend,
240 struct dvb_adapter *dvb_adapter)
242 int ret;
244 dmxdev->filternum = 256;
245 dmxdev->demux = &dvbdemux->dmx;
246 dmxdev->capabilities = 0;
247 ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
248 if (ret < 0)
249 return ret;
251 hw_frontend->source = DMX_FRONTEND_0;
252 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
253 mem_frontend->source = DMX_MEMORY_FE;
254 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
255 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);