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>
41 static int ci_tsfix
= 1;
42 module_param(ci_tsfix
, int, 0444);
43 MODULE_PARM_DESC(ci_tsfix
, "Detect and fix TS buffer offset shifts in conjunction with CI expansions (default: 1/enabled)");
45 /****************************************************************************/
46 /* COMMAND API interface ****************************************************/
47 /****************************************************************************/
49 static ssize_t
ts_write(struct file
*file
, const char __user
*buf
,
50 size_t count
, loff_t
*ppos
)
52 struct dvb_device
*dvbdev
= file
->private_data
;
53 struct ngene_channel
*chan
= dvbdev
->priv
;
54 struct ngene
*dev
= chan
->dev
;
56 if (wait_event_interruptible(dev
->tsout_rbuf
.queue
,
58 (&dev
->tsout_rbuf
) >= count
) < 0)
61 dvb_ringbuffer_write_user(&dev
->tsout_rbuf
, buf
, count
);
66 static ssize_t
ts_read(struct file
*file
, char __user
*buf
,
67 size_t count
, loff_t
*ppos
)
69 struct dvb_device
*dvbdev
= file
->private_data
;
70 struct ngene_channel
*chan
= dvbdev
->priv
;
71 struct ngene
*dev
= chan
->dev
;
76 if (wait_event_interruptible(
78 dvb_ringbuffer_avail(&dev
->tsin_rbuf
) > 0) < 0)
80 avail
= dvb_ringbuffer_avail(&dev
->tsin_rbuf
);
83 dvb_ringbuffer_read_user(&dev
->tsin_rbuf
, buf
, avail
);
90 static __poll_t
ts_poll(struct file
*file
, poll_table
*wait
)
92 struct dvb_device
*dvbdev
= file
->private_data
;
93 struct ngene_channel
*chan
= dvbdev
->priv
;
94 struct ngene
*dev
= chan
->dev
;
95 struct dvb_ringbuffer
*rbuf
= &dev
->tsin_rbuf
;
96 struct dvb_ringbuffer
*wbuf
= &dev
->tsout_rbuf
;
99 poll_wait(file
, &rbuf
->queue
, wait
);
100 poll_wait(file
, &wbuf
->queue
, wait
);
102 if (!dvb_ringbuffer_empty(rbuf
))
103 mask
|= EPOLLIN
| EPOLLRDNORM
;
104 if (dvb_ringbuffer_free(wbuf
) >= 188)
105 mask
|= EPOLLOUT
| EPOLLWRNORM
;
110 static const struct file_operations ci_fops
= {
111 .owner
= THIS_MODULE
,
114 .open
= dvb_generic_open
,
115 .release
= dvb_generic_release
,
120 struct dvb_device ngene_dvbdev_ci
= {
129 /****************************************************************************/
130 /* DVB functions and API interface ******************************************/
131 /****************************************************************************/
133 static void swap_buffer(u32
*p
, u32 len
)
142 /* start of filler packet */
143 static u8 fill_ts
[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER
};
145 static int tsin_find_offset(void *buf
, u32 len
)
149 l
= len
- sizeof(fill_ts
);
153 for (i
= 0; i
< l
; i
++) {
154 if (((char *)buf
)[i
] == 0x47) {
155 if (!memcmp(buf
+ i
, fill_ts
, sizeof(fill_ts
)))
163 static inline void tsin_copy_stripped(struct ngene
*dev
, void *buf
)
165 if (memcmp(buf
, fill_ts
, sizeof(fill_ts
)) != 0) {
166 if (dvb_ringbuffer_free(&dev
->tsin_rbuf
) >= 188) {
167 dvb_ringbuffer_write(&dev
->tsin_rbuf
, buf
, 188);
168 wake_up(&dev
->tsin_rbuf
.queue
);
173 void *tsin_exchange(void *priv
, void *buf
, u32 len
, u32 clock
, u32 flags
)
175 struct ngene_channel
*chan
= priv
;
176 struct ngene
*dev
= chan
->dev
;
179 if (flags
& DF_SWAP32
)
180 swap_buffer(buf
, len
);
182 if (dev
->ci
.en
&& chan
->number
== 2) {
183 /* blindly copy buffers if ci_tsfix is disabled */
186 tsin_copy_stripped(dev
, buf
);
197 * since the remainder of the TS packet which got cut off
198 * in the previous tsin_exchange() run is at the beginning
199 * of the new TS buffer, append this to the temp buffer and
200 * send it to the DVB ringbuffer afterwards.
202 if (chan
->tsin_offset
) {
203 memcpy(&chan
->tsin_buffer
[(188 - chan
->tsin_offset
)],
204 buf
, chan
->tsin_offset
);
205 tsin_copy_stripped(dev
, &chan
->tsin_buffer
);
207 buf
+= chan
->tsin_offset
;
208 len
-= chan
->tsin_offset
;
212 * copy TS packets to the DVB ringbuffer and detect new offset
213 * shifts by checking for a valid TS SYNC byte
216 if (*((char *)buf
) != 0x47) {
218 * no SYNC header, find new offset shift
219 * (max. 188 bytes, tsoff will be mod 188)
221 tsoff
= tsin_find_offset(buf
, len
);
223 chan
->tsin_offset
+= tsoff
;
224 chan
->tsin_offset
%= 188;
229 dev_info(&dev
->pci_dev
->dev
,
230 "%s(): tsin_offset shift by %d on channel %d\n",
235 * offset corrected. re-check remaining
236 * len for a full TS frame, break and
237 * skip to fragment handling if < 188.
244 tsin_copy_stripped(dev
, buf
);
251 * if a fragment is left, copy to temp buffer. The remainder
252 * will be appended in the next tsin_exchange() iteration.
254 if (len
> 0 && len
< 188)
255 memcpy(&chan
->tsin_buffer
, buf
, len
);
261 dvb_dmx_swfilter(&chan
->demux
, buf
, len
);
266 void *tsout_exchange(void *priv
, void *buf
, u32 len
, u32 clock
, u32 flags
)
268 struct ngene_channel
*chan
= priv
;
269 struct ngene
*dev
= chan
->dev
;
272 alen
= dvb_ringbuffer_avail(&dev
->tsout_rbuf
);
276 FillTSBuffer(buf
+ alen
, len
- alen
, flags
);
279 dvb_ringbuffer_read(&dev
->tsout_rbuf
, buf
, alen
);
280 if (flags
& DF_SWAP32
)
281 swap_buffer((u32
*)buf
, alen
);
282 wake_up_interruptible(&dev
->tsout_rbuf
.queue
);
288 int ngene_start_feed(struct dvb_demux_feed
*dvbdmxfeed
)
290 struct dvb_demux
*dvbdmx
= dvbdmxfeed
->demux
;
291 struct ngene_channel
*chan
= dvbdmx
->priv
;
293 if (chan
->users
== 0) {
294 if (!chan
->dev
->cmd_timeout_workaround
|| !chan
->running
)
295 set_transfer(chan
, 1);
298 return ++chan
->users
;
301 int ngene_stop_feed(struct dvb_demux_feed
*dvbdmxfeed
)
303 struct dvb_demux
*dvbdmx
= dvbdmxfeed
->demux
;
304 struct ngene_channel
*chan
= dvbdmx
->priv
;
309 if (!chan
->dev
->cmd_timeout_workaround
)
310 set_transfer(chan
, 0);
315 int my_dvb_dmx_ts_card_init(struct dvb_demux
*dvbdemux
, char *id
,
316 int (*start_feed
)(struct dvb_demux_feed
*),
317 int (*stop_feed
)(struct dvb_demux_feed
*),
320 dvbdemux
->priv
= priv
;
322 dvbdemux
->filternum
= 256;
323 dvbdemux
->feednum
= 256;
324 dvbdemux
->start_feed
= start_feed
;
325 dvbdemux
->stop_feed
= stop_feed
;
326 dvbdemux
->write_to_decoder
= NULL
;
327 dvbdemux
->dmx
.capabilities
= (DMX_TS_FILTERING
|
328 DMX_SECTION_FILTERING
|
329 DMX_MEMORY_BASED_FILTERING
);
330 return dvb_dmx_init(dvbdemux
);
333 int my_dvb_dmxdev_ts_card_init(struct dmxdev
*dmxdev
,
334 struct dvb_demux
*dvbdemux
,
335 struct dmx_frontend
*hw_frontend
,
336 struct dmx_frontend
*mem_frontend
,
337 struct dvb_adapter
*dvb_adapter
)
341 dmxdev
->filternum
= 256;
342 dmxdev
->demux
= &dvbdemux
->dmx
;
343 dmxdev
->capabilities
= 0;
344 ret
= dvb_dmxdev_init(dmxdev
, dvb_adapter
);
348 hw_frontend
->source
= DMX_FRONTEND_0
;
349 dvbdemux
->dmx
.add_frontend(&dvbdemux
->dmx
, hw_frontend
);
350 mem_frontend
->source
= DMX_MEMORY_FE
;
351 dvbdemux
->dmx
.add_frontend(&dvbdemux
->dmx
, mem_frontend
);
352 return dvbdemux
->dmx
.connect_frontend(&dvbdemux
->dmx
, hw_frontend
);