Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }