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>
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>
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
,
55 (&dev
->tsout_rbuf
) >= count
) < 0)
58 dvb_ringbuffer_write_user(&dev
->tsout_rbuf
, buf
, 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
;
73 if (wait_event_interruptible(
75 dvb_ringbuffer_avail(&dev
->tsin_rbuf
) > 0) < 0)
77 avail
= dvb_ringbuffer_avail(&dev
->tsin_rbuf
);
80 dvb_ringbuffer_read_user(&dev
->tsin_rbuf
, buf
, avail
);
87 static const struct file_operations ci_fops
= {
91 .open
= dvb_generic_open
,
92 .release
= dvb_generic_release
,
95 struct dvb_device ngene_dvbdev_ci
= {
103 /****************************************************************************/
104 /* DVB functions and API interface ******************************************/
105 /****************************************************************************/
107 static void swap_buffer(u32
*p
, u32 len
)
116 /* start of filler packet */
117 static u8 fill_ts
[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER
};
119 /* #define DEBUG_CI_XFER */
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) {
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
);
154 if (ok
% 100 == 0 && overflow
)
155 printk(KERN_WARNING
"%s: ok %u overflow %u dropped %u\n", __func__
, ok
, overflow
, stripped
);
164 dvb_dmx_swfilter(&chan
->demux
, buf
, len
);
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
;
175 alen
= dvb_ringbuffer_avail(&dev
->tsout_rbuf
);
179 FillTSBuffer(buf
+ alen
, len
- alen
, flags
);
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
);
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
;
212 if (!chan
->dev
->cmd_timeout_workaround
)
213 set_transfer(chan
, 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
*),
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
)
244 dmxdev
->filternum
= 256;
245 dmxdev
->demux
= &dvbdemux
->dmx
;
246 dmxdev
->capabilities
= 0;
247 ret
= dvb_dmxdev_init(dmxdev
, dvb_adapter
);
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
);