^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ngene-dvb.c: nGene PCIe bridge driver - DVB functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005-2007 Micronas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Modifications for new nGene firmware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * support for EEPROM-copying,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * support for new dual DVB-S2 card prototype
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/byteorder/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "ngene.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int ci_tsfix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) module_param(ci_tsfix, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_PARM_DESC(ci_tsfix, "Detect and fix TS buffer offset shifts in conjunction with CI expansions (default: 1/enabled)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* COMMAND API interface ****************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static ssize_t ts_write(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct dvb_device *dvbdev = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct ngene_channel *chan = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct ngene *dev = chan->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (wait_event_interruptible(dev->tsout_rbuf.queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dvb_ringbuffer_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) (&dev->tsout_rbuf) >= count) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static ssize_t ts_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct dvb_device *dvbdev = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct ngene_channel *chan = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct ngene *dev = chan->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int left, avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) left = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) while (left) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (wait_event_interruptible(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dev->tsin_rbuf.queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (avail > left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) avail = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) left -= avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) buf += avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static __poll_t ts_poll(struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct dvb_device *dvbdev = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct ngene_channel *chan = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct ngene *dev = chan->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct dvb_ringbuffer *rbuf = &dev->tsin_rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct dvb_ringbuffer *wbuf = &dev->tsout_rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) __poll_t mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) poll_wait(file, &rbuf->queue, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) poll_wait(file, &wbuf->queue, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!dvb_ringbuffer_empty(rbuf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mask |= EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (dvb_ringbuffer_free(wbuf) >= 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mask |= EPOLLOUT | EPOLLWRNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct file_operations ci_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .read = ts_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .write = ts_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .open = dvb_generic_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .release = dvb_generic_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .poll = ts_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .mmap = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct dvb_device ngene_dvbdev_ci = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .priv = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .readers = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .writers = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .users = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .fops = &ci_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* DVB functions and API interface ******************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void swap_buffer(u32 *p, u32 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *p = swab32(*p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) len -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* start of filler packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int tsin_find_offset(void *buf, u32 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int i, l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) l = len - sizeof(fill_ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (l <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for (i = 0; i < l; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (((char *)buf)[i] == 0x47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!memcmp(buf + i, fill_ts, sizeof(fill_ts)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return i % 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline void tsin_copy_stripped(struct ngene *dev, void *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (memcmp(buf, fill_ts, sizeof(fill_ts)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) wake_up(&dev->tsin_rbuf.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct ngene_channel *chan = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct ngene *dev = chan->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int tsoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (flags & DF_SWAP32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) swap_buffer(buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (dev->ci.en && chan->number == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* blindly copy buffers if ci_tsfix is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (!ci_tsfix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) while (len >= 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) tsin_copy_stripped(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) buf += 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) len -= 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* ci_tsfix = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * since the remainder of the TS packet which got cut off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * in the previous tsin_exchange() run is at the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * of the new TS buffer, append this to the temp buffer and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * send it to the DVB ringbuffer afterwards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (chan->tsin_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) memcpy(&chan->tsin_buffer[(188 - chan->tsin_offset)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) buf, chan->tsin_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) tsin_copy_stripped(dev, &chan->tsin_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) buf += chan->tsin_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) len -= chan->tsin_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * copy TS packets to the DVB ringbuffer and detect new offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * shifts by checking for a valid TS SYNC byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) while (len >= 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (*((char *)buf) != 0x47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * no SYNC header, find new offset shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * (max. 188 bytes, tsoff will be mod 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) tsoff = tsin_find_offset(buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (tsoff > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) chan->tsin_offset += tsoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) chan->tsin_offset %= 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) buf += tsoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) len -= tsoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_info(&dev->pci_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) "%s(): tsin_offset shift by %d on channel %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) __func__, tsoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) chan->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * offset corrected. re-check remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * len for a full TS frame, break and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * skip to fragment handling if < 188.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (len < 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) tsin_copy_stripped(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) buf += 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) len -= 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * if a fragment is left, copy to temp buffer. The remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * will be appended in the next tsin_exchange() iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (len > 0 && len < 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) memcpy(&chan->tsin_buffer, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (chan->users > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dvb_dmx_swfilter(&chan->demux, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct ngene_channel *chan = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct ngene *dev = chan->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 alen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) alen -= alen % 188;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (alen < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) FillTSBuffer(buf + alen, len - alen, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) alen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (flags & DF_SWAP32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) swap_buffer((u32 *)buf, alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) wake_up_interruptible(&dev->tsout_rbuf.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct ngene_channel *chan = dvbdmx->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (chan->users == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!chan->dev->cmd_timeout_workaround || !chan->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) set_transfer(chan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return ++chan->users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct ngene_channel *chan = dvbdmx->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (--chan->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return chan->users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!chan->dev->cmd_timeout_workaround)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) set_transfer(chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int (*start_feed)(struct dvb_demux_feed *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int (*stop_feed)(struct dvb_demux_feed *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dvbdemux->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dvbdemux->filternum = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dvbdemux->feednum = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dvbdemux->start_feed = start_feed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dvbdemux->stop_feed = stop_feed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dvbdemux->write_to_decoder = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) DMX_SECTION_FILTERING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) DMX_MEMORY_BASED_FILTERING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return dvb_dmx_init(dvbdemux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct dvb_demux *dvbdemux,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct dmx_frontend *hw_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct dmx_frontend *mem_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct dvb_adapter *dvb_adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) dmxdev->filternum = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dmxdev->demux = &dvbdemux->dmx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dmxdev->capabilities = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) hw_frontend->source = DMX_FRONTEND_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) mem_frontend->source = DMX_MEMORY_FE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }