mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	adapt to current mainline kernel dvb-core
This commit is contained in:
		
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							| @@ -2,10 +2,15 @@ kernelver ?= $(shell uname -r) | ||||
| KDIR	?= /lib/modules/$(kernelver)/build | ||||
| PWD	:= $(shell pwd) | ||||
|  | ||||
| MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m  CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=m | ||||
| MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m  CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=y DDDVB=y | ||||
|  | ||||
| KBUILD_EXTMOD = $(PWD) | ||||
|  | ||||
| DDDVB_INC = "-I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/frontends" | ||||
|  | ||||
|  | ||||
| all:  | ||||
| 	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules | ||||
| 	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC) | ||||
| 	$(MAKE) -C apps | ||||
|  | ||||
| libdddvb: | ||||
| @@ -22,6 +27,7 @@ dep: | ||||
|  | ||||
| install: all | ||||
| 	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install | ||||
| 	depmod -a | ||||
|  | ||||
| clean: | ||||
| 	rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules* | ||||
|   | ||||
| @@ -3,9 +3,11 @@ EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -D | ||||
| ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o | ||||
| octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o | ||||
| #mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o | ||||
| obj-$(CONFIG_DVB_OCTONET) += octonet.o | ||||
|  | ||||
| EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends | ||||
| EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||||
| NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core | ||||
| #EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends | ||||
| #EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||||
| #NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core | ||||
| @@ -1,14 +1,15 @@ | ||||
| # | ||||
| # Makefile for the ddbridge device driver | ||||
| # | ||||
| #NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/dvb-frontends -I$(KBUILD_EXTMOD)/tuners | ||||
|  | ||||
| ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o | ||||
| octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_OCTONET) += octonet.o | ||||
|  | ||||
| ccflags-y += -Idrivers/media/dvb-core/ | ||||
| ccflags-y += -Idrivers/media/dvb-frontends/ | ||||
| ccflags-y += -Idrivers/media/tuners/ | ||||
|  | ||||
| #ccflags-y += -Idrivers/media/include/linux/ | ||||
| #ccflags-y += -Idrivers/media/dvb-frontends/ | ||||
| #ccflags-y += -Idrivers/media/tuners/ | ||||
|   | ||||
| @@ -329,7 +329,7 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate) | ||||
| 	case DDB_CI_EXTERNAL_XO2_B: | ||||
| 		ci_xo2_attach(port); | ||||
| 		break; | ||||
| 		 | ||||
|  | ||||
| 	case DDB_CI_INTERNAL: | ||||
| 		ci_attach(port); | ||||
| 		break; | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-i2c.h" | ||||
| #include "ddbridge-io.h" | ||||
| #include "dvb_net.h" | ||||
| #include <media/dvb_net.h> | ||||
|  | ||||
| struct workqueue_struct *ddb_wq; | ||||
|  | ||||
| @@ -103,6 +103,7 @@ struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr, | ||||
| 	irq->data = data; | ||||
| 	return irq; | ||||
| } | ||||
| EXPORT_SYMBOL(ddb_irq_set); | ||||
|  | ||||
| static void ddb_set_dma_table(struct ddb_io *io) | ||||
| { | ||||
| @@ -486,9 +487,8 @@ static void ddb_output_start_unlocked(struct ddb_output *output) | ||||
| 	} | ||||
| 	if (output->port->class != DDB_PORT_MOD) | ||||
| 		ddbwritel(dev, con | 1, TS_CONTROL(output)); | ||||
| 	if (output->dma) { | ||||
| 	if (output->dma) | ||||
| 		output->dma->running = 1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void ddb_output_start(struct ddb_output *output) | ||||
| @@ -669,7 +669,7 @@ static u32 ddb_output_free(struct ddb_output *output) | ||||
|  | ||||
| 	if (output->dma->cbuf != idx) { | ||||
| 		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && | ||||
| 		    (output->dma->size - output->dma->coff <= 2*188)) | ||||
| 		    (output->dma->size - output->dma->coff <= 2 * 188)) | ||||
| 			return 0; | ||||
| 		return 188; | ||||
| 	} | ||||
| @@ -679,25 +679,6 @@ static u32 ddb_output_free(struct ddb_output *output) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static u32 ddb_dma_free(struct ddb_dma *dma) | ||||
| { | ||||
| 	u32 idx, off, stat = dma->stat; | ||||
| 	s32 p1, p2, diff; | ||||
|  | ||||
| 	idx = (stat >> 11) & 0x1f; | ||||
| 	off = (stat & 0x7ff) << 7; | ||||
|  | ||||
| 	p1 = idx * dma->size + off; | ||||
| 	p2 = dma->cbuf * dma->size + dma->coff; | ||||
|  | ||||
| 	diff = p1 - p2; | ||||
| 	if (diff <= 0) | ||||
| 		diff += dma->num * dma->size; | ||||
| 	return diff; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static ssize_t ddb_output_write(struct ddb_output *output, | ||||
| 				const __user u8 *buf, size_t count) | ||||
| { | ||||
| @@ -753,79 +734,6 @@ static ssize_t ddb_output_write(struct ddb_output *output, | ||||
| 	return count - left; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static u32 ddb_input_free_bytes(struct ddb_input *input) | ||||
| { | ||||
| 	struct ddb *dev = input->port->dev; | ||||
| 	u32 idx, off, stat = input->dma->stat; | ||||
| 	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma)); | ||||
|  | ||||
| 	idx = (stat >> 11) & 0x1f; | ||||
| 	off = (stat & 0x7ff) << 7; | ||||
|  | ||||
| 	if (ctrl & 4) | ||||
| 		return 0; | ||||
| 	if (input->dma->cbuf != idx) | ||||
| 		return 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static s32 ddb_output_used_bufs(struct ddb_output *output) | ||||
| { | ||||
| 	u32 idx, off, stat, ctrl; | ||||
| 	s32 diff; | ||||
|  | ||||
| 	spin_lock_irq(&output->dma->lock); | ||||
| 	stat = output->dma->stat; | ||||
| 	ctrl = output->dma->ctrl; | ||||
| 	spin_unlock_irq(&output->dma->lock); | ||||
|  | ||||
| 	idx = (stat >> 11) & 0x1f; | ||||
| 	off = (stat & 0x7ff) << 7; | ||||
|  | ||||
| 	if (ctrl & 4) | ||||
| 		return 0; | ||||
| 	diff = output->dma->cbuf - idx; | ||||
| 	if (diff == 0 && off < output->dma->coff) | ||||
| 		return 0; | ||||
| 	if (diff <= 0) | ||||
| 		diff += output->dma->num; | ||||
| 	return diff; | ||||
| } | ||||
|  | ||||
| static s32 ddb_input_free_bufs(struct ddb_input *input) | ||||
| { | ||||
| 	u32 idx, off, stat, ctrl; | ||||
| 	s32 free; | ||||
|  | ||||
| 	spin_lock_irq(&input->dma->lock); | ||||
| 	ctrl = input->dma->ctrl; | ||||
| 	stat = input->dma->stat; | ||||
| 	spin_unlock_irq(&input->dma->lock); | ||||
| 	if (ctrl & 4) | ||||
| 		return 0; | ||||
| 	idx = (stat >> 11) & 0x1f; | ||||
| 	off = (stat & 0x7ff) << 7; | ||||
| 	free = input->dma->cbuf - idx; | ||||
| 	if (free == 0 && off < input->dma->coff) | ||||
| 		return 0; | ||||
| 	if (free <= 0) | ||||
| 		free += input->dma->num; | ||||
| 	return free - 1; | ||||
| } | ||||
|  | ||||
| static u32 ddb_output_ok(struct ddb_output *output) | ||||
| { | ||||
| 	struct ddb_input *input = output->port->input[0]; | ||||
| 	s32 diff; | ||||
|  | ||||
| 	diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output); | ||||
| 	if (diff > 0) | ||||
| 		return 1; | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static u32 ddb_input_avail(struct ddb_input *input) | ||||
| { | ||||
| 	struct ddb *dev = input->port->dev; | ||||
| @@ -1125,20 +1033,20 @@ static struct dvb_frontend_ops dummy_ops = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 }, | ||||
| 	.info = { | ||||
| 		.name = "DUMMY DVB-C/C2 DVB-T/T2", | ||||
| 		.frequency_stepsize = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_stepsize_hz = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||||
| 		        FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		        FE_CAN_QAM_AUTO |  | ||||
| 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 			FE_CAN_FEC_4_5 | | ||||
| 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||||
| 			FE_CAN_TRANSMISSION_MODE_AUTO | | ||||
| 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | | ||||
| 			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | ||||
| 		FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		FE_CAN_QAM_AUTO | | ||||
| 		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 		FE_CAN_FEC_4_5 | | ||||
| 		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||||
| 		FE_CAN_TRANSMISSION_MODE_AUTO | | ||||
| 		FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | | ||||
| 		FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | ||||
| 	}, | ||||
| 	.release = dummy_release, | ||||
| 	.read_status = dummy_read_status, | ||||
| @@ -1484,29 +1392,6 @@ static int tuner_attach_stv6111(struct ddb_input *input, int type) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int start_input(struct ddb_input *input) | ||||
| { | ||||
| 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; | ||||
|  | ||||
| 	if (!dvb->users) | ||||
| 		ddb_input_start_all(input); | ||||
|  | ||||
| 	return ++dvb->users; | ||||
| } | ||||
|  | ||||
| static int stop_input(struct ddb_input *input) | ||||
| { | ||||
| 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; | ||||
|  | ||||
| 	if (--dvb->users) | ||||
| 		return dvb->users; | ||||
|  | ||||
| 	ddb_input_stop_all(input); | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||||
| { | ||||
| 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||||
| @@ -1603,7 +1488,7 @@ static int dvb_register_adapters(struct ddb *dev) | ||||
|  | ||||
| 	if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD || | ||||
| 	    dev->link[0].info->type == DDB_OCTONET || | ||||
| 	    dev->link[0].info->type == DDB_OCTOPRO ) { | ||||
| 	    dev->link[0].info->type == DDB_OCTOPRO) { | ||||
| 		port = &dev->port[0]; | ||||
| 		adap = port->dvb[0].adap; | ||||
| 		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, | ||||
| @@ -2118,16 +2003,6 @@ static void ddb_port_probe(struct ddb_port *port) | ||||
| 		port->class = DDB_PORT_MOD; | ||||
| 		return; | ||||
| 	} | ||||
| #if 0 | ||||
| 	if (link->info->type == DDB_OCTOPRO_HDIN) { | ||||
| 		if (port->nr == 0) { | ||||
| 			dev->link[l].info->type = DDB_OCTOPUS; | ||||
| 			port->name = "HDIN"; | ||||
| 			port->class = DDB_PORT_LOOP; | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| 	if (link->info->type == DDB_OCTOPUS_MAX) { | ||||
| 		port->name = "DUAL DVB-S2 MAX"; | ||||
| 		port->type_name = "MXL5XX"; | ||||
| @@ -2286,7 +2161,7 @@ static int ddb_port_attach(struct ddb_port *port) | ||||
| 		if (ret < 0) | ||||
| 			break; | ||||
| 		/* fallthrough */ | ||||
| 	case DDB_PORT_LOOP:  | ||||
| 	case DDB_PORT_LOOP: | ||||
| 		ret = dvb_register_device(port->dvb[0].adap, | ||||
| 					  &port->dvb[0].dev, | ||||
| 					  &dvbdev_ci, (void *)port->output, | ||||
| @@ -2447,17 +2322,15 @@ static void input_tasklet(unsigned long data) | ||||
| 	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma)); | ||||
| 	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma)); | ||||
|  | ||||
| #if 1 | ||||
| 	{ | ||||
| 		u32 packet_loss = dma->packet_loss; | ||||
| 		u32 cur_counter = TS_STAT(input) & 0xFFFF; | ||||
| 		 | ||||
| 		if ( cur_counter < (packet_loss & 0xFFFF)  ) | ||||
| 		u32 cur_counter = ddbreadl(dev, TS_STAT(input)) & 0xffff; | ||||
|  | ||||
| 		if (cur_counter < (packet_loss & 0xffff)) | ||||
| 			packet_loss += 0x10000; | ||||
| 		packet_loss = ((packet_loss & 0xFFFF0000) | cur_counter); | ||||
| 		packet_loss = ((packet_loss & 0xffff0000) | cur_counter); | ||||
| 		dma->packet_loss = packet_loss; | ||||
| 	} | ||||
| #endif | ||||
| 	if (4 & dma->ctrl) | ||||
| 		dma->stall_count++; | ||||
| 	if (input->redi) | ||||
| @@ -2468,7 +2341,7 @@ static void input_tasklet(unsigned long data) | ||||
| 	spin_unlock_irqrestore(&dma->lock, flags); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| #ifdef OPTIMIZE_TASKLETS | ||||
| static void input_handler(unsigned long data) | ||||
| { | ||||
| 	struct ddb_input *input = (struct ddb_input *)data; | ||||
| @@ -2530,7 +2403,7 @@ unlock_exit: | ||||
| 	spin_unlock_irqrestore(&dma->lock, flags); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| #ifdef OPTIMIZE_TASKLETS | ||||
| static void output_handler(void *data) | ||||
| { | ||||
| 	struct ddb_output *output = (struct ddb_output *)data; | ||||
| @@ -2620,10 +2493,6 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr) | ||||
| 		dma->div = 1; | ||||
| 	} | ||||
| 	ddbwritel(io->port->dev, 0, DMA_BUFFER_ACK(dma)); | ||||
| #if 0 | ||||
| 	dev_info(io->port->dev->dev, "init link %u, io %u, dma %u, dmaregs %08x bufregs %08x\n", | ||||
| 		 io->port->lnr, io->nr, nr, dma->regs, dma->bufregs); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr) | ||||
| @@ -2648,10 +2517,6 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr) | ||||
| 		if (port->lnr) | ||||
| 			dma_nr += 32 + (port->lnr - 1) * 8; | ||||
|  | ||||
| #if 0 | ||||
| 		dev_info(dev->dev, "init link %u, input %u, handler %u\n", | ||||
| 			 port->lnr, nr, dma_nr + base); | ||||
| #endif | ||||
| 		ddb_irq_set(dev, 0, dma_nr + base, &input_handler, input); | ||||
| 		ddb_dma_init(input, dma_nr, 0, dma_nr + base); | ||||
| 	} | ||||
| @@ -2669,10 +2534,6 @@ static void ddb_output_init(struct ddb_port *port, int nr) | ||||
| 	rm = io_regmap(output, 1); | ||||
| 	output->regs = DDB_LINK_TAG(port->lnr) | | ||||
| 		(rm->output->base + rm->output->size * nr); | ||||
| #if 0 | ||||
| 	dev_info(dev->dev, "init link %u, output %u, regs %08x\n", | ||||
| 		 port->lnr, nr, output->regs); | ||||
| #endif | ||||
| 	if (dev->has_dma) { | ||||
| 		const struct ddb_regmap *rm0 = io_regmap(output, 0); | ||||
| 		u32 base = rm0->irq_base_odma; | ||||
| @@ -3683,7 +3544,7 @@ static ssize_t temp_show(struct device *device, | ||||
| 		l = attr->attr.name[5] - 0x30; | ||||
| 	link = &dev->link[l]; | ||||
|  | ||||
| 	if (link->info->type == DDB_MOD ) { | ||||
| 	if (link->info->type == DDB_MOD) { | ||||
| 		if (link->info->version >= 2) { | ||||
| 			temp = 0xffff & ddbreadl(dev, TEMPMON2_BOARD); | ||||
| 			temp = (temp * 1000) >> 8; | ||||
| @@ -3755,25 +3616,6 @@ static ssize_t ctemp_show(struct device *device, | ||||
| 	return sprintf(buf, "%d\n", temp); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static ssize_t qam_show(struct device *device, | ||||
| 			struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct ddb *dev = dev_get_drvdata(device); | ||||
| 	struct i2c_adapter *adap; | ||||
| 	u8 tmp[4]; | ||||
| 	s16 i, q; | ||||
|  | ||||
| 	adap = &dev->i2c[1].adap; | ||||
| 	if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0) | ||||
| 		return sprintf(buf, "read_error\n"); | ||||
| 	i = (s16)(((u16)tmp[1]) << 14) | (((u16)tmp[0]) << 6); | ||||
| 	q = (s16)(((u16)tmp[3]) << 14) | (((u16)tmp[2]) << 6); | ||||
|  | ||||
| 	return sprintf(buf, "%d %d\n", i, q); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static ssize_t mod_show(struct device *device, | ||||
| 			struct device_attribute *attr, char *buf) | ||||
| { | ||||
| @@ -3954,32 +3796,6 @@ static ssize_t redirect_store(struct device *device, | ||||
| 	return count; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| /* A L P I  AAAAAALLPPPPPPII */ | ||||
| /* AAAAAAAA LLLLLLLL PPPPPPII */ | ||||
| static ssize_t redirect2_show(struct device *device, | ||||
| 			      struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static ssize_t redirect2_store(struct device *device, | ||||
| 			       struct device_attribute *attr, | ||||
| 			       const char *buf, size_t count) | ||||
| { | ||||
| 	unsigned int i, p; | ||||
| 	int res; | ||||
|  | ||||
| 	if (sscanf(buf, "%x %x\n", &i, &p) != 2) | ||||
| 		return -EINVAL; | ||||
| 	res = ddb_redirect(i, p); | ||||
| 	if (res < 0) | ||||
| 		return res; | ||||
| 	dev_info(device, "redirect: %02x, %02x\n", i, p); | ||||
| 	return count; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static ssize_t gap_show(struct device *device, | ||||
| 			struct device_attribute *attr, char *buf) | ||||
| { | ||||
| @@ -4137,9 +3953,6 @@ static struct device_attribute ddb_attrs[] = { | ||||
| 	__ATTR_MRO(devid3, devid_show), | ||||
| 	__ATTR_RO(hwid), | ||||
| 	__ATTR_RO(regmap), | ||||
| #if 0 | ||||
| 	__ATTR_RO(qam), | ||||
| #endif | ||||
| 	__ATTR(redirect, 0664, redirect_show, redirect_store), | ||||
| 	__ATTR_MRO(snr,  bsnr_show), | ||||
| 	__ATTR_RO(bpsnr), | ||||
| @@ -4239,7 +4052,6 @@ static void ddb_device_attrs_del(struct ddb *dev) | ||||
| 		if (dev->link[i].info && | ||||
| 		    dev->link[i].info->temp_num) | ||||
| 			device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]); | ||||
| 	for (i = 0; i < dev->link[0].info->temp_num; i++) | ||||
| 	for (i = 0; i < dev->link[0].info->port_num; i++) | ||||
| 		device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]); | ||||
| 	for (i = 0; i < dev->link[0].info->fan_num; i++) | ||||
| @@ -4377,7 +4189,9 @@ static void link_tasklet(unsigned long data) | ||||
| static void gtl_irq_handler(void *priv) | ||||
| { | ||||
| 	struct ddb_link *link = (struct ddb_link *)priv; | ||||
| #if 1 | ||||
| #ifdef USE_LINK_TASKLET | ||||
| 	tasklet_schedule(&link->tasklet); | ||||
| #else | ||||
| 	struct ddb *dev = link->dev; | ||||
| 	u32 s, l = link->nr, tag = DDB_LINK_TAG(link->nr); | ||||
|  | ||||
| @@ -4389,8 +4203,6 @@ static void gtl_irq_handler(void *priv) | ||||
| 		LINK_IRQ_HANDLE(l, 3); | ||||
| 		LINK_IRQ_HANDLE(l, 24); | ||||
| 	} | ||||
| #else | ||||
| 	tasklet_schedule(&link->tasklet); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| @@ -4434,7 +4246,7 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l) | ||||
| 				  subid & 0xffff, subid >> 16); | ||||
| 	if (link->info->type != DDB_OCTOPUS_MAX_CT && | ||||
| 	    link->info->type != DDB_OCTOPUS_MAX  && | ||||
| 	    link->info->type != DDB_OCTOPUS_MCI ) { | ||||
| 	    link->info->type != DDB_OCTOPUS_MCI) { | ||||
| 		dev_info(dev->dev, | ||||
| 			 "Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.", | ||||
| 			 id); | ||||
|   | ||||
| @@ -801,7 +801,7 @@ static const struct ddb_device_id ddb_device_ids[] = { | ||||
| 	DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a), | ||||
| 	DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini), | ||||
|  | ||||
|         /* Modulators */ | ||||
| 	/* Modulators */ | ||||
| 	DDB_DEVID(0x0201, 0x0001, ddb_mod), | ||||
| 	DDB_DEVID(0x0201, 0x0002, ddb_mod), | ||||
| 	DDB_DEVID(0x0201, 0x0004, ddb_mod_4),  /* dummy entry ! */ | ||||
| @@ -827,10 +827,10 @@ const struct ddb_info *get_ddb_info(u16 vendor, u16 device, | ||||
| 				    u16 subvendor, u16 subdevice) | ||||
| { | ||||
| 	int i; | ||||
| 	 | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(ddb_device_ids); i++) { | ||||
| 		const struct ddb_device_id *id = &ddb_device_ids[i]; | ||||
| 		 | ||||
|  | ||||
| 		if (vendor == id->vendor && | ||||
| 		    device == id->device && | ||||
| 		    subvendor == id->subvendor && | ||||
|   | ||||
| @@ -35,33 +35,30 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) | ||||
| 	stat = wait_for_completion_timeout(&i2c->completion, HZ); | ||||
| 	val = ddbreadl(dev, i2c->regs + I2C_COMMAND); | ||||
| 	if (stat == 0) { | ||||
| 		u32 istat = ddbreadl(dev, INTERRUPT_STATUS); | ||||
|  | ||||
| 		dev_err(dev->dev, "I2C timeout, card %d, port %d, link %u\n", | ||||
| 			dev->nr, i2c->nr, i2c->link); | ||||
| #if 1 | ||||
| 		{ | ||||
| 			u32 istat = ddbreadl(dev, INTERRUPT_STATUS); | ||||
| 		dev_err(dev->dev, "DDBridge IRS %08x\n", istat); | ||||
|  | ||||
| 			dev_err(dev->dev, "DDBridge IRS %08x\n", istat); | ||||
| 			if (i2c->link) { | ||||
| 				u32 listat = | ||||
| 					ddbreadl(dev, | ||||
| 						 DDB_LINK_TAG(i2c->link) | | ||||
| 						 INTERRUPT_STATUS); | ||||
| 				dev_err(dev->dev, | ||||
| 					"DDBridge link %u IRS %08x\n", | ||||
| 					i2c->link, listat); | ||||
| 			} | ||||
| 			if (istat & 1) { | ||||
| 				ddbwritel(dev, istat & 1, INTERRUPT_ACK); | ||||
| 			} else { | ||||
| 				u32 mon = ddbreadl(dev, | ||||
| 						   i2c->regs + I2C_MONITOR); | ||||
|  | ||||
| 				dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n", | ||||
| 					val, mon); | ||||
| 			} | ||||
| 		if (i2c->link) { | ||||
| 			u32 listat = | ||||
| 				ddbreadl(dev, | ||||
| 					 DDB_LINK_TAG(i2c->link) | | ||||
| 					 INTERRUPT_STATUS); | ||||
| 			dev_err(dev->dev, | ||||
| 				"DDBridge link %u IRS %08x\n", | ||||
| 				i2c->link, listat); | ||||
| 		} | ||||
| 		if (istat & 1) { | ||||
| 			ddbwritel(dev, istat & 1, INTERRUPT_ACK); | ||||
| 		} else { | ||||
| 			u32 mon = ddbreadl(dev, | ||||
| 					   i2c->regs + I2C_MONITOR); | ||||
|  | ||||
| 			dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n", | ||||
| 				val, mon); | ||||
| 		} | ||||
| #endif | ||||
| 		return -EIO; | ||||
| 	} | ||||
| 	val &= 0x70000; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * ddbridge-i2c.h: Digital Devices bridge i2c driver | ||||
|  * | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-io.c: Digital Devices bridge I/O functions | ||||
|  * | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * ddbridge-io.h: Digital Devices bridge I/O functions | ||||
|  * | ||||
| @@ -64,7 +65,7 @@ static inline u32 ddblreadl0(struct ddb_link *link, u32 adr) | ||||
| 	return readl(link->dev->regs + adr); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| #ifdef DEBUG_GTLW | ||||
| static inline void gtlw(struct ddb_link *link) | ||||
| { | ||||
| 	u32 count = 0; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-m4.c: Digital Devices MAX M4 driver | ||||
|  * | ||||
| @@ -335,6 +336,7 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	int res; | ||||
| 	//struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
|  | ||||
| 	stop(fe); | ||||
|  | ||||
| @@ -343,6 +345,7 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 	state->iq_constellation_point_max = 0; | ||||
|  | ||||
| 	state->iq_constellation_tap = 0; | ||||
| 	//printk("bw = %u\n", p->bandwidth_hz); | ||||
| 	switch (fe->dtv_property_cache.delivery_system) { | ||||
| 	case SYS_DVBS: | ||||
| 	case SYS_DVBS2: | ||||
| @@ -450,7 +453,7 @@ static void release(struct dvb_frontend *fe) | ||||
| 	kfree(state); | ||||
| } | ||||
|  | ||||
| static int get_algo(struct dvb_frontend *fe) | ||||
| static enum dvbfe_algo get_algo(struct dvb_frontend *fe) | ||||
| { | ||||
| 	return DVBFE_ALGO_HW; | ||||
| } | ||||
| @@ -470,21 +473,21 @@ static struct dvb_frontend_ops m4_ops = { | ||||
| 		    SYS_DVBS, SYS_DVBS2, SYS_ISDBS, }, | ||||
| 	.info = { | ||||
| 		.name = "M4", | ||||
| 		.frequency_min = 950000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_min_hz = 47125000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 2150000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 100000, | ||||
| 		.symbol_rate_max = 100000000, | ||||
| 		.frequency_stepsize	= 0, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_stepsize_hz	= 0, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||||
| 		        FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		        FE_CAN_QAM_AUTO |  | ||||
| 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 			FE_CAN_FEC_4_5 | | ||||
| 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||||
| 			FE_CAN_TRANSMISSION_MODE_AUTO | | ||||
| 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | | ||||
| 			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | ||||
| 		FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		FE_CAN_QAM_AUTO | | ||||
| 		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 		FE_CAN_FEC_4_5 | | ||||
| 		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||||
| 		FE_CAN_TRANSMISSION_MODE_AUTO | | ||||
| 		FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | | ||||
| 		FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | ||||
| 	}, | ||||
| 	.release                        = release, | ||||
| 	.get_frontend_algo              = get_algo, | ||||
|   | ||||
| @@ -360,17 +360,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
| 	if (dev->link[0].info->type == DDB_MOD | ||||
| 	    && dev->link[0].info->version == 2) { | ||||
| 		u32 lic = ddbreadl(dev, 0x1c) & 7; | ||||
| 		 | ||||
|  | ||||
| 		switch (lic) { | ||||
| 		case 0:  | ||||
| 		case 0: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000); | ||||
| 			break; | ||||
| 		case 1:  | ||||
| 		case 1: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003); | ||||
| 			break; | ||||
| 		case 3:  | ||||
| 		case 3: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002); | ||||
| 			break; | ||||
| @@ -458,11 +458,9 @@ static pci_ers_result_t ddb_pci_error_detected(struct pci_dev *pdev, | ||||
| { | ||||
| 	switch (state) { | ||||
| 	case pci_channel_io_frozen: | ||||
| 		 | ||||
| 		return PCI_ERS_RESULT_CAN_RECOVER; | ||||
| 	case pci_channel_io_perm_failure: | ||||
| 		return PCI_ERS_RESULT_DISCONNECT; | ||||
| 		break; | ||||
| 	case pci_channel_io_normal: | ||||
| 	default: | ||||
| 		break; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-max.c: Digital Devices MAX card line support functions | ||||
|  * | ||||
| @@ -67,7 +68,7 @@ static int max_emulate_switch(struct dvb_frontend *fe, | ||||
| { | ||||
| 	int input; | ||||
|  | ||||
| 	if (len !=4) | ||||
| 	if (len != 4) | ||||
| 		return -1; | ||||
|  | ||||
| 	if ((cmd[0] != 0xe0) || (cmd[1] != 0x10) || (cmd[2] != 0x39)) | ||||
| @@ -490,9 +491,6 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input) | ||||
|  | ||||
| /* MAX MCI related functions */ | ||||
|  | ||||
| extern struct mci_cfg ddb_max_sx8_cfg; | ||||
| extern struct mci_cfg ddb_max_m4_cfg; | ||||
|  | ||||
| int ddb_fe_attach_mci(struct ddb_input *input, u32 type) | ||||
| { | ||||
| 	struct ddb *dev = input->port->dev; | ||||
| @@ -502,7 +500,7 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) | ||||
| 	int demod, tuner; | ||||
| 	struct mci_cfg cfg; | ||||
| 	int fm = fmode; | ||||
| 	 | ||||
|  | ||||
| 	demod = input->nr; | ||||
| 	tuner = demod & 3; | ||||
| 	switch (type) { | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-mci.c: Digital Devices microcode interface | ||||
|  * | ||||
| @@ -38,7 +39,7 @@ static int mci_reset(struct mci *state) | ||||
| 	msleep(300); | ||||
| 	ddblwritel(link, 0, MCI_CONTROL); | ||||
|  | ||||
| 	while(1) { | ||||
| 	while (1) { | ||||
| 		status = ddblreadl(link, MCI_CONTROL); | ||||
| 		if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) | ||||
| 			break; | ||||
| @@ -46,7 +47,7 @@ static int mci_reset(struct mci *state) | ||||
| 			break; | ||||
| 		msleep(50); | ||||
| 	} | ||||
| 	if ((status & MCI_CONTROL_READY) == 0 ) | ||||
| 	if ((status & MCI_CONTROL_READY) == 0) | ||||
| 		return -1; | ||||
| 	if (link->ids.device == 0x0009  || link->ids.device == 0x000b) | ||||
| 		ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); | ||||
| @@ -71,7 +72,7 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state, | ||||
| 	struct ddb_link *link = state->base->link; | ||||
| 	u32 i, val; | ||||
| 	unsigned long stat; | ||||
| 	 | ||||
|  | ||||
| 	val = ddblreadl(link, MCI_CONTROL); | ||||
| 	if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) | ||||
| 		return -EIO; | ||||
| @@ -80,19 +81,21 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state, | ||||
| 			ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); | ||||
| 	val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); | ||||
| 	ddblwritel(link, val, MCI_CONTROL); | ||||
| 	 | ||||
|  | ||||
| 	stat = wait_for_completion_timeout(&state->base->completion, HZ); | ||||
| 	if (stat == 0) { | ||||
| 		u32 istat = ddblreadl(link, INTERRUPT_STATUS); | ||||
|  | ||||
| 		printk("MCI timeout\n"); | ||||
| 		dev_err(state->base->link->dev->dev, "MCI timeout\n"); | ||||
| 		val = ddblreadl(link, MCI_CONTROL); | ||||
| 		if (val == 0xffffffff) { | ||||
| 			printk("Lost PCIe link!\n"); | ||||
| 			dev_err(state->base->link->dev->dev, | ||||
| 				"Lost PCIe link!\n"); | ||||
| 			return -EIO; | ||||
| 		} else { | ||||
| 			printk("DDBridge IRS %08x link %u\n", istat, link->nr); | ||||
| 			if (istat & 1)  | ||||
| 			dev_err(state->base->link->dev->dev, | ||||
| 				"DDBridge IRS %08x link %u\n", istat, link->nr); | ||||
| 			if (istat & 1) | ||||
| 				ddblwritel(link, istat, INTERRUPT_ACK); | ||||
| 			if (link->nr) | ||||
| 				ddbwritel(link->dev, 0xffffff, INTERRUPT_ACK); | ||||
| @@ -110,7 +113,7 @@ int ddb_mci_cmd_unlocked(struct mci *state, | ||||
| { | ||||
| 	u32 *cmd = (u32 *) command; | ||||
| 	u32 *res = (u32 *) result; | ||||
| 	 | ||||
|  | ||||
| 	return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32), | ||||
| 					res, sizeof(*result)/sizeof(u32)); | ||||
| } | ||||
| @@ -141,7 +144,7 @@ int ddb_mci_cmd_raw(struct mci *state, | ||||
| 		    struct mci_result *result, u32 result_len) | ||||
| { | ||||
| 	int stat; | ||||
| 	 | ||||
|  | ||||
| 	mutex_lock(&state->base->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(state, | ||||
| 					(u32 *)command, command_len, | ||||
| @@ -186,8 +189,7 @@ int ddb_mci_get_snr(struct dvb_frontend *fe) | ||||
|  | ||||
| 	p->cnr.len = 1; | ||||
| 	p->cnr.stat[0].scale = FE_SCALE_DECIBEL; | ||||
| 	p->cnr.stat[0].svalue = (s64) mci-> | ||||
| 		signal_info.dvbs2_signal_info.signal_to_noise * 10; | ||||
| 	p->cnr.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -249,7 +251,7 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 		ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10, | ||||
| 		ROLLOFF_5, ROLLOFF_15, ROLLOFF_35, ROLLOFF_35 | ||||
| 	}; | ||||
| 	 | ||||
|  | ||||
| 	p->frequency = | ||||
| 		mci->signal_info.dvbs2_signal_info.frequency; | ||||
| 	switch (p->delivery_system) { | ||||
| @@ -259,7 +261,6 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 	{ | ||||
| 		u32 pls_code = | ||||
| 			mci->signal_info.dvbs2_signal_info.pls_code; | ||||
| 		 | ||||
| 		p->frequency = | ||||
| 			mci->signal_info.dvbs2_signal_info.frequency / 1000; | ||||
| 		p->delivery_system = | ||||
| @@ -267,11 +268,10 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 			SYS_DVBS2 : SYS_DVBS; | ||||
| 		if (mci->signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 			u32 modcod = (0x7c & pls_code) >> 2; | ||||
| 			 | ||||
|  | ||||
| 			p->delivery_system = SYS_DVBS2; | ||||
| 			p->rolloff = | ||||
| 				ro_lut[mci->signal_info. | ||||
| 				       dvbs2_signal_info.roll_off & 7]; | ||||
| 				ro_lut[mci->signal_info.dvbs2_signal_info.roll_off & 7]; | ||||
| 			p->pilot = (pls_code & 1) ? PILOT_ON : PILOT_OFF; | ||||
| 			p->fec_inner = modcod2fec[modcod]; | ||||
| 			p->modulation = modcod2mod[modcod]; | ||||
| @@ -314,8 +314,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
|  | ||||
| 	p->cnr.len = 1; | ||||
| 	p->cnr.stat[0].scale = FE_SCALE_DECIBEL; | ||||
| 	p->cnr.stat[0].svalue = (s64) mci-> | ||||
| 		signal_info.dvbs2_signal_info.signal_to_noise * 10; | ||||
| 	p->cnr.stat[0].svalue = (s64) | ||||
| 		mci->signal_info.dvbs2_signal_info.signal_to_noise * 10; | ||||
|  | ||||
| 	p->strength.len = 1; | ||||
| 	p->strength.stat[0].scale = FE_SCALE_DECIBEL; | ||||
|   | ||||
| @@ -644,14 +644,13 @@ struct mci_result { | ||||
| 			u8  min_input_stream_id; | ||||
| 			u8  max_input_stream_id; | ||||
| 		} BBHeader; | ||||
| 		 | ||||
|  | ||||
| 		struct { | ||||
| 			u8  Mode;          // FFT Mode   1,2,3 | ||||
| 			u8  GuardInterval; // 1/32, 1/16, 1/8, /14    | ||||
| 			 | ||||
| 			u8  TMCCInfo[13];      // TMCC B20 - B121,  byte 0 bit 7: B20,  byte 12 bit 2: B121  | ||||
| 			u8  GuardInterval; // 1/32, 1/16, 1/8, /14 | ||||
| 			u8  TMCCInfo[13];  // TMCC B20 - B121,  byte 0 bit 7: B20,  byte 12 bit 2: B121 | ||||
| 		} ISDBT_TMCCInfo; | ||||
| 		 | ||||
|  | ||||
| 		struct { | ||||
| 			u8   Change;  // 5 bits, increments with every change | ||||
| 			struct { | ||||
| @@ -710,7 +709,7 @@ struct mci_result { | ||||
|  | ||||
| /* DVB-T2 L1-Post Signalling Data   ( ETSI EN 302 755 V1.4.1 Chapter 7.2.3 ) */ | ||||
|  | ||||
| #define L1POST_SUB_SLICES_PER_FRAME(p)     (((u16)(p)[ 0] & 0x7F) | (p)[ 1]) | ||||
| #define L1POST_SUB_SLICES_PER_FRAME(p)     (((u16)(p)[0] & 0x7F) | (p)[1]) | ||||
| #define L1POST_NUM_PLP(p)                  ((p)[2] & 0xFF) | ||||
| #define L1POST_NUM_AUX(p)                  ((p)[3] & 0x0F) | ||||
| #define L1POST_AUX_CONFIG_RFU(p)           ((p)[4] & 0xFF) | ||||
| @@ -750,8 +749,6 @@ struct mci_base { | ||||
| 	void                *key; | ||||
| 	struct ddb_link     *link; | ||||
| 	struct completion    completion; | ||||
| 	struct i2c_adapter  *i2c; | ||||
| 	struct mutex         i2c_lock; | ||||
| 	struct mutex         tuner_lock; | ||||
| 	struct mutex         mci_lock; | ||||
| 	int                  count; | ||||
| @@ -788,4 +785,7 @@ int ddb_mci_get_info(struct mci *mci); | ||||
| int ddb_mci_get_strength(struct dvb_frontend *fe); | ||||
| void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); | ||||
|  | ||||
| extern struct mci_cfg ddb_max_sx8_cfg; | ||||
| extern struct mci_cfg ddb_max_m4_cfg; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -441,11 +441,11 @@ static int ns_start(struct dvbnss *nss) | ||||
| 		reg |= 0x40; | ||||
| 	if (nss->params.flags & DVB_NS_IPV6) | ||||
| 		reg |= 0x80; | ||||
| 	ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16), | ||||
| 		  STREAM_CONTROL(dns->nr)); | ||||
| 	if (dns->fe != input) | ||||
| 		ddb_dvb_ns_input_start(dns->fe); | ||||
| 	ddb_dvb_ns_input_start(input); | ||||
| 	ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16), | ||||
| 		  STREAM_CONTROL(dns->nr)); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -501,7 +501,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune, | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int get_algo(struct dvb_frontend *fe) | ||||
| static enum dvbfe_algo get_algo(struct dvb_frontend *fe) | ||||
| { | ||||
| 	return DVBFE_ALGO_HW; | ||||
| } | ||||
| @@ -541,10 +541,10 @@ static struct dvb_frontend_ops sx8_ops = { | ||||
| 	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */ | ||||
| 	.info = { | ||||
| 		.name = "DVB-S/S2X", | ||||
| 		.frequency_min		= 950000, | ||||
| 		.frequency_max		= 2150000, | ||||
| 		.frequency_stepsize	= 0, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_min_hz	= 950000000, | ||||
| 		.frequency_max_hz	= 2150000000, | ||||
| 		.frequency_stepsize_hz	= 0, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.symbol_rate_min	= 100000, | ||||
| 		.symbol_rate_max	= 100000000, | ||||
| 		.caps			= FE_CAN_INVERSION_AUTO | | ||||
|   | ||||
| @@ -60,22 +60,20 @@ | ||||
| #include <linux/mutex.h> | ||||
| #include <asm/dma.h> | ||||
| #include <asm/irq.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/uaccess.h> | ||||
|  | ||||
| #include <linux/dvb/ca.h> | ||||
| #include <linux/socket.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/io.h> | ||||
|  | ||||
| #include "dvb_netstream.h" | ||||
| #include "dmxdev.h" | ||||
| #include "dvbdev.h" | ||||
| #include "dvb_demux.h" | ||||
| #include "dvb_frontend.h" | ||||
| #include "dvb_ringbuffer.h" | ||||
| #include "dvb_ca_en50221.h" | ||||
| #include "dvb_net.h" | ||||
| #include <media/dmxdev.h> | ||||
| #include <media/dvbdev.h> | ||||
| #include <media/dvb_demux.h> | ||||
| #include <media/dvb_frontend.h> | ||||
| #include <media/dvb_ringbuffer.h> | ||||
| #include <media/dvb_ca_en50221.h> | ||||
| #include <media/dvb_net.h> | ||||
|  | ||||
| #include "tda18271c2dd.h" | ||||
| #include "stv6110x.h" | ||||
| @@ -238,7 +236,7 @@ struct ddb_dvb { | ||||
| 	enum fe_sec_tone_mode  tone; | ||||
| 	enum fe_sec_voltage    voltage; | ||||
|  | ||||
| 	int (*i2c_gate_ctrl)(struct dvb_frontend *, int); | ||||
| 	int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int val); | ||||
| 	int (*set_voltage)(struct dvb_frontend *fe, | ||||
| 			   enum fe_sec_voltage voltage); | ||||
| 	int (*set_input)(struct dvb_frontend *fe, int input); | ||||
| @@ -408,7 +406,7 @@ struct ddb_lnb { | ||||
| }; | ||||
|  | ||||
| struct ddb_irq { | ||||
| 	void                   (*handler)(void *); | ||||
| 	void                   (*handler)(void *data); | ||||
| 	void                   *data; | ||||
| }; | ||||
|  | ||||
| @@ -542,7 +540,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg); | ||||
| int ddbridge_mod_init(struct ddb *dev); | ||||
| void ddbridge_mod_output_stop(struct ddb_output *output); | ||||
| int ddbridge_mod_output_start(struct ddb_output *output); | ||||
| void ddbridge_mod_rate_handler(void *); | ||||
| void ddbridge_mod_rate_handler(void *data); | ||||
|  | ||||
| void ddb_device_destroy(struct ddb *dev); | ||||
| void ddb_nsd_detach(struct ddb *dev); | ||||
|   | ||||
| @@ -38,7 +38,7 @@ | ||||
| #include <asm/uaccess.h> | ||||
| #include <linux/dvb/ns.h> | ||||
|  | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
|  | ||||
| #define DVBNS_MAXPIDS 32 | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,32 @@ | ||||
| # DVB device configuration | ||||
| # | ||||
|  | ||||
| config DVB_MMAP | ||||
| 	bool "Enable DVB memory-mapped API (EXPERIMENTAL)" | ||||
| 	depends on DVB_CORE | ||||
| 	depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE | ||||
| 	select VIDEOBUF2_VMALLOC | ||||
| 	help | ||||
| 	  This option enables DVB experimental memory-mapped API, which | ||||
| 	  reduces the number of context switches to read DVB buffers, as | ||||
| 	  the buffers can use mmap() syscalls. | ||||
|  | ||||
| 	  Support for it is experimental. Use with care. If unsure, | ||||
| 	  say N. | ||||
|  | ||||
| config DVB_NET | ||||
| 	bool "DVB Network Support" | ||||
| 	default (NET && INET) | ||||
| 	depends on NET && INET && DVB_CORE | ||||
| 	help | ||||
| 	  This option enables DVB Network Support which is a part of the DVB | ||||
| 	  standard. It is used, for example, by automatic firmware updates used | ||||
| 	  on Set-Top-Boxes. It can also be used to access the Internet via the | ||||
| 	  DVB card, if the network provider supports it. | ||||
|  | ||||
| 	  You may want to disable the network support on embedded devices. If | ||||
| 	  unsure say Y. | ||||
|  | ||||
| config DVB_MAX_ADAPTERS | ||||
| 	int "maximum number of DVB/ATSC adapters" | ||||
| 	depends on DVB_CORE | ||||
| @@ -19,7 +45,7 @@ config DVB_MAX_ADAPTERS | ||||
| config DVB_DYNAMIC_MINORS | ||||
| 	bool "Dynamic DVB minor allocation" | ||||
| 	depends on DVB_CORE | ||||
| 	default n | ||||
| 	default y | ||||
| 	help | ||||
| 	  If you say Y here, the DVB subsystem will use dynamic minor | ||||
| 	  allocation for any device that uses the DVB major number. | ||||
| @@ -32,7 +58,6 @@ config DVB_DYNAMIC_MINORS | ||||
| config DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 	bool "Enable DVB demux section packet loss log" | ||||
| 	depends on DVB_CORE | ||||
| 	default n | ||||
| 	help | ||||
| 	  Enable extra log messages meant to detect packet loss | ||||
| 	  inside the Kernel. | ||||
| @@ -41,3 +66,15 @@ config DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 	  be very verbose. | ||||
|  | ||||
| 	  If you are unsure about this, say N here. | ||||
|  | ||||
| config DVB_ULE_DEBUG | ||||
| 	bool "Enable DVB net ULE packet debug messages" | ||||
| 	depends on DVB_CORE | ||||
| 	help | ||||
| 	  Enable extra log messages meant to detect problems while | ||||
| 	  handling DVB network ULE packet loss inside the Kernel. | ||||
|  | ||||
| 	  Should not be enabled on normal cases, as logs can | ||||
| 	  be very verbose. | ||||
|  | ||||
| 	  If you are unsure about this, say N here. | ||||
|   | ||||
| @@ -3,11 +3,14 @@ | ||||
| # Makefile for the kernel DVB device drivers. | ||||
| # | ||||
|  | ||||
| dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\ | ||||
| dvb-net-$(CONFIG_DVB_NET) := dvb_net.o | ||||
| dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o | ||||
|  | ||||
| dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o		 	\ | ||||
| 		 dvb_ca_en50221.o dvb_frontend.o 		\ | ||||
| 		 dvb_net.o dvb_ringbuffer.o dvb_math.o | ||||
| 		 $(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_CORE) += dvb-core.o | ||||
|  | ||||
| EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET | ||||
| NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core | ||||
| #NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux | ||||
|   | ||||
| @@ -9,3 +9,5 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\ | ||||
| 		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_CORE) += dvb-core.o | ||||
|  | ||||
| ccflags-y += -Idrivers/media/dvb-core/ | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
|  | ||||
| #define pr_fmt(fmt) "dmxdev: " fmt | ||||
|  | ||||
| #include <linux/version.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/slab.h> | ||||
| @@ -27,8 +28,10 @@ | ||||
| #include <linux/ioctl.h> | ||||
| #include <linux/wait.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/version.h> | ||||
| #include "dmxdev.h" | ||||
| #include <media/dmxdev.h> | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| #include <media/dvb_vb2.h> | ||||
| #endif | ||||
|  | ||||
| static int debug; | ||||
|  | ||||
| @@ -128,6 +131,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | ||||
| 	struct dvb_device *dvbdev = file->private_data; | ||||
| 	struct dmxdev *dmxdev = dvbdev->priv; | ||||
| 	struct dmx_frontend *front; | ||||
| 	bool need_ringbuffer = false; | ||||
|  | ||||
| 	dprintk("%s\n", __func__); | ||||
|  | ||||
| @@ -139,14 +143,33 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
|  | ||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDWR) { | ||||
| 	dmxdev->may_do_mmap = 0; | ||||
|  | ||||
| 	/* | ||||
| 	 * The logic here is a little tricky due to the ifdef. | ||||
| 	 * | ||||
| 	 * The ringbuffer is used for both read and mmap. | ||||
| 	 * | ||||
| 	 * It is not needed, however, on two situations: | ||||
| 	 *	- Write devices (access with O_WRONLY); | ||||
| 	 *	- For duplex device nodes, opened with O_RDWR. | ||||
| 	 */ | ||||
|  | ||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||||
| 		need_ringbuffer = true; | ||||
| 	else if ((file->f_flags & O_ACCMODE) == O_RDWR) { | ||||
| 		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 			dmxdev->may_do_mmap = 1; | ||||
| 			need_ringbuffer = true; | ||||
| #else | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -EOPNOTSUPP; | ||||
| #endif | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||||
| 	if (need_ringbuffer) { | ||||
| 		void *mem; | ||||
|  | ||||
| 		if (!dvbdev->readers) { | ||||
| @@ -159,6 +182,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 		if (dmxdev->may_do_mmap) | ||||
| 			dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", | ||||
| 				     file->f_flags & O_NONBLOCK); | ||||
| #endif | ||||
| 		dvbdev->readers--; | ||||
| 	} | ||||
|  | ||||
| @@ -196,7 +224,15 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) | ||||
| 		dmxdev->demux->connect_frontend(dmxdev->demux, | ||||
| 						dmxdev->dvr_orig_fe); | ||||
| 	} | ||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||||
| 	if (((file->f_flags & O_ACCMODE) == O_RDONLY) || | ||||
| 	    dmxdev->may_do_mmap) { | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 		if (dmxdev->may_do_mmap) { | ||||
| 			if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) | ||||
| 				dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); | ||||
| 			dvb_vb2_release(&dmxdev->dvr_vb2_ctx); | ||||
| 		} | ||||
| #endif | ||||
| 		dvbdev->readers++; | ||||
| 		if (dmxdev->dvr_buffer.data) { | ||||
| 			void *mem = dmxdev->dvr_buffer.data; | ||||
| @@ -381,12 +417,18 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) | ||||
| #endif | ||||
| static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 				       const u8 *buffer2, size_t buffer2_len, | ||||
| 				       struct dmx_section_filter *filter) | ||||
| 				       struct dmx_section_filter *filter, | ||||
| 				       u32 *buffer_flags) | ||||
| { | ||||
| 	struct dmxdev_filter *dmxdevfilter = filter->priv; | ||||
| 	int ret; | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) && | ||||
| 	    dmxdevfilter->buffer.error) { | ||||
| #else | ||||
| 	if (dmxdevfilter->buffer.error) { | ||||
| #endif | ||||
| 		wake_up(&dmxdevfilter->buffer.queue); | ||||
| 		return 0; | ||||
| 	} | ||||
| @@ -397,12 +439,31 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 	} | ||||
| 	del_timer(&dmxdevfilter->timer); | ||||
| 	dprintk("section callback %*ph\n", 6, buffer1); | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { | ||||
| 		ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, | ||||
| 					  buffer1, buffer1_len, | ||||
| 					  buffer_flags); | ||||
| 		if (ret == buffer1_len) | ||||
| 			ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, | ||||
| 						  buffer2, buffer2_len, | ||||
| 						  buffer_flags); | ||||
| 	} else { | ||||
| 		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, | ||||
| 					      buffer1, buffer1_len); | ||||
| 		if (ret == buffer1_len) { | ||||
| 			ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, | ||||
| 						      buffer2, buffer2_len); | ||||
| 		} | ||||
| 	} | ||||
| #else | ||||
| 	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, | ||||
| 				      buffer1_len); | ||||
| 	if (ret == buffer1_len) { | ||||
| 		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, | ||||
| 					      buffer2_len); | ||||
| 	} | ||||
| #endif | ||||
| 	if (ret < 0) | ||||
| 		dmxdevfilter->buffer.error = ret; | ||||
| 	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) | ||||
| @@ -414,7 +475,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | ||||
|  | ||||
| static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 				  const u8 *buffer2, size_t buffer2_len, | ||||
| 				  struct dmx_ts_feed *feed) | ||||
| 				       struct dmx_ts_feed *feed, | ||||
| 				       u32 *buffer_flags) | ||||
| { | ||||
| 	struct dmxdev_filter *dmxdevfilter = feed->priv; | ||||
| 	struct dvb_ringbuffer *buffer; | ||||
| @@ -426,19 +488,40 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP | ||||
| 	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) | ||||
| 	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP || | ||||
| 	    dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { | ||||
| 		buffer = &dmxdevfilter->buffer; | ||||
| 	else | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 		ctx = &dmxdevfilter->vb2_ctx; | ||||
| #endif | ||||
| 	} else { | ||||
| 		buffer = &dmxdevfilter->dev->dvr_buffer; | ||||
| 	if (buffer->error) { | ||||
| 		spin_unlock(&dmxdevfilter->dev->lock); | ||||
| 		wake_up(&buffer->queue); | ||||
| 		return 0; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 		ctx = &dmxdevfilter->dev->dvr_vb2_ctx; | ||||
| #endif | ||||
| 	} | ||||
| 	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||||
| 	if (ret == buffer1_len) | ||||
| 		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (dvb_vb2_is_streaming(ctx)) { | ||||
| 		ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len, | ||||
| 					  buffer_flags); | ||||
| 		if (ret == buffer1_len) | ||||
| 			ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len, | ||||
| 						  buffer_flags); | ||||
| 	} else { | ||||
| #endif | ||||
| 		if (buffer->error) { | ||||
| 			spin_unlock(&dmxdevfilter->dev->lock); | ||||
| 			wake_up(&buffer->queue); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||||
| 		if (ret == buffer1_len) | ||||
| 			ret = dvb_dmxdev_buffer_write(buffer, | ||||
| 						      buffer2, buffer2_len); | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	} | ||||
| #endif | ||||
| 	if (ret < 0) | ||||
| 		buffer->error = ret; | ||||
| 	spin_unlock(&dmxdevfilter->dev->lock); | ||||
| @@ -585,7 +668,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, | ||||
| 				 struct dmxdev_filter *filter, | ||||
| 				 struct dmxdev_feed *feed) | ||||
| { | ||||
| 	ktime_t timeout; | ||||
| 	ktime_t timeout = ktime_set(0, 0); | ||||
| 	struct dmx_pes_filter_params *para = &filter->params.pes; | ||||
| 	enum dmx_output otype; | ||||
| 	int ret; | ||||
| @@ -593,7 +676,6 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, | ||||
| 	enum dmx_ts_pes ts_pes; | ||||
| 	struct dmx_ts_feed *tsfeed; | ||||
|  | ||||
| 	timeout = ktime_set(0, 0); | ||||
| 	feed->ts = NULL; | ||||
| 	otype = para->output; | ||||
|  | ||||
| @@ -777,7 +859,17 @@ static int dvb_demux_open(struct inode *inode, struct file *file) | ||||
| 	mutex_init(&dmxdevfilter->mutex); | ||||
| 	file->private_data = dmxdevfilter; | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	dmxdev->may_do_mmap = 1; | ||||
| #else | ||||
| 	dmxdev->may_do_mmap = 0; | ||||
| #endif | ||||
|  | ||||
| 	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter", | ||||
| 		     file->f_flags & O_NONBLOCK); | ||||
| #endif | ||||
| 	dmxdevfilter->type = DMXDEV_TYPE_NONE; | ||||
| 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) | ||||
| @@ -797,6 +889,11 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, | ||||
| { | ||||
| 	mutex_lock(&dmxdev->mutex); | ||||
| 	mutex_lock(&dmxdevfilter->mutex); | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) | ||||
| 		dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx); | ||||
| 	dvb_vb2_release(&dmxdevfilter->vb2_ctx); | ||||
| #endif | ||||
|  | ||||
| 	dvb_dmxdev_filter_stop(dmxdevfilter); | ||||
| 	dvb_dmxdev_filter_reset(dmxdevfilter); | ||||
| @@ -1084,8 +1181,56 @@ static int dvb_demux_do_ioctl(struct file *file, | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	case DMX_REQBUFS: | ||||
| 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -ERESTARTSYS; | ||||
| 		} | ||||
| 		ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg); | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_QUERYBUF: | ||||
| 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -ERESTARTSYS; | ||||
| 		} | ||||
| 		ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg); | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_EXPBUF: | ||||
| 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -ERESTARTSYS; | ||||
| 		} | ||||
| 		ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg); | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_QBUF: | ||||
| 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -ERESTARTSYS; | ||||
| 		} | ||||
| 		ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg); | ||||
| 		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) | ||||
| 			ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx); | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_DQBUF: | ||||
| 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 			mutex_unlock(&dmxdev->mutex); | ||||
| 			return -ERESTARTSYS; | ||||
| 		} | ||||
| 		ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg); | ||||
| 		mutex_unlock(&dmxdevfilter->mutex); | ||||
| 		break; | ||||
| #endif | ||||
| 	default: | ||||
| 		ret = -EINVAL; | ||||
| 		ret = -ENOTTY; | ||||
| 		break; | ||||
| 	} | ||||
| 	mutex_unlock(&dmxdev->mutex); | ||||
| @@ -1098,30 +1243,70 @@ static long dvb_demux_ioctl(struct file *file, unsigned int cmd, | ||||
| 	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); | ||||
| } | ||||
|  | ||||
| static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) | ||||
| typedef unsigned int __poll_t; | ||||
| #define EPOLLIN POLLIN | ||||
| #define EPOLLERR POLLERR | ||||
| #define EPOLLPRI POLLPRI | ||||
| #define EPOLLRDNORM POLLRDNORM | ||||
| #define EPOLLWRNORM POLLWRNORM | ||||
| #define EPOLLOUT POLLOUT | ||||
| #endif | ||||
|  | ||||
| static __poll_t dvb_demux_poll(struct file *file, poll_table *wait) | ||||
| { | ||||
| 	struct dmxdev_filter *dmxdevfilter = file->private_data; | ||||
| 	unsigned int mask = 0; | ||||
|  | ||||
| 	if ((!dmxdevfilter) || dmxdevfilter->dev->exit) | ||||
| 		return POLLERR; | ||||
| 	__poll_t mask = 0; | ||||
|  | ||||
| 	poll_wait(file, &dmxdevfilter->buffer.queue, wait); | ||||
|  | ||||
| 	if ((!dmxdevfilter) || dmxdevfilter->dev->exit) | ||||
| 		return EPOLLERR; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) | ||||
| 		return dvb_vb2_poll(&dmxdevfilter->vb2_ctx, file, wait); | ||||
| #endif | ||||
|  | ||||
| 	if (dmxdevfilter->state != DMXDEV_STATE_GO && | ||||
| 	    dmxdevfilter->state != DMXDEV_STATE_DONE && | ||||
| 	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (dmxdevfilter->buffer.error) | ||||
| 		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||||
| 		mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); | ||||
|  | ||||
| 	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) | ||||
| 		mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||||
| 		mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI); | ||||
|  | ||||
| 	return mask; | ||||
| } | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) | ||||
| { | ||||
| 	struct dmxdev_filter *dmxdevfilter = file->private_data; | ||||
| 	struct dmxdev *dmxdev = dmxdevfilter->dev; | ||||
| 	int ret; | ||||
|  | ||||
| 	if (!dmxdev->may_do_mmap) | ||||
| 		return -ENOTTY; | ||||
|  | ||||
| 	if (mutex_lock_interruptible(&dmxdev->mutex)) | ||||
| 		return -ERESTARTSYS; | ||||
|  | ||||
| 	if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||||
| 		mutex_unlock(&dmxdev->mutex); | ||||
| 		return -ERESTARTSYS; | ||||
| 	} | ||||
| 	ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma); | ||||
|  | ||||
| 	mutex_unlock(&dmxdevfilter->mutex); | ||||
| 	mutex_unlock(&dmxdev->mutex); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int dvb_demux_release(struct inode *inode, struct file *file) | ||||
| { | ||||
| 	struct dmxdev_filter *dmxdevfilter = file->private_data; | ||||
| @@ -1146,10 +1331,14 @@ static const struct file_operations dvb_demux_fops = { | ||||
| 	.owner = THIS_MODULE, | ||||
| 	.read = dvb_demux_read, | ||||
| 	.unlocked_ioctl = dvb_demux_ioctl, | ||||
| 	.compat_ioctl = dvb_demux_ioctl, | ||||
| 	.open = dvb_demux_open, | ||||
| 	.release = dvb_demux_release, | ||||
| 	.poll = dvb_demux_poll, | ||||
| 	.llseek = default_llseek, | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	.mmap = dvb_demux_mmap, | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static const struct dvb_device dvbdev_demux = { | ||||
| @@ -1178,8 +1367,31 @@ static int dvb_dvr_do_ioctl(struct file *file, | ||||
| 		ret = dvb_dvr_set_buffer_size(dmxdev, arg); | ||||
| 		break; | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	case DMX_REQBUFS: | ||||
| 		ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_QUERYBUF: | ||||
| 		ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_EXPBUF: | ||||
| 		ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_QBUF: | ||||
| 		ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg); | ||||
| 		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) | ||||
| 			ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx); | ||||
| 		break; | ||||
|  | ||||
| 	case DMX_DQBUF: | ||||
| 		ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg); | ||||
| 		break; | ||||
| #endif | ||||
| 	default: | ||||
| 		ret = -EINVAL; | ||||
| 		ret = -ENOTTY; | ||||
| 		break; | ||||
| 	} | ||||
| 	mutex_unlock(&dmxdev->mutex); | ||||
| @@ -1192,31 +1404,58 @@ static long dvb_dvr_ioctl(struct file *file, | ||||
| 	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); | ||||
| } | ||||
|  | ||||
| static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) | ||||
| static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) | ||||
| { | ||||
| 	struct dvb_device *dvbdev = file->private_data; | ||||
| 	struct dmxdev *dmxdev = dvbdev->priv; | ||||
| 	unsigned int mask = 0; | ||||
| 	__poll_t mask = 0; | ||||
|  | ||||
| 	dprintk("%s\n", __func__); | ||||
|  | ||||
| 	if (dmxdev->exit) | ||||
| 		return POLLERR; | ||||
|  | ||||
| 	poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | ||||
|  | ||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||||
| 	if (dmxdev->exit) | ||||
| 		return EPOLLERR; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) | ||||
| 		return dvb_vb2_poll(&dmxdev->dvr_vb2_ctx, file, wait); | ||||
| #endif | ||||
|  | ||||
| 	if (((file->f_flags & O_ACCMODE) == O_RDONLY) || | ||||
| 	    dmxdev->may_do_mmap) { | ||||
| 		if (dmxdev->dvr_buffer.error) | ||||
| 			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||||
| 			mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); | ||||
|  | ||||
| 		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) | ||||
| 			mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||||
| 			mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI); | ||||
| 	} else | ||||
| 		mask |= (POLLOUT | POLLWRNORM | POLLPRI); | ||||
| 		mask |= (EPOLLOUT | EPOLLWRNORM | EPOLLPRI); | ||||
|  | ||||
| 	return mask; | ||||
| } | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) | ||||
| { | ||||
| 	struct dvb_device *dvbdev = file->private_data; | ||||
| 	struct dmxdev *dmxdev = dvbdev->priv; | ||||
| 	int ret; | ||||
|  | ||||
| 	if (!dmxdev->may_do_mmap) | ||||
| 		return -ENOTTY; | ||||
|  | ||||
| 	if (dmxdev->exit) | ||||
| 		return -ENODEV; | ||||
|  | ||||
| 	if (mutex_lock_interruptible(&dmxdev->mutex)) | ||||
| 		return -ERESTARTSYS; | ||||
|  | ||||
| 	ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma); | ||||
| 	mutex_unlock(&dmxdev->mutex); | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static const struct file_operations dvb_dvr_fops = { | ||||
| 	.owner = THIS_MODULE, | ||||
| 	.read = dvb_dvr_read, | ||||
| @@ -1226,6 +1465,9 @@ static const struct file_operations dvb_dvr_fops = { | ||||
| 	.release = dvb_dvr_release, | ||||
| 	.poll = dvb_dvr_poll, | ||||
| 	.llseek = default_llseek, | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	.mmap = dvb_dvr_mmap, | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static const struct dvb_device dvbdev_dvr = { | ||||
| @@ -1237,6 +1479,7 @@ static const struct dvb_device dvbdev_dvr = { | ||||
| #endif | ||||
| 	.fops = &dvb_dvr_fops | ||||
| }; | ||||
|  | ||||
| int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | ||||
| { | ||||
| 	int i; | ||||
| @@ -1244,7 +1487,12 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | ||||
| 	if (dmxdev->demux->open(dmxdev->demux) < 0) | ||||
| 		return -EUSERS; | ||||
|  | ||||
| 	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)) | ||||
| 	dmxdev->filter = vmalloc(sizeof(struct dmxdev_filter) * dmxdev->filternum); | ||||
| #else | ||||
| 	dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter), | ||||
| 					    dmxdev->filternum)); | ||||
| #endif | ||||
| 	if (!dmxdev->filter) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
|   | ||||
| @@ -1,115 +0,0 @@ | ||||
| /* | ||||
|  * dmxdev.h | ||||
|  * | ||||
|  * Copyright (C) 2000 Ralph Metzler & Marcus Metzler | ||||
|  *                    for convergence integrated media GmbH | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public License | ||||
|  * as published by the Free Software Foundation; either version 2.1 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _DMXDEV_H_ | ||||
| #define _DMXDEV_H_ | ||||
|  | ||||
| #include <linux/types.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/time.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/wait.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include <linux/dvb/dmx.h> | ||||
|  | ||||
| #include "dvbdev.h" | ||||
| #include "demux.h" | ||||
| #include "dvb_ringbuffer.h" | ||||
|  | ||||
| enum dmxdev_type { | ||||
| 	DMXDEV_TYPE_NONE, | ||||
| 	DMXDEV_TYPE_SEC, | ||||
| 	DMXDEV_TYPE_PES, | ||||
| }; | ||||
|  | ||||
| enum dmxdev_state { | ||||
| 	DMXDEV_STATE_FREE, | ||||
| 	DMXDEV_STATE_ALLOCATED, | ||||
| 	DMXDEV_STATE_SET, | ||||
| 	DMXDEV_STATE_GO, | ||||
| 	DMXDEV_STATE_DONE, | ||||
| 	DMXDEV_STATE_TIMEDOUT | ||||
| }; | ||||
|  | ||||
| struct dmxdev_feed { | ||||
| 	u16 pid; | ||||
| 	struct dmx_ts_feed *ts; | ||||
| 	struct list_head next; | ||||
| }; | ||||
|  | ||||
| struct dmxdev_filter { | ||||
| 	union { | ||||
| 		struct dmx_section_filter *sec; | ||||
| 	} filter; | ||||
|  | ||||
| 	union { | ||||
| 		/* list of TS and PES feeds (struct dmxdev_feed) */ | ||||
| 		struct list_head ts; | ||||
| 		struct dmx_section_feed *sec; | ||||
| 	} feed; | ||||
|  | ||||
| 	union { | ||||
| 		struct dmx_sct_filter_params sec; | ||||
| 		struct dmx_pes_filter_params pes; | ||||
| 	} params; | ||||
|  | ||||
| 	enum dmxdev_type type; | ||||
| 	enum dmxdev_state state; | ||||
| 	struct dmxdev *dev; | ||||
| 	struct dvb_ringbuffer buffer; | ||||
|  | ||||
| 	struct mutex mutex; | ||||
|  | ||||
| 	/* only for sections */ | ||||
| 	struct timer_list timer; | ||||
| 	int todo; | ||||
| 	u8 secheader[3]; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct dmxdev { | ||||
| 	struct dvb_device *dvbdev; | ||||
| 	struct dvb_device *dvr_dvbdev; | ||||
|  | ||||
| 	struct dmxdev_filter *filter; | ||||
| 	struct dmx_demux *demux; | ||||
|  | ||||
| 	int filternum; | ||||
| 	int capabilities; | ||||
|  | ||||
| 	unsigned int exit:1; | ||||
| #define DMXDEV_CAP_DUPLEX 1 | ||||
| 	struct dmx_frontend *dvr_orig_fe; | ||||
|  | ||||
| 	struct dvb_ringbuffer dvr_buffer; | ||||
| #define DVR_BUFFER_SIZE (10*188*1024) | ||||
|  | ||||
| 	struct mutex mutex; | ||||
| 	spinlock_t lock; | ||||
| }; | ||||
|  | ||||
|  | ||||
| int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *); | ||||
| void dvb_dmxdev_release(struct dmxdev *dmxdev); | ||||
|  | ||||
| #endif /* _DMXDEV_H_ */ | ||||
| @@ -34,8 +34,8 @@ | ||||
| #endif | ||||
| #include <linux/kthread.h> | ||||
|  | ||||
| #include "dvb_ca_en50221.h" | ||||
| #include "dvb_ringbuffer.h" | ||||
| #include <media/dvb_ca_en50221.h> | ||||
| #include <media/dvb_ringbuffer.h> | ||||
|  | ||||
| static int dvb_ca_en50221_debug; | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
| #include <linux/uaccess.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_demux.h" | ||||
| #include <media/dvb_demux.h> | ||||
|  | ||||
|  | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) | ||||
| @@ -68,6 +68,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts, | ||||
| 		dprintk(x);				\ | ||||
| } while (0) | ||||
|  | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| #  define dprintk_sect_loss(x...) dprintk(x) | ||||
| #else | ||||
| #  define dprintk_sect_loss(x...) | ||||
| #endif | ||||
|  | ||||
| #define set_buf_flags(__feed, __flag)			\ | ||||
| 	do {						\ | ||||
| 		(__feed)->buffer_flags |= (__flag);	\ | ||||
| 	} while (0) | ||||
|  | ||||
| /****************************************************************************** | ||||
|  * static inlined helper functions | ||||
|  ******************************************************************************/ | ||||
| @@ -117,30 +128,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, | ||||
| { | ||||
| 	int count = payload(buf); | ||||
| 	int p; | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 	int ccok; | ||||
| 	u8 cc; | ||||
| #endif | ||||
|  | ||||
| 	if (count == 0) | ||||
| 		return -1; | ||||
|  | ||||
| 	p = 188 - count; | ||||
|  | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 	cc = buf[3] & 0x0f; | ||||
| 	ccok = ((feed->cc + 1) & 0x0f) == cc; | ||||
| 	feed->cc = cc; | ||||
| 	if (!ccok) | ||||
| 		dprintk("missed packet!\n"); | ||||
| #endif | ||||
| 	if (!ccok) { | ||||
| 		set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 		dprintk_sect_loss("missed packet: %d instead of %d!\n", | ||||
| 				  cc, (feed->cc + 1) & 0x0f); | ||||
| 	} | ||||
|  | ||||
| 	if (buf[1] & 0x40)	// PUSI ? | ||||
| 		feed->peslen = 0xfffa; | ||||
|  | ||||
| 	feed->peslen += count; | ||||
|  | ||||
| 	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts); | ||||
| 	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, | ||||
| 			   &feed->buffer_flags); | ||||
| } | ||||
|  | ||||
| static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, | ||||
| @@ -162,7 +173,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, | ||||
| 		return 0; | ||||
|  | ||||
| 	return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, | ||||
| 			    NULL, 0, &f->filter); | ||||
| 			    NULL, 0, &f->filter, &feed->buffer_flags); | ||||
| } | ||||
|  | ||||
| static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) | ||||
| @@ -181,8 +192,10 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) | ||||
| 	if (sec->check_crc) { | ||||
| 		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); | ||||
| 		if (section_syntax_indicator && | ||||
| 		    demux->check_crc32(feed, sec->secbuf, sec->seclen)) | ||||
| 		    demux->check_crc32(feed, sec->secbuf, sec->seclen)) { | ||||
| 			set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| @@ -199,9 +212,8 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) | ||||
| { | ||||
| 	struct dmx_section_feed *sec = &feed->feed.sec; | ||||
|  | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 	if (sec->secbufp < sec->tsfeedp) { | ||||
| 		int i, n = sec->tsfeedp - sec->secbufp; | ||||
| 		int n = sec->tsfeedp - sec->secbufp; | ||||
|  | ||||
| 		/* | ||||
| 		 * Section padding is done with 0xff bytes entirely. | ||||
| @@ -209,15 +221,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) | ||||
| 		 * but just first and last. | ||||
| 		 */ | ||||
| 		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { | ||||
| 			dprintk("dvb_demux.c section ts padding loss: %d/%d\n", | ||||
| 			       n, sec->tsfeedp); | ||||
| 			dprintk("dvb_demux.c pad data:"); | ||||
| 			for (i = 0; i < n; i++) | ||||
| 				pr_cont(" %02x", sec->secbuf[i]); | ||||
| 			pr_cont("\n"); | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 			dprintk_sect_loss("section ts padding loss: %d/%d\n", | ||||
| 					  n, sec->tsfeedp); | ||||
| 			dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf); | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	sec->tsfeedp = sec->secbufp = sec->seclen = 0; | ||||
| 	sec->secbuf = sec->secbuf_base; | ||||
| @@ -236,10 +246,10 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) | ||||
|  *  when the second packet arrives. | ||||
|  * | ||||
|  * Fix: | ||||
|  * when demux is started, let feed->pusi_seen = 0 to | ||||
|  * when demux is started, let feed->pusi_seen = false to | ||||
|  * prevent initial feeding of garbage from the end of | ||||
|  * previous section. When you for the first time see PUSI=1 | ||||
|  * then set feed->pusi_seen = 1 | ||||
|  * then set feed->pusi_seen = true | ||||
|  */ | ||||
| static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, | ||||
| 					      const u8 *buf, u8 len) | ||||
| @@ -252,11 +262,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, | ||||
| 		return 0; | ||||
|  | ||||
| 	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 		dprintk("dvb_demux.c section buffer full loss: %d/%d\n", | ||||
| 		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, | ||||
| 		       DMX_MAX_SECFEED_SIZE); | ||||
| #endif | ||||
| 		set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 		dprintk_sect_loss("section buffer full loss: %d/%d\n", | ||||
| 				  sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, | ||||
| 				  DMX_MAX_SECFEED_SIZE); | ||||
| 		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; | ||||
| 	} | ||||
|  | ||||
| @@ -284,12 +293,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, | ||||
| 		sec->seclen = seclen; | ||||
| 		sec->crc_val = ~0; | ||||
| 		/* dump [secbuf .. secbuf+seclen) */ | ||||
| 		if (feed->pusi_seen) | ||||
| 		if (feed->pusi_seen) { | ||||
| 			dvb_dmx_swfilter_section_feed(feed); | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 		else | ||||
| 			dprintk("dvb_demux.c pusi not seen, discarding section data\n"); | ||||
| #endif | ||||
| 		} else { | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 			dprintk_sect_loss("pusi not seen, discarding section data\n"); | ||||
| 		} | ||||
| 		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */ | ||||
| 		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */ | ||||
| 	} | ||||
| @@ -322,19 +332,31 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, | ||||
| 	} | ||||
|  | ||||
| 	if (!ccok || dc_i) { | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 		dprintk("dvb_demux.c discontinuity detected %d bytes lost\n", | ||||
| 			count); | ||||
| 		if (dc_i) { | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR); | ||||
| 			dprintk_sect_loss("%d frame with disconnect indicator\n", | ||||
| 				cc); | ||||
| 		} else { | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 			dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n", | ||||
| 				cc, (feed->cc + 1) & 0x0f, count + 4); | ||||
| 		} | ||||
| 		/* | ||||
| 		 * those bytes under sume circumstances will again be reported | ||||
| 		 * those bytes under some circumstances will again be reported | ||||
| 		 * in the following dvb_dmx_swfilter_section_new | ||||
| 		 */ | ||||
| #endif | ||||
|  | ||||
| 		/* | ||||
| 		 * Discontinuity detected. Reset pusi_seen = 0 to | ||||
| 		 * Discontinuity detected. Reset pusi_seen to | ||||
| 		 * stop feeding of suspicious data until next PUSI=1 arrives | ||||
| 		 * | ||||
| 		 * FIXME: does it make sense if the MPEG-TS is the one | ||||
| 		 *	reporting discontinuity? | ||||
| 		 */ | ||||
| 		feed->pusi_seen = 0; | ||||
|  | ||||
| 		feed->pusi_seen = false; | ||||
| 		dvb_dmx_swfilter_section_new(feed); | ||||
| 	} | ||||
|  | ||||
| @@ -348,17 +370,16 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, | ||||
|  | ||||
| 			dvb_dmx_swfilter_section_copy_dump(feed, before, | ||||
| 							   before_len); | ||||
| 			/* before start of new section, set pusi_seen = 1 */ | ||||
| 			feed->pusi_seen = 1; | ||||
| 			/* before start of new section, set pusi_seen */ | ||||
| 			feed->pusi_seen = true; | ||||
| 			dvb_dmx_swfilter_section_new(feed); | ||||
| 			dvb_dmx_swfilter_section_copy_dump(feed, after, | ||||
| 							   after_len); | ||||
| 		} else if (count > 0) { | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 			dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count); | ||||
| 		} | ||||
| #ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG | ||||
| 		else if (count > 0) | ||||
| 			dprintk("dvb_demux.c PUSI=1 but %d bytes lost\n", | ||||
| 				count); | ||||
| #endif | ||||
| 	} else { | ||||
| 		/* PUSI=0 (is not set), no section boundary */ | ||||
| 		dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); | ||||
| @@ -378,8 +399,10 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, | ||||
| 			if (feed->ts_type & TS_PAYLOAD_ONLY) | ||||
| 				dvb_dmx_swfilter_payload(feed, buf); | ||||
| 			else | ||||
| 				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); | ||||
| 				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, | ||||
| 					    &feed->buffer_flags); | ||||
| 		} | ||||
| 		/* Used only on full-featured devices */ | ||||
| 		if (feed->ts_type & TS_DECODER) | ||||
| 			if (feed->demux->write_to_decoder) | ||||
| 				feed->demux->write_to_decoder(feed, buf, 188); | ||||
| @@ -426,9 +449,10 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||||
| 						1024); | ||||
| 				speed_timedelta = ktime_ms_delta(cur_time, | ||||
| 							demux->speed_last_time); | ||||
| 				dprintk("TS speed %llu Kbits/sec \n", | ||||
| 					div64_u64(speed_bytes, | ||||
| 						  speed_timedelta)); | ||||
| 				if (speed_timedelta) | ||||
| 					dprintk("TS speed %llu Kbits/sec \n", | ||||
| 						div64_u64(speed_bytes, | ||||
| 							  speed_timedelta)); | ||||
| 			} | ||||
|  | ||||
| 			demux->speed_last_time = cur_time; | ||||
| @@ -437,6 +461,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||||
| 	} | ||||
|  | ||||
| 	if (buf[1] & 0x80) { | ||||
| 		list_for_each_entry(feed, &demux->feed_list, list_head) { | ||||
| 			if ((feed->pid != pid) && (feed->pid != 0x2000)) | ||||
| 				continue; | ||||
| 			set_buf_flags(feed, DMX_BUFFER_FLAG_TEI); | ||||
| 		} | ||||
| 		dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n", | ||||
| 				pid, buf[1]); | ||||
| 		/* data in this packet can't be trusted - drop it unless | ||||
| @@ -452,6 +481,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||||
| 						(demux->cnt_storage[pid] + 1) & 0xf; | ||||
|  | ||||
| 				if ((buf[3] & 0xf) != demux->cnt_storage[pid]) { | ||||
| 					list_for_each_entry(feed, &demux->feed_list, list_head) { | ||||
| 						if ((feed->pid != pid) && (feed->pid != 0x2000)) | ||||
| 							continue; | ||||
| 						set_buf_flags(feed, | ||||
| 							      DMX_BUFFER_PKT_COUNTER_MISMATCH); | ||||
| 					} | ||||
|  | ||||
| 					dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n", | ||||
| 						pid, demux->cnt_storage[pid], | ||||
| 						buf[3] & 0xf); | ||||
| @@ -473,7 +509,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||||
| 		if (feed->pid == pid) | ||||
| 			dvb_dmx_swfilter_packet_type(feed, buf); | ||||
| 		else if (feed->pid == 0x2000) | ||||
| 			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); | ||||
| 			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, | ||||
| 				    &feed->buffer_flags); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -592,7 +629,16 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count) | ||||
|  | ||||
| 	spin_lock_irqsave(&demux->lock, flags); | ||||
|  | ||||
| 	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts); | ||||
| #if 1 | ||||
| 	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, | ||||
| 			   &demux->feed->buffer_flags); | ||||
| #else | ||||
| 	struct dvb_demux_feed *feed; | ||||
| 	list_for_each_entry(feed, &demux->feed_list, list_head) { | ||||
| 		feed->cb.ts(buf, count, NULL, 0, &feed->feed.ts, | ||||
| 			    &feed->buffer_flags); | ||||
| 	} | ||||
| #endif	 | ||||
|  | ||||
| 	spin_unlock_irqrestore(&demux->lock, flags); | ||||
| } | ||||
| @@ -792,6 +838,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, | ||||
| 	feed->demux = demux; | ||||
| 	feed->pid = 0xffff; | ||||
| 	feed->peslen = 0xfffa; | ||||
| 	feed->buffer_flags = 0; | ||||
|  | ||||
| 	(*ts_feed) = &feed->feed.ts; | ||||
| 	(*ts_feed)->parent = dmx; | ||||
| @@ -911,14 +958,14 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) | ||||
| 		return; | ||||
| 	do { | ||||
| 		sf = &f->filter; | ||||
| 		doneq = 0; | ||||
| 		doneq = false; | ||||
| 		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { | ||||
| 			mode = sf->filter_mode[i]; | ||||
| 			mask = sf->filter_mask[i]; | ||||
| 			f->maskandmode[i] = mask & mode; | ||||
| 			doneq |= f->maskandnotmode[i] = mask & ~mode; | ||||
| 		} | ||||
| 		f->doneq = doneq ? 1 : 0; | ||||
| 		f->doneq = doneq ? true : false; | ||||
| 	} while ((f = f->next)); | ||||
| } | ||||
|  | ||||
| @@ -945,6 +992,7 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) | ||||
| 	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||||
| 	dvbdmxfeed->feed.sec.secbufp = 0; | ||||
| 	dvbdmxfeed->feed.sec.seclen = 0; | ||||
| 	dvbdmxfeed->pusi_seen = false; | ||||
|  | ||||
| 	if (!dvbdmx->start_feed) { | ||||
| 		mutex_unlock(&dvbdmx->mutex); | ||||
| @@ -1049,6 +1097,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, | ||||
| 	dvbdmxfeed->cb.sec = callback; | ||||
| 	dvbdmxfeed->demux = dvbdmx; | ||||
| 	dvbdmxfeed->pid = 0xffff; | ||||
| 	dvbdmxfeed->buffer_flags = 0; | ||||
| 	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||||
| 	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; | ||||
| 	dvbdmxfeed->feed.sec.tsfeedp = 0; | ||||
| @@ -1220,12 +1269,25 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) | ||||
|  | ||||
| 	dvbdemux->cnt_storage = NULL; | ||||
| 	dvbdemux->users = 0; | ||||
| 	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)) | ||||
| 	dvbdemux->filter = vmalloc(sizeof(struct dvb_demux_filter) * | ||||
| 				   dvbdemux->filternum); | ||||
|  | ||||
| 	if (!dvbdemux->filter) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); | ||||
| 	dvbdemux->feed = vmalloc(sizeof(struct dvb_demux_feed) * | ||||
| 				 dvbdemux->feednum); | ||||
| #else | ||||
| 	dvbdemux->filter = vmalloc(array_size(sizeof(struct dvb_demux_filter), | ||||
| 					      dvbdemux->filternum)); | ||||
|  | ||||
| 	if (!dvbdemux->filter) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	dvbdemux->feed = vmalloc(array_size(sizeof(struct dvb_demux_feed), | ||||
| 					    dvbdemux->feednum)); | ||||
| #endif | ||||
| 	if (!dvbdemux->feed) { | ||||
| 		vfree(dvbdemux->filter); | ||||
| 		dvbdemux->filter = NULL; | ||||
|   | ||||
| @@ -1,145 +0,0 @@ | ||||
| /* | ||||
|  * dvb_demux.h: DVB kernel demux API | ||||
|  * | ||||
|  * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler | ||||
|  *                         for convergence integrated media GmbH | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public License | ||||
|  * as published by the Free Software Foundation; either version 2.1 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _DVB_DEMUX_H_ | ||||
| #define _DVB_DEMUX_H_ | ||||
|  | ||||
| #include <linux/time.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/mutex.h> | ||||
|  | ||||
| #include "demux.h" | ||||
|  | ||||
| #define DMX_TYPE_TS  0 | ||||
| #define DMX_TYPE_SEC 1 | ||||
| #define DMX_TYPE_PES 2 | ||||
|  | ||||
| #define DMX_STATE_FREE      0 | ||||
| #define DMX_STATE_ALLOCATED 1 | ||||
| #define DMX_STATE_SET       2 | ||||
| #define DMX_STATE_READY     3 | ||||
| #define DMX_STATE_GO        4 | ||||
|  | ||||
| #define DVB_DEMUX_MASK_MAX 18 | ||||
|  | ||||
| #define MAX_PID 0x1fff | ||||
|  | ||||
| #define SPEED_PKTS_INTERVAL 50000 | ||||
|  | ||||
| struct dvb_demux_filter { | ||||
| 	struct dmx_section_filter filter; | ||||
| 	u8 maskandmode[DMX_MAX_FILTER_SIZE]; | ||||
| 	u8 maskandnotmode[DMX_MAX_FILTER_SIZE]; | ||||
| 	int doneq; | ||||
|  | ||||
| 	struct dvb_demux_filter *next; | ||||
| 	struct dvb_demux_feed *feed; | ||||
| 	int index; | ||||
| 	int state; | ||||
| 	int type; | ||||
|  | ||||
| 	u16 hw_handle; | ||||
| 	struct timer_list timer; | ||||
| }; | ||||
|  | ||||
| #define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head) | ||||
|  | ||||
| struct dvb_demux_feed { | ||||
| 	union { | ||||
| 		struct dmx_ts_feed ts; | ||||
| 		struct dmx_section_feed sec; | ||||
| 	} feed; | ||||
|  | ||||
| 	union { | ||||
| 		dmx_ts_cb ts; | ||||
| 		dmx_section_cb sec; | ||||
| 	} cb; | ||||
|  | ||||
| 	struct dvb_demux *demux; | ||||
| 	void *priv; | ||||
| 	int type; | ||||
| 	int state; | ||||
| 	u16 pid; | ||||
|  | ||||
| 	ktime_t timeout; | ||||
| 	struct dvb_demux_filter *filter; | ||||
|  | ||||
| 	int ts_type; | ||||
| 	enum dmx_ts_pes pes_type; | ||||
|  | ||||
| 	int cc; | ||||
| 	int pusi_seen;		/* prevents feeding of garbage from previous section */ | ||||
|  | ||||
| 	u16 peslen; | ||||
|  | ||||
| 	struct list_head list_head; | ||||
| 	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */ | ||||
| }; | ||||
|  | ||||
| struct dvb_demux { | ||||
| 	struct dmx_demux dmx; | ||||
| 	void *priv; | ||||
| 	int filternum; | ||||
| 	int feednum; | ||||
| 	int (*start_feed)(struct dvb_demux_feed *feed); | ||||
| 	int (*stop_feed)(struct dvb_demux_feed *feed); | ||||
| 	int (*write_to_decoder)(struct dvb_demux_feed *feed, | ||||
| 				 const u8 *buf, size_t len); | ||||
| 	u32 (*check_crc32)(struct dvb_demux_feed *feed, | ||||
| 			    const u8 *buf, size_t len); | ||||
| 	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst, | ||||
| 			 const u8 *src, size_t len); | ||||
|  | ||||
| 	int users; | ||||
| #define MAX_DVB_DEMUX_USERS 10 | ||||
| 	struct dvb_demux_filter *filter; | ||||
| 	struct dvb_demux_feed *feed; | ||||
|  | ||||
| 	struct list_head frontend_list; | ||||
|  | ||||
| 	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER]; | ||||
| 	u16 pids[DMX_PES_OTHER]; | ||||
| 	int playing; | ||||
| 	int recording; | ||||
|  | ||||
| #define DMX_MAX_PID 0x2000 | ||||
| 	struct list_head feed_list; | ||||
| 	u8 tsbuf[204]; | ||||
| 	int tsbufp; | ||||
|  | ||||
| 	struct mutex mutex; | ||||
| 	spinlock_t lock; | ||||
|  | ||||
| 	uint8_t *cnt_storage; /* for TS continuity check */ | ||||
|  | ||||
| 	ktime_t speed_last_time; /* for TS speed check */ | ||||
| 	uint32_t speed_pkts_cnt; /* for TS speed check */ | ||||
| }; | ||||
|  | ||||
| int dvb_dmx_init(struct dvb_demux *dvbdemux); | ||||
| void dvb_dmx_release(struct dvb_demux *dvbdemux); | ||||
| void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, | ||||
| 			      size_t count); | ||||
| void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); | ||||
| void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, | ||||
| 			  size_t count); | ||||
| void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, | ||||
| 			  size_t count); | ||||
|  | ||||
| #endif /* _DVB_DEMUX_H_ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -19,7 +19,7 @@ | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <asm/bug.h> | ||||
| #include "dvb_math.h" | ||||
| #include <media/dvb_math.h> | ||||
|  | ||||
| static const unsigned short logtable[256] = { | ||||
| 	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
| /* | ||||
|  * dvb_net.c | ||||
|  * | ||||
| @@ -13,18 +14,6 @@ | ||||
|  *                      and Wolfram Stering <wstering@cosy.sbg.ac.at> | ||||
|  * | ||||
|  * ULE Decaps according to RFC 4326. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * as published by the Free Software Foundation; either version 2 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * To obtain the license, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| @@ -38,7 +27,7 @@ | ||||
|  *                       Competence Center for Advanced Satellite Communications. | ||||
|  *                     Bugfixes and robustness improvements. | ||||
|  *                     Filtering on dest MAC addresses, if present (D-Bit = 0) | ||||
|  *                     ULE_DEBUG compile-time option. | ||||
|  *                     DVB_ULE_DEBUG compile-time option. | ||||
|  * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by | ||||
|  *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>, | ||||
|  *                       Paris Lodron University of Salzburg. | ||||
| @@ -69,8 +58,8 @@ | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/sched.h> | ||||
|  | ||||
| #include "dvb_demux.h" | ||||
| #include "dvb_net.h" | ||||
| #include <media/dvb_demux.h> | ||||
| #include <media/dvb_net.h> | ||||
|  | ||||
| static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) | ||||
| { | ||||
| @@ -83,15 +72,20 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) | ||||
|  | ||||
| #define DVB_NET_MULTICAST_MAX 10 | ||||
|  | ||||
| #undef ULE_DEBUG | ||||
| #undef DVB_ULE_DEBUG | ||||
|  | ||||
| #ifdef ULE_DEBUG | ||||
| #ifdef DVB_ULE_DEBUG | ||||
| /* | ||||
|  * The code inside DVB_ULE_DEBUG keeps a history of the | ||||
|  * last 100 TS cells processed. | ||||
|  */ | ||||
| static unsigned char ule_hist[100*TS_SZ] = { 0 }; | ||||
| static unsigned char *ule_where = ule_hist, ule_dump; | ||||
|  | ||||
| static void hexdump(const unsigned char *buf, unsigned short len) | ||||
| { | ||||
| 	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| struct dvb_net_priv { | ||||
| @@ -130,7 +124,7 @@ struct dvb_net_priv { | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  *	Determine the packet's protocol ID. The rule here is that we | ||||
|  *	assume 802.3 if the type field is short enough to be a length. | ||||
|  *	This is normal practice and works for any 'now in use' protocol. | ||||
| @@ -160,7 +154,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, | ||||
|  | ||||
| 	rawp = skb->data; | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 *	This is a magic hack to spot IPX packets. Older Novell breaks | ||||
| 	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC | ||||
| 	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | ||||
| @@ -169,7 +163,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, | ||||
| 	if (*(unsigned short *)rawp == 0xFFFF) | ||||
| 		return htons(ETH_P_802_3); | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 *	Real 802.2 LLC | ||||
| 	 */ | ||||
| 	return htons(ETH_P_802_2); | ||||
| @@ -220,7 +214,8 @@ static int ule_exthdr_padding(struct dvb_net_priv *p) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /** Handle ULE extension headers. | ||||
| /* | ||||
|  *  Handle ULE extension headers. | ||||
|  *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. | ||||
|  *  Returns: >= 0: nr. of bytes consumed by next extension header | ||||
|  *	     -1:   Mandatory extension header that is not recognized or TEST SNDU; discard. | ||||
| @@ -284,11 +279,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p ) | ||||
| 		if (l < 0) | ||||
| 			return l;	/* Stop extension header processing and discard SNDU. */ | ||||
| 		total_ext_len += l; | ||||
| #ifdef ULE_DEBUG | ||||
| 		pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n", | ||||
| 			 p->ule_next_hdr, (int)p->ule_sndu_type, | ||||
| 			 l, total_ext_len); | ||||
| #endif | ||||
|  | ||||
| 	} while (p->ule_sndu_type < ETH_P_802_3_MIN); | ||||
|  | ||||
| @@ -296,7 +289,7 @@ static int handle_ule_extensions( struct dvb_net_priv *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| /** Prepare for a new ULE SNDU: reset the decoder state. */ | ||||
| /* Prepare for a new ULE SNDU: reset the decoder state. */ | ||||
| static inline void reset_ule( struct dvb_net_priv *p ) | ||||
| { | ||||
| 	p->ule_skb = NULL; | ||||
| @@ -309,7 +302,7 @@ static inline void reset_ule( struct dvb_net_priv *p ) | ||||
| 	p->ule_bridged = 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of | ||||
|  * TS cells of a single PID. | ||||
|  */ | ||||
| @@ -324,29 +317,21 @@ struct dvb_net_ule_handle { | ||||
| 	const u8 *ts, *ts_end, *from_where; | ||||
| 	u8 ts_remain, how_much, new_ts; | ||||
| 	bool error; | ||||
| #ifdef ULE_DEBUG | ||||
| 	/* | ||||
| 	 * The code inside ULE_DEBUG keeps a history of the | ||||
| 	 * last 100 TS cells processed. | ||||
| 	 */ | ||||
| 	static unsigned char ule_hist[100*TS_SZ]; | ||||
| 	static unsigned char *ule_where = ule_hist, ule_dump; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static int dvb_net_ule_new_ts_cell(struct dvb_net_ule_handle *h) | ||||
| { | ||||
| 	/* We are about to process a new TS cell. */ | ||||
|  | ||||
| #ifdef ULE_DEBUG | ||||
| 	if (h->ule_where >= &h->ule_hist[100*TS_SZ]) | ||||
| 		h->ule_where = h->ule_hist; | ||||
| 	memcpy(h->ule_where, h->ts, TS_SZ); | ||||
| 	if (h->ule_dump) { | ||||
| 		hexdump(h->ule_where, TS_SZ); | ||||
| 		h->ule_dump = 0; | ||||
| #ifdef DVB_ULE_DEBUG | ||||
| 	if (ule_where >= &ule_hist[100*TS_SZ]) | ||||
| 		ule_where = ule_hist; | ||||
| 	memcpy(ule_where, h->ts, TS_SZ); | ||||
| 	if (ule_dump) { | ||||
| 		hexdump(ule_where, TS_SZ); | ||||
| 		ule_dump = 0; | ||||
| 	} | ||||
| 	h->ule_where += TS_SZ; | ||||
| 	ule_where += TS_SZ; | ||||
| #endif | ||||
|  | ||||
| 	/* | ||||
| @@ -664,6 +649,7 @@ static int dvb_net_ule_should_drop(struct dvb_net_ule_handle *h) | ||||
|  | ||||
|  | ||||
| static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, | ||||
| 				  struct kvec iov[3], | ||||
| 				  u32 ule_crc, u32 expected_crc) | ||||
| { | ||||
| 	u8 dest_addr[ETH_ALEN]; | ||||
| @@ -676,22 +662,22 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, | ||||
| 			h->ts_remain > 2 ? | ||||
| 				*(unsigned short *)h->from_where : 0); | ||||
|  | ||||
| 	#ifdef ULE_DEBUG | ||||
|         #ifdef DVB_ULE_DEBUG | ||||
| 		hexdump(iov[0].iov_base, iov[0].iov_len); | ||||
| 		hexdump(iov[1].iov_base, iov[1].iov_len); | ||||
| 		hexdump(iov[2].iov_base, iov[2].iov_len); | ||||
|  | ||||
| 		if (h->ule_where == h->ule_hist) { | ||||
| 			hexdump(&h->ule_hist[98*TS_SZ], TS_SZ); | ||||
| 			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ); | ||||
| 		} else if (h->ule_where == &h->ule_hist[TS_SZ]) { | ||||
| 			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ); | ||||
| 			hexdump(h->ule_hist, TS_SZ); | ||||
| 		if (ule_where == ule_hist) { | ||||
| 			hexdump(&ule_hist[98*TS_SZ], TS_SZ); | ||||
| 			hexdump(&ule_hist[99*TS_SZ], TS_SZ); | ||||
| 		} else if (ule_where == &ule_hist[TS_SZ]) { | ||||
| 			hexdump(&ule_hist[99*TS_SZ], TS_SZ); | ||||
| 			hexdump(ule_hist, TS_SZ); | ||||
| 		} else { | ||||
| 			hexdump(h->ule_where - TS_SZ - TS_SZ, TS_SZ); | ||||
| 			hexdump(h->ule_where - TS_SZ, TS_SZ); | ||||
| 			hexdump(ule_where - TS_SZ - TS_SZ, TS_SZ); | ||||
| 			hexdump(ule_where - TS_SZ, TS_SZ); | ||||
| 		} | ||||
| 		h->ule_dump = 1; | ||||
| 		ule_dump = 1; | ||||
| 	#endif | ||||
|  | ||||
| 		h->dev->stats.rx_errors++; | ||||
| @@ -709,11 +695,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, | ||||
|  | ||||
| 	if (!h->priv->ule_dbit) { | ||||
| 		if (dvb_net_ule_should_drop(h)) { | ||||
| #ifdef ULE_DEBUG | ||||
| 			netdev_dbg(h->dev, | ||||
| 				   "Dropping SNDU: MAC destination address does not match: dest addr: %pM, h->dev addr: %pM\n", | ||||
| 				   h->priv->ule_skb->data, h->dev->dev_addr); | ||||
| #endif | ||||
| 			dev_kfree_skb(h->priv->ule_skb); | ||||
| 			return; | ||||
| 		} | ||||
| @@ -784,6 +768,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) | ||||
| 	struct dvb_net_ule_handle h = { | ||||
| 		.dev = dev, | ||||
| 		.priv = netdev_priv(dev), | ||||
| 		.ethh = NULL, | ||||
| 		.buf = buf, | ||||
| 		.buf_len = buf_len, | ||||
| 		.skipped = 0L, | ||||
| @@ -793,11 +778,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) | ||||
| 		.ts_remain = 0, | ||||
| 		.how_much = 0, | ||||
| 		.new_ts = 1, | ||||
| 		.ethh = NULL, | ||||
| 		.error = false, | ||||
| #ifdef ULE_DEBUG | ||||
| 		.ule_where = ule_hist, | ||||
| #endif | ||||
| 	}; | ||||
|  | ||||
| 	/* | ||||
| @@ -869,7 +850,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) | ||||
| 				       *(tail - 2) << 8 | | ||||
| 				       *(tail - 1); | ||||
|  | ||||
| 			dvb_net_ule_check_crc(&h, ule_crc, expected_crc); | ||||
| 			dvb_net_ule_check_crc(&h, iov, ule_crc, expected_crc); | ||||
|  | ||||
| 			/* Prepare for next SNDU. */ | ||||
| 			reset_ule(h.priv); | ||||
| @@ -902,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) | ||||
|  | ||||
| static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 			       const u8 *buffer2, size_t buffer2_len, | ||||
| 			       struct dmx_ts_feed *feed) | ||||
| 			       struct dmx_ts_feed *feed, | ||||
| 			       u32 *buffer_flags) | ||||
| { | ||||
| 	struct net_device *dev = feed->priv; | ||||
|  | ||||
| @@ -1010,12 +992,12 @@ static void dvb_net_sec(struct net_device *dev, | ||||
| } | ||||
|  | ||||
| static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 		 const u8 *buffer2, size_t buffer2_len, | ||||
| 		 struct dmx_section_filter *filter) | ||||
| 				const u8 *buffer2, size_t buffer2_len, | ||||
| 				struct dmx_section_filter *filter, u32 *buffer_flags) | ||||
| { | ||||
| 	struct net_device *dev = filter->priv; | ||||
|  | ||||
| 	/** | ||||
| 	/* | ||||
| 	 * we rely on the DVB API definition where exactly one complete | ||||
| 	 * section is delivered in buffer1 | ||||
| 	 */ | ||||
| @@ -1023,7 +1005,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) | ||||
| static netdev_tx_t dvb_net_tx(struct sk_buff *skb, struct net_device *dev) | ||||
| { | ||||
| 	dev_kfree_skb(skb); | ||||
| 	return NETDEV_TX_OK; | ||||
|   | ||||
| @@ -34,7 +34,7 @@ | ||||
| #include <linux/uaccess.h> | ||||
| #endif | ||||
|  | ||||
| #include "dvb_ringbuffer.h" | ||||
| #include <media/dvb_ringbuffer.h> | ||||
|  | ||||
| #define PKT_READY 0 | ||||
| #define PKT_DISPOSED 1 | ||||
| @@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) | ||||
| 	 * this pairs with smp_store_release() in dvb_ringbuffer_write(), | ||||
| 	 * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() | ||||
| 	 * | ||||
| 	 * for memory barriers also see Documentation/circular-buffers.txt | ||||
| 	 * for memory barriers also see Documentation/core-api/circular-buffers.txt | ||||
| 	 */ | ||||
| 	return (rbuf->pread == smp_load_acquire(&rbuf->pwrite)); | ||||
| #endif | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include <linux/string.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/device.h> | ||||
| @@ -31,7 +32,7 @@ | ||||
| #include <linux/cdev.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/version.h> | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
|  | ||||
| #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0)) | ||||
| /* Due to enum tuner_pad_index */ | ||||
| @@ -54,8 +55,19 @@ static LIST_HEAD(dvb_adapter_list); | ||||
| static DEFINE_MUTEX(dvbdev_register_lock); | ||||
|  | ||||
| static const char * const dnames[] = { | ||||
| 	"video", "audio", "sec", "frontend", "demux", "dvr", "ca", | ||||
| 	"net", "osd", "ci", "mod", "ns", "nsd" | ||||
| 	[DVB_DEVICE_VIDEO] =		"video", | ||||
| 	[DVB_DEVICE_AUDIO] =		"audio", | ||||
| 	[DVB_DEVICE_SEC] =		"sec", | ||||
| 	[DVB_DEVICE_FRONTEND] =		"frontend", | ||||
| 	[DVB_DEVICE_DEMUX] =		"demux", | ||||
| 	[DVB_DEVICE_DVR] =		"dvr", | ||||
| 	[DVB_DEVICE_CA] =		"ca", | ||||
| 	[DVB_DEVICE_NET] =		"net", | ||||
| 	[DVB_DEVICE_OSD] =		"osd", | ||||
| 	[DVB_DEVICE_CI] =		"ci", | ||||
| 	[DVB_DEVICE_MOD] =		"mod", | ||||
| 	[DVB_DEVICE_NS] =		"ns", | ||||
| 	[DVB_DEVICE_NSD] =		"nsd", | ||||
| }; | ||||
|  | ||||
| #ifdef CONFIG_DVB_DYNAMIC_MINORS | ||||
| @@ -63,7 +75,22 @@ static const char * const dnames[] = { | ||||
| #define DVB_MAX_IDS		MAX_DVB_MINORS | ||||
| #else | ||||
| #define DVB_MAX_IDS		4 | ||||
| #define nums2minor(num, type, id)	((num << 6) | (id << 4) | type) | ||||
|  | ||||
| static const u8 minor_type[] = { | ||||
|        [DVB_DEVICE_VIDEO]      = 0, | ||||
|        [DVB_DEVICE_AUDIO]      = 1, | ||||
|        [DVB_DEVICE_SEC]        = 2, | ||||
|        [DVB_DEVICE_FRONTEND]   = 3, | ||||
|        [DVB_DEVICE_DEMUX]      = 4, | ||||
|        [DVB_DEVICE_DVR]        = 5, | ||||
|        [DVB_DEVICE_CA]         = 6, | ||||
|        [DVB_DEVICE_NET]        = 7, | ||||
|        [DVB_DEVICE_OSD]        = 8, | ||||
| }; | ||||
|  | ||||
| #define nums2minor(num, type, id) \ | ||||
|        (((num) << 6) | ((id) << 4) | minor_type[type]) | ||||
|  | ||||
| #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64) | ||||
| #endif | ||||
|  | ||||
| @@ -319,8 +346,10 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, | ||||
| 	if (npads) { | ||||
| 		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), | ||||
| 				       GFP_KERNEL); | ||||
| 		if (!dvbdev->pads) | ||||
| 		if (!dvbdev->pads){ | ||||
| 			kfree(dvbdev->entity); | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch (type) { | ||||
| @@ -420,8 +449,10 @@ static int dvb_register_media_device(struct dvb_device *dvbdev, | ||||
| 	if (!dvbdev->entity) | ||||
| 		return 0; | ||||
|  | ||||
| 	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, | ||||
| 				      MEDIA_LNK_FL_ENABLED); | ||||
| 	link = media_create_intf_link(dvbdev->entity, | ||||
| 				      &dvbdev->intf_devnode->intf, | ||||
| 				      MEDIA_LNK_FL_ENABLED | | ||||
| 				      MEDIA_LNK_FL_IMMUTABLE); | ||||
| 	if (!link) | ||||
| 		return -ENOMEM; | ||||
| #endif | ||||
| @@ -429,8 +460,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev, | ||||
| } | ||||
|  | ||||
| int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 			const struct dvb_device *template, void *priv, int type, | ||||
| 			int demux_sink_pads) | ||||
| 			const struct dvb_device *template, void *priv, | ||||
| 			enum dvb_device_type type, int demux_sink_pads) | ||||
| { | ||||
| 	struct dvb_device *dvbdev; | ||||
| 	struct file_operations *dvbdevfops; | ||||
| @@ -454,7 +485,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
|  | ||||
| 	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); | ||||
| 	dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); | ||||
|  | ||||
| 	if (!dvbdevfops){ | ||||
| 		kfree (dvbdev); | ||||
| @@ -470,7 +501,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 	dvbdev->fops = dvbdevfops; | ||||
| 	init_waitqueue_head (&dvbdev->wait_queue); | ||||
|  | ||||
| 	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); | ||||
| 	dvbdevfops->owner = adap->module; | ||||
|  | ||||
| 	list_add_tail (&dvbdev->list_head, &adap->device_list); | ||||
| @@ -504,7 +534,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 		dvb_media_device_free(dvbdev); | ||||
| 		kfree(dvbdevfops); | ||||
| 		kfree(dvbdev); | ||||
| 		up_write(&minor_rwsem); | ||||
| 		mutex_unlock(&dvbdev_register_lock); | ||||
| 		return ret; | ||||
| 	} | ||||
| @@ -579,7 +608,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap, | ||||
| 			if (strncmp(entity->name, name, strlen(name))) | ||||
| 				continue; | ||||
| 			link = media_create_intf_link(entity, intf, | ||||
| 						      MEDIA_LNK_FL_ENABLED); | ||||
| 						      MEDIA_LNK_FL_ENABLED | | ||||
| 						      MEDIA_LNK_FL_IMMUTABLE); | ||||
| 			if (!link) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
| @@ -598,8 +628,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 	unsigned demux_pad = 0; | ||||
| 	unsigned dvr_pad = 0; | ||||
| 	unsigned ntuner = 0, ndemod = 0; | ||||
| 	u16 source_pad = 0; | ||||
| 	int ret; | ||||
| 	int ret, pad_source, pad_sink; | ||||
| 	static const char *connector_name = "Television"; | ||||
|  | ||||
| 	if (!mdev) | ||||
| @@ -660,17 +689,6 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 			return ret; | ||||
| 		 | ||||
| 		if (!ntuner) { | ||||
|  | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) | ||||
| 		        if ((ret =  media_get_pad_index(tuner, true, | ||||
|   						    PAD_SIGNAL_ANALOG)) < 0) | ||||
| 			        return ret; | ||||
| 		        source_pad = (u16) ret; | ||||
| 			ret = 0; | ||||
| #else | ||||
| 			source_pad = TUNER_PAD_RF_INPUT; | ||||
| #endif | ||||
| 		 | ||||
| 			ret = media_create_pad_links(mdev, | ||||
| 						     MEDIA_ENT_F_CONN_RF, | ||||
| 						     conn, 0, | ||||
| @@ -679,32 +697,40 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 						     MEDIA_LNK_FL_ENABLED, | ||||
| 						     false); | ||||
| 		} else { | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) | ||||
| 			pad_sink = media_get_pad_index(tuner, true, | ||||
| 						       PAD_SIGNAL_ANALOG); | ||||
| 			if (pad_sink < 0) | ||||
| 				return -EINVAL; | ||||
| 			ret = media_create_pad_links(mdev, | ||||
| 						     MEDIA_ENT_F_CONN_RF, | ||||
| 						     conn, 0, | ||||
| 						     MEDIA_ENT_F_TUNER, | ||||
| 						     tuner, source_pad, | ||||
| 						     tuner, pad_sink, | ||||
| 						     MEDIA_LNK_FL_ENABLED, | ||||
| 						     false); | ||||
| #else | ||||
| 			pad_sink = TUNER_PAD_RF_INPUT; | ||||
| #endif | ||||
| 		} | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 	} | ||||
|  | ||||
| 	if (ntuner && ndemod) { | ||||
| 		     | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) | ||||
| 	        if ((ret =  media_get_pad_index(tuner, true, PAD_SIGNAL_ANALOG)) < 0) | ||||
| 		        return ret; | ||||
| 		source_pad = (u16) ret; | ||||
| 		ret = 0; | ||||
| 		/* NOTE: first found tuner source pad presumed correct */ | ||||
| 		pad_source = media_get_pad_index(tuner, false, | ||||
| 						 PAD_SIGNAL_ANALOG); | ||||
| 		if (pad_source < 0) | ||||
| 			return -EINVAL; | ||||
| #else | ||||
| 		source_pad = TUNER_PAD_OUTPUT; | ||||
| 		pad_source = TUNER_PAD_OUTPUT; | ||||
| #endif | ||||
| 		 | ||||
| 		ret = media_create_pad_links(mdev, | ||||
| 					     MEDIA_ENT_F_TUNER, | ||||
| 					     tuner, source_pad, | ||||
| 					     tuner, pad_source, | ||||
| 					     MEDIA_ENT_F_DTV_DEMOD, | ||||
| 					     demod, 0, MEDIA_LNK_FL_ENABLED, | ||||
| 					     false); | ||||
| @@ -757,14 +783,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 	media_device_for_each_intf(intf, mdev) { | ||||
| 		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) { | ||||
| 			link = media_create_intf_link(ca, intf, | ||||
| 						      MEDIA_LNK_FL_ENABLED); | ||||
| 						      MEDIA_LNK_FL_ENABLED | | ||||
| 						      MEDIA_LNK_FL_IMMUTABLE); | ||||
| 			if (!link) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
|  | ||||
| 		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) { | ||||
| 			link = media_create_intf_link(tuner, intf, | ||||
| 						      MEDIA_LNK_FL_ENABLED); | ||||
| 						      MEDIA_LNK_FL_ENABLED | | ||||
| 						      MEDIA_LNK_FL_IMMUTABLE); | ||||
| 			if (!link) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
| @@ -776,7 +804,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 		 */ | ||||
| 		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) { | ||||
| 			link = media_create_intf_link(demux, intf, | ||||
| 						      MEDIA_LNK_FL_ENABLED); | ||||
| 						      MEDIA_LNK_FL_ENABLED | | ||||
| 						      MEDIA_LNK_FL_IMMUTABLE); | ||||
| 			if (!link) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
| @@ -862,6 +891,10 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||||
| 	adap->mfe_dvbdev = NULL; | ||||
| 	mutex_init (&adap->mfe_lock); | ||||
|  | ||||
| #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||||
| 	mutex_init(&adap->mdev_lock); | ||||
| #endif | ||||
|  | ||||
| 	list_add_tail (&adap->list_head, &dvb_adapter_list); | ||||
|  | ||||
| 	mutex_unlock(&dvbdev_register_lock); | ||||
| @@ -882,7 +915,7 @@ EXPORT_SYMBOL(dvb_unregister_adapter); | ||||
|  | ||||
| /* if the miracle happens and "generic_usercopy()" is included into | ||||
|    the kernel, then this can vanish. please don't make the mistake and | ||||
|    define this as video_usercopy(). this will introduce a dependecy | ||||
|    define this as video_usercopy(). this will introduce a dependency | ||||
|    to the v4l "videodev.o" module, which is unnecessary for some | ||||
|    cards (ie. the budget dvb-cards don't need the v4l module...) */ | ||||
| int dvb_usercopy(struct file *file, | ||||
| @@ -946,6 +979,57 @@ out: | ||||
| } | ||||
| EXPORT_SYMBOL(dvb_usercopy); | ||||
|  | ||||
| #if IS_ENABLED(CONFIG_I2C) | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)) | ||||
| struct i2c_client *dvb_module_probe(const char *module_name, | ||||
| 				    const char *name, | ||||
| 				    struct i2c_adapter *adap, | ||||
| 				    unsigned char addr, | ||||
| 				    void *platform_data) | ||||
| { | ||||
|  	struct i2c_client *client; | ||||
| 	struct i2c_board_info *board_info; | ||||
|  | ||||
| 	board_info = kzalloc(sizeof(*board_info), GFP_KERNEL); | ||||
| 	if (!board_info) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (name) | ||||
| 		strscpy(board_info->type, name, I2C_NAME_SIZE); | ||||
| 	else | ||||
| 		strscpy(board_info->type, module_name, I2C_NAME_SIZE); | ||||
|  | ||||
| 	board_info->addr = addr; | ||||
| 	board_info->platform_data = platform_data; | ||||
| 	request_module(module_name); | ||||
| 	client = i2c_new_client_device(adap, board_info); | ||||
| 	if (!i2c_client_has_driver(client)) { | ||||
| 		kfree(board_info); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (!try_module_get(client->dev.driver->owner)) { | ||||
| 		i2c_unregister_device(client); | ||||
| 		client = NULL; | ||||
| 	} | ||||
|  | ||||
| 	kfree(board_info); | ||||
| 	return client; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(dvb_module_probe); | ||||
|  | ||||
| void dvb_module_release(struct i2c_client *client) | ||||
| { | ||||
| 	if (!client) | ||||
| 		return; | ||||
|  | ||||
| 	module_put(client->dev.driver->owner); | ||||
| 	i2c_unregister_device(client); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(dvb_module_release); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) | ||||
| { | ||||
| 	struct dvb_device *dvbdev = dev_get_drvdata(dev); | ||||
|   | ||||
| @@ -16,7 +16,6 @@ EXTRA_CFLAGS += -DCONFIG_DVB_LNBH25 | ||||
| EXTRA_CFLAGS += -DCONFIG_DVB_MXL5XX | ||||
| EXTRA_CFLAGS += -DCONFIG_DVB_CXD2099 | ||||
| EXTRA_CFLAGS += -DDBVALS | ||||
| NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core | ||||
|  | ||||
| drxk-objs := drxk_hard.o  | ||||
| obj-$(CONFIG_DVB_DRXK) += drxk.o | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #ifndef _CXD2099_H_ | ||||
| #define _CXD2099_H_ | ||||
|  | ||||
| #include <dvb_ca_en50221.h> | ||||
| #include <media/dvb_ca_en50221.h> | ||||
|  | ||||
| struct cxd2099_cfg { | ||||
| 	u32 bitrate; | ||||
|   | ||||
| @@ -35,8 +35,8 @@ | ||||
| #include <linux/mutex.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include "dvb_math.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include <media/dvb_math.h> | ||||
| #include "cxd2843.h" | ||||
|  | ||||
| #define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1)) | ||||
| @@ -105,8 +105,12 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) | ||||
| static int writeregs(struct cxd_state *state, u8 adr, u8 reg, | ||||
| 		     u8 *regd, u16 len) | ||||
| { | ||||
| 	u8 data[len + 1]; | ||||
| 	u8 data[16]; | ||||
|  | ||||
| 	if (len >= 15) { | ||||
| 		pr_err("cxd2843: writeregs length %u too large\n", len); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	data[0] = reg; | ||||
| 	memcpy(data + 1, regd, len); | ||||
| 	return i2c_write(state->i2c, adr, data, len + 1); | ||||
| @@ -2240,7 +2244,7 @@ static enum dvbfe_search search(struct dvb_frontend *fe) | ||||
| 		return DVBFE_ALGO_SEARCH_AGAIN; | ||||
| } | ||||
|  | ||||
| static int get_algo(struct dvb_frontend *fe) | ||||
| static enum dvbfe_algo get_algo(struct dvb_frontend *fe) | ||||
| { | ||||
| 	return DVBFE_ALGO_HW; | ||||
| } | ||||
| @@ -2489,9 +2493,9 @@ static struct dvb_frontend_ops common_ops_2854 = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT }, | ||||
| 	.info = { | ||||
| 		.name = "CXD2854 DVB-C/C2 DVB-T/T2 ISDB-T", | ||||
| 		.frequency_stepsize = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_stepsize_hz = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||||
| @@ -2523,9 +2527,9 @@ static struct dvb_frontend_ops common_ops_2843 = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 }, | ||||
| 	.info = { | ||||
| 		.name = "CXD2843 DVB-C/C2 DVB-T/T2", | ||||
| 		.frequency_stepsize = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_stepsize_hz = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||||
| @@ -2562,9 +2566,9 @@ static struct dvb_frontend_ops common_ops_2837 = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, | ||||
| 	.info = { | ||||
| 		.name = "CXD2837 DVB-C DVB-T/T2", | ||||
| 		.frequency_stepsize = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_stepsize_hz = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||||
| @@ -2601,9 +2605,9 @@ static struct dvb_frontend_ops common_ops_2838 = { | ||||
| 	.delsys = { SYS_ISDBT }, | ||||
| 	.info = { | ||||
| 		.name = "CXD2838 ISDB-T", | ||||
| 		.frequency_stepsize = 166667, | ||||
| 		.frequency_min = 47000000, | ||||
| 		.frequency_max = 865000000, | ||||
| 		.frequency_stepsize_hz = 166667, | ||||
| 		.frequency_min_hz = 47000000, | ||||
| 		.frequency_max_hz = 865000000, | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "drxk.h" | ||||
| #include "drxk_hard.h" | ||||
|  | ||||
| @@ -2804,10 +2804,12 @@ static int DVBTScCommand(struct drxk_state *state, | ||||
| 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM: | ||||
| 		status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1); | ||||
| 		/* All commands using 1 parameters */ | ||||
| 		/* fall through */ | ||||
| 	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: | ||||
| 	case OFDM_SC_RA_RAM_CMD_USER_IO: | ||||
| 		status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0); | ||||
| 		/* All commands using 0 parameters */ | ||||
| 		/* fall through */ | ||||
| 	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM: | ||||
| 	case OFDM_SC_RA_RAM_CMD_NULL: | ||||
| 		/* Write command */ | ||||
| @@ -3215,7 +3217,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 		case TRANSMISSION_MODE_AUTO: | ||||
| 		default: | ||||
| 			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; | ||||
| 			/* fall through , try first guess DRX_FFTMODE_8K */ | ||||
| 			/* try first guess DRX_FFTMODE_8K */ | ||||
| 			/* fall through */ | ||||
| 		case TRANSMISSION_MODE_8K: | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; | ||||
| 			break; | ||||
| @@ -3233,7 +3236,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 		default: | ||||
| 		case GUARD_INTERVAL_AUTO: | ||||
| 			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; | ||||
| 			/* fall through , try first guess DRX_GUARD_1DIV4 */ | ||||
| 			/* try first guess DRX_GUARD_1DIV4 */ | ||||
| 			/* fall through */ | ||||
| 		case GUARD_INTERVAL_1_4: | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; | ||||
| 			break; | ||||
| @@ -3258,9 +3262,10 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 		case 	HIERARCHY_NONE: | ||||
| 		default: | ||||
| 			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; | ||||
| 			/* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ | ||||
| 			/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ | ||||
| 			//	transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; | ||||
| 			//break; | ||||
| 			/* fall through */ | ||||
| 		case 	HIERARCHY_1: | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; | ||||
| 			break; | ||||
| @@ -3282,7 +3287,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 		case QAM_AUTO: | ||||
| 		default: | ||||
| 			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; | ||||
| 			/* fall through , try first guess DRX_CONSTELLATION_QAM64 */ | ||||
| 			/* try first guess DRX_CONSTELLATION_QAM64 */ | ||||
| 			/* fall through */ | ||||
| 		case QAM_64: | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; | ||||
| 			break; | ||||
| @@ -3325,7 +3331,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 		case FEC_AUTO: | ||||
| 		default: | ||||
| 			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; | ||||
| 			/* fall through , try first guess DRX_CODERATE_2DIV3 */ | ||||
| 			/* try first guess DRX_CODERATE_2DIV3 */ | ||||
| 			/* fall through */ | ||||
| 		case FEC_2_3  : | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; | ||||
| 			break; | ||||
| @@ -4994,12 +5001,12 @@ static int drxk_t_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_prop | ||||
| } | ||||
|  | ||||
| static struct dvb_frontend_ops drxk_c_ops = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C }, | ||||
| 	.info = { | ||||
| 		.name = "DRXK DVB-C", | ||||
| 		.type = FE_QAM, | ||||
| 		.frequency_stepsize = 62500, | ||||
| 		.frequency_min = 47000000, | ||||
| 		.frequency_max = 862000000, | ||||
| 		.frequency_stepsize_hz = 62500, | ||||
| 		.frequency_min_hz = 47000000, | ||||
| 		.frequency_max_hz = 862000000, | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | | ||||
| @@ -5022,13 +5029,13 @@ static struct dvb_frontend_ops drxk_c_ops = { | ||||
| }; | ||||
|  | ||||
| static struct dvb_frontend_ops drxk_t_ops = { | ||||
| 	.delsys = { SYS_DVBT }, | ||||
| 	.info = { | ||||
| 		.name			= "DRXK DVB-T", | ||||
| 		.type			= FE_OFDM, | ||||
| 		.frequency_min		= 47125000, | ||||
| 		.frequency_max		= 865000000, | ||||
| 		.frequency_stepsize	= 166667, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_min_hz	= 47125000, | ||||
| 		.frequency_max_hz	= 865000000, | ||||
| 		.frequency_stepsize_hz	= 166667, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | ||||
| 		FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||||
| 		FE_CAN_FEC_AUTO | | ||||
|   | ||||
| @@ -30,7 +30,7 @@ | ||||
| #include <linux/string.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "lnbh25.h" | ||||
|  | ||||
| struct lnbh25 { | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
| #include <linux/string.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "lnbp21.h" | ||||
| #include "lnbh24.h" | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,7 @@ | ||||
| #include <asm/div64.h> | ||||
| #include <asm/unaligned.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "mxl5xx.h" | ||||
| #include "mxl5xx_regs.h" | ||||
| #include "mxl5xx_defs.h" | ||||
| @@ -392,7 +392,7 @@ static void release(struct dvb_frontend *fe) | ||||
| 	kfree(state); | ||||
| } | ||||
|  | ||||
| static int get_algo(struct dvb_frontend *fe) | ||||
| static enum dvbfe_algo get_algo(struct dvb_frontend *fe) | ||||
| { | ||||
| 	return DVBFE_ALGO_HW; | ||||
| } | ||||
| @@ -786,6 +786,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 		/* fallthrough */ | ||||
| 	case SYS_DVBS: | ||||
| 		switch ((MXL_HYDRA_MODULATION_E) | ||||
| 			regData[DMD_MODULATION_SCHEME_ADDR]) { | ||||
| @@ -833,10 +834,10 @@ static struct dvb_frontend_ops mxl_ops = { | ||||
| 	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */ | ||||
| 	.info = { | ||||
| 		.name			= "MXL5XX", | ||||
| 		.frequency_min		= 300000, | ||||
| 		.frequency_max		= 2350000, | ||||
| 		.frequency_stepsize	= 0, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_min_hz	= 300000000, | ||||
| 		.frequency_max_hz	= 2350000000, | ||||
| 		.frequency_stepsize_hz	= 0, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.symbol_rate_min	= 1000000, | ||||
| 		.symbol_rate_max	= 45000000, | ||||
| 		.caps			= FE_CAN_INVERSION_AUTO | | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "stv0367dd.h" | ||||
| #include "stv0367dd_regs.h" | ||||
|  | ||||
| @@ -2074,9 +2074,9 @@ static struct dvb_frontend_ops common_ops = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, | ||||
| 	.info = { | ||||
| 		.name = "STV0367 DVB-C DVB-T", | ||||
| 		.frequency_stepsize = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.frequency_stepsize_hz = 166667,	/* DVB-T only */ | ||||
| 		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */ | ||||
| 		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */ | ||||
| 		.symbol_rate_min = 870000, | ||||
| 		.symbol_rate_max = 11700000, | ||||
| 		.caps = /* DVB-C */ | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| #include <linux/mutex.h> | ||||
|  | ||||
| #include <linux/dvb/frontend.h> | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| #include "stv6110x.h" /* for demodulator internal modes */ | ||||
|  | ||||
| @@ -5142,10 +5142,10 @@ static struct dvb_frontend_ops stv090x_ops = { | ||||
| #ifdef USE_API3 | ||||
| 		.type			= FE_QPSK, | ||||
| #endif | ||||
| 		.frequency_min		= 950000, | ||||
| 		.frequency_max 		= 2150000, | ||||
| 		.frequency_stepsize	= 0, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_min_hz	= 950000000, | ||||
| 		.frequency_max_hz	= 2150000000, | ||||
| 		.frequency_stepsize_hz	= 0, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.symbol_rate_min 	= 1000000, | ||||
| 		.symbol_rate_max 	= 45000000, | ||||
| 		.caps			= FE_CAN_INVERSION_AUTO | | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| #ifndef __STV090x_PRIV_H | ||||
| #define __STV090x_PRIV_H | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| #define FE_ERROR				0 | ||||
| #define FE_NOTICE				1 | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
| #include "stv0910.h" | ||||
| #include "stv0910_regs.h" | ||||
|  | ||||
| @@ -1581,7 +1581,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune, | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int get_algo(struct dvb_frontend *fe) | ||||
| static enum dvbfe_algo get_algo(struct dvb_frontend *fe) | ||||
| { | ||||
| 	return DVBFE_ALGO_HW; | ||||
| } | ||||
| @@ -1801,10 +1801,10 @@ static struct dvb_frontend_ops stv0910_ops = { | ||||
| 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, | ||||
| 	.info = { | ||||
| 		.name			= "STV0910", | ||||
| 		.frequency_min		= 950000, | ||||
| 		.frequency_max		= 2150000, | ||||
| 		.frequency_stepsize	= 0, | ||||
| 		.frequency_tolerance	= 0, | ||||
| 		.frequency_min_hz		= 950000000, | ||||
| 		.frequency_max_hz		= 2150000000, | ||||
| 		.frequency_stepsize_hz	= 0, | ||||
| 		.frequency_tolerance_hz	= 0, | ||||
| 		.symbol_rate_min	= 100000, | ||||
| 		.symbol_rate_max	= 70000000, | ||||
| 		.caps			= FE_CAN_INVERSION_AUTO | | ||||
|   | ||||
| @@ -26,7 +26,7 @@ | ||||
| #include <linux/slab.h> | ||||
| #include <linux/string.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| #include "stv6110x_reg.h" | ||||
| #include "stv6110x.h" | ||||
| @@ -345,10 +345,10 @@ static void stv6110x_release(struct dvb_frontend *fe) | ||||
|  | ||||
| static const struct dvb_tuner_ops stv6110x_ops = { | ||||
| 	.info = { | ||||
| 		.name		= "STV6110(A) Silicon Tuner", | ||||
| 		.frequency_min	=  950000, | ||||
| 		.frequency_max	= 2150000, | ||||
| 		.frequency_step	= 0, | ||||
| 		.name		   = "STV6110(A) Silicon Tuner", | ||||
| 		.frequency_min_hz  =  950000000, | ||||
| 		.frequency_max_hz  = 2150000000, | ||||
| 		.frequency_step_hz = 0, | ||||
| 	}, | ||||
| 	.release		= stv6110x_release | ||||
| }; | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| static inline u32 MulDiv32(u32 a, u32 b, u32 c) | ||||
| { | ||||
| @@ -706,9 +706,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||||
| static struct dvb_tuner_ops tuner_ops = { | ||||
| 	.info = { | ||||
| 		.name = "STV6111", | ||||
| 		.frequency_min  =  950000, | ||||
| 		.frequency_max  = 2150000, | ||||
| 		.frequency_step =       0 | ||||
| 		.frequency_min_hz  =  950000000, | ||||
| 		.frequency_max_hz  = 2150000000, | ||||
| 		.frequency_step_hz =       0 | ||||
| 	}, | ||||
| 	.init              = init, | ||||
| 	.sleep             = sleep, | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| #ifndef CHK_ERROR | ||||
| #define CHK_ERROR(s) if ((status = s) < 0) break | ||||
| @@ -889,9 +889,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||||
| static struct dvb_tuner_ops tuner_ops = { | ||||
| 	.info = { | ||||
| 		.name = "NXP TDA18212", | ||||
| 		.frequency_min  =  47125000, | ||||
| 		.frequency_max  = 865000000, | ||||
| 		.frequency_step =     62500 | ||||
| 		.frequency_min_hz  =  47125000, | ||||
| 		.frequency_max_hz  = 865000000, | ||||
| 		.frequency_step_hz =     62500 | ||||
| 	}, | ||||
| 	.init              = init, | ||||
| 	.sleep             = sleep, | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
| #include <linux/version.h> | ||||
| #include <asm/div64.h> | ||||
|  | ||||
| #include "dvb_frontend.h" | ||||
| #include <media/dvb_frontend.h> | ||||
|  | ||||
| struct SStandardParam { | ||||
| 	s32   m_IFFrequency; | ||||
| @@ -1183,6 +1183,7 @@ static int set_params(struct dvb_frontend *fe, | ||||
|  | ||||
| 	switch (delsys) { | ||||
| 	case  SYS_DVBT: | ||||
| 		/* fallthrough */ | ||||
| 	case  SYS_DVBT2: | ||||
| 		switch (bw) { | ||||
| 		case 6000000: | ||||
| @@ -1197,7 +1198,9 @@ static int set_params(struct dvb_frontend *fe, | ||||
| 		default: | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		break; | ||||
| 	case SYS_DVBC_ANNEX_A: | ||||
| 		/* fallthrough */ | ||||
| 	case SYS_DVBC_ANNEX_C: | ||||
| 		if (bw <= 6000000) | ||||
| 			Standard = HF_DVBC_6MHZ; | ||||
| @@ -1292,9 +1295,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||||
| static struct dvb_tuner_ops tuner_ops = { | ||||
| 	.info = { | ||||
| 		.name = "NXP TDA18271C2D", | ||||
| 		.frequency_min  =  47125000, | ||||
| 		.frequency_max  = 865000000, | ||||
| 		.frequency_step =     62500 | ||||
| 		.frequency_min_hz  =  47125000, | ||||
| 		.frequency_max_hz  = 865000000, | ||||
| 		.frequency_step_hz =     62500 | ||||
| 	}, | ||||
| 	.init              = init, | ||||
| 	.sleep             = sleep, | ||||
|   | ||||
| @@ -117,7 +117,7 @@ struct dmx_ts_feed { | ||||
|  *		  specified by @filter_value that will be used on the filter | ||||
|  *		  match logic. | ||||
|  * @filter_mode:  Contains a 16 bytes (128 bits) filter mode. | ||||
|  * @parent:	  Pointer to struct dmx_section_feed. | ||||
|  * @parent:	  Back-pointer to struct dmx_section_feed. | ||||
|  * @priv:	  Pointer to private data of the API client. | ||||
|  * | ||||
|  * | ||||
| @@ -130,8 +130,9 @@ struct dmx_section_filter { | ||||
| 	u8 filter_value[DMX_MAX_FILTER_SIZE]; | ||||
| 	u8 filter_mask[DMX_MAX_FILTER_SIZE]; | ||||
| 	u8 filter_mode[DMX_MAX_FILTER_SIZE]; | ||||
| 	struct dmx_section_feed *parent; /* Back-pointer */ | ||||
| 	void *priv; /* Pointer to private data of the API client */ | ||||
| 	struct dmx_section_feed *parent; | ||||
| 
 | ||||
| 	void *priv; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @@ -193,6 +194,10 @@ struct dmx_section_feed { | ||||
|  * @buffer2:		Pointer to the tail of the filtered TS packets, or NULL. | ||||
|  * @buffer2_length:	Length of the TS data in buffer2. | ||||
|  * @source:		Indicates which TS feed is the source of the callback. | ||||
|  * @buffer_flags:	Address where buffer flags are stored. Those are | ||||
|  *			used to report discontinuity users via DVB | ||||
|  *			memory mapped API, as defined by | ||||
|  *			&enum dmx_buffer_flags. | ||||
|  * | ||||
|  * This function callback prototype, provided by the client of the demux API, | ||||
|  * is called from the demux code. The function is only called when filtering | ||||
| @@ -245,7 +250,8 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1, | ||||
| 			 size_t buffer1_length, | ||||
| 			 const u8 *buffer2, | ||||
| 			 size_t buffer2_length, | ||||
| 			 struct dmx_ts_feed *source); | ||||
| 			 struct dmx_ts_feed *source, | ||||
| 			 u32 *buffer_flags); | ||||
| 
 | ||||
| /**
 | ||||
|  * typedef dmx_section_cb - DVB demux TS filter callback function prototype | ||||
| @@ -261,6 +267,10 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1, | ||||
|  *			including headers and CRC. | ||||
|  * @source:		Indicates which section feed is the source of the | ||||
|  *			callback. | ||||
|  * @buffer_flags:	Address where buffer flags are stored. Those are | ||||
|  *			used to report discontinuity users via DVB | ||||
|  *			memory mapped API, as defined by | ||||
|  *			&enum dmx_buffer_flags. | ||||
|  * | ||||
|  * This function callback prototype, provided by the client of the demux API, | ||||
|  * is called from the demux code. The function is only called when | ||||
| @@ -286,7 +296,8 @@ typedef int (*dmx_section_cb)(const u8 *buffer1, | ||||
| 			      size_t buffer1_len, | ||||
| 			      const u8 *buffer2, | ||||
| 			      size_t buffer2_len, | ||||
| 			      struct dmx_section_filter *source); | ||||
| 			      struct dmx_section_filter *source, | ||||
| 			      u32 *buffer_flags); | ||||
| 
 | ||||
| /*
 | ||||
|  * DVB Front-End | ||||
							
								
								
									
										220
									
								
								include/linux/media/dmxdev.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								include/linux/media/dmxdev.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | ||||
| /* | ||||
|  * dmxdev.h | ||||
|  * | ||||
|  * Copyright (C) 2000 Ralph Metzler & Marcus Metzler | ||||
|  *                    for convergence integrated media GmbH | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public License | ||||
|  * as published by the Free Software Foundation; either version 2.1 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _DMXDEV_H_ | ||||
| #define _DMXDEV_H_ | ||||
|  | ||||
| #include <linux/types.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/time.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/wait.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include <linux/dvb/dmx.h> | ||||
|  | ||||
| #include <media/dvbdev.h> | ||||
| #include <media/demux.h> | ||||
| #include <media/dvb_ringbuffer.h> | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| #include <media/dvb_vb2.h> | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * enum dmxdev_type - type of demux filter type. | ||||
|  * | ||||
|  * @DMXDEV_TYPE_NONE:	no filter set. | ||||
|  * @DMXDEV_TYPE_SEC:	section filter. | ||||
|  * @DMXDEV_TYPE_PES:	Program Elementary Stream (PES) filter. | ||||
|  */ | ||||
| enum dmxdev_type { | ||||
| 	DMXDEV_TYPE_NONE, | ||||
| 	DMXDEV_TYPE_SEC, | ||||
| 	DMXDEV_TYPE_PES, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * enum dmxdev_state - state machine for the dmxdev. | ||||
|  * | ||||
|  * @DMXDEV_STATE_FREE:		indicates that the filter is freed. | ||||
|  * @DMXDEV_STATE_ALLOCATED:	indicates that the filter was allocated | ||||
|  *				to be used. | ||||
|  * @DMXDEV_STATE_SET:		indicates that the filter parameters are set. | ||||
|  * @DMXDEV_STATE_GO:		indicates that the filter is running. | ||||
|  * @DMXDEV_STATE_DONE:		indicates that a packet was already filtered | ||||
|  *				and the filter is now disabled. | ||||
|  *				Set only if %DMX_ONESHOT. See | ||||
|  *				&dmx_sct_filter_params. | ||||
|  * @DMXDEV_STATE_TIMEDOUT:	Indicates a timeout condition. | ||||
|  */ | ||||
| enum dmxdev_state { | ||||
| 	DMXDEV_STATE_FREE, | ||||
| 	DMXDEV_STATE_ALLOCATED, | ||||
| 	DMXDEV_STATE_SET, | ||||
| 	DMXDEV_STATE_GO, | ||||
| 	DMXDEV_STATE_DONE, | ||||
| 	DMXDEV_STATE_TIMEDOUT | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmxdev_feed - digital TV dmxdev feed | ||||
|  * | ||||
|  * @pid:	Program ID to be filtered | ||||
|  * @ts:		pointer to &struct dmx_ts_feed | ||||
|  * @next:	&struct list_head pointing to the next feed. | ||||
|  */ | ||||
|  | ||||
| struct dmxdev_feed { | ||||
| 	u16 pid; | ||||
| 	struct dmx_ts_feed *ts; | ||||
| 	struct list_head next; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmxdev_filter - digital TV dmxdev filter | ||||
|  * | ||||
|  * @filter:	a union describing a dmxdev filter. | ||||
|  *		Currently used only for section filters. | ||||
|  * @filter.sec: a &struct dmx_section_filter pointer. | ||||
|  *		For section filter only. | ||||
|  * @feed:	a union describing a dmxdev feed. | ||||
|  *		Depending on the filter type, it can be either | ||||
|  *		@feed.ts or @feed.sec. | ||||
|  * @feed.ts:	a &struct list_head list. | ||||
|  *		For TS and PES feeds. | ||||
|  * @feed.sec:	a &struct dmx_section_feed pointer. | ||||
|  *		For section feed only. | ||||
|  * @params:	a union describing dmxdev filter parameters. | ||||
|  *		Depending on the filter type, it can be either | ||||
|  *		@params.sec or @params.pes. | ||||
|  * @params.sec:	a &struct dmx_sct_filter_params embedded struct. | ||||
|  *		For section filter only. | ||||
|  * @params.pes:	a &struct dmx_pes_filter_params embedded struct. | ||||
|  *		For PES filter only. | ||||
|  * @type:	type of the dmxdev filter, as defined by &enum dmxdev_type. | ||||
|  * @state:	state of the dmxdev filter, as defined by &enum dmxdev_state. | ||||
|  * @dev:	pointer to &struct dmxdev. | ||||
|  * @buffer:	an embedded &struct dvb_ringbuffer buffer. | ||||
|  * @vb2_ctx:	control struct for VB2 handler | ||||
|  * @mutex:	protects the access to &struct dmxdev_filter. | ||||
|  * @timer:	&struct timer_list embedded timer, used to check for | ||||
|  *		feed timeouts. | ||||
|  *		Only for section filter. | ||||
|  * @todo:	index for the @secheader. | ||||
|  *		Only for section filter. | ||||
|  * @secheader:	buffer cache to parse the section header. | ||||
|  *		Only for section filter. | ||||
|  */ | ||||
| struct dmxdev_filter { | ||||
| 	union { | ||||
| 		struct dmx_section_filter *sec; | ||||
| 	} filter; | ||||
|  | ||||
| 	union { | ||||
| 		/* list of TS and PES feeds (struct dmxdev_feed) */ | ||||
| 		struct list_head ts; | ||||
| 		struct dmx_section_feed *sec; | ||||
| 	} feed; | ||||
|  | ||||
| 	union { | ||||
| 		struct dmx_sct_filter_params sec; | ||||
| 		struct dmx_pes_filter_params pes; | ||||
| 	} params; | ||||
|  | ||||
| 	enum dmxdev_type type; | ||||
| 	enum dmxdev_state state; | ||||
| 	struct dmxdev *dev; | ||||
| 	struct dvb_ringbuffer buffer; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	struct dvb_vb2_ctx vb2_ctx; | ||||
| #endif | ||||
|  | ||||
| 	struct mutex mutex; | ||||
|  | ||||
| 	/* only for sections */ | ||||
| 	struct timer_list timer; | ||||
| 	int todo; | ||||
| 	u8 secheader[3]; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmxdev - Describes a digital TV demux device. | ||||
|  * | ||||
|  * @dvbdev:		pointer to &struct dvb_device associated with | ||||
|  *			the demux device node. | ||||
|  * @dvr_dvbdev:		pointer to &struct dvb_device associated with | ||||
|  *			the dvr device node. | ||||
|  * @filter:		pointer to &struct dmxdev_filter. | ||||
|  * @demux:		pointer to &struct dmx_demux. | ||||
|  * @filternum:		number of filters. | ||||
|  * @capabilities:	demux capabilities as defined by &enum dmx_demux_caps. | ||||
|  * @may_do_mmap:	flag used to indicate if the device may do mmap. | ||||
|  * @exit:		flag to indicate that the demux is being released. | ||||
|  * @dvr_orig_fe:	pointer to &struct dmx_frontend. | ||||
|  * @dvr_buffer:		embedded &struct dvb_ringbuffer for DVB output. | ||||
|  * @dvr_vb2_ctx:	control struct for VB2 handler | ||||
|  * @mutex:		protects the usage of this structure. | ||||
|  * @lock:		protects access to &dmxdev->filter->data. | ||||
|  */ | ||||
| struct dmxdev { | ||||
| 	struct dvb_device *dvbdev; | ||||
| 	struct dvb_device *dvr_dvbdev; | ||||
|  | ||||
| 	struct dmxdev_filter *filter; | ||||
| 	struct dmx_demux *demux; | ||||
|  | ||||
| 	int filternum; | ||||
| 	int capabilities; | ||||
|  | ||||
| 	unsigned int may_do_mmap:1; | ||||
| 	unsigned int exit:1; | ||||
| #define DMXDEV_CAP_DUPLEX 1 | ||||
| 	struct dmx_frontend *dvr_orig_fe; | ||||
|  | ||||
| 	struct dvb_ringbuffer dvr_buffer; | ||||
| #define DVR_BUFFER_SIZE (10*188*1024) | ||||
|  | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	struct dvb_vb2_ctx dvr_vb2_ctx; | ||||
| #endif | ||||
|  | ||||
| 	struct mutex mutex; | ||||
| 	spinlock_t lock; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * dvb_dmxdev_init - initializes a digital TV demux and registers both demux | ||||
|  *	and DVR devices. | ||||
|  * | ||||
|  * @dmxdev: pointer to &struct dmxdev. | ||||
|  * @adap: pointer to &struct dvb_adapter. | ||||
|  */ | ||||
| int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmxdev_release - releases a digital TV demux and unregisters it. | ||||
|  * | ||||
|  * @dmxdev: pointer to &struct dmxdev. | ||||
|  */ | ||||
| void dvb_dmxdev_release(struct dmxdev *dmxdev); | ||||
|  | ||||
| #endif /* _DMXDEV_H_ */ | ||||
| @@ -20,7 +20,7 @@ | ||||
| #include <linux/list.h> | ||||
| #include <linux/dvb/ca.h> | ||||
| 
 | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
| 
 | ||||
| #define DVB_CA_EN50221_POLL_CAM_PRESENT	1 | ||||
| #define DVB_CA_EN50221_POLL_CAM_CHANGED	2 | ||||
							
								
								
									
										354
									
								
								include/linux/media/dvb_demux.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								include/linux/media/dvb_demux.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | ||||
| /* | ||||
|  * dvb_demux.h: DVB kernel demux API | ||||
|  * | ||||
|  * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler | ||||
|  *                         for convergence integrated media GmbH | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public License | ||||
|  * as published by the Free Software Foundation; either version 2.1 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _DVB_DEMUX_H_ | ||||
| #define _DVB_DEMUX_H_ | ||||
|  | ||||
| #include <linux/time.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/mutex.h> | ||||
|  | ||||
| #include <media/demux.h> | ||||
|  | ||||
| /** | ||||
|  * enum dvb_dmx_filter_type - type of demux feed. | ||||
|  * | ||||
|  * @DMX_TYPE_TS:	feed is in TS mode. | ||||
|  * @DMX_TYPE_SEC:	feed is in Section mode. | ||||
|  */ | ||||
| enum dvb_dmx_filter_type { | ||||
| 	DMX_TYPE_TS, | ||||
| 	DMX_TYPE_SEC, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * enum dvb_dmx_state - state machine for a demux filter. | ||||
|  * | ||||
|  * @DMX_STATE_FREE:		indicates that the filter is freed. | ||||
|  * @DMX_STATE_ALLOCATED:	indicates that the filter was allocated | ||||
|  *				to be used. | ||||
|  * @DMX_STATE_READY:		indicates that the filter is ready | ||||
|  *				to be used. | ||||
|  * @DMX_STATE_GO:		indicates that the filter is running. | ||||
|  */ | ||||
| enum dvb_dmx_state { | ||||
| 	DMX_STATE_FREE, | ||||
| 	DMX_STATE_ALLOCATED, | ||||
| 	DMX_STATE_READY, | ||||
| 	DMX_STATE_GO, | ||||
| }; | ||||
|  | ||||
| #define DVB_DEMUX_MASK_MAX 18 | ||||
|  | ||||
| #define MAX_PID 0x1fff | ||||
|  | ||||
| #define SPEED_PKTS_INTERVAL 50000 | ||||
|  | ||||
| /** | ||||
|  * struct dvb_demux_filter - Describes a DVB demux section filter. | ||||
|  * | ||||
|  * @filter:		Section filter as defined by &struct dmx_section_filter. | ||||
|  * @maskandmode:	logical ``and`` bit mask. | ||||
|  * @maskandnotmode:	logical ``and not`` bit mask. | ||||
|  * @doneq:		flag that indicates when a filter is ready. | ||||
|  * @next:		pointer to the next section filter. | ||||
|  * @feed:		&struct dvb_demux_feed pointer. | ||||
|  * @index:		index of the used demux filter. | ||||
|  * @state:		state of the filter as described by &enum dvb_dmx_state. | ||||
|  * @type:		type of the filter as described | ||||
|  *			by &enum dvb_dmx_filter_type. | ||||
|  */ | ||||
|  | ||||
| struct dvb_demux_filter { | ||||
| 	struct dmx_section_filter filter; | ||||
| 	u8 maskandmode[DMX_MAX_FILTER_SIZE]; | ||||
| 	u8 maskandnotmode[DMX_MAX_FILTER_SIZE]; | ||||
| 	bool doneq; | ||||
|  | ||||
| 	struct dvb_demux_filter *next; | ||||
| 	struct dvb_demux_feed *feed; | ||||
| 	int index; | ||||
| 	enum dvb_dmx_state state; | ||||
| 	enum dvb_dmx_filter_type type; | ||||
|  | ||||
| 	/* private: used only by av7110 */ | ||||
| 	u16 hw_handle; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dvb_demux_feed - describes a DVB field | ||||
|  * | ||||
|  * @feed:	a union describing a digital TV feed. | ||||
|  *		Depending on the feed type, it can be either | ||||
|  *		@feed.ts or @feed.sec. | ||||
|  * @feed.ts:	a &struct dmx_ts_feed pointer. | ||||
|  *		For TS feed only. | ||||
|  * @feed.sec:	a &struct dmx_section_feed pointer. | ||||
|  *		For section feed only. | ||||
|  * @cb:		a union describing digital TV callbacks. | ||||
|  *		Depending on the feed type, it can be either | ||||
|  *		@cb.ts or @cb.sec. | ||||
|  * @cb.ts:	a dmx_ts_cb() calback function pointer. | ||||
|  *		For TS feed only. | ||||
|  * @cb.sec:	a dmx_section_cb() callback function pointer. | ||||
|  *		For section feed only. | ||||
|  * @demux:	pointer to &struct dvb_demux. | ||||
|  * @priv:	private data that can optionally be used by a DVB driver. | ||||
|  * @type:	type of the filter, as defined by &enum dvb_dmx_filter_type. | ||||
|  * @state:	state of the filter as defined by &enum dvb_dmx_state. | ||||
|  * @pid:	PID to be filtered. | ||||
|  * @timeout:	feed timeout. | ||||
|  * @filter:	pointer to &struct dvb_demux_filter. | ||||
|  * @buffer_flags: Buffer flags used to report discontinuity users via DVB | ||||
|  *		  memory mapped API, as defined by &enum dmx_buffer_flags. | ||||
|  * @ts_type:	type of TS, as defined by &enum ts_filter_type. | ||||
|  * @pes_type:	type of PES, as defined by &enum dmx_ts_pes. | ||||
|  * @cc:		MPEG-TS packet continuity counter | ||||
|  * @pusi_seen:	if true, indicates that a discontinuity was detected. | ||||
|  *		it is used to prevent feeding of garbage from previous section. | ||||
|  * @peslen:	length of the PES (Packet Elementary Stream). | ||||
|  * @list_head:	head for the list of digital TV demux feeds. | ||||
|  * @index:	a unique index for each feed. Can be used as hardware | ||||
|  *		pid filter index. | ||||
|  */ | ||||
| struct dvb_demux_feed { | ||||
| 	union { | ||||
| 		struct dmx_ts_feed ts; | ||||
| 		struct dmx_section_feed sec; | ||||
| 	} feed; | ||||
|  | ||||
| 	union { | ||||
| 		dmx_ts_cb ts; | ||||
| 		dmx_section_cb sec; | ||||
| 	} cb; | ||||
|  | ||||
| 	struct dvb_demux *demux; | ||||
| 	void *priv; | ||||
| 	enum dvb_dmx_filter_type type; | ||||
| 	enum dvb_dmx_state state; | ||||
| 	u16 pid; | ||||
|  | ||||
| 	ktime_t timeout; | ||||
| 	struct dvb_demux_filter *filter; | ||||
|  | ||||
| 	u32 buffer_flags; | ||||
|  | ||||
| 	enum ts_filter_type ts_type; | ||||
| 	enum dmx_ts_pes pes_type; | ||||
|  | ||||
| 	int cc; | ||||
| 	bool pusi_seen; | ||||
|  | ||||
| 	u16 peslen; | ||||
|  | ||||
| 	struct list_head list_head; | ||||
| 	unsigned int index; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dvb_demux - represents a digital TV demux | ||||
|  * @dmx:		embedded &struct dmx_demux with demux capabilities | ||||
|  *			and callbacks. | ||||
|  * @priv:		private data that can optionally be used by | ||||
|  *			a DVB driver. | ||||
|  * @filternum:		maximum amount of DVB filters. | ||||
|  * @feednum:		maximum amount of DVB feeds. | ||||
|  * @start_feed:		callback routine to be called in order to start | ||||
|  *			a DVB feed. | ||||
|  * @stop_feed:		callback routine to be called in order to stop | ||||
|  *			a DVB feed. | ||||
|  * @write_to_decoder:	callback routine to be called if the feed is TS and | ||||
|  *			it is routed to an A/V decoder, when a new TS packet | ||||
|  *			is received. | ||||
|  *			Used only on av7110-av.c. | ||||
|  * @check_crc32:	callback routine to check CRC. If not initialized, | ||||
|  *			dvb_demux will use an internal one. | ||||
|  * @memcopy:		callback routine to memcopy received data. | ||||
|  *			If not initialized, dvb_demux will default to memcpy(). | ||||
|  * @users:		counter for the number of demux opened file descriptors. | ||||
|  *			Currently, it is limited to 10 users. | ||||
|  * @filter:		pointer to &struct dvb_demux_filter. | ||||
|  * @feed:		pointer to &struct dvb_demux_feed. | ||||
|  * @frontend_list:	&struct list_head with frontends used by the demux. | ||||
|  * @pesfilter:		array of &struct dvb_demux_feed with the PES types | ||||
|  *			that will be filtered. | ||||
|  * @pids:		list of filtered program IDs. | ||||
|  * @feed_list:		&struct list_head with feeds. | ||||
|  * @tsbuf:		temporary buffer used internally to store TS packets. | ||||
|  * @tsbufp:		temporary buffer index used internally. | ||||
|  * @mutex:		pointer to &struct mutex used to protect feed set | ||||
|  *			logic. | ||||
|  * @lock:		pointer to &spinlock_t, used to protect buffer handling. | ||||
|  * @cnt_storage:	buffer used for TS/TEI continuity check. | ||||
|  * @speed_last_time:	&ktime_t used for TS speed check. | ||||
|  * @speed_pkts_cnt:	packets count used for TS speed check. | ||||
|  */ | ||||
| struct dvb_demux { | ||||
| 	struct dmx_demux dmx; | ||||
| 	void *priv; | ||||
| 	int filternum; | ||||
| 	int feednum; | ||||
| 	int (*start_feed)(struct dvb_demux_feed *feed); | ||||
| 	int (*stop_feed)(struct dvb_demux_feed *feed); | ||||
| 	int (*write_to_decoder)(struct dvb_demux_feed *feed, | ||||
| 				 const u8 *buf, size_t len); | ||||
| 	u32 (*check_crc32)(struct dvb_demux_feed *feed, | ||||
| 			    const u8 *buf, size_t len); | ||||
| 	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst, | ||||
| 			 const u8 *src, size_t len); | ||||
|  | ||||
| 	int users; | ||||
| #define MAX_DVB_DEMUX_USERS 10 | ||||
| 	struct dvb_demux_filter *filter; | ||||
| 	struct dvb_demux_feed *feed; | ||||
|  | ||||
| 	struct list_head frontend_list; | ||||
|  | ||||
| 	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER]; | ||||
| 	u16 pids[DMX_PES_OTHER]; | ||||
|  | ||||
| #define DMX_MAX_PID 0x2000 | ||||
| 	struct list_head feed_list; | ||||
| 	u8 tsbuf[204]; | ||||
| 	int tsbufp; | ||||
|  | ||||
| 	struct mutex mutex; | ||||
| 	spinlock_t lock; | ||||
|  | ||||
| 	uint8_t *cnt_storage; /* for TS continuity check */ | ||||
|  | ||||
| 	ktime_t speed_last_time; /* for TS speed check */ | ||||
| 	uint32_t speed_pkts_cnt; /* for TS speed check */ | ||||
|  | ||||
| 	/* private: used only on av7110 */ | ||||
| 	int playing; | ||||
| 	int recording; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_init - initialize a digital TV demux struct. | ||||
|  * | ||||
|  * @demux: &struct dvb_demux to be initialized. | ||||
|  * | ||||
|  * Before being able to register a digital TV demux struct, drivers | ||||
|  * should call this routine. On its typical usage, some fields should | ||||
|  * be initialized at the driver before calling it. | ||||
|  * | ||||
|  * A typical usecase is:: | ||||
|  * | ||||
|  *	dvb->demux.dmx.capabilities = | ||||
|  *		DMX_TS_FILTERING | DMX_SECTION_FILTERING | | ||||
|  *		DMX_MEMORY_BASED_FILTERING; | ||||
|  *	dvb->demux.priv       = dvb; | ||||
|  *	dvb->demux.filternum  = 256; | ||||
|  *	dvb->demux.feednum    = 256; | ||||
|  *	dvb->demux.start_feed = driver_start_feed; | ||||
|  *	dvb->demux.stop_feed  = driver_stop_feed; | ||||
|  *	ret = dvb_dmx_init(&dvb->demux); | ||||
|  *	if (ret < 0) | ||||
|  *		return ret; | ||||
|  */ | ||||
| int dvb_dmx_init(struct dvb_demux *demux); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_release - releases a digital TV demux internal buffers. | ||||
|  * | ||||
|  * @demux: &struct dvb_demux to be released. | ||||
|  * | ||||
|  * The DVB core internally allocates data at @demux. This routine | ||||
|  * releases those data. Please notice that the struct itelf is not | ||||
|  * released, as it can be embedded on other structs. | ||||
|  */ | ||||
| void dvb_dmx_release(struct dvb_demux *demux); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_swfilter_packets - use dvb software filter for a buffer with | ||||
|  *	multiple MPEG-TS packets with 188 bytes each. | ||||
|  * | ||||
|  * @demux: pointer to &struct dvb_demux | ||||
|  * @buf: buffer with data to be filtered | ||||
|  * @count: number of MPEG-TS packets with size of 188. | ||||
|  * | ||||
|  * The routine will discard a DVB packet that don't start with 0x47. | ||||
|  * | ||||
|  * Use this routine if the DVB demux fills MPEG-TS buffers that are | ||||
|  * already aligned. | ||||
|  * | ||||
|  * NOTE: The @buf size should have size equal to ``count * 188``. | ||||
|  */ | ||||
| void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | ||||
| 			      size_t count); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_swfilter -  use dvb software filter for a buffer with | ||||
|  *	multiple MPEG-TS packets with 188 bytes each. | ||||
|  * | ||||
|  * @demux: pointer to &struct dvb_demux | ||||
|  * @buf: buffer with data to be filtered | ||||
|  * @count: number of MPEG-TS packets with size of 188. | ||||
|  * | ||||
|  * If a DVB packet doesn't start with 0x47, it will seek for the first | ||||
|  * byte that starts with 0x47. | ||||
|  * | ||||
|  * Use this routine if the DVB demux fill buffers that may not start with | ||||
|  * a packet start mark (0x47). | ||||
|  * | ||||
|  * NOTE: The @buf size should have size equal to ``count * 188``. | ||||
|  */ | ||||
| void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_swfilter_204 -  use dvb software filter for a buffer with | ||||
|  *	multiple MPEG-TS packets with 204 bytes each. | ||||
|  * | ||||
|  * @demux: pointer to &struct dvb_demux | ||||
|  * @buf: buffer with data to be filtered | ||||
|  * @count: number of MPEG-TS packets with size of 204. | ||||
|  * | ||||
|  * If a DVB packet doesn't start with 0x47, it will seek for the first | ||||
|  * byte that starts with 0x47. | ||||
|  * | ||||
|  * Use this routine if the DVB demux fill buffers that may not start with | ||||
|  * a packet start mark (0x47). | ||||
|  * | ||||
|  * NOTE: The @buf size should have size equal to ``count * 204``. | ||||
|  */ | ||||
| void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, | ||||
| 			  size_t count); | ||||
|  | ||||
| /** | ||||
|  * dvb_dmx_swfilter_raw -  make the raw data available to userspace without | ||||
|  *	filtering | ||||
|  * | ||||
|  * @demux: pointer to &struct dvb_demux | ||||
|  * @buf: buffer with data | ||||
|  * @count: number of packets to be passed. The actual size of each packet | ||||
|  *	depends on the &dvb_demux->feed->cb.ts logic. | ||||
|  * | ||||
|  * Use it if the driver needs to deliver the raw payload to userspace without | ||||
|  * passing through the kernel demux. That is meant to support some | ||||
|  * delivery systems that aren't based on MPEG-TS. | ||||
|  * | ||||
|  * This function relies on &dvb_demux->feed->cb.ts to actually handle the | ||||
|  * buffer. | ||||
|  */ | ||||
| void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, | ||||
| 			  size_t count); | ||||
|  | ||||
| #endif /* _DVB_DEMUX_H_ */ | ||||
| @@ -46,10 +46,11 @@ | ||||
| #include <linux/delay.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/bitops.h> | ||||
| 
 | ||||
| #include <linux/dvb/frontend.h> | ||||
| 
 | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Maximum number of Delivery systems per frontend. It | ||||
| @@ -57,6 +58,10 @@ | ||||
|  */ | ||||
| #define MAX_DELSYS	16 | ||||
| 
 | ||||
| /* Helper definitions to be used at frontend drivers */ | ||||
| #define kHz 1000UL | ||||
| #define MHz 1000000UL | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dvb_frontend_tune_settings - parameters to adjust frontend tuning | ||||
|  * | ||||
| @@ -78,22 +83,19 @@ struct dvb_frontend; | ||||
|  * struct dvb_tuner_info - Frontend name and min/max ranges/bandwidths | ||||
|  * | ||||
|  * @name:		name of the Frontend | ||||
|  * @frequency_min:	minimal frequency supported | ||||
|  * @frequency_max:	maximum frequency supported | ||||
|  * @frequency_step:	frequency step | ||||
|  * @frequency_min_hz:	minimal frequency supported in Hz | ||||
|  * @frequency_max_hz:	maximum frequency supported in Hz | ||||
|  * @frequency_step_hz:	frequency step in Hz | ||||
|  * @bandwidth_min:	minimal frontend bandwidth supported | ||||
|  * @bandwidth_max:	maximum frontend bandwidth supported | ||||
|  * @bandwidth_step:	frontend bandwidth step | ||||
|  * | ||||
|  * NOTE: frequency parameters are in Hz, for terrestrial/cable or kHz for | ||||
|  * satellite. | ||||
|  */ | ||||
| struct dvb_tuner_info { | ||||
| 	char name[128]; | ||||
| 
 | ||||
| 	u32 frequency_min; | ||||
| 	u32 frequency_max; | ||||
| 	u32 frequency_step; | ||||
| 	u32 frequency_min_hz; | ||||
| 	u32 frequency_max_hz; | ||||
| 	u32 frequency_step_hz; | ||||
| 
 | ||||
| 	u32 bandwidth_min; | ||||
| 	u32 bandwidth_max; | ||||
| @@ -104,10 +106,10 @@ struct dvb_tuner_info { | ||||
|  * struct analog_parameters - Parameters to tune into an analog/radio channel | ||||
|  * | ||||
|  * @frequency:	Frequency used by analog TV tuner (either in 62.5 kHz step, | ||||
|  * 		for TV, or 62.5 Hz for radio) | ||||
|  *		for TV, or 62.5 Hz for radio) | ||||
|  * @mode:	Tuner mode, as defined on enum v4l2_tuner_type | ||||
|  * @audmode:	Audio mode as defined for the rxsubchans field at videodev2.h, | ||||
|  * 		e. g. V4L2_TUNER_MODE_* | ||||
|  *		e. g. V4L2_TUNER_MODE_* | ||||
|  * @std:	TV standard bitmap as defined at videodev2.h, e. g. V4L2_STD_* | ||||
|  * | ||||
|  * Hybrid tuners should be supported by both V4L2 and DVB APIs. This | ||||
| @@ -145,10 +147,10 @@ struct analog_parameters { | ||||
|  *	These devices have AUTO recovery capabilities from LOCK failure | ||||
|  */ | ||||
| enum dvbfe_algo { | ||||
| 	DVBFE_ALGO_HW			= (1 <<  0), | ||||
| 	DVBFE_ALGO_SW			= (1 <<  1), | ||||
| 	DVBFE_ALGO_CUSTOM		= (1 <<  2), | ||||
| 	DVBFE_ALGO_RECOVERY		= (1 << 31) | ||||
| 	DVBFE_ALGO_HW			= BIT(0), | ||||
| 	DVBFE_ALGO_SW			= BIT(1), | ||||
| 	DVBFE_ALGO_CUSTOM		= BIT(2), | ||||
| 	DVBFE_ALGO_RECOVERY		= BIT(31), | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @@ -164,7 +166,7 @@ enum dvbfe_algo { | ||||
|  *	The frontend search for a signal failed | ||||
|  * | ||||
|  * @DVBFE_ALGO_SEARCH_INVALID: | ||||
|  *	The frontend search algorith was probably supplied with invalid | ||||
|  *	The frontend search algorithm was probably supplied with invalid | ||||
|  *	parameters and the search is an invalid one | ||||
|  * | ||||
|  * @DVBFE_ALGO_SEARCH_ERROR: | ||||
| @@ -174,19 +176,19 @@ enum dvbfe_algo { | ||||
|  *	The frontend search algorithm was requested to search again | ||||
|  */ | ||||
| enum dvbfe_search { | ||||
| 	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0), | ||||
| 	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1), | ||||
| 	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2), | ||||
| 	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3), | ||||
| 	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4), | ||||
| 	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31), | ||||
| 	DVBFE_ALGO_SEARCH_SUCCESS	= BIT(0), | ||||
| 	DVBFE_ALGO_SEARCH_ASLEEP	= BIT(1), | ||||
| 	DVBFE_ALGO_SEARCH_FAILED	= BIT(2), | ||||
| 	DVBFE_ALGO_SEARCH_INVALID	= BIT(3), | ||||
| 	DVBFE_ALGO_SEARCH_AGAIN		= BIT(4), | ||||
| 	DVBFE_ALGO_SEARCH_ERROR		= BIT(31), | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dvb_tuner_ops - Tuner information and callbacks | ||||
|  * | ||||
|  * @info:		embedded struct dvb_tuner_info with tuner properties | ||||
|  * @release:		callback function called when frontend is dettached. | ||||
|  * @info:		embedded &struct dvb_tuner_info with tuner properties | ||||
|  * @release:		callback function called when frontend is detached. | ||||
|  *			drivers should free any allocated memory. | ||||
|  * @init:		callback function used to initialize the tuner device. | ||||
|  * @sleep:		callback function used to put the tuner to sleep. | ||||
| @@ -196,25 +198,25 @@ enum dvbfe_search { | ||||
|  *			resuming from suspend. | ||||
|  * @set_params:		callback function used to inform the tuner to tune | ||||
|  *			into a digital TV channel. The properties to be used | ||||
|  *			are stored at @dvb_frontend.dtv_property_cache;. The | ||||
|  *			tuner demod can change the parameters to reflect the | ||||
|  *			changes needed for the channel to be tuned, and | ||||
|  *			are stored at &struct dvb_frontend.dtv_property_cache. | ||||
|  *			The tuner demod can change the parameters to reflect | ||||
|  *			the changes needed for the channel to be tuned, and | ||||
|  *			update statistics. This is the recommended way to set | ||||
|  *			the tuner parameters and should be used on newer | ||||
|  *			drivers. | ||||
|  * @set_analog_params:	callback function used to tune into an analog TV | ||||
|  *			channel on hybrid tuners. It passes @analog_parameters; | ||||
|  *			channel on hybrid tuners. It passes @analog_parameters | ||||
|  *			to the driver. | ||||
|  * @set_config:		callback function used to send some tuner-specific | ||||
|  *			parameters. | ||||
|  * @get_frequency:	get the actual tuned frequency | ||||
|  * @get_bandwidth:	get the bandwitdh used by the low pass filters | ||||
|  * @get_bandwidth:	get the bandwidth used by the low pass filters | ||||
|  * @get_if_frequency:	get the Intermediate Frequency, in Hz. For baseband, | ||||
|  * 			should return 0. | ||||
|  *			should return 0. | ||||
|  * @get_status:		returns the frontend lock status | ||||
|  * @get_rf_strength:	returns the RF signal strengh. Used mostly to support | ||||
|  * @get_rf_strength:	returns the RF signal strength. Used mostly to support | ||||
|  *			analog TV and radio. Digital TV should report, instead, | ||||
|  *			via DVBv5 API (@dvb_frontend.dtv_property_cache;). | ||||
|  *			via DVBv5 API (&struct dvb_frontend.dtv_property_cache). | ||||
|  * @get_afc:		Used only by analog TV core. Reports the frequency | ||||
|  *			drift due to AFC. | ||||
|  * @calc_regs:		callback function used to pass register data settings | ||||
| @@ -222,7 +224,7 @@ enum dvbfe_search { | ||||
|  * @set_frequency:	Set a new frequency. Shouldn't be used on newer drivers. | ||||
|  * @set_bandwidth:	Set a new frequency. Shouldn't be used on newer drivers. | ||||
|  * | ||||
|  * NOTE: frequencies used on get_frequency and set_frequency are in Hz for | ||||
|  * NOTE: frequencies used on @get_frequency and @set_frequency are in Hz for | ||||
|  * terrestrial/cable or kHz for satellite. | ||||
|  * | ||||
|  */ | ||||
| @@ -236,7 +238,7 @@ struct dvb_tuner_ops { | ||||
| 	int (*suspend)(struct dvb_frontend *fe); | ||||
| 	int (*resume)(struct dvb_frontend *fe); | ||||
| 
 | ||||
| 	/* This is the recomended way to set the tuner */ | ||||
| 	/* This is the recommended way to set the tuner */ | ||||
| 	int (*set_params)(struct dvb_frontend *fe); | ||||
| 	int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); | ||||
| 
 | ||||
| @@ -288,14 +290,14 @@ struct analog_demod_info { | ||||
|  * @set_params:		callback function used to inform the demod to set the | ||||
|  *			demodulator parameters needed to decode an analog or | ||||
|  *			radio channel. The properties are passed via | ||||
|  *			struct @analog_params;. | ||||
|  *			&struct analog_params. | ||||
|  * @has_signal:		returns 0xffff if has signal, or 0 if it doesn't. | ||||
|  * @get_afc:		Used only by analog TV core. Reports the frequency | ||||
|  *			drift due to AFC. | ||||
|  * @tuner_status:	callback function that returns tuner status bits, e. g. | ||||
|  *			TUNER_STATUS_LOCKED and TUNER_STATUS_STEREO. | ||||
|  *			%TUNER_STATUS_LOCKED and %TUNER_STATUS_STEREO. | ||||
|  * @standby:		set the tuner to standby mode. | ||||
|  * @release:		callback function called when frontend is dettached. | ||||
|  * @release:		callback function called when frontend is detached. | ||||
|  *			drivers should free any allocated memory. | ||||
|  * @i2c_gate_ctrl:	controls the I2C gate. Newer drivers should use I2C | ||||
|  *			mux support instead. | ||||
| @@ -321,20 +323,48 @@ struct analog_demod_ops { | ||||
| 
 | ||||
| struct dtv_frontend_properties; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dvb_frontend_internal_info - Frontend properties and capabilities | ||||
|  * | ||||
|  * @name:			Name of the frontend | ||||
|  * @frequency_min_hz:		Minimal frequency supported by the frontend. | ||||
|  * @frequency_max_hz:		Minimal frequency supported by the frontend. | ||||
|  * @frequency_stepsize_hz:	All frequencies are multiple of this value. | ||||
|  * @frequency_tolerance_hz:	Frequency tolerance. | ||||
|  * @symbol_rate_min:		Minimal symbol rate, in bauds | ||||
|  *				(for Cable/Satellite systems). | ||||
|  * @symbol_rate_max:		Maximal symbol rate, in bauds | ||||
|  *				(for Cable/Satellite systems). | ||||
|  * @symbol_rate_tolerance:	Maximal symbol rate tolerance, in ppm | ||||
|  *				(for Cable/Satellite systems). | ||||
|  * @caps:			Capabilities supported by the frontend, | ||||
|  *				as specified in &enum fe_caps. | ||||
|  */ | ||||
| struct dvb_frontend_internal_info { | ||||
| 	char	name[128]; | ||||
| 	u32	frequency_min_hz; | ||||
| 	u32	frequency_max_hz; | ||||
| 	u32	frequency_stepsize_hz; | ||||
| 	u32	frequency_tolerance_hz; | ||||
| 	u32	symbol_rate_min; | ||||
| 	u32	symbol_rate_max; | ||||
| 	u32	symbol_rate_tolerance; | ||||
| 	enum fe_caps caps; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dvb_frontend_ops - Demodulation information and callbacks for | ||||
|  *			      ditialt TV | ||||
|  * | ||||
|  * @info:		embedded struct dvb_tuner_info with tuner properties | ||||
|  * @info:		embedded &struct dvb_tuner_info with tuner properties | ||||
|  * @delsys:		Delivery systems supported by the frontend | ||||
|  * @detach:		callback function called when frontend is detached. | ||||
|  *			drivers should clean up, but not yet free the struct | ||||
|  *			drivers should clean up, but not yet free the &struct | ||||
|  *			dvb_frontend allocation. | ||||
|  * @release:		callback function called when frontend is ready to be | ||||
|  *			freed. | ||||
|  *			drivers should free any allocated memory. | ||||
|  * @release_sec:	callback function requesting that the Satelite Equipment | ||||
|  * @release_sec:	callback function requesting that the Satellite Equipment | ||||
|  *			Control (SEC) driver to release and free any memory | ||||
|  *			allocated by the driver. | ||||
|  * @init:		callback function used to initialize the tuner device. | ||||
| @@ -343,57 +373,57 @@ struct dtv_frontend_properties; | ||||
|  *			allow other drivers to write data into their registers. | ||||
|  *			Should not be used on new drivers. | ||||
|  * @tune:		callback function used by demod drivers that use | ||||
|  *			@DVBFE_ALGO_HW; to tune into a frequency. | ||||
|  *			@DVBFE_ALGO_HW to tune into a frequency. | ||||
|  * @get_frontend_algo:	returns the desired hardware algorithm. | ||||
|  * @set_frontend:	callback function used to inform the demod to set the | ||||
|  *			parameters for demodulating a digital TV channel. | ||||
|  *			The properties to be used are stored at | ||||
|  *			@dvb_frontend.dtv_property_cache;. The demod can change | ||||
|  *			The properties to be used are stored at &struct | ||||
|  *			dvb_frontend.dtv_property_cache. The demod can change | ||||
|  *			the parameters to reflect the changes needed for the | ||||
|  *			channel to be decoded, and update statistics. | ||||
|  * @get_tune_settings:	callback function | ||||
|  * @get_frontend:	callback function used to inform the parameters | ||||
|  *			actuall in use. The properties to be used are stored at | ||||
|  *			@dvb_frontend.dtv_property_cache; and update | ||||
|  *			&struct dvb_frontend.dtv_property_cache and update | ||||
|  *			statistics. Please notice that it should not return | ||||
|  *			an error code if the statistics are not available | ||||
|  *			because the demog is not locked. | ||||
|  * @read_status:	returns the locking status of the frontend. | ||||
|  * @read_ber:		legacy callback function to return the bit error rate. | ||||
|  *			Newer drivers should provide such info via DVBv5 API, | ||||
|  *			e. g. @set_frontend;/@get_frontend;, implementing this | ||||
|  *			e. g. @set_frontend;/@get_frontend, implementing this | ||||
|  *			callback only if DVBv3 API compatibility is wanted. | ||||
|  * @read_signal_strength: legacy callback function to return the signal | ||||
|  *			strength. Newer drivers should provide such info via | ||||
|  *			DVBv5 API, e. g. @set_frontend;/@get_frontend;, | ||||
|  *			DVBv5 API, e. g. @set_frontend/@get_frontend, | ||||
|  *			implementing this callback only if DVBv3 API | ||||
|  *			compatibility is wanted. | ||||
|  * @read_snr:		legacy callback function to return the Signal/Noise | ||||
|  * 			rate. Newer drivers should provide such info via | ||||
|  *			DVBv5 API, e. g. @set_frontend;/@get_frontend;, | ||||
|  *			rate. Newer drivers should provide such info via | ||||
|  *			DVBv5 API, e. g. @set_frontend/@get_frontend, | ||||
|  *			implementing this callback only if DVBv3 API | ||||
|  *			compatibility is wanted. | ||||
|  * @read_ucblocks:	legacy callback function to return the Uncorrected Error | ||||
|  *			Blocks. Newer drivers should provide such info via | ||||
|  *			DVBv5 API, e. g. @set_frontend;/@get_frontend;, | ||||
|  *			DVBv5 API, e. g. @set_frontend/@get_frontend, | ||||
|  *			implementing this callback only if DVBv3 API | ||||
|  *			compatibility is wanted. | ||||
|  * @diseqc_reset_overload: callback function to implement the | ||||
|  *			FE_DISEQC_RESET_OVERLOAD ioctl (only Satellite) | ||||
|  *			FE_DISEQC_RESET_OVERLOAD() ioctl (only Satellite) | ||||
|  * @diseqc_send_master_cmd: callback function to implement the | ||||
|  *			FE_DISEQC_SEND_MASTER_CMD ioctl (only Satellite). | ||||
|  *			FE_DISEQC_SEND_MASTER_CMD() ioctl (only Satellite). | ||||
|  * @diseqc_recv_slave_reply: callback function to implement the | ||||
|  *			FE_DISEQC_RECV_SLAVE_REPLY ioctl (only Satellite) | ||||
|  *			FE_DISEQC_RECV_SLAVE_REPLY() ioctl (only Satellite) | ||||
|  * @diseqc_send_burst:	callback function to implement the | ||||
|  *			FE_DISEQC_SEND_BURST ioctl (only Satellite). | ||||
|  *			FE_DISEQC_SEND_BURST() ioctl (only Satellite). | ||||
|  * @set_tone:		callback function to implement the | ||||
|  *			FE_SET_TONE ioctl (only Satellite). | ||||
|  *			FE_SET_TONE() ioctl (only Satellite). | ||||
|  * @set_voltage:	callback function to implement the | ||||
|  *			FE_SET_VOLTAGE ioctl (only Satellite). | ||||
|  *			FE_SET_VOLTAGE() ioctl (only Satellite). | ||||
|  * @enable_high_lnb_voltage: callback function to implement the | ||||
|  *			FE_ENABLE_HIGH_LNB_VOLTAGE ioctl (only Satellite). | ||||
|  *			FE_ENABLE_HIGH_LNB_VOLTAGE() ioctl (only Satellite). | ||||
|  * @dishnetwork_send_legacy_command: callback function to implement the | ||||
|  *			FE_DISHNETWORK_SEND_LEGACY_CMD ioctl (only Satellite). | ||||
|  *			FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl (only Satellite). | ||||
|  *			Drivers should not use this, except when the DVB | ||||
|  *			core emulation fails to provide proper support (e.g. | ||||
|  *			if @set_voltage takes more than 8ms to work), and | ||||
| @@ -404,16 +434,12 @@ struct dtv_frontend_properties; | ||||
|  * @ts_bus_ctrl:	callback function used to take control of the TS bus. | ||||
|  * @set_lna:		callback function to power on/off/auto the LNA. | ||||
|  * @search:		callback function used on some custom algo search algos. | ||||
|  * @tuner_ops:		pointer to struct dvb_tuner_ops | ||||
|  * @analog_ops:		pointer to struct analog_demod_ops | ||||
|  * @set_property:	callback function to allow the frontend to validade | ||||
|  *			incoming properties. Should not be used on new drivers. | ||||
|  * @get_property:	callback function to allow the frontend to override | ||||
|  *			outcoming properties. Should not be used on new drivers. | ||||
|  * @tuner_ops:		pointer to &struct dvb_tuner_ops | ||||
|  * @analog_ops:		pointer to &struct analog_demod_ops | ||||
|  */ | ||||
| struct dvb_frontend_ops { | ||||
| 
 | ||||
| 	struct dvb_frontend_info info; | ||||
| 	struct dvb_frontend_internal_info info; | ||||
| 
 | ||||
| 	u8 delsys[MAX_DELSYS]; | ||||
| 
 | ||||
| @@ -473,9 +499,6 @@ struct dvb_frontend_ops { | ||||
| 	struct dvb_tuner_ops tuner_ops; | ||||
| 	struct analog_demod_ops analog_ops; | ||||
| 
 | ||||
| 	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||||
| 	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||||
| 
 | ||||
| 	u8 xbar[3]; | ||||
| }; | ||||
| 
 | ||||
| @@ -506,7 +529,7 @@ struct dvb_fe_events { | ||||
|  * @fec_inner:		Forward error correction inner Code Rate | ||||
|  * @transmission_mode:	Transmission Mode | ||||
|  * @bandwidth_hz:	Bandwidth, in Hz. A zero value means that userspace | ||||
|  * 			wants to autodetect. | ||||
|  *			wants to autodetect. | ||||
|  * @guard_interval:	Guard Interval | ||||
|  * @hierarchy:		Hierarchy | ||||
|  * @symbol_rate:	Symbol Rate | ||||
| @@ -529,8 +552,8 @@ struct dvb_fe_events { | ||||
|  * @layer.interleaving:	 per layer interleaving. | ||||
|  * @stream_id:		If different than zero, enable substream filtering, if | ||||
|  *			hardware supports (DVB-S2 and DVB-T2). | ||||
|  * @scrambling_sequence_index: Carries the index of the DVB-S2 physical layer | ||||
|  *                             scrambling sequence. | ||||
|  * @scrambling_sequence_index:	Carries the index of the DVB-S2 physical layer | ||||
|  *				scrambling sequence. | ||||
|  * @atscmh_fic_ver:	Version number of the FIC (Fast Information Channel) | ||||
|  *			signaling data (only ATSC-M/H) | ||||
|  * @atscmh_parade_id:	Parade identification number (only ATSC-M/H) | ||||
| @@ -554,7 +577,7 @@ struct dvb_fe_events { | ||||
|  * @lna:		Power ON/OFF/AUTO the Linear Now-noise Amplifier (LNA) | ||||
|  * @strength:		DVBv5 API statistics: Signal Strength | ||||
|  * @cnr:		DVBv5 API statistics: Signal to Noise ratio of the | ||||
|  * 			(main) carrier | ||||
|  *			(main) carrier | ||||
|  * @pre_bit_error:	DVBv5 API statistics: pre-Viterbi bit error count | ||||
|  * @pre_bit_count:	DVBv5 API statistics: pre-Viterbi bit count | ||||
|  * @post_bit_error:	DVBv5 API statistics: post-Viterbi bit error count | ||||
| @@ -575,15 +598,15 @@ struct dtv_frontend_properties { | ||||
| 
 | ||||
| 	enum fe_sec_voltage	voltage; | ||||
| 	enum fe_sec_tone_mode	sectone; | ||||
| 	enum fe_spectral_inversion	inversion; | ||||
| 	enum fe_code_rate		fec_inner; | ||||
| 	enum fe_spectral_inversion inversion; | ||||
| 	enum fe_code_rate	fec_inner; | ||||
| 	enum fe_transmit_mode	transmission_mode; | ||||
| 	u32			bandwidth_hz;	/* 0 = AUTO */ | ||||
| 	enum fe_guard_interval	guard_interval; | ||||
| 	enum fe_hierarchy		hierarchy; | ||||
| 	enum fe_hierarchy	hierarchy; | ||||
| 	u32			symbol_rate; | ||||
| 	enum fe_code_rate		code_rate_HP; | ||||
| 	enum fe_code_rate		code_rate_LP; | ||||
| 	enum fe_code_rate	code_rate_HP; | ||||
| 	enum fe_code_rate	code_rate_LP; | ||||
| 
 | ||||
| 	enum fe_pilot		pilot; | ||||
| 	enum fe_rolloff		rolloff; | ||||
| @@ -610,7 +633,7 @@ struct dtv_frontend_properties { | ||||
| 	u32			stream_id; | ||||
| 
 | ||||
| 	/* Physical Layer Scrambling specifics */ | ||||
| 	u32                     scrambling_sequence_index; | ||||
| 	u32			scrambling_sequence_index; | ||||
| 
 | ||||
| 	/* ATSC-MH specifics */ | ||||
| 	u8			atscmh_fic_ver; | ||||
| @@ -642,11 +665,6 @@ struct dtv_frontend_properties { | ||||
| 	struct dtv_fe_stats	post_bit_count; | ||||
| 	struct dtv_fe_stats	block_error; | ||||
| 	struct dtv_fe_stats	block_count; | ||||
| 
 | ||||
| 	/* private: */ | ||||
| 	/* Cache State */ | ||||
| 	u32			state; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #define DVB_FE_NO_EXIT  0 | ||||
| @@ -657,16 +675,16 @@ struct dtv_frontend_properties { | ||||
| /**
 | ||||
|  * struct dvb_frontend - Frontend structure to be used on drivers. | ||||
|  * | ||||
|  * @refcount:		refcount to keep track of struct dvb_frontend | ||||
|  * @refcount:		refcount to keep track of &struct dvb_frontend | ||||
|  *			references | ||||
|  * @ops:		embedded struct dvb_frontend_ops | ||||
|  * @dvb:		pointer to struct dvb_adapter | ||||
|  * @ops:		embedded &struct dvb_frontend_ops | ||||
|  * @dvb:		pointer to &struct dvb_adapter | ||||
|  * @demodulator_priv:	demod private data | ||||
|  * @tuner_priv:		tuner private data | ||||
|  * @frontend_priv:	frontend private data | ||||
|  * @sec_priv:		SEC private data | ||||
|  * @analog_demod_priv:	Analog demod private data | ||||
|  * @dtv_property_cache:	embedded struct dtv_frontend_properties | ||||
|  * @dtv_property_cache:	embedded &struct dtv_frontend_properties | ||||
|  * @callback:		callback function used on some drivers to call | ||||
|  *			either the tuner or the demodulator. | ||||
|  * @id:			Frontend ID | ||||
| @@ -695,8 +713,8 @@ struct dvb_frontend { | ||||
| /**
 | ||||
|  * dvb_register_frontend() - Registers a DVB frontend at the adapter | ||||
|  * | ||||
|  * @dvb: pointer to the dvb adapter | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @dvb: pointer to &struct dvb_adapter | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * Allocate and initialize the private data needed by the frontend core to | ||||
|  * manage the frontend and calls dvb_register_device() to register a new | ||||
| @@ -709,7 +727,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb, | ||||
| /**
 | ||||
|  * dvb_unregister_frontend() - Unregisters a DVB frontend | ||||
|  * | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * Stops the frontend kthread, calls dvb_unregister_device() and frees the | ||||
|  * private frontend data allocated by dvb_register_frontend(). | ||||
| @@ -723,14 +741,14 @@ int dvb_unregister_frontend(struct dvb_frontend *fe); | ||||
| /**
 | ||||
|  * dvb_frontend_detach() - Detaches and frees frontend specific data | ||||
|  * | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * This function should be called after dvb_unregister_frontend(). It | ||||
|  * calls the SEC, tuner and demod release functions: | ||||
|  * &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release, | ||||
|  * &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release. | ||||
|  * | ||||
|  * If the driver is compiled with CONFIG_MEDIA_ATTACH, it also decreases | ||||
|  * If the driver is compiled with %CONFIG_MEDIA_ATTACH, it also decreases | ||||
|  * the module reference count, needed to allow userspace to remove the | ||||
|  * previously used DVB frontend modules. | ||||
|  */ | ||||
| @@ -739,7 +757,7 @@ void dvb_frontend_detach(struct dvb_frontend *fe); | ||||
| /**
 | ||||
|  * dvb_frontend_suspend() - Suspends a Digital TV frontend | ||||
|  * | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * This function prepares a Digital TV frontend to suspend. | ||||
|  * | ||||
| @@ -757,7 +775,7 @@ int dvb_frontend_suspend(struct dvb_frontend *fe); | ||||
| /**
 | ||||
|  * dvb_frontend_resume() - Resumes a Digital TV frontend | ||||
|  * | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * This function resumes the usual operation of the tuner after resume. | ||||
|  * | ||||
| @@ -778,7 +796,7 @@ int dvb_frontend_resume(struct dvb_frontend *fe); | ||||
| /**
 | ||||
|  * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend | ||||
|  * | ||||
|  * @fe: pointer to the frontend struct | ||||
|  * @fe: pointer to &struct dvb_frontend | ||||
|  * | ||||
|  * Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\), | ||||
|  * and resets SEC tone and voltage (for Satellite systems). | ||||
| @@ -793,16 +811,16 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe); | ||||
|  * dvb_frontend_sleep_until() - Sleep for the amount of time given by | ||||
|  *                      add_usec parameter | ||||
|  * | ||||
|  * @waketime: pointer to a struct ktime_t | ||||
|  * @waketime: pointer to &struct ktime_t | ||||
|  * @add_usec: time to sleep, in microseconds | ||||
|  * | ||||
|  * This function is used to measure the time required for the | ||||
|  * %FE_DISHNETWORK_SEND_LEGACY_CMD ioctl to work. It needs to be as precise | ||||
|  * FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl to work. It needs to be as precise | ||||
|  * as possible, as it affects the detection of the dish tone command at the | ||||
|  * satellite subsystem. | ||||
|  * | ||||
|  * Its used internally by the DVB frontend core, in order to emulate | ||||
|  * %FE_DISHNETWORK_SEND_LEGACY_CMD using the &dvb_frontend_ops.set_voltage\(\) | ||||
|  * FE_DISHNETWORK_SEND_LEGACY_CMD() using the &dvb_frontend_ops.set_voltage\(\) | ||||
|  * callback. | ||||
|  * | ||||
|  * NOTE: it should not be used at the drivers, as the emulation for the | ||||
| @@ -24,12 +24,28 @@ | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/skbuff.h> | ||||
| 
 | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
| 
 | ||||
| #define DVB_NET_DEVICES_MAX 10 | ||||
| 
 | ||||
| #ifdef CONFIG_DVB_NET | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dvb_net - describes a DVB network interface | ||||
|  * | ||||
|  * @dvbdev:		pointer to &struct dvb_device. | ||||
|  * @device:		array of pointers to &struct net_device. | ||||
|  * @state:		array of integers to each net device. A value | ||||
|  *			different than zero means that the interface is | ||||
|  *			in usage. | ||||
|  * @exit:		flag to indicate when the device is being removed. | ||||
|  * @demux:		pointer to &struct dmx_demux. | ||||
|  * @ioctl_mutex:	protect access to this struct. | ||||
|  * | ||||
|  * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network | ||||
|  * devices. | ||||
|  */ | ||||
| 
 | ||||
| struct dvb_net { | ||||
| 	struct dvb_device *dvbdev; | ||||
| 	struct net_device *device[DVB_NET_DEVICES_MAX]; | ||||
| @@ -39,8 +55,22 @@ struct dvb_net { | ||||
| 	struct mutex ioctl_mutex; | ||||
| }; | ||||
| 
 | ||||
| void dvb_net_release(struct dvb_net *); | ||||
| int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); | ||||
| /**
 | ||||
|  * dvb_net_init - nitializes a digital TV network device and registers it. | ||||
|  * | ||||
|  * @adap:	pointer to &struct dvb_adapter. | ||||
|  * @dvbnet:	pointer to &struct dvb_net. | ||||
|  * @dmxdemux:	pointer to &struct dmx_demux. | ||||
|  */ | ||||
| int dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, | ||||
| 		  struct dmx_demux *dmxdemux); | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_net_release - releases a digital TV network device and unregisters it. | ||||
|  * | ||||
|  * @dvbnet:	pointer to &struct dvb_net. | ||||
|  */ | ||||
| void dvb_net_release(struct dvb_net *dvbnet); | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
							
								
								
									
										280
									
								
								include/linux/media/dvb_vb2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								include/linux/media/dvb_vb2.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,280 @@ | ||||
| /* | ||||
|  * SPDX-License-Identifier: GPL-2.0 | ||||
|  * | ||||
|  * dvb-vb2.h - DVB driver helper framework for streaming I/O | ||||
|  * | ||||
|  * Copyright (C) 2015 Samsung Electronics | ||||
|  * | ||||
|  * Author: jh1009.sung@samsung.com | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation. | ||||
|  */ | ||||
|  | ||||
| #ifndef _DVB_VB2_H | ||||
| #define _DVB_VB2_H | ||||
|  | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/poll.h> | ||||
| #include <linux/dvb/dmx.h> | ||||
| #include <media/videobuf2-core.h> | ||||
| #include <media/videobuf2-dma-contig.h> | ||||
| #include <media/videobuf2-vmalloc.h> | ||||
|  | ||||
| /** | ||||
|  * enum dvb_buf_type - types of Digital TV memory-mapped buffers | ||||
|  * | ||||
|  * @DVB_BUF_TYPE_CAPTURE: buffer is filled by the Kernel, | ||||
|  *			  with a received Digital TV stream | ||||
|  */ | ||||
| enum dvb_buf_type { | ||||
| 	DVB_BUF_TYPE_CAPTURE        = 1, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * enum dvb_vb2_states - states to control VB2 state machine | ||||
|  * @DVB_VB2_STATE_NONE: | ||||
|  *	VB2 engine not initialized yet, init failed or VB2 was released. | ||||
|  * @DVB_VB2_STATE_INIT: | ||||
|  *	VB2 engine initialized. | ||||
|  * @DVB_VB2_STATE_REQBUFS: | ||||
|  *	Buffers were requested | ||||
|  * @DVB_VB2_STATE_STREAMON: | ||||
|  *	VB2 is streaming. Callers should not check it directly. Instead, | ||||
|  *	they should use dvb_vb2_is_streaming(). | ||||
|  * | ||||
|  * Note: | ||||
|  * | ||||
|  * Callers should not touch at the state machine directly. This | ||||
|  * is handled inside dvb_vb2.c. | ||||
|  */ | ||||
| enum dvb_vb2_states { | ||||
| 	DVB_VB2_STATE_NONE	= 0x0, | ||||
| 	DVB_VB2_STATE_INIT	= 0x1, | ||||
| 	DVB_VB2_STATE_REQBUFS	= 0x2, | ||||
| 	DVB_VB2_STATE_STREAMON	= 0x4, | ||||
| }; | ||||
|  | ||||
| #define DVB_VB2_NAME_MAX (20) | ||||
|  | ||||
| /** | ||||
|  * struct dvb_buffer - video buffer information for v4l2. | ||||
|  * | ||||
|  * @vb:		embedded struct &vb2_buffer. | ||||
|  * @list:	list of &struct dvb_buffer. | ||||
|  */ | ||||
| struct dvb_buffer { | ||||
| 	struct vb2_buffer	vb; | ||||
| 	struct list_head	list; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dvb_vb2_ctx - control struct for VB2 handler | ||||
|  * @vb_q:	pointer to &struct vb2_queue with videobuf2 queue. | ||||
|  * @mutex:	mutex to serialize vb2 operations. Used by | ||||
|  *		vb2 core %wait_prepare and %wait_finish operations. | ||||
|  * @slock:	spin lock used to protect buffer filling at dvb_vb2.c. | ||||
|  * @dvb_q:	List of buffers that are not filled yet. | ||||
|  * @buf:	Pointer to the buffer that are currently being filled. | ||||
|  * @offset:	index to the next position at the @buf to be filled. | ||||
|  * @remain:	How many bytes are left to be filled at @buf. | ||||
|  * @state:	bitmask of buffer states as defined by &enum dvb_vb2_states. | ||||
|  * @buf_siz:	size of each VB2 buffer. | ||||
|  * @buf_cnt:	number of VB2 buffers. | ||||
|  * @nonblocking: | ||||
|  *		If different than zero, device is operating on non-blocking | ||||
|  *		mode. | ||||
|  * @flags:	buffer flags as defined by &enum dmx_buffer_flags. | ||||
|  *		Filled only at &DMX_DQBUF. &DMX_QBUF should zero this field. | ||||
|  * @count:	monotonic counter for filled buffers. Helps to identify | ||||
|  *		data stream loses. Filled only at &DMX_DQBUF. &DMX_QBUF should | ||||
|  *		zero this field. | ||||
|  * | ||||
|  * @name:	name of the device type. Currently, it can either be | ||||
|  *		"dvr" or "demux_filter". | ||||
|  */ | ||||
| struct dvb_vb2_ctx { | ||||
| 	struct vb2_queue	vb_q; | ||||
| 	struct mutex		mutex; | ||||
| 	spinlock_t		slock; | ||||
| 	struct list_head	dvb_q; | ||||
| 	struct dvb_buffer	*buf; | ||||
| 	int	offset; | ||||
| 	int	remain; | ||||
| 	int	state; | ||||
| 	int	buf_siz; | ||||
| 	int	buf_cnt; | ||||
| 	int	nonblocking; | ||||
|  | ||||
| 	enum dmx_buffer_flags flags; | ||||
| 	u32	count; | ||||
|  | ||||
| 	char	name[DVB_VB2_NAME_MAX + 1]; | ||||
| }; | ||||
|  | ||||
| #ifndef CONFIG_DVB_MMAP | ||||
| static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx, | ||||
| 			       const char *name, int non_blocking) | ||||
| { | ||||
| 	return 0; | ||||
| }; | ||||
| static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx) | ||||
| { | ||||
| 	return 0; | ||||
| }; | ||||
| #define dvb_vb2_is_streaming(ctx) (0) | ||||
| #define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0) | ||||
|  | ||||
| static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, | ||||
| 				    struct file *file, | ||||
| 				    poll_table *wait) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| #else | ||||
| /** | ||||
|  * dvb_vb2_init - initializes VB2 handler | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @name:	name for the VB2 handler | ||||
|  * @non_blocking: | ||||
|  *		if not zero, it means that the device is at non-blocking mode | ||||
|  */ | ||||
| int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int non_blocking); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_release - Releases the VB2 handler allocated resources and | ||||
|  *	put @ctx at DVB_VB2_STATE_NONE state. | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  */ | ||||
| int dvb_vb2_release(struct dvb_vb2_ctx *ctx); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_is_streaming - checks if the VB2 handler is streaming | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * | ||||
|  * Return: 0 if not streaming, 1 otherwise. | ||||
|  */ | ||||
| int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_fill_buffer - fills a VB2 buffer | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @src:	place where the data is stored | ||||
|  * @len:	number of bytes to be copied from @src | ||||
|  * @buffer_flags: | ||||
|  *		pointer to buffer flags as defined by &enum dmx_buffer_flags. | ||||
|  *		can be NULL. | ||||
|  */ | ||||
| int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, | ||||
| 			const unsigned char *src, int len, | ||||
| 			enum dmx_buffer_flags *buffer_flags); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV | ||||
|  *      buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @file:	&struct file argument passed to the poll | ||||
|  *		file operation handler. | ||||
|  * @wait:	&poll_table wait argument passed to the poll | ||||
|  *		file operation handler. | ||||
|  * | ||||
|  * Implements poll syscall() logic. | ||||
|  */ | ||||
| __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file, | ||||
| 		      poll_table *wait); | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_stream_on() - Wrapper to vb2_core_streamon() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * | ||||
|  * Starts dvb streaming | ||||
|  */ | ||||
| int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx); | ||||
| /** | ||||
|  * dvb_vb2_stream_off() - Wrapper to vb2_core_streamoff() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * | ||||
|  * Stops dvb streaming | ||||
|  */ | ||||
| int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_reqbufs() - Wrapper to vb2_core_reqbufs() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @req:	&struct dmx_requestbuffers passed from userspace in | ||||
|  *		order to handle &DMX_REQBUFS. | ||||
|  * | ||||
|  * Initiate streaming by requesting a number of buffers. Also used to | ||||
|  * free previously requested buffers, is ``req->count`` is zero. | ||||
|  */ | ||||
| int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_querybuf() - Wrapper to vb2_core_querybuf() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @b:		&struct dmx_buffer passed from userspace in | ||||
|  *		order to handle &DMX_QUERYBUF. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
| int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_expbuf() - Wrapper to vb2_core_expbuf() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @exp:	&struct dmx_exportbuffer passed from userspace in | ||||
|  *		order to handle &DMX_EXPBUF. | ||||
|  * | ||||
|  * Export a buffer as a file descriptor. | ||||
|  */ | ||||
| int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_qbuf() - Wrapper to vb2_core_qbuf() for Digital TV buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @b:		&struct dmx_buffer passed from userspace in | ||||
|  *		order to handle &DMX_QBUF. | ||||
|  * | ||||
|  * Queue a Digital TV buffer as requested by userspace | ||||
|  */ | ||||
| int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_dqbuf() - Wrapper to vb2_core_dqbuf() for Digital TV | ||||
|  *	buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @b:		&struct dmx_buffer passed from userspace in | ||||
|  *		order to handle &DMX_DQBUF. | ||||
|  * | ||||
|  * Dequeue a Digital TV buffer to the userspace | ||||
|  */ | ||||
| int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b); | ||||
|  | ||||
| /** | ||||
|  * dvb_vb2_mmap() - Wrapper to vb2_mmap() for Digital TV buffer handling. | ||||
|  * | ||||
|  * @ctx:	control struct for VB2 handler | ||||
|  * @vma:        pointer to &struct vm_area_struct with the vma passed | ||||
|  *              to the mmap file operation handler in the driver. | ||||
|  * | ||||
|  * map Digital TV video buffers into application address space. | ||||
|  */ | ||||
| int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma); | ||||
|  | ||||
| #endif /* _DVB_VB2_H */ | ||||
| @@ -35,19 +35,42 @@ | ||||
| 
 | ||||
| #define DVB_UNSET (-1) | ||||
| 
 | ||||
| #define DVB_DEVICE_VIDEO      0 | ||||
| #define DVB_DEVICE_AUDIO      1 | ||||
| #define DVB_DEVICE_SEC        2 | ||||
| #define DVB_DEVICE_FRONTEND   3 | ||||
| #define DVB_DEVICE_DEMUX      4 | ||||
| #define DVB_DEVICE_DVR        5 | ||||
| #define DVB_DEVICE_CA         6 | ||||
| #define DVB_DEVICE_NET        7 | ||||
| #define DVB_DEVICE_OSD        8 | ||||
| #define DVB_DEVICE_CI         9 | ||||
| #define DVB_DEVICE_MOD       10 | ||||
| #define DVB_DEVICE_NS        11 | ||||
| #define DVB_DEVICE_NSD       12 | ||||
| /* List of DVB device types */ | ||||
| 
 | ||||
| /**
 | ||||
|  * enum dvb_device_type - type of the Digital TV device | ||||
|  * | ||||
|  * @DVB_DEVICE_SEC:		Digital TV standalone Common Interface (CI) | ||||
|  * @DVB_DEVICE_FRONTEND:	Digital TV frontend. | ||||
|  * @DVB_DEVICE_DEMUX:		Digital TV demux. | ||||
|  * @DVB_DEVICE_DVR:		Digital TV digital video record (DVR). | ||||
|  * @DVB_DEVICE_CA:		Digital TV Conditional Access (CA). | ||||
|  * @DVB_DEVICE_NET:		Digital TV network. | ||||
|  * | ||||
|  * @DVB_DEVICE_VIDEO:		Digital TV video decoder. | ||||
|  *				Deprecated. Used only on av7110-av. | ||||
|  * @DVB_DEVICE_AUDIO:		Digital TV audio decoder. | ||||
|  *				Deprecated. Used only on av7110-av. | ||||
|  * @DVB_DEVICE_OSD:		Digital TV On Screen Display (OSD). | ||||
|  *				Deprecated. Used only on av7110. | ||||
|  */ | ||||
| enum dvb_device_type { | ||||
| 	DVB_DEVICE_SEC, | ||||
| 	DVB_DEVICE_FRONTEND, | ||||
| 	DVB_DEVICE_DEMUX, | ||||
| 	DVB_DEVICE_DVR, | ||||
| 	DVB_DEVICE_CA, | ||||
| 	DVB_DEVICE_NET, | ||||
| 
 | ||||
| 	DVB_DEVICE_VIDEO, | ||||
| 	DVB_DEVICE_AUDIO, | ||||
| 	DVB_DEVICE_OSD, | ||||
| 
 | ||||
| 	DVB_DEVICE_CI, | ||||
| 	DVB_DEVICE_MOD, | ||||
| 	DVB_DEVICE_NS, | ||||
| 	DVB_DEVICE_NSD, | ||||
| }; | ||||
| 
 | ||||
| #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ | ||||
| 	static short adapter_nr[] = \ | ||||
| @@ -68,11 +91,12 @@ struct dvb_frontend; | ||||
|  * @priv:		private data | ||||
|  * @device:		pointer to struct device | ||||
|  * @module:		pointer to struct module | ||||
|  * @mfe_shared:		mfe shared: indicates mutually exclusive frontends | ||||
|  *			Thie usage of this flag is currently deprecated | ||||
|  * @mfe_shared:		indicates mutually exclusive frontends. | ||||
|  *			Use of this flag is currently deprecated. | ||||
|  * @mfe_dvbdev:		Frontend device in use, in the case of MFE | ||||
|  * @mfe_lock:		Lock to prevent using the other frontends when MFE is | ||||
|  *			used. | ||||
|  * @mdev_lock:          Protect access to the mdev pointer. | ||||
|  * @mdev:		pointer to struct media_device, used when the media | ||||
|  *			controller is used. | ||||
|  * @conn:		RF connector. Used only if the device has no separate | ||||
| @@ -96,6 +120,7 @@ struct dvb_adapter { | ||||
| 	struct mutex mfe_lock;		/* access lock for thread creation */ | ||||
| 
 | ||||
| #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | ||||
| 	struct mutex mdev_lock; | ||||
| 	struct media_device *mdev; | ||||
| 	struct media_entity *conn; | ||||
| 	struct media_pad *conn_pads; | ||||
| @@ -108,8 +133,7 @@ struct dvb_adapter { | ||||
|  * @list_head:	List head with all DVB devices | ||||
|  * @fops:	pointer to struct file_operations | ||||
|  * @adapter:	pointer to the adapter that holds this device node | ||||
|  * @type:	type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, | ||||
|  *		DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET | ||||
|  * @type:	type of the device, as defined by &enum dvb_device_type. | ||||
|  * @minor:	devnode minor number. Major number is always DVB_MAJOR. | ||||
|  * @id:		device ID number, inside the adapter | ||||
|  * @readers:	Initialized by the caller. Each call to open() in Read Only mode | ||||
| @@ -139,7 +163,7 @@ struct dvb_device { | ||||
| 	struct list_head list_head; | ||||
| 	const struct file_operations *fops; | ||||
| 	struct dvb_adapter *adapter; | ||||
| 	int type; | ||||
| 	enum dvb_device_type type; | ||||
| 	int minor; | ||||
| 	u32 id; | ||||
| 
 | ||||
| @@ -176,7 +200,7 @@ struct dvb_device { | ||||
|  * @module:	initialized with THIS_MODULE at the caller | ||||
|  * @device:	pointer to struct device that corresponds to the device driver | ||||
|  * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; | ||||
|  * 		to select among them. Typically, initialized with: | ||||
|  *		to select among them. Typically, initialized with: | ||||
|  *		DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) | ||||
|  */ | ||||
| int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||||
| @@ -198,9 +222,7 @@ int dvb_unregister_adapter(struct dvb_adapter *adap); | ||||
|  *		stored | ||||
|  * @template:	Template used to create &pdvbdev; | ||||
|  * @priv:	private data | ||||
|  * @type:	type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, | ||||
|  *		%DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, | ||||
|  *		%DVB_DEVICE_NET | ||||
|  * @type:	type of the device, as defined by &enum dvb_device_type. | ||||
|  * @demux_sink_pads: Number of demux outputs, to be used to create the TS | ||||
|  *		outputs via the Media Controller. | ||||
|  */ | ||||
| @@ -208,7 +230,7 @@ int dvb_register_device(struct dvb_adapter *adap, | ||||
| 			struct dvb_device **pdvbdev, | ||||
| 			const struct dvb_device *template, | ||||
| 			void *priv, | ||||
| 			int type, | ||||
| 			enum dvb_device_type type, | ||||
| 			int demux_sink_pads); | ||||
| 
 | ||||
| /**
 | ||||
| @@ -244,9 +266,9 @@ void dvb_unregister_device(struct dvb_device *dvbdev); | ||||
| #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||||
| /**
 | ||||
|  * dvb_create_media_graph - Creates media graph for the Digital TV part of the | ||||
|  * 				device. | ||||
|  *				device. | ||||
|  * | ||||
|  * @adap:			pointer to struct dvb_adapter | ||||
|  * @adap:			pointer to &struct dvb_adapter | ||||
|  * @create_rf_connector:	if true, it creates the RF connector too | ||||
|  * | ||||
|  * This function checks all DVB-related functions at the media controller | ||||
| @@ -259,14 +281,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev); | ||||
| __must_check int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 					bool create_rf_connector); | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_register_media_controller - registers a media controller at DVB adapter | ||||
|  * | ||||
|  * @adap:			pointer to &struct dvb_adapter | ||||
|  * @mdev:			pointer to &struct media_device | ||||
|  */ | ||||
| static inline void dvb_register_media_controller(struct dvb_adapter *adap, | ||||
| 						 struct media_device *mdev) | ||||
| { | ||||
| 	adap->mdev = mdev; | ||||
| } | ||||
| 
 | ||||
| static inline struct media_device | ||||
| *dvb_get_media_controller(struct dvb_adapter *adap) | ||||
| /**
 | ||||
|  * dvb_get_media_controller - gets the associated media controller | ||||
|  * | ||||
|  * @adap:			pointer to &struct dvb_adapter | ||||
|  */ | ||||
| static inline struct media_device * | ||||
| dvb_get_media_controller(struct dvb_adapter *adap) | ||||
| { | ||||
| 	return adap->mdev; | ||||
| } | ||||
| @@ -281,20 +314,131 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| #define dvb_get_media_controller(a) NULL | ||||
| #endif | ||||
| 
 | ||||
| int dvb_generic_open (struct inode *inode, struct file *file); | ||||
| int dvb_generic_release (struct inode *inode, struct file *file); | ||||
| long dvb_generic_ioctl (struct file *file, | ||||
| 			      unsigned int cmd, unsigned long arg); | ||||
| /**
 | ||||
|  * dvb_generic_open - Digital TV open function, used by DVB devices | ||||
|  * | ||||
|  * @inode: pointer to &struct inode. | ||||
|  * @file: pointer to &struct file. | ||||
|  * | ||||
|  * Checks if a DVB devnode is still valid, and if the permissions are | ||||
|  * OK and increment negative use count. | ||||
|  */ | ||||
| int dvb_generic_open(struct inode *inode, struct file *file); | ||||
| 
 | ||||
| /* we don't mess with video_usercopy() any more,
 | ||||
| we simply define out own dvb_usercopy(), which will hopefully become | ||||
| generic_usercopy()  someday... */ | ||||
| /**
 | ||||
|  * dvb_generic_close - Digital TV close function, used by DVB devices | ||||
|  * | ||||
|  * @inode: pointer to &struct inode. | ||||
|  * @file: pointer to &struct file. | ||||
|  * | ||||
|  * Checks if a DVB devnode is still valid, and if the permissions are | ||||
|  * OK and decrement negative use count. | ||||
|  */ | ||||
| int dvb_generic_release(struct inode *inode, struct file *file); | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_generic_ioctl - Digital TV close function, used by DVB devices | ||||
|  * | ||||
|  * @file: pointer to &struct file. | ||||
|  * @cmd: Ioctl name. | ||||
|  * @arg: Ioctl argument. | ||||
|  * | ||||
|  * Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid. | ||||
|  * If so, calls dvb_usercopy(). | ||||
|  */ | ||||
| long dvb_generic_ioctl(struct file *file, | ||||
| 		       unsigned int cmd, unsigned long arg); | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_usercopy - copies data from/to userspace memory when an ioctl is | ||||
|  *      issued. | ||||
|  * | ||||
|  * @file: Pointer to struct &file. | ||||
|  * @cmd: Ioctl name. | ||||
|  * @arg: Ioctl argument. | ||||
|  * @func: function that will actually handle the ioctl | ||||
|  * | ||||
|  * Ancillary function that uses ioctl direction and size to copy from | ||||
|  * userspace. Then, it calls @func, and, if needed, data is copied back | ||||
|  * to userspace. | ||||
|  */ | ||||
| int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||||
| 		 int (*func)(struct file *file, unsigned int cmd, void *arg)); | ||||
| 
 | ||||
| /** generic DVB attach function. */ | ||||
| #if IS_ENABLED(CONFIG_I2C) | ||||
| 
 | ||||
| struct i2c_adapter; | ||||
| struct i2c_client; | ||||
| /**
 | ||||
|  * dvb_module_probe - helper routine to probe an I2C module | ||||
|  * | ||||
|  * @module_name: | ||||
|  *	Name of the I2C module to be probed | ||||
|  * @name: | ||||
|  *	Optional name for the I2C module. Used for debug purposes. | ||||
|  * 	If %NULL, defaults to @module_name. | ||||
|  * @adap: | ||||
|  *	pointer to &struct i2c_adapter that describes the I2C adapter where | ||||
|  *	the module will be bound. | ||||
|  * @addr: | ||||
|  *	I2C address of the adapter, in 7-bit notation. | ||||
|  * @platform_data: | ||||
|  *	Platform data to be passed to the I2C module probed. | ||||
|  * | ||||
|  * This function binds an I2C device into the DVB core. Should be used by | ||||
|  * all drivers that use I2C bus to control the hardware. A module bound | ||||
|  * with dvb_module_probe() should use dvb_module_release() to unbind. | ||||
|  * | ||||
|  * Return: | ||||
|  *	On success, return an &struct i2c_client, pointing to the bound | ||||
|  *	I2C device. %NULL otherwise. | ||||
|  * | ||||
|  * .. note:: | ||||
|  * | ||||
|  *    In the past, DVB modules (mainly, frontends) were bound via dvb_attach() | ||||
|  *    macro, with does an ugly hack, using I2C low level functions. Such | ||||
|  *    usage is deprecated and will be removed soon. Instead, use this routine. | ||||
|  */ | ||||
| struct i2c_client *dvb_module_probe(const char *module_name, | ||||
| 				    const char *name, | ||||
| 				    struct i2c_adapter *adap, | ||||
| 				    unsigned char addr, | ||||
| 				    void *platform_data); | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_module_release - releases an I2C device allocated with | ||||
|  *	 dvb_module_probe(). | ||||
|  * | ||||
|  * @client: pointer to &struct i2c_client with the I2C client to be released. | ||||
|  *	    can be %NULL. | ||||
|  * | ||||
|  * This function should be used to free all resources reserved by | ||||
|  * dvb_module_probe() and unbinding the I2C hardware. | ||||
|  */ | ||||
| void dvb_module_release(struct i2c_client *client); | ||||
| 
 | ||||
| #endif /* CONFIG_I2C */ | ||||
| 
 | ||||
| /* Legacy generic DVB attach function. */ | ||||
| #ifdef CONFIG_MEDIA_ATTACH | ||||
| /**
 | ||||
|  * dvb_attach - attaches a DVB frontend into the DVB core. | ||||
|  * | ||||
|  * @FUNCTION:	function on a frontend module to be called. | ||||
|  * @ARGS...:	@FUNCTION arguments. | ||||
|  * | ||||
|  * This ancillary function loads a frontend module in runtime and runs | ||||
|  * the @FUNCTION function there, with @ARGS. | ||||
|  * As it increments symbol usage cont, at unregister, dvb_detach() | ||||
|  * should be called. | ||||
|  * | ||||
|  * .. note:: | ||||
|  * | ||||
|  *    In the past, DVB modules (mainly, frontends) were bound via dvb_attach() | ||||
|  *    macro, with does an ugly hack, using I2C low level functions. Such | ||||
|  *    usage is deprecated and will be removed soon. Instead, you should use | ||||
|  *    dvb_module_probe(). | ||||
|  */ | ||||
| #define dvb_attach(FUNCTION, ARGS...) ({ \ | ||||
| 	void *__r = NULL; \ | ||||
| 	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ | ||||
| @@ -308,6 +452,14 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||||
| 	__r; \ | ||||
| }) | ||||
| 
 | ||||
| /**
 | ||||
|  * dvb_detach - detaches a DVB frontend loaded via dvb_attach() | ||||
|  * | ||||
|  * @FUNC:	attach function | ||||
|  * | ||||
|  * Decrements usage count for a function previously called via dvb_attach(). | ||||
|  */ | ||||
| 
 | ||||
| #define dvb_detach(FUNC)	symbol_put_addr(FUNC) | ||||
| 
 | ||||
| #else | ||||
| @@ -317,6 +469,6 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||||
| 
 | ||||
| #define dvb_detach(FUNC)	{} | ||||
| 
 | ||||
| #endif | ||||
| #endif	/* CONFIG_MEDIA_ATTACH */ | ||||
| 
 | ||||
| #endif /* #ifndef _DVBDEV_H_ */ | ||||
		Reference in New Issue
	
	Block a user