mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	Compare commits
	
		
			402 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 979cb7a237 | ||
|  | 7ce5232cd7 | ||
|  | 3f296bef62 | ||
|  | ad01e9f508 | ||
|  | e312df576c | ||
|  | 4b5cd433f9 | ||
|  | 6c068c0cc3 | ||
|  | 1488f326d0 | ||
|  | c86cb59638 | ||
|  | c78905d4a2 | ||
|  | 31589952a8 | ||
|  | 7eb5c6e658 | ||
|  | 172c6c93ba | ||
|  | f125fd503c | ||
|  | 0dd4f106ab | ||
|  | 60426304db | ||
|  | 00b0036b33 | ||
|  | 177e71d62a | ||
|  | 83a6dc3a1d | ||
|  | cc03d96de2 | ||
|  | 6336bd3689 | ||
|  | be79cec76e | ||
|  | 24801ab41a | ||
|  | 390f67c03b | ||
|  | fa4e3331d8 | ||
|  | 29cc552a6b | ||
|  | 42a0b65235 | ||
|  | b8abf46d06 | ||
|  | ce06e50881 | ||
|  | 22ffb0ecac | ||
|  | 92f2132d79 | ||
|  | 727fba48be | ||
|  | 09e8a15d78 | ||
|  | 45c9f076bd | ||
|  | 5c2757d581 | ||
|  | 817a464f4a | ||
|  | d627e6995f | ||
|  | ab4b0c8306 | ||
|  | c8c1ee1835 | ||
|  | 002f39787a | ||
|  | 871821d6a0 | ||
|  | 2a88d220e4 | ||
|  | e0539d5074 | ||
|  | 457cb550bb | ||
|  | d0793274d2 | ||
|  | ffe8764c01 | ||
|  | fb4f263aa3 | ||
|  | 0892a225d2 | ||
|  | 431dd4f5ee | ||
|  | e9ccab3578 | ||
|  | cdc5395996 | ||
|  | a5f3b75d0a | ||
|  | 69fcf5d649 | ||
|  | d5d63ea2ef | ||
|  | 4b69ae5399 | ||
|  | 1cf0526b24 | ||
|  | 73e8b9943e | ||
|  | 4b09ad7e42 | ||
|  | c39b234fd6 | ||
|  | c2f86b6438 | ||
|  | 6a3ef9873d | ||
|  | 98b466a2d3 | ||
|  | 78d30ff6ff | ||
|  | d849abd626 | ||
|  | 9517d698dc | ||
|  | 75821a6e3c | ||
|  | 2194f8e03a | ||
|  | d9a846d199 | ||
|  | 31a781c2e3 | ||
|  | 9b458a72de | ||
|  | e0fd8a0f35 | ||
|  | 1b49bfb8f1 | ||
|  | 4ce76407e2 | ||
|  | a6c53f5ece | ||
|  | 86579d353e | ||
|  | 63df691561 | ||
|  | 4aa7a68e21 | ||
|  | b6d2a37ac2 | ||
|  | 90e6d4806b | ||
|  | d995849fdb | ||
|  | b5bb500106 | ||
|  | 24b7f979c4 | ||
|  | be19cdb31d | ||
|  | 56afb2acc1 | ||
|  | 08b3218e5a | ||
|  | e17abdbbb9 | ||
|  | 811bea8010 | ||
|  | e89a868ad5 | ||
|  | f02b135bdb | ||
|  | 8bda007f05 | ||
|  | ec655e1438 | ||
|  | b606a7b2b2 | ||
|  | 81793729e6 | ||
|  | 3757c4671e | ||
|  | 719ac4d231 | ||
|  | a3c6b5acc1 | ||
|  | 8986494cd3 | ||
|  | eeb013e0fa | ||
|  | 7f40a54b39 | ||
|  | 1518ba54a4 | ||
|  | a97787c3b6 | ||
|  | d676919e72 | ||
|  | fbc39f71f4 | ||
|  | 19eea5d42d | ||
|  | b23187a049 | ||
|  | 0165538f13 | ||
|  | 0b9d3ffa6b | ||
|  | 61fd25836f | ||
|  | d4aa1c634e | ||
|  | 5bb0a95b02 | ||
|  | 0a5fb7d6b9 | ||
|  | fd21dbbd5e | ||
|  | f7fcc1511d | ||
|  | 37ae102d57 | ||
|  | 66b1cf3623 | ||
|  | 7f002f1356 | ||
|  | 418bd83b40 | ||
|  | ccc13aed48 | ||
|  | 442b1c3bf6 | ||
|  | c23435e275 | ||
|  | 0fe2c2feb3 | ||
|  | 8f5af7742d | ||
|  | 4a93d1056a | ||
|  | 309713674c | ||
|  | bfddf62f64 | ||
|  | 2b0e5eb9d2 | ||
|  | 1d96274993 | ||
|  | 3ff4d900a5 | ||
|  | e1e569975f | ||
|  | b9998ee9e2 | ||
|  | dfe6b385a9 | ||
|  | 6e926c1452 | ||
|  | 8039097426 | ||
|  | f3d5adc777 | ||
|  | e974925430 | ||
|  | 23bdd90595 | ||
|  | 7bafb76461 | ||
|  | 9cde52a6d8 | ||
|  | 50e354c49a | ||
|  | 03d84ba75a | ||
|  | c4f82de8b0 | ||
|  | a5ad0b0584 | ||
|  | 3cb3df51cf | ||
|  | 2311b94970 | ||
|  | f12fe91b51 | ||
|  | 35c283bf2f | ||
|  | 41a9626be4 | ||
|  | 0d66d5bab0 | ||
|  | 91af1be97e | ||
|  | a6c3b82f83 | ||
|  | e863a2037a | ||
|  | 92cd675f5d | ||
|  | dda8698514 | ||
|  | fc9a89c870 | ||
|  | 4b0a0c4ff2 | ||
|  | 2ac970ef83 | ||
|  | c3c734b0e8 | ||
|  | 8380cb185f | ||
|  | f9eb03a065 | ||
|  | f8c97ad3d6 | ||
|  | 60646a6b26 | ||
|  | de0e970999 | ||
|  | cf35c3038b | ||
|  | 4c96f54ddf | ||
|  | eb427a8df2 | ||
|  | b200ce3596 | ||
|  | 31f36de0d7 | ||
|  | 9269270c79 | ||
|  | 04fa5041d3 | ||
|  | 8f4cd19539 | ||
|  | f3cbbf3ba7 | ||
|  | a2d39f90d5 | ||
|  | 7af71dfdcb | ||
|  | acb5931ed0 | ||
|  | 476a105de7 | ||
|  | b025599e9f | ||
|  | 9028e75f63 | ||
|  | 177e6b0fd6 | ||
|  | de82a50b4e | ||
|  | 5714b85238 | ||
|  | 01ca1b8805 | ||
|  | 28e09191af | ||
|  | abb2c56ddc | ||
|  | c6ada48892 | ||
|  | baf6a090b8 | ||
|  | d259d69808 | ||
|  | f72c7b2256 | ||
|  | c82c9d3218 | ||
|  | 1598ab98bc | ||
|  | 7efa935a30 | ||
|  | fc728ab51e | ||
|  | ea41e57ba3 | ||
|  | cd3868afff | ||
|  | b72f0365ea | ||
|  | b3f2580e84 | ||
|  | f1976b5f74 | ||
|  | ee6787d2d0 | ||
|  | 37eb11fb4b | ||
|  | a276a370cb | ||
|  | 1863ad2270 | ||
|  | 8b787bbc0d | ||
|  | e5e6e44b76 | ||
|  | cfbe430b4a | ||
|  | 2a1b96a6ad | ||
|  | 7d8a151127 | ||
|  | cbfd9b18ea | ||
|  | bfa8cec850 | ||
|  | e413baeab9 | ||
|  | 46c42c6ef0 | ||
|  | 4b053c68ef | ||
|  | 46a4f7476a | ||
|  | 65b3128cbe | ||
|  | 22c52fbf86 | ||
|  | 766ca0e652 | ||
|  | 4459f50538 | ||
|  | b0e1770268 | ||
|  | 9b50e3bdc7 | ||
|  | 3b1fcec9e1 | ||
|  | 0a9fd4c2e1 | ||
|  | b1b3e92a50 | ||
|  | 50fe2d6ebe | ||
|  | 1d3e21894c | ||
|  | 0e13bdcb08 | ||
|  | d2e6c9b2cb | ||
|  | 55aec3cf72 | ||
|  | c93f96b6ec | ||
|  | 310a5e0f05 | ||
|  | 22475860d5 | ||
|  | a375cd1716 | ||
|  | e0e9b82f5a | ||
|  | b60efcdaad | ||
|  | 527f6a47a3 | ||
|  | 16909b37a0 | ||
|  | d808f1d37a | ||
|  | b46b89d4b5 | ||
|  | 1b11064b83 | ||
|  | 072689735c | ||
|  | 8e39e291a0 | ||
|  | 97a88de738 | ||
|  | 7f19a0c04b | ||
|  | 83f5b45928 | ||
|  | dc300198a9 | ||
|  | 4747cbd553 | ||
|  | ddac58d082 | ||
|  | 982dc4d366 | ||
|  | bb5e9e7f39 | ||
|  | ed8bb5af82 | ||
|  | 67a13e4f34 | ||
|  | cbf73572b7 | ||
|  | c1100645be | ||
|  | d20457544e | ||
|  | 54e8bb1575 | ||
|  | ee6eab9ead | ||
|  | 93335e856e | ||
|  | 5138ba3f91 | ||
|  | 02329a7d55 | ||
|  | 8c950053a7 | ||
|  | 5abf74a952 | ||
|  | b43160a03a | ||
|  | 938090b5e6 | ||
|  | 5f648d7a02 | ||
|  | 83cfff7082 | ||
|  | 03cc9ae142 | ||
|  | ed5f89a0c4 | ||
|  | 5b17d32804 | ||
|  | 6e57fd96b9 | ||
|  | ade4caa718 | ||
|  | aa1b5369ac | ||
|  | b946de7e44 | ||
|  | 0522573b46 | ||
|  | 2610424e1c | ||
|  | b3848a362d | ||
|  | fe80bc1154 | ||
|  | b185b5fb66 | ||
|  | 75a4a733f2 | ||
|  | a5d0a9718b | ||
|  | 2c6530aa8d | ||
|  | 74e040f020 | ||
|  | ee3e352c0c | ||
|  | e4b1c1a077 | ||
|  | e9f2f5788c | ||
|  | e736554ff0 | ||
|  | 1b9d2782ba | ||
|  | 569674e427 | ||
|  | 154ea8f3c9 | ||
|  | 5a536040b5 | ||
|  | 2886f9daef | ||
|  | 86eaeed6c1 | ||
|  | 71fc781e4b | ||
|  | 44d5488c4a | ||
|  | f11ed620f2 | ||
|  | 2186362136 | ||
|  | d2337b6620 | ||
|  | e3da57495f | ||
|  | ca24ca8029 | ||
|  | e0481f37bb | ||
|  | 1784a361ad | ||
|  | 7925537b58 | ||
|  | 960ee48a10 | ||
|  | 4ce013bbb7 | ||
|  | 1a41b8af21 | ||
|  | 269e66ddca | ||
|  | 11bd28ea82 | ||
|  | 3422b8d138 | ||
|  | 60b374ac2a | ||
|  | 1fa617abef | ||
|  | 1b849c6ef2 | ||
|  | ab0f16099b | ||
|  | 2e392cfe43 | ||
|  | a19a066b39 | ||
|  | d3d574c13c | ||
|  | 8b0550222d | ||
|  | 123e46e7a9 | ||
|  | a153bfd7b2 | ||
|  | 0cc91fbe5f | ||
|  | b86ea4524f | ||
|  | d293b9a702 | ||
|  | 35e0de3968 | ||
|  | 4196458803 | ||
|  | 83344e1349 | ||
|  | 9c462b89ec | ||
|  | bf8460adfb | ||
|  | 5ccf01a7f5 | ||
|  | 78866a12b4 | ||
|  | ecc5aeb15a | ||
|  | 1cb42ad5bf | ||
|  | 36e3205574 | ||
|  | 5d1fdcb961 | ||
|  | a8c7d06316 | ||
|  | 31a833acfd | ||
|  | e7f6f67a49 | ||
|  | 4de414351c | ||
|  | 565cf88969 | ||
|  | d5c6dc7905 | ||
|  | 710d08c5a9 | ||
|  | 0595603734 | ||
|  | 1064f47fd9 | ||
|  | f2ca278710 | ||
|  | f57b5c8b20 | ||
|  | d350eef406 | ||
|  | cb24f29e84 | ||
|  | e68df13ad0 | ||
|  | 0248e43bc7 | ||
|  | 040a1c58b6 | ||
|  | 4783d0eab2 | ||
|  | ad0d1316a7 | ||
|  | 8cab284a65 | ||
|  | c0af1d7e45 | ||
|  | ab59d9b705 | ||
|  | e746d013ec | ||
|  | 16b15dfcc0 | ||
|  | af0a513d12 | ||
|  | da39fb4c0d | ||
|  | 1d4fa8f5a3 | ||
|  | 2508919151 | ||
|  | 2e3c59ecc3 | ||
|  | 6e5dc4e367 | ||
|  | 3bba565cc5 | ||
|  | a6f981eb04 | ||
|  | d422786f00 | ||
|  | 530f9d130a | ||
|  | f2d3efd577 | ||
|  | 4e95332ced | ||
|  | 6d09ef98fc | ||
|  | 3c3430cdbc | ||
|  | 46641db50e | ||
|  | e360182847 | ||
|  | 6e39d83c7b | ||
|  | e73ae1a4c6 | ||
|  | e554de3138 | ||
|  | 1672bdfcb8 | ||
|  | 0b042c1fc3 | ||
|  | 89401e8478 | ||
|  | a783a02679 | ||
|  | e11c70c118 | ||
|  | c914fc9b13 | ||
|  | 67f0820a53 | ||
|  | 448b07091d | ||
|  | dc45a08c10 | ||
|  | 0fa1f815c5 | ||
|  | bbb551ce8a | ||
|  | 21aefddd4b | ||
|  | 42a0b24511 | ||
|  | 405eb3e5b4 | ||
|  | 0d8987862f | ||
|  | 010cdf1ce8 | ||
|  | f17d1e8ee1 | ||
|  | 821793ec96 | ||
|  | f670b28603 | ||
|  | 7e0b402256 | ||
|  | 065dd1a238 | ||
|  | f291491231 | ||
|  | 03ce6c980c | ||
|  | b52eb4bd17 | ||
|  | bf3cad1094 | ||
|  | bc2e1a39ff | ||
|  | 21f00bd922 | ||
|  | 6089b4f5c2 | ||
|  | 8521ce4753 | ||
|  | 06aecc3d66 | ||
|  | e6b06c1f3d | ||
|  | cf77db4fcd | 
							
								
								
									
										6
									
								
								Kbuild
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Kbuild
									
									
									
									
									
								
							| @@ -2,6 +2,12 @@ | ||||
| # Makefile for the kernel multimedia device drivers. | ||||
| # | ||||
|  | ||||
| ifeq ($(KERNEL_DVB_CORE),y) | ||||
| obj-y        := ddbridge/       \ | ||||
| 		frontends/ | ||||
|  | ||||
| else | ||||
| obj-y        := dvb-core/	\ | ||||
| 		ddbridge/       \ | ||||
| 		frontends/ | ||||
| endif | ||||
							
								
								
									
										27
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,21 +1,40 @@ | ||||
| kernelver ?= $(shell uname -r) | ||||
| MDIR	?= | ||||
| 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) | ||||
|  | ||||
| ifeq ($(KERNEL_DVB_CORE),y) | ||||
| DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD) -DKERNEL_DVB_CORE=y" | ||||
| else | ||||
| DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux" | ||||
| endif | ||||
|  | ||||
| all:  | ||||
| 	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules | ||||
| 	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC) | ||||
| 	$(MAKE) -C apps | ||||
|  | ||||
| libdddvb: | ||||
| 	$(MAKE) -C lib | ||||
|  | ||||
| libdddvb-install: | ||||
| 	$(MAKE) -C lib install | ||||
|  | ||||
| libdddvb-clean: | ||||
| 	$(MAKE) -C lib clean | ||||
|  | ||||
| dep: | ||||
| 	DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep) | ||||
| 	DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep) | ||||
|  | ||||
| install: all | ||||
| 	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install | ||||
| 	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) INSTALL_MOD_PATH=$(MDIR) modules_install | ||||
| 	depmod $(kernelver) | ||||
|  | ||||
| clean: | ||||
| 	rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules* | ||||
| 	$(MAKE) -C apps clean | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,9 @@ We can only accept patches which don't break compilation for older kernels (as f | ||||
| Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain | ||||
| incompatiblities to this driver package. | ||||
|  | ||||
| For installation instructions see: | ||||
|  | ||||
| http://support.digital-devices.eu/index.php?article=152 | ||||
| ### Prepare for Building | ||||
|  | ||||
|    TBD | ||||
|   | ||||
| @@ -1,4 +1,20 @@ | ||||
| all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 | ||||
| TARGETS = cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq modtest | ||||
|  | ||||
| all: $(TARGETS)  | ||||
|  | ||||
| CFLAGS =  -g -Wall -Wno-unused  -Wno-format | ||||
| FFMPEG := $(shell command -v ffmpeg 2> /dev/null) | ||||
|  | ||||
| modtest: modtest.c | ||||
| 	$(CC) -o modtest modtest.c -I../include/ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE | ||||
|  | ||||
| test.ts: | ||||
| ifndef FFMPEG | ||||
| 	$(error "ffmpeg is not available please install to create test.ts") | ||||
| endif | ||||
| 	ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30  \ | ||||
| 	-f lavfi -i sine=f=440:b=4  -shortest   -metadata \ | ||||
| 	service_provider="DD"      -metadata service_name="Test" test.ts | ||||
|  | ||||
| cit: cit.c | ||||
| 	$(CC) -o cit cit.c -lpthread | ||||
| @@ -15,6 +31,22 @@ setmod2: setmod2.c | ||||
| setmod3: setmod3.c | ||||
| 	$(CC) -o setmod3 setmod3.c -I../include/ | ||||
|  | ||||
| %.o: %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ $< | ||||
| modconfig: modconfig.c | ||||
| 	$(CC) -o modconfig modconfig.c -I../include/ | ||||
|  | ||||
| clean: | ||||
| 	rm cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq | ||||
|  | ||||
| %: %.c | ||||
| 	$(CC) $(CFLAGS) -I../ddbridge  -I../include/ $< -o $@ | ||||
|  | ||||
| %.o: %.c | ||||
| 	$(CC) $(CFLAGS) -I../ddbridge -o $@ $< | ||||
|  | ||||
|  | ||||
| clean: | ||||
| 	for f in $(TARGETS) *.o *~ ; do \ | ||||
| 		if [ -e "$$f" ]; then \ | ||||
| 			rm "$$f" || exit 1; \ | ||||
| 		fi \ | ||||
| 	done | ||||
|   | ||||
							
								
								
									
										16
									
								
								apps/cit.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								apps/cit.c
									
									
									
									
									
								
							| @@ -27,6 +27,7 @@ uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10, | ||||
|    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | ||||
| 		   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; | ||||
|  | ||||
| #if 0 | ||||
| uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00, | ||||
|    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | ||||
|    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | ||||
| @@ -40,6 +41,21 @@ uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00, | ||||
|    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | ||||
|    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | ||||
| 		   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; | ||||
| #else | ||||
| uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, | ||||
|    0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, | ||||
|    0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, | ||||
|    0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, | ||||
|    0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, | ||||
|    0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, | ||||
| 		   0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa }; | ||||
| #endif | ||||
|  | ||||
| void proc_buf(uint8_t *buf, uint32_t *d) | ||||
| { | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| #include <sys/ioctl.h> | ||||
| #include <linux/dvb/dmx.h> | ||||
| #include <linux/dvb/frontend.h> | ||||
| #include <linux/dvb/video.h> | ||||
|  | ||||
| void proc_ts(int i, uint8_t *buf) | ||||
| { | ||||
|   | ||||
							
								
								
									
										544
									
								
								apps/ddinfo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										544
									
								
								apps/ddinfo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,544 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <linux/types.h> | ||||
| #include <getopt.h> | ||||
|  | ||||
| typedef uint8_t u8; | ||||
| typedef uint16_t u16; | ||||
| typedef int16_t s16; | ||||
| typedef uint32_t u32; | ||||
| typedef uint64_t u64; | ||||
|  | ||||
| #include "../ddbridge/ddbridge-mci.h" | ||||
| #include "../ddbridge/ddbridge-ioctl.h" | ||||
|  | ||||
| char *Rolloff[8] = { | ||||
| 	"0.35", | ||||
| 	"0.25", | ||||
| 	"0.20", | ||||
| 	"0.10", | ||||
| 	"0.05", | ||||
| 	"0.15", | ||||
| 	"rsvd", | ||||
| 	"rsvd", | ||||
| }; | ||||
|  | ||||
| void dump(const uint8_t *b, int l) | ||||
| { | ||||
| 	int i, j; | ||||
| 	 | ||||
| 	for (j = 0; j < l; j += 16, b += 16) { | ||||
| 		printf("%04x: ", j); | ||||
| 		for (i = 0; i < 16; i++) | ||||
| 			if (i + j < l) | ||||
| 				printf("%02x ", b[i]); | ||||
| 			else | ||||
| 				printf("   "); | ||||
| 		printf("\n"); | ||||
| 	} | ||||
| }        | ||||
|  | ||||
| void print_temp(struct mci_result *res) | ||||
| { | ||||
| 	printf("Die temperature = %u\n", res->sx8_bist.temperature); | ||||
| } | ||||
|  | ||||
| int temp_info(int dev, uint32_t link) | ||||
| { | ||||
| 	struct ddb_mci_msg msg = { | ||||
| 		.link = link, | ||||
| 		.cmd.command = SX8_CMD_GETBIST, | ||||
| 	}; | ||||
| 	int ret; | ||||
| 	int i; | ||||
| 	 | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("Error: %d %d\n", ret, errno); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (msg.res.status & 0x80) { | ||||
| 		printf("MCI errror %02x\n", msg.res.status); | ||||
| 		return ret; | ||||
| 	} | ||||
| 		 | ||||
| 	print_temp(&msg.res); | ||||
| 	printf("BIST info dump:  "); | ||||
| 	dump((uint8_t *) &msg.res, 16); | ||||
| 	 | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| #define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0])) | ||||
|  | ||||
| char *DemodStatus[] = { | ||||
|     "Idle", | ||||
|     "IQ Mode", | ||||
|     "Wait for Signal", | ||||
|     "DVB-S2 Wait for MATYPE", | ||||
|     "DVB-S2 Wait for FEC", | ||||
|     "DVB-S1 Wait for FEC", | ||||
|     "Wait for TS", | ||||
|     "Unknown 7", | ||||
|     "Unknown 8", | ||||
|     "Unknown 9", | ||||
|     "Unknown 10", | ||||
|     "Unknown 11", | ||||
|     "Unknown 12", | ||||
|     "Unknown 13", | ||||
|     "Timeout", | ||||
|     "Locked", | ||||
|     "C2 Scan", | ||||
| }; | ||||
|  | ||||
| char* S2ModCods[32] = { | ||||
| /* 0x00 */    "DummyPL"     ,  | ||||
|  | ||||
| // Legacy S2:   index is S2_Modcod * 2 + short | ||||
|  | ||||
| /* 0x01 */    "QPSK 1/4"    , | ||||
| /* 0x02 */    "QPSK 1/3"    , | ||||
| /* 0x03 */    "QPSK 2/5"    , | ||||
| /* 0x04 */    "QPSK 1/2"    , | ||||
| /* 0x05 */    "QPSK 3/5"    , | ||||
| /* 0x06 */    "QPSK 2/3"    , | ||||
| /* 0x07 */    "QPSK 3/4"    , | ||||
| /* 0x08 */    "QPSK 4/5"    , | ||||
| /* 0x09 */    "QPSK 5/6"    , | ||||
| /* 0x0A */    "QPSK 8/9"    , | ||||
| /* 0x0B */    "QPSK 9/10"   , | ||||
|                               | ||||
| /* 0x0C */    "8PSK 3/5"    , | ||||
| /* 0x0D */    "8PSK 2/3"    , | ||||
| /* 0x0E */    "8PSK 3/4"    , | ||||
| /* 0x0F */    "8PSK 5/6"    , | ||||
| /* 0x10 */    "8PSK 8/9"    , | ||||
| /* 0x11 */    "8PSK 9/10"   , | ||||
|                               | ||||
| /* 0x12 */    "16APSK 2/3"  , | ||||
| /* 0x13 */    "16APSK 3/4"  , | ||||
| /* 0x14 */    "16APSK 4/5"  , | ||||
| /* 0x15 */    "16APSK 5/6"  , | ||||
| /* 0x16 */    "16APSK 8/9"  , | ||||
| /* 0x17 */    "16APSK 9/10" , | ||||
|                               | ||||
| /* 0x18 */    "32APSK 3/4"  , | ||||
| /* 0x19 */    "32APSK 4/5"  , | ||||
| /* 0x1A */    "32APSK 5/6"  , | ||||
| /* 0x1B */    "32APSK 8/9"  , | ||||
| /* 0x1C */    "32APSK 9/10" , | ||||
|                               | ||||
| /* 0x1D */    "rsvd 0x1D"   , | ||||
| /* 0x1E */    "rsvd 0x1E"   , | ||||
| /* 0x1F */    "rsvd 0x1F"   , | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///* 129 */    "VLSNR1"          ,   | ||||
| ///* 131 */    "VLSNR2"          ,   | ||||
|  | ||||
| char* S2XModCods[59] = { | ||||
| /* 0x42 */    "QPSK 13/45"      ,  | ||||
| /* 0x43 */    "QPSK 9/20"       ,  | ||||
| /* 0x44 */    "QPSK 11/20"      ,  | ||||
|                                    | ||||
| /* 0x45 */    "8APSK 5/9-L"     ,  | ||||
| /* 0x46 */    "8APSK 26/45-L"   ,  | ||||
| /* 0x47 */    "8PSK 23/36"      ,  | ||||
| /* 0x48 */    "8PSK 25/36"      ,  | ||||
| /* 0x49 */    "8PSK 13/18"      ,  | ||||
|                                    | ||||
| /* 0x4A */    "16APSK 1/2-L"    ,  | ||||
| /* 0x4B */    "16APSK 8/15-L"   ,  | ||||
| /* 0x4C */    "16APSK 5/9-L"    ,  | ||||
| /* 0x4D */    "16APSK 26/45"    ,  | ||||
| /* 0x4E */    "16APSK 3/5"      ,  | ||||
| /* 0x4F */    "16APSK 3/5-L"    ,  | ||||
| /* 0x50 */    "16APSK 28/45"    ,  | ||||
| /* 0x51 */    "16APSK 23/36"    ,  | ||||
| /* 0x52 */    "16APSK 2/3-L"    ,  | ||||
| /* 0x53 */    "16APSK 25/36"    ,  | ||||
| /* 0x54 */    "16APSK 13/18"    ,  | ||||
|                                    | ||||
| /* 0x55 */    "16APSK 7/9"      ,  | ||||
| /* 0x56 */    "16APSK 77/90"    ,  | ||||
|                                    | ||||
| /* 0x57 */    "32APSK 2/3-L"    ,  | ||||
| /* 0x58 */    "rsvd 32APSK"     ,  | ||||
| /* 0x59 */    "32APSK 32/45"    ,  | ||||
| /* 0x5A */    "32APSK 11/15"    ,  | ||||
| /* 0x5B */    "32APSK 7/9"      ,  | ||||
|                                    | ||||
| /* 0x5C */    "64APSK 32/45-L"  ,  | ||||
| /* 0x5D */    "64APSK 11/15"    ,  | ||||
| /* 0x5E */    "rsvd 64APSK"     ,  | ||||
| /* 0x5F */    "64APSK 7/9"      ,  | ||||
|                                    | ||||
| /* 0x60 */    "rsvd 64APSK"     ,  | ||||
| /* 0x61 */    "64APSK 4/5"      ,  | ||||
| /* 0x62 */    "rsvd 64APSK"     ,  | ||||
| /* 0x63 */    "64APSK 5/6"      ,  | ||||
|                                    | ||||
| /* 0x64 */    "128APSK 3/4"     ,  | ||||
| /* 0x65 */    "128APSK 7/9"     ,  | ||||
|  | ||||
| /* 0x66 */    "256APSK 29/45-L" ,  | ||||
| /* 0x67 */    "256APSK 2/3-L"   ,  | ||||
| /* 0x68 */    "256APSK 31/45-L" ,  | ||||
| /* 0x69 */    "256APSK 32/45"   ,  | ||||
| /* 0x6A */    "256APSK 11/15-L" ,  | ||||
| /* 0x6B */    "256APSK 3/4"     ,  | ||||
|  | ||||
| /* 0x6C */    "QPSK 11/45-S"    , | ||||
| /* 0x6D */    "QPSK 4/15-S"     , | ||||
| /* 0x6E */    "QPSK 14/45-S"    , | ||||
| /* 0x6F */    "QPSK 7/15-S"     , | ||||
| /* 0x70 */    "QPSK 8/15-S"     , | ||||
| /* 0x71 */    "QPSK 32/45-S"    , | ||||
|                                   | ||||
| /* 0x72 */    "8PSK 7/15-S"     , | ||||
| /* 0x73 */    "8PSK 8/15-S"     , | ||||
| /* 0x74 */    "8PSK 26/45-S"    , | ||||
| /* 0x75 */    "8PSK 32/45-S"    , | ||||
|                                   | ||||
| /* 0x76 */    "16APSK 7/15-S"   , | ||||
| /* 0x77 */    "16APSK 8/15-S"   , | ||||
| /* 0x78 */    "16APSK 26/45-S"  , | ||||
| /* 0x79 */    "16APSK 3/5-S"    , | ||||
| /* 0x7A */    "16APSK 32/45-S"  , | ||||
|                                   | ||||
| /* 0x7B */    "32APSK 2/3-S"    , | ||||
| /* 0x7C */    "32APSK 32/45-S"  , | ||||
| }; | ||||
|  | ||||
| char* S2Xrsvd[] = { | ||||
| /* 250 */    "rsvd 8PSK"       , | ||||
| /* 251 */    "rsvd 16APSK"     , | ||||
| /* 252 */    "rsvd 32APSK"     , | ||||
| /* 253 */    "rsvd 64APSK"     , | ||||
| /* 254 */    "rsvd 256APSK"    , | ||||
| /* 255 */    "rsvd 1024APSK"   , | ||||
| }; | ||||
|  | ||||
| char* PunctureRates[32] = { | ||||
| /* 0x00 */    "QPSK 1/2",   // DVB-S1  | ||||
| /* 0x01 */    "QPSK 2/3",   // DVB-S1  | ||||
| /* 0x02 */    "QPSK 3/4",   // DVB-S1  | ||||
| /* 0x03 */    "QPSK 5/6",   // DVB-S1  | ||||
| /* 0x04 */    "QPSK 6/7",   // DSS | ||||
| /* 0x05 */    "QPSK 7/8",   // DVB-S1  | ||||
| /* 0x06 */    "rsvd 6.0", | ||||
| /* 0x07 */    "rsvd 7.0", | ||||
| }; | ||||
|  | ||||
| int mci_bb(int dev, uint32_t link, uint8_t demod) | ||||
| { | ||||
| 	struct ddb_mci_msg msg = { | ||||
| 		.link = link, | ||||
| 		.cmd.command = MCI_CMD_GET_BBHEADER, | ||||
| 		.cmd.demod = demod, | ||||
| 		.cmd.get_bb_header.select = 0, | ||||
| 	}; | ||||
| 	struct mci_result *res = &msg.res; | ||||
| 	int ret; | ||||
| 	int i; | ||||
| 	 | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("Error: %d %d\n", ret, errno); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (res->bb_header.valid) { | ||||
| 		printf("MATYPE1: %02x\n", res->bb_header.matype_1); | ||||
| 		printf("MATYPE2: %02x\n", res->bb_header.matype_2); | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res) | ||||
| { | ||||
| 	if (res->status == MCI_DEMOD_STOPPED) { | ||||
| 		printf("\nDemod %u: stopped\n", demod); | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	printf("\nDemod %u:\n", demod); | ||||
| 	if (res->status == MCI_DEMOD_LOCKED) { | ||||
| 		switch (res->mode) { | ||||
| 		case 0: | ||||
| 		case M4_MODE_DVBSX: | ||||
| 			if (res->dvbs2_signal_info.standard != 1) { | ||||
| 				int short_frame = 0, pilots = 0; | ||||
| 				char *modcod = "unknown"; | ||||
| 				uint8_t pls = res->dvbs2_signal_info.pls_code; | ||||
| 				 | ||||
| 				if ((pls >= 128) || ((res->dvbs2_signal_info.roll_off & 0x7f) > 2)) | ||||
| 					printf("Demod Locked:  DVB-S2X\n"); | ||||
| 				else | ||||
| 					printf("Demod Locked:  DVB-S2\n"); | ||||
| 				printf("PLS-Code:      %u\n", res->dvbs2_signal_info.pls_code); | ||||
| 				mci_bb(dev, link, demod); | ||||
| 				if (pls >= 250)  { | ||||
| 					pilots = 1; | ||||
| 					modcod = S2Xrsvd[pls - 250]; | ||||
| 				} else if (pls >= 132) { | ||||
| 					pilots = pls & 1; | ||||
| 					short_frame = pls > 216; | ||||
| 					modcod = S2XModCods[(pls - 132)/2]; | ||||
| 				} else if (pls < 128) { | ||||
| 					pilots = pls & 1; | ||||
| 					short_frame = pls & 2; | ||||
| 					modcod = S2ModCods[pls / 4]; | ||||
| 				} | ||||
| 				printf("Roll-Off:      %s\n", Rolloff[res->dvbs2_signal_info.roll_off & 7]); | ||||
| 				printf("Pilots:        %s\n", pilots ? "On" : "Off"); | ||||
| 				printf("Frame:         %s\n", short_frame ? "Short" : "Normal"); | ||||
| 			} else { | ||||
| 				printf("Demod Locked:  DVB-S\n"); | ||||
| 				printf("PR:            %s\n", | ||||
| 				       PunctureRates[res->dvbs2_signal_info.pls_code & 0x07]); | ||||
| 			} | ||||
| 			printf("Inversion:     %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off"); | ||||
| 			break; | ||||
| 		case M4_MODE_DVBT: | ||||
| 			printf("Locked DVB-T\n"); | ||||
| 			break; | ||||
| 		case M4_MODE_DVBT2: | ||||
| 			printf("Locked DVB-T2\n"); | ||||
| 			break; | ||||
| 		} | ||||
| 		printf("SNR:           %.2f dB\n", (float) res->dvbs2_signal_info.signal_to_noise / 100); | ||||
| 		printf("Packet Errors: %u\n", res->dvbs2_signal_info.packet_errors); | ||||
| 		printf("BER Numerator: %u\n", res->dvbs2_signal_info.ber_numerator); | ||||
| 		printf("BER Denom.:    %u\n", res->dvbs2_signal_info.ber_denominator); | ||||
| 	} else { | ||||
| 		printf("Demod State:   %s\n", | ||||
| 		       res->status < SIZE_OF_ARRAY(DemodStatus) ? DemodStatus[res->status] : "?"); | ||||
| 		 | ||||
| 	} | ||||
| 	printf("Frequency:     %u Hz\n", res->dvbs2_signal_info.frequency); | ||||
| 	printf("Symbol Rate:   %u Symbols/s\n", res->dvbs2_signal_info.symbol_rate); | ||||
| 	printf("Channel Power: %.2f dBm\n", (float) res->dvbs2_signal_info.channel_power / 100); | ||||
| 	if (res->dvbs2_signal_info.band_power > -10000) | ||||
| 		printf("Band Power:    %.2f dBm\n", (float) res->dvbs2_signal_info.band_power / 100); | ||||
| 	 | ||||
| } | ||||
|  | ||||
| int readreg(int dev, uint32_t reg, uint32_t link, uint32_t *val) | ||||
| { | ||||
| 	struct ddb_reg ddbreg; | ||||
|  | ||||
|         ddbreg.reg =  reg + (link << 28); | ||||
| 	if (ioctl(dev, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||
| 		return -1; | ||||
| 	*val = ddbreg.val; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void mci_firmware(int dev, uint32_t link) | ||||
| { | ||||
| 	union { | ||||
| 		uint32_t u[4]; | ||||
| 		char  s[16]; | ||||
| 	} version; | ||||
| 	 | ||||
| 	readreg(dev, MIC_INTERFACE_VER     , link, &version.u[0]); | ||||
| 	readreg(dev, MIC_INTERFACE_VER +  4, link, &version.u[1]); | ||||
| 	readreg(dev, MIC_INTERFACE_VER +  8, link, &version.u[2]); | ||||
| 	readreg(dev, MIC_INTERFACE_VER + 12, link, &version.u[3]); | ||||
|      | ||||
| 	printf("MCI firmware: %s.%d\n", &version.s, version.s[15]); | ||||
| } | ||||
|  | ||||
|  | ||||
| int mci_info(int dev, uint32_t link, uint8_t demod) | ||||
| { | ||||
| 	struct ddb_mci_msg msg = { | ||||
| 		.link = link, | ||||
| 		.cmd.command = MCI_CMD_GETSIGNALINFO, | ||||
| 		.cmd.demod = demod | ||||
| 	}; | ||||
| 	int ret; | ||||
| 	int i; | ||||
| 	 | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("Error: %d %d\n", ret, errno); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	print_info(dev, link, demod, &msg.res); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int get_id(int fd, int link, struct ddb_id *id) | ||||
| { | ||||
| 	struct ddb_reg ddbreg; | ||||
|  | ||||
| 	if (link == 0) { | ||||
| 		if (ioctl(fd, IOCTL_DDB_ID, id) < 0) | ||||
| 			return -1; | ||||
| 		return 0; | ||||
| 	} | ||||
|         ddbreg.reg = 8 + (link << 28); | ||||
| 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||
| 		return -1; | ||||
| 	id->vendor = ddbreg.val; | ||||
| 	id->device = ddbreg.val >> 16; | ||||
|  | ||||
|         ddbreg.reg = 12 + (link << 28); | ||||
| 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||
| 		return -1; | ||||
| 	id->subvendor = ddbreg.val; | ||||
| 	id->subdevice = ddbreg.val >> 16; | ||||
|  | ||||
|         ddbreg.reg = 0 + (link << 28); | ||||
| 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||
| 		return -1; | ||||
| 	id->hw = ddbreg.val; | ||||
|  | ||||
| 	ddbreg.reg = 4 + (link << 28); | ||||
| 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||
| 		return -1; | ||||
| 	id->regmap = ddbreg.val; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static char *id2name(uint16_t id) | ||||
| { | ||||
| 	switch (id) { | ||||
| 	case 0x222: | ||||
| 		return "MOD"; | ||||
| 	case 0x0009: | ||||
| 		return "MAX SX8"; | ||||
| 	case 0x000b: | ||||
| 		return "MAX SX8 Basic"; | ||||
| 	case 0x000a: | ||||
| 		return "MAX M4"; | ||||
| 	default: | ||||
| 		return " "; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int card_info(int ddbnum, int demod) | ||||
| { | ||||
| 	char ddbname[80]; | ||||
| 	struct ddb_id ddbid; | ||||
| 	int ddb, ret, link, links = 1, i; | ||||
| 	struct ddb_id id; | ||||
| 	 | ||||
| 	sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum); | ||||
| 	ddb = open(ddbname, O_RDWR); | ||||
| 	if (ddb < 0) | ||||
| 		return -3; | ||||
|  | ||||
| 	for (link = 0; link < links; link++) { | ||||
| 		ret = get_id(ddb, link, &id); | ||||
| 		if (ret < 0) | ||||
| 			goto out; | ||||
| 		if (!link) { | ||||
| 			switch (id.device) { | ||||
| 			case 0x20: | ||||
| 				links = 4; | ||||
| 				break; | ||||
| 			case 0x300: | ||||
| 			case 0x301: | ||||
| 			case 0x307: | ||||
| 				links = 2; | ||||
| 				break; | ||||
| 			 | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		printf("\n\nCard %s link %u id %04x (%s):\n", | ||||
| 		       ddbname, link, id.device, id2name(id.device)); | ||||
| 		printf("HW %08x REGMAP %08x FW %u.%u\n", | ||||
| 		       id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff)); | ||||
| 		switch (id.device) { | ||||
| 		case 0x0009: | ||||
| 			mci_firmware(ddb, link); | ||||
| 			if (demod >= 0) | ||||
| 				mci_info(ddb, link, demod); | ||||
| 			else { | ||||
| 				for (i = 0; i < 8; i++) | ||||
| 					mci_info(ddb, link, i); | ||||
| 			} | ||||
| 			temp_info(ddb, link); | ||||
| 			break; | ||||
| 		case 0x000a: | ||||
| 			mci_firmware(ddb, link); | ||||
| 			if (demod >= 0) | ||||
| 				mci_info(ddb, link, demod); | ||||
| 			else { | ||||
| 				for (i = 0; i < 4; i++) | ||||
| 					mci_info(ddb, link, i); | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| out: | ||||
| 	close(ddb); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int main(int argc, char*argv[]) | ||||
| { | ||||
| 	int fd = -1, all = 1, i, ret = 0; | ||||
| 	char fn[128]; | ||||
| 	int32_t device = -1, demod = -1; | ||||
| 	 | ||||
| 	while (1) { | ||||
| 		int cur_optind = optind ? optind : 1; | ||||
| 		int option_index = 0; | ||||
| 		int c; | ||||
| 		static struct option long_options[] = { | ||||
| 			{"device", required_argument, 0, 'd'}, | ||||
| 			{"demod", required_argument, 0, 'n'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
|                 c = getopt_long(argc, argv, "ad:n:", | ||||
| 				long_options, &option_index); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
| 		switch (c) { | ||||
| 		case 'd': | ||||
| 			device = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			demod = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'a': | ||||
| 			all = 1; | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (device >=0) | ||||
| 		ret = card_info(device, demod); | ||||
| 	else | ||||
| 		for (i = 0; i < 100; i++) { | ||||
| 			ret = card_info(i, -1); | ||||
| 			 | ||||
| 			if (ret == -3)     /* could not open, no more cards! */ | ||||
| 				break;  | ||||
| 			if (ret < 0) | ||||
| 				return i; /* fatal error */  | ||||
| 		} | ||||
| } | ||||
| @@ -32,16 +32,18 @@ | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <linux/types.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "flash.h" | ||||
| #include "flash.c" | ||||
|  | ||||
| void get_id(int ddb, struct ddb_id *ddbid) { | ||||
| void get_ddid(int ddb, struct ddb_id *ddbid) { | ||||
| 	uint8_t id[4]; | ||||
|  | ||||
| 	if (ioctl(ddb, IOCTL_DDB_ID, ddbid)>=0) | ||||
| 		return; | ||||
| 	memset(ddbid, 0, sizeof(*ddbid)); | ||||
| 	flashread(ddb, id, 0, 4); | ||||
| 	flashread(ddb, linknr, id, 0, 4); | ||||
| 	printf("%02x %02x %02x %02x\n",  | ||||
| 	       id[0], id[1], id[2], id[3]); | ||||
| 	ddbid->subvendor=(id[0] << 8) | id[1]; | ||||
| @@ -70,6 +72,7 @@ int sure() | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	char ddbname[80]; | ||||
| 	char *flashname; | ||||
| 	int type = 0; | ||||
| 	struct ddb_id ddbid; | ||||
| 	uint8_t *buffer; | ||||
| @@ -145,10 +148,10 @@ int main(int argc, char **argv) | ||||
| 		printf("Could not open device\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	Flash = flashdetect(ddb, &SectorSize, &FlashSize); | ||||
| 	Flash = flashdetect(ddb, &SectorSize, &FlashSize, &flashname); | ||||
|  | ||||
| 	get_id(ddb, &ddbid); | ||||
| #if 1 | ||||
| 	get_ddid(ddb, &ddbid); | ||||
| #if 0 | ||||
| 	printf("%04x %04x %04x %04x %08x %08x\n", | ||||
| 	       ddbid.vendor, ddbid.device, | ||||
| 	       ddbid.subvendor, ddbid.subdevice, | ||||
| @@ -156,7 +159,7 @@ int main(int argc, char **argv) | ||||
| #endif | ||||
|  | ||||
| 	if (dump) { | ||||
| 		flashdump(ddb, dump, 128); | ||||
| 		flashdump(ddb, linknr, dump, 128); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| @@ -202,73 +205,13 @@ int main(int argc, char **argv) | ||||
| 	} else { | ||||
| 		int fh, i; | ||||
| 		int fsize; | ||||
| 		char *name; | ||||
|  | ||||
| 		if (!fname)  | ||||
| 		switch (ddbid.device) { | ||||
| 		case 0x0002: | ||||
| 			fname="DVBBridgeV1A_DVBBridgeV1A.bit"; | ||||
| 			printf("Octopus 35\n"); | ||||
| 			break; | ||||
| 		case 0x0003: | ||||
| 			fname="DVBBridgeV1B_DVBBridgeV1B.fpga"; | ||||
| 			printf("Octopus\n"); | ||||
| 			break; | ||||
| 		case 0x0005: | ||||
| 			fname="DVBBridgeV2A_DD01_0005_STD.fpga"; | ||||
| 			printf("Octopus Classic\n"); | ||||
| 			break; | ||||
| 		case 0x0006: | ||||
| 			fname="DVBBridgeV2A_DD01_0006_STD.fpga"; | ||||
| 			printf("CineS2 V7\n"); | ||||
| 			break; | ||||
| 		case 0x0007: | ||||
| 			fname="DVBBridgeV2A_DD01_0007_MXL.fpga"; | ||||
| 			printf("Octopus 4/8\n"); | ||||
| 			break; | ||||
| 		case 0x0008: | ||||
| 			fname="DVBBridgeV2A_DD01_0008_CXD.fpga"; | ||||
| 			printf("Octopus 4/8\n"); | ||||
| 			break; | ||||
| 		case 0x0009: | ||||
| 			fname="DVBBridgeV2A_DD01_0009_SX8.fpga"; | ||||
| 			printf("Octopus MAXSX8\n"); | ||||
| 			break; | ||||
| 		case 0x000a: | ||||
| 			fname="DVBBridgeV2A_DD01_000A_M4.fpga"; | ||||
| 			printf("Octopus MAXSX8\n"); | ||||
| 			break; | ||||
| 		case 0x0011: | ||||
| 			fname="CIBridgeV1B_CIBridgeV1B.fpga"; | ||||
| 			printf("Octopus CI\n"); | ||||
| 			break; | ||||
| 		case 0x0012: | ||||
| 			fname="DVBBridgeV2B_DD01_0012_STD.fpga"; | ||||
| 			printf("Octopus CI\n"); | ||||
| 			break; | ||||
| 		case 0x0013: | ||||
| 			fname="DVBBridgeV2B_DD01_0013_PRO.fpga"; | ||||
| 			printf("Octopus PRO\n"); | ||||
| 			break; | ||||
| 		case 0x0201: | ||||
| 			fname="DVBModulatorV1B_DVBModulatorV1B.bit"; | ||||
| 			printf("Modulator\n"); | ||||
| 			break; | ||||
| 		case 0x0203: | ||||
| 			fname="DVBModulatorV1B_DD01_0203.fpga"; | ||||
| 			printf("Modulator Test\n"); | ||||
| 			break; | ||||
| 		case 0x0210: | ||||
| 			fname="DVBModulatorV2A_DD01_0210.fpga"; | ||||
| 			printf("Modulator V2\n"); | ||||
| 			break; | ||||
| 		case 0x0220: | ||||
| 			fname="SDRModulatorV1A_DD01_0220.fpga"; | ||||
| 			printf("SDRModulator\n"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			printf("UNKNOWN\n"); | ||||
| 			break; | ||||
| 		} | ||||
| 			fname = devid2fname(ddbid.device, &name); | ||||
| 		if (name) | ||||
| 			printf("Card: %s\n", name); | ||||
| 		 | ||||
| 		fh = open(fname, O_RDONLY); | ||||
| 		if (fh < 0 ) { | ||||
| 			printf("File %s not found \n", fname); | ||||
| @@ -277,7 +220,7 @@ int main(int argc, char **argv) | ||||
| 		printf("Using bitstream %s\n", fname); | ||||
|  | ||||
| 		fsize = lseek(fh,0,SEEK_END); | ||||
| 		if( fsize > 4000000 || fsize < SectorSize ) | ||||
| 		if( fsize > FlashSize/2 - 0x10000 || fsize < SectorSize ) | ||||
| 		{ | ||||
| 			close(fh); | ||||
| 			printf("Invalid File Size \n"); | ||||
| @@ -331,6 +274,8 @@ int main(int argc, char **argv) | ||||
| 		break; | ||||
|         case SPANSION_S25FL116K: | ||||
|         case SPANSION_S25FL164K: | ||||
| 	case WINBOND_W25Q16JV: | ||||
| 	case WINBOND_W25Q32JV: | ||||
| 		err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C); | ||||
| 		break;             | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										100
									
								
								apps/getiq.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								apps/getiq.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <linux/types.h> | ||||
| #include <getopt.h> | ||||
|  | ||||
| typedef uint8_t u8; | ||||
| typedef uint16_t u16; | ||||
| typedef int16_t s16; | ||||
| typedef uint32_t u32; | ||||
| typedef uint64_t u64; | ||||
|  | ||||
| #include "../ddbridge/ddbridge-mci.h" | ||||
| #include "../ddbridge/ddbridge-ioctl.h" | ||||
|  | ||||
| void print_iq(struct mci_result *res, int fd) | ||||
| { | ||||
| 	dprintf(fd, "%d,%d\n", res->iq_symbol.i, res->iq_symbol.q); | ||||
| } | ||||
|  | ||||
| int get_iq(int dev, uint32_t link, uint8_t demod, int fd) | ||||
| { | ||||
| 	struct ddb_mci_msg msg = { | ||||
| 		.link = link, | ||||
| 		.cmd.command = MCI_CMD_GET_IQSYMBOL, | ||||
| 		.cmd.demod = demod, | ||||
| 		.cmd.get_iq_symbol.tap = 0, | ||||
| 		.cmd.get_iq_symbol.point = 0, | ||||
| 	}; | ||||
| 	int ret; | ||||
| 	int i; | ||||
| 	 | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("Error: %d %d\n", ret, errno); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (msg.res.status & 0x80) { | ||||
| 		printf("MCI errror %02x\n", msg.res.status); | ||||
| 		return ret; | ||||
| 	} | ||||
| 		 | ||||
| 	print_iq(&msg.res, fd); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| #define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0])) | ||||
|  | ||||
| int main(int argc, char*argv[]) | ||||
| { | ||||
| 	char ddbname[80]; | ||||
| 	int fd = -1, all = 1, i, ret = 0, ddb; | ||||
| 	char fn[128]; | ||||
| 	int32_t device = -1, demod = -1; | ||||
| 	 | ||||
| 	while (1) { | ||||
| 		int cur_optind = optind ? optind : 1; | ||||
| 		int option_index = 0; | ||||
| 		int c; | ||||
| 		static struct option long_options[] = { | ||||
| 			{"device", required_argument, 0, 'd'}, | ||||
| 			{"demod", required_argument, 0, 'n'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
|                 c = getopt_long(argc, argv, "ad:n:", | ||||
| 				long_options, &option_index); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
| 		switch (c) { | ||||
| 		case 'd': | ||||
| 			device = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			demod = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'a': | ||||
| 			all = 1; | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	sprintf(ddbname, "/dev/ddbridge/card%d", device); | ||||
| 	ddb = open(ddbname, O_RDWR); | ||||
| 	if (ddb < 0) | ||||
| 		return -3; | ||||
| 	for (i = 0; i < 20000; i++) | ||||
| 		get_iq(ddb, 0, demod, 1); | ||||
| } | ||||
							
								
								
									
										531
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										531
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,531 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <linux/types.h> | ||||
| #include <getopt.h> | ||||
| #include <ctype.h> | ||||
|  | ||||
| typedef uint8_t u8; | ||||
| typedef uint16_t u16; | ||||
| typedef int16_t s16; | ||||
| typedef uint32_t u32; | ||||
| typedef uint64_t u64; | ||||
|  | ||||
| #include "../ddbridge/ddbridge-mci.h" | ||||
| #include "../ddbridge/ddbridge-ioctl.h" | ||||
|  | ||||
| struct mconf { | ||||
| 	int set_output; | ||||
| 	int set_channels; | ||||
| 	int fd; | ||||
|  | ||||
| 	struct mci_command channels; | ||||
| 	struct mci_command stream; | ||||
| 	struct mci_command output; | ||||
| }; | ||||
|  | ||||
| void strim(char *s) | ||||
| { | ||||
| 	int l = strlen(s); | ||||
|  | ||||
| 	while (l && isspace(s[l-1])) | ||||
| 		l--; | ||||
| 	s[l] = 0; | ||||
| } | ||||
|  | ||||
| void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *)) | ||||
| { | ||||
| 	char line[256], csec[80], par[80], val[80], *p; | ||||
| 	FILE *f; | ||||
|  | ||||
| 	if ((f = fopen(fname, "r")) == NULL) | ||||
| 		return; | ||||
| 	while ((p = fgets(line, sizeof(line), f))) { | ||||
| 		if (*p == '\r' || *p == '\n' || *p == '#') | ||||
| 			continue; | ||||
| 		if (*p == '[') { | ||||
| 			if ((p = strtok(line + 1, "]")) == NULL) | ||||
| 				continue; | ||||
| 			strncpy(csec, p, sizeof(csec)); | ||||
| 			if (!strcmp(sec, csec) && cb) | ||||
| 				cb(priv, NULL, NULL); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!(p = strtok(line, "="))) | ||||
| 			continue; | ||||
| 		while (isspace(*p)) | ||||
| 			p++; | ||||
| 		strncpy(par, p, sizeof(par)); | ||||
| 		strim(par); | ||||
| 		if (!(p = strtok(NULL, "="))) | ||||
| 			continue; | ||||
| 		while (isspace(*p)) | ||||
| 			p++; | ||||
| 		strncpy (val, p, sizeof(val)); | ||||
| 		strim(val); | ||||
| 		if (!strcmp(sec, csec) && cb) | ||||
| 			cb(priv, par, val); | ||||
| 	} | ||||
| 	if (!strcmp(sec, csec) && cb) | ||||
| 		cb(priv, NULL, NULL); | ||||
| 	fclose(f); | ||||
| } | ||||
|  | ||||
| struct param_table_entry { | ||||
| 	int value; | ||||
| 	char* name; | ||||
| }; | ||||
|  | ||||
| struct param_table_entry mod_standard_table[] = { | ||||
| 	{ .name = "0", .value = MOD_STANDARD_GENERIC }, | ||||
| 	{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC }, | ||||
|  | ||||
| 	{ .name = "1", .value = MOD_STANDARD_DVBT_8 }, | ||||
| 	{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 }, | ||||
| 	{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_STANDARD_DVBT_7 }, | ||||
| 	{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 }, | ||||
| 	{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 }, | ||||
|  | ||||
| 	{ .name = "3", .value = MOD_STANDARD_DVBT_6 }, | ||||
| 	{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 }, | ||||
| 	{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 }, | ||||
|  | ||||
| 	{ .name = "4", .value = MOD_STANDARD_DVBT_5 }, | ||||
| 	{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 }, | ||||
| 	{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 }, | ||||
|  | ||||
| 	{ .name = "8", .value = MOD_STANDARD_DVBC_8 }, | ||||
| 	{ .name = "DVBC_8", .value = MOD_STANDARD_DVBC_8 }, | ||||
|  | ||||
| 	{ .name = "9", .value = MOD_STANDARD_DVBC_7 }, | ||||
| 	{ .name = "DVBC_7", .value = MOD_STANDARD_DVBC_7 }, | ||||
|  | ||||
| 	{ .name = "10", .value = MOD_STANDARD_DVBC_6 }, | ||||
| 	{ .name = "DVBC_6", .value = MOD_STANDARD_DVBC_6 }, | ||||
|  | ||||
| 	{ .name = "11", .value = MOD_STANDARD_J83B_QAM64 }, | ||||
| 	{ .name = "J83B_QAM64", .value = MOD_STANDARD_J83B_QAM64 }, | ||||
|  | ||||
| 	{ .name = "12", .value = MOD_STANDARD_J83B_QAM256 }, | ||||
| 	{ .name = "J83B_QAM256", .value = MOD_STANDARD_J83B_QAM256 }, | ||||
|  | ||||
| 	{ .name = "13", .value = MOD_STANDARD_ISDBC_QAM64 }, | ||||
| 	{ .name = "ISDBC_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 }, | ||||
| 	{ .name = "J83C_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 }, | ||||
|  | ||||
| 	{ .name = "14", .value = MOD_STANDARD_ISDBC_QAM256 }, | ||||
| 	{ .name = "ISDBC_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 }, | ||||
| 	{ .name = "J83C_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 }, | ||||
|  | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
| struct param_table_entry stream_format_table[] = { | ||||
| 	{ .name = "0", .value = MOD_FORMAT_DEFAULT }, | ||||
| 	{ .name = "default", .value = MOD_FORMAT_DEFAULT }, | ||||
|  | ||||
| 	{ .name = "1", .value = MOD_FORMAT_IQ16 }, | ||||
| 	{ .name = "IQ16", .value = MOD_FORMAT_IQ16 }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_FORMAT_IQ8 }, | ||||
| 	{ .name = "IQ8", .value = MOD_FORMAT_IQ8 }, | ||||
|  | ||||
| 	{ .name = "3", .value = MOD_FORMAT_IDX8 }, | ||||
| 	{ .name = "IDX8", .value = MOD_FORMAT_IDX8 }, | ||||
|  | ||||
| 	{ .name = "4", .value = MOD_FORMAT_TS }, | ||||
| 	{ .name = "TS", .value = MOD_FORMAT_TS }, | ||||
|  | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct param_table_entry guard_interval_table[] = { | ||||
| 	{ .name = "0", .value = MOD_DVBT_GI_1_32 }, | ||||
| 	{ .name = "1/32", .value = MOD_DVBT_GI_1_32 }, | ||||
|  | ||||
| 	{ .name = "1", .value = MOD_DVBT_GI_1_16 }, | ||||
| 	{ .name = "1/16", .value = MOD_DVBT_GI_1_16 }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_DVBT_GI_1_8	}, | ||||
| 	{ .name = "1/8", .value = MOD_DVBT_GI_1_8 }, | ||||
|  | ||||
| 	{ .name = "3", .value = MOD_DVBT_GI_1_4	}, | ||||
| 	{ .name = "1/4", .value = MOD_DVBT_GI_1_4 }, | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
| struct param_table_entry puncture_rate_table[] = { | ||||
| 	{ .name = "1", .value = MOD_DVBT_PR_1_2 }, | ||||
| 	{ .name = "1/2", .value = MOD_DVBT_PR_1_2 }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_DVBT_PR_2_3 }, | ||||
| 	{ .name = "2/3", .value = MOD_DVBT_PR_2_3 }, | ||||
|  | ||||
| 	{ .name = "3", .value = MOD_DVBT_PR_3_4 }, | ||||
| 	{ .name = "3/4", .value = MOD_DVBT_PR_3_4 }, | ||||
|  | ||||
| 	{ .name = "5", .value = MOD_DVBT_PR_5_6 }, | ||||
| 	{ .name = "5/6", .value = MOD_DVBT_PR_5_6 }, | ||||
|  | ||||
| 	{ .name = "7", .value = MOD_DVBT_PR_7_8 }, | ||||
| 	{ .name = "7/8", .value = MOD_DVBT_PR_7_8 }, | ||||
|  | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
| struct param_table_entry dvbt_constellation_table[] = { | ||||
| 	{ .name = "0", .value = MOD_DVBT_QPSK }, | ||||
| 	{ .name = "qpsk", .value = MOD_DVBT_QPSK }, | ||||
|  | ||||
| 	{ .name = "1", .value = MOD_DVBT_16QAM }, | ||||
| 	{ .name = "16qam", .value = MOD_DVBT_16QAM }, | ||||
| 	{ .name = "qam16", .value = MOD_DVBT_16QAM }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_DVBT_64QAM }, | ||||
| 	{ .name = "64qam", .value = MOD_DVBT_64QAM }, | ||||
| 	{ .name = "qam64", .value = MOD_DVBT_64QAM }, | ||||
|  | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
| struct param_table_entry qam_modulation_table[] = { | ||||
| 	{ .name = "0", .value = MOD_QAM_DVBC_16 }, | ||||
| 	{ .name = "qam_dvbc_16", .value = MOD_QAM_DVBC_16 }, | ||||
|  | ||||
| 	{ .name = "1", .value = MOD_QAM_DVBC_32 }, | ||||
| 	{ .name = "qam_dvbc_32", .value = MOD_QAM_DVBC_32 }, | ||||
|  | ||||
| 	{ .name = "2", .value = MOD_QAM_DVBC_64 }, | ||||
| 	{ .name = "qam_dvbc_64", .value = MOD_QAM_DVBC_64 }, | ||||
|  | ||||
| 	{ .name = "3", .value = MOD_QAM_DVBC_128 }, | ||||
| 	{ .name = "qam_dvbc_128", .value = MOD_QAM_DVBC_128 }, | ||||
|  | ||||
| 	{ .name = "4", .value = MOD_QAM_DVBC_256 }, | ||||
| 	{ .name = "qam_dvbc_256", .value = MOD_QAM_DVBC_256 }, | ||||
|  | ||||
| 	{ .name = "5", .value = MOD_QAM_J83B_64 }, | ||||
| 	{ .name = "qam_j83b_64", .value = MOD_QAM_J83B_64 }, | ||||
|  | ||||
| 	{ .name = "6", .value = MOD_QAM_DVBC_256 }, | ||||
| 	{ .name = "qam_j83b_256", .value = MOD_QAM_J83B_256 }, | ||||
|  | ||||
| 	{ .name = "7", .value = MOD_QAM_GENERIC }, | ||||
| 	{ .name = "qam_generic", .value = MOD_QAM_GENERIC }, | ||||
|  | ||||
| 	{ .name = "8", .value = MOD_QAM_ISDBC_64 }, | ||||
| 	{ .name = "qam_isdbc_64", .value = MOD_QAM_ISDBC_64 }, | ||||
|  | ||||
| 	{ .name = "9", .value = MOD_QAM_ISDBC_256 }, | ||||
| 	{ .name = "qam_isdbc_256", .value = MOD_QAM_ISDBC_256 }, | ||||
|  | ||||
| 	{ .name = NULL, .value = 0 } | ||||
| }; | ||||
|  | ||||
| int parse_param(char *val, struct param_table_entry *table, int *value) { | ||||
| 	if (value) { | ||||
| 		*value = 0; | ||||
| 		if (table) { | ||||
| 			while (table->name) { | ||||
| 				if( !strcasecmp(val,table->name)) { | ||||
| 					*value = table->value; | ||||
| 					printf("%s=%u\n", val, *value); | ||||
| 					return 0; | ||||
| 				} | ||||
| 				table++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	printf("unknown value %s\n", val); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| void dump(const uint8_t *b, int l) | ||||
| { | ||||
| 	int i, j; | ||||
| 	 | ||||
| 	for (j = 0; j < l; j += 16, b += 16) {  | ||||
| 		for (i = 0; i < 16; i++) | ||||
| 			if (i + j < l) | ||||
| 				printf("%02x ", b[i]); | ||||
| 			else | ||||
| 				printf("   "); | ||||
| 		printf(" | "); | ||||
| 		for (i = 0; i < 16; i++) | ||||
| 			if (i + j < l) | ||||
| 				putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.'); | ||||
| 		printf("\n"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int mci_cmd(int dev, struct mci_command *cmd) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct ddb_mci_msg msg; | ||||
| 	uint8_t status; | ||||
|  | ||||
| 	memset(&msg, 0, sizeof(msg)); | ||||
| 	msg.link = 0; | ||||
| 	memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); | ||||
| 	//dump((const uint8_t *) &msg.cmd, sizeof(msg.cmd)); | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 	    dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno)); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	status = msg.res.status; | ||||
| 	if (status == MCI_STATUS_OK) | ||||
| 		return ret; | ||||
| 	if (status == MCI_STATUS_UNSUPPORTED) { | ||||
| 		dprintf(2, "Unsupported MCI command\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (status == MCI_STATUS_INVALID_PARAMETER) { | ||||
| 		dprintf(2, "Invalid MCI parameters\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| struct mci_command msg_channels = { | ||||
| 	.mod_command = MOD_SETUP_CHANNELS, | ||||
| 	.mod_channel = 0, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_channels[0] = { | ||||
| 		.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID, | ||||
| 		.standard = MOD_STANDARD_DVBT_8, | ||||
| 		.num_channels = 25, | ||||
| 		.frequency = 474000000, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| struct mci_command msg_stream = { | ||||
| 	.mod_command = MOD_SETUP_STREAM, | ||||
| 	.mod_channel = 1, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_stream = { | ||||
| 		.standard = MOD_STANDARD_DVBC_8, | ||||
| #if 0 | ||||
| 		.ofdm = { | ||||
| 			.fft_size = 1, | ||||
| 			.guard_interval = 0, | ||||
| 		} | ||||
| #endif | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| struct mci_command msg_output = { | ||||
| 	.mod_command = MOD_SETUP_OUTPUT, | ||||
| 	.mod_channel = 0, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_output = { | ||||
| 		.connector = MOD_CONNECTOR_F, | ||||
| 		.num_channels = 16, | ||||
| 		.unit = MOD_UNIT_DBUV, | ||||
| 		.channel_power = 5000, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| void output_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		mc->set_output = 1; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!strcasecmp(par, "connector")) { | ||||
| 		if (!strcasecmp(val, "F")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_F; | ||||
| 		} else if (!strcasecmp(val, "SMA")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_SMA; | ||||
| 		} else if (!strcasecmp(val, "OFF")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_OFF; | ||||
| 		} else | ||||
| 			printf("invalid connector\n"); | ||||
| 	} else if (!strcasecmp(par, "power")) { | ||||
| 		mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0); | ||||
| 	} else if (!strcasecmp(par, "channels")) { | ||||
| 		mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "unit")) { | ||||
| 		if (!strcasecmp(val, "DBUV")) { | ||||
| 			mc->output.mod_setup_output.unit = MOD_UNIT_DBUV; | ||||
| 		} else if (!strcasecmp(val, "DBM")) { | ||||
| 			mc->output.mod_setup_output.unit = MOD_UNIT_DBM; | ||||
| 		} else | ||||
| 			printf("invalid unit\n"); | ||||
| 	} else | ||||
| 		printf("invalid output parameter: %s\n", par); | ||||
| } | ||||
|  | ||||
| void channels_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
| 	int value; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		mc->set_channels = 1; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!strcasecmp(par, "frequency")) { | ||||
| 		mc->channels.mod_setup_channels[0].frequency =	(uint32_t) (strtod(val, NULL) * 1000000.0); | ||||
| 		printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency); | ||||
| 	} else if (!strcasecmp(par, "channels")) { | ||||
| 		mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "standard")) { | ||||
| 		if (!parse_param(val,mod_standard_table, &value)) | ||||
| 			mc->channels.mod_setup_channels[0].standard = value; | ||||
| 		printf("standard = %u\n", value); | ||||
| 	} else if (!strcasecmp(par, "offset")) { | ||||
| 		mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||
| 	} else if (!strcasecmp(par, "bandwidth")) { | ||||
| 		mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||
| 		mc->channels.mod_setup_channels[0].offset = | ||||
| 			mc->channels.mod_setup_channels[0].bandwidth / 2; | ||||
| 	} else | ||||
| 		printf("invalid channels parameter: %s\n", par); | ||||
| } | ||||
|  | ||||
| void streams_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
| 	int value; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!strcasecmp(par, "fft_size")) { | ||||
| 		mc->stream.mod_setup_stream.ofdm.fft_size = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "guard_interval")) { | ||||
| 		if (!parse_param(val, guard_interval_table, &value)) | ||||
| 			mc->stream.mod_setup_stream.ofdm.guard_interval = value; | ||||
| 	} else if (!strcasecmp(par, "puncture_rate")) { | ||||
| 		if (!parse_param(val, puncture_rate_table, &value)) | ||||
| 			mc->stream.mod_setup_stream.ofdm.puncture_rate = value; | ||||
| 	} else if (!strcasecmp(par, "constellation")) { | ||||
| 		if (!parse_param(val,dvbt_constellation_table,&value)) | ||||
| 			mc->stream.mod_setup_stream.ofdm.constellation = value; | ||||
| 	} else if (!strcasecmp(par, "cell_identifier")) { | ||||
| 		mc->stream.mod_setup_stream.ofdm.cell_identifier = strtol(val, NULL, 0); | ||||
| 	} else if (!strcasecmp(par, "modulation")) { | ||||
| 		if (!parse_param(val, qam_modulation_table, &value)) | ||||
| 			mc->stream.mod_setup_stream.qam.modulation = value; | ||||
| 	} else if (!strcasecmp(par, "rolloff")) { | ||||
| 		mc->stream.mod_setup_stream.qam.rolloff = strtol(val, NULL, 0); | ||||
| 	} else if (!strcasecmp(par, "standard")) { | ||||
| 		if (!parse_param(val,mod_standard_table,&value)) | ||||
| 			mc->stream.mod_setup_stream.standard = value; | ||||
| 	} else if (!strcasecmp(par, "stream_format")) { | ||||
| 		if (!parse_param(val,stream_format_table,&value)) | ||||
| 			mc->stream.mod_setup_stream.stream_format = value; | ||||
| 	} else if (!strcasecmp(par, "symbol_rate")) { | ||||
| 		mc->stream.mod_setup_stream.symbol_rate = (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||
| 	} else if (!strcasecmp(par, "channel")) { | ||||
| 		mc->stream.mod_channel = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "stream")) { | ||||
| 		mc->stream.mod_stream = strtol(val, NULL, 10); | ||||
| 		printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel); | ||||
| 		mci_cmd(mc->fd, &mc->stream); | ||||
| 	} else | ||||
| 		printf("invalid streams parameter: %s = %s\n", par, val); | ||||
| } | ||||
|  | ||||
| int mci_lic(int dev) | ||||
| { | ||||
| 	struct ddb_mci_msg msg = { | ||||
| 		.cmd.command = CMD_EXPORT_LICENSE, | ||||
| 		.cmd.get_bb_header.select = 0, | ||||
| 	}; | ||||
| 	struct mci_result *res = &msg.res; | ||||
| 	int ret; | ||||
| 	int i; | ||||
| 	 | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("Error: %d %d\n", ret, errno); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (res->bb_header.valid) { | ||||
| 		printf("MATYPE1: %02x\n", res->bb_header.matype_1); | ||||
| 		printf("MATYPE2: %02x\n", res->bb_header.matype_2); | ||||
| 	} | ||||
| 	dump((const uint8_t *)&res->license, sizeof(res->license)); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int main(int argc, char*argv[]) | ||||
| { | ||||
| 	int fd = -1; | ||||
| 	char fn[128]; | ||||
| 	uint32_t device = 0; | ||||
| 	uint32_t frequency = 0; | ||||
| 	char *configname = "modulator.conf"; | ||||
| 	struct mconf mc; | ||||
|  | ||||
| 	memset(&mc, 0, sizeof(mc)); | ||||
| 	mc.channels = msg_channels; | ||||
| 	mc.stream = msg_stream; | ||||
| 	mc.output = msg_output; | ||||
|  | ||||
| 	while (1) { | ||||
| 		int cur_optind = optind ? optind : 1; | ||||
| 		int option_index = 0; | ||||
| 		int c; | ||||
| 		static struct option long_options[] = { | ||||
| 			{"device", required_argument, 0, 'd'}, | ||||
| 			{"config", required_argument, 0, 'c'}, | ||||
| 			{"help", no_argument, 0, 'h'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
| 		c = getopt_long(argc, argv, "d:c:", | ||||
| 				long_options, &option_index); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
| 		switch (c) { | ||||
| 		case 'd': | ||||
| 			device = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			configname = optarg; | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 			dprintf(2, "modconfig [-d device_number] [-c config_file]\n"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	//snprintf(fn, 127, "/dev/ddbridge/card%u", device); | ||||
| 	snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", device); | ||||
| 	fd = open(fn, O_RDWR); | ||||
| 	if (fd < 0) { | ||||
| 		dprintf(2, "Could not open %s\n", fn); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	//mci_lic(fd); | ||||
| 	mc.fd = fd; | ||||
| 	parse(configname, "channels", (void *) &mc, channels_cb); | ||||
| 	if (mc.set_channels) { | ||||
| 		printf("setting channels.\n"); | ||||
| 		mci_cmd(fd, &mc.channels); | ||||
| 	} | ||||
| 	parse(configname, "streams", (void *) &mc, streams_cb); | ||||
| 	parse(configname, "output", (void *) &mc, output_cb); | ||||
| 	if (mc.set_output) { | ||||
| 		printf("setting output.\n"); | ||||
| 		mci_cmd(fd, &mc.output); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										1313
									
								
								apps/modtest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1313
									
								
								apps/modtest.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										51
									
								
								apps/modulator.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								apps/modulator.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| [output] | ||||
| # connector = OFF, SMA or F | ||||
| connector = F | ||||
| # number of total channels to be used at the same time | ||||
| # use lower number to have fewer channels but stronger signal per channel | ||||
| channels = 16 | ||||
| # unit of power in DBUV or DBM | ||||
| unit = DBUV | ||||
| # power output in units of above unit | ||||
| power = 50.0 | ||||
|  | ||||
|  | ||||
| # define channels: | ||||
| # channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned | ||||
|  | ||||
| [channels] | ||||
| # standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz  | ||||
| standard = 1 | ||||
|  | ||||
| # numbers of channels to allocate, starting from frequency below | ||||
| # this defines 25 channels at 474, 474+8, 474+16, etc. Mhz | ||||
| channels = 25 | ||||
| # frequency of channel 0, following channels are spaced according to set standard | ||||
| frequency = 474.0 | ||||
|  | ||||
|  | ||||
| [streams] | ||||
| # number of streams depends on the card hardware | ||||
| # streams correspond to devices mod0, mod1, ... | ||||
| # channels are defined above in channels section | ||||
|  | ||||
| # 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4  | ||||
| guard_interval = 0 | ||||
| # 0 = 2K, 1 = 8K  (2K not yet supported) | ||||
| fft_size = 1 | ||||
|  | ||||
| # all following streams will be set according to the last set other parameters | ||||
|  | ||||
| # example: | ||||
| # this would set mod 1 to 474 MHz and mod0 to 482 MHz (474 + 8 MHz) | ||||
| # both with guard interval 1/32 and 8K FFT | ||||
| # and mod2 to 490MHz, guard interval 1/16 and 8K FFT | ||||
| channel = 1 | ||||
| stream = 0 | ||||
| # | ||||
| channel = 0 | ||||
| stream = 1 | ||||
| # | ||||
| guard_interval = 1 | ||||
| channel = 2 | ||||
| stream = 2 | ||||
| @@ -1,17 +1,21 @@ | ||||
| all: ddtest octonet octokey ddflash | ||||
| all: ddtest octonet octokey ddflash ddupdate | ||||
|  | ||||
| install: all | ||||
| 	install -m 0755 ddtest $(DESTDIR)/usr/bin | ||||
| 	install -m 0755 octonet $(DESTDIR)/usr/bin | ||||
| 	install -m 0755 octokey $(DESTDIR)/usr/bin | ||||
| 	install -m 0755 ddflash $(DESTDIR)/usr/bin | ||||
| 	install -m 0755 ddupdate $(DESTDIR)/usr/bin | ||||
|  | ||||
| ddflash: ddflash.c | ||||
| ddflash: ddflash.c flash.h flash.c | ||||
| 	$(CC) -o ddflash ddflash.c | ||||
|  | ||||
| ddtest: ddtest.c | ||||
| ddtest: ddtest.c flash.h flash.c | ||||
| 	$(CC) -o ddtest ddtest.c | ||||
|  | ||||
| ddupdate: ddupdate.c flash.h flash.c | ||||
| 	$(CC) -o ddupdate ddupdate.c | ||||
|  | ||||
| octonet: octonet.c | ||||
| 	$(CC) -o octonet octonet.c | ||||
|  | ||||
|   | ||||
| @@ -36,559 +36,7 @@ | ||||
| #include <linux/types.h> | ||||
|  | ||||
| #include "flash.h" | ||||
|  | ||||
| static int reboot(uint32_t off) | ||||
| { | ||||
| 	FILE *f; | ||||
| 	uint32_t time; | ||||
|  | ||||
| 	if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL) | ||||
| 		return -1; | ||||
| 	fscanf(f, "%u", &time); | ||||
| 	fclose(f); | ||||
|  | ||||
| 	if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL) | ||||
| 		return -1; | ||||
| 	fprintf(f, "%u", time + off); | ||||
| 	fclose(f); | ||||
| 	system("/sbin/poweroff"); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct ddflash { | ||||
| 	int fd; | ||||
| 	struct ddb_id id; | ||||
| 	uint32_t version; | ||||
|  | ||||
| 	uint32_t flash_type; | ||||
| 	uint32_t sector_size; | ||||
| 	uint32_t size; | ||||
|  | ||||
| 	uint32_t bufsize; | ||||
| 	uint32_t block_erase; | ||||
|  | ||||
| 	uint8_t *buffer; | ||||
| }; | ||||
|  | ||||
| int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset, | ||||
| 			uint8_t LockBits, uint32_t fw_off) | ||||
| { | ||||
| 	int err = 0; | ||||
| 	uint8_t cmd[260]; | ||||
| 	int i, j; | ||||
| 	uint32_t flen, blen; | ||||
| 	 | ||||
| 	blen = flen = lseek(dev, 0, SEEK_END) - fw_off; | ||||
| 	if (blen % 0xff) | ||||
| 		blen = (blen + 0xff) & 0xffffff00;  | ||||
| 	printf("blen = %u, flen = %u\n", blen, flen); | ||||
| 	     | ||||
| 	do { | ||||
| 		cmd[0] = 0x50;  // EWSR | ||||
| 		err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 		if (err < 0) | ||||
| 			break; | ||||
| 		 | ||||
| 		cmd[0] = 0x01;  // WRSR | ||||
| 		cmd[1] = 0x00;  // BPx = 0, Unlock all blocks | ||||
| 		err = flashio(ddf->fd, cmd, 2, NULL, 0); | ||||
| 		if (err < 0) | ||||
| 			break; | ||||
| 		 | ||||
| 		for (i = 0; i < flen; i += 4096) { | ||||
| 			if ((i & 0xFFFF) == 0) | ||||
| 				printf(" Erase    %08x\n", FlashOffset + i); | ||||
| 			 | ||||
| 			cmd[0] = 0x06;  // WREN | ||||
| 			err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
| 			 | ||||
| 			cmd[0] = 0x20;  // Sector erase ( 4Kb) | ||||
| 			cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF ); | ||||
| 			cmd[2] = ( (( FlashOffset + i ) >>  8) & 0xFF ); | ||||
| 			cmd[3] = 0x00; | ||||
| 			err = flashio(ddf->fd, cmd, 4, NULL, 0); | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
|  | ||||
| 			while (1) { | ||||
| 				cmd[0] = 0x05;  // RDRS | ||||
| 				err = flashio(ddf->fd, cmd, 1, &cmd[0], 1); | ||||
| 				if (err < 0) | ||||
| 					break; | ||||
| 				if ((cmd[0] & 0x01) == 0) | ||||
| 					break; | ||||
| 			} | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
| 			 | ||||
| 		} | ||||
| 		if (err < 0) | ||||
| 			break; | ||||
| 		 | ||||
| 		for (j = blen - 256; j >= 0; j -= 256 ) { | ||||
| 			uint32_t len = 256;  | ||||
| 			ssize_t rlen; | ||||
| 			 | ||||
| 			if (lseek(dev, j + fw_off, SEEK_SET) < 0) { | ||||
| 				printf("seek error\n"); | ||||
| 				return -1; | ||||
| 			} | ||||
| 			if (flen - j < 256) { | ||||
| 				len = flen - j; | ||||
| 				memset(ddf->buffer, 0xff, 256); | ||||
| 			} | ||||
| 			rlen = read(dev, ddf->buffer, len); | ||||
| 			if (rlen < 0 || rlen != len) { | ||||
| 				printf("file read error %d,%d at %u\n", rlen, errno, j); | ||||
| 				return -1; | ||||
| 			} | ||||
| 			printf ("write %u bytes at %08x\n", len, j); | ||||
| 			 | ||||
| 			 | ||||
| 			if ((j & 0xFFFF) == 0) | ||||
| 				printf(" Programm %08x\n", FlashOffset + j); | ||||
| 			 | ||||
| 			cmd[0] = 0x06;  // WREN | ||||
| 			err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
| 			 | ||||
| 			cmd[0] = 0x02;  // PP | ||||
| 			cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF ); | ||||
| 			cmd[2] = ( (( FlashOffset + j ) >>  8) & 0xFF ); | ||||
| 			cmd[3] = 0x00; | ||||
| 			memcpy(&cmd[4], ddf->buffer, 256); | ||||
| 			err = flashio(ddf->fd, cmd, 260, NULL, 0); | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
| 			 | ||||
| 			while(1) { | ||||
| 				cmd[0] = 0x05;  // RDRS | ||||
| 				err = flashio(ddf->fd, cmd,1, &cmd[0], 1); | ||||
| 				if (err < 0) | ||||
| 					break; | ||||
| 				if ((cmd[0] & 0x01) == 0) | ||||
| 					break; | ||||
| 			} | ||||
| 			if (err < 0) | ||||
| 				break; | ||||
| 			 | ||||
| 		} | ||||
| 		if (err < 0) | ||||
| 			break; | ||||
| 		 | ||||
| 		cmd[0] = 0x50;  // EWSR | ||||
| 		err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 		if (err < 0) | ||||
| 			break; | ||||
| 		 | ||||
| 		cmd[0] = 0x01;  // WRSR | ||||
| 		cmd[1] = LockBits;  // BPx = 0, Lock all blocks | ||||
| 		err = flashio(ddf->fd, cmd, 2, NULL, 0); | ||||
| 	} while(0); | ||||
| 	return err; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int flashwrite_SSTI(struct ddflash *ddf, int fs, uint32_t FlashOffset, uint32_t maxlen, uint32_t fw_off) | ||||
| { | ||||
|     int err = 0; | ||||
|     uint8_t cmd[6]; | ||||
|     int i, j; | ||||
|     uint32_t flen, blen; | ||||
|  | ||||
|     blen = flen = lseek(fs, 0, SEEK_END) - fw_off; | ||||
|     if (blen % 0xfff) | ||||
| 	    blen = (blen + 0xfff) & 0xfffff000;  | ||||
|     printf("blen = %u, flen = %u\n", blen, flen); | ||||
|     do { | ||||
| #if 1 | ||||
| 	    cmd[0] = 0x50;  // EWSR | ||||
| 	    err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 	    if (err < 0)  | ||||
| 		    break; | ||||
|  | ||||
| 	    cmd[0] = 0x01;  // WRSR | ||||
| 	    cmd[1] = 0x00;  // BPx = 0, Unlock all blocks | ||||
| 	    err = flashio(ddf->fd, cmd, 2, NULL, 0); | ||||
| 	    if (err < 0 ) | ||||
| 		    break; | ||||
| 	     | ||||
| 	    for (i = 0; i < flen; i += 4096) { | ||||
| 		    if ((i & 0xFFFF) == 0 ) | ||||
| 			    printf("Erase %08x\n", FlashOffset + i); | ||||
| 		    cmd[0] = 0x06;  // WREN | ||||
| 		    err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 		    if (err < 0 ) | ||||
| 			    break; | ||||
| 		     | ||||
| 		    cmd[0] = 0x20;  // Sector erase ( 4Kb) | ||||
| 		    cmd[1] = (((FlashOffset + i ) >> 16) & 0xFF); | ||||
| 		    cmd[2] = (((FlashOffset + i ) >>  8) & 0xFF); | ||||
| 		    cmd[3] = 0x00; | ||||
| 		    err = flashio(ddf->fd,cmd,4,NULL,0); | ||||
| 		    if (err < 0 ) | ||||
| 			    break; | ||||
| 		     | ||||
| 		    while(1) { | ||||
| 			    cmd[0] = 0x05;  // RDRS | ||||
| 			    err = flashio(ddf->fd,cmd,1,&cmd[0],1); | ||||
| 			    if (err < 0 ) break; | ||||
| 			    if ((cmd[0] & 0x01) == 0 ) break; | ||||
| 		    } | ||||
| 		    if (err < 0 ) break; | ||||
| 	    } | ||||
| 	    if (err < 0 )  | ||||
| 		    break; | ||||
| #endif | ||||
| 	    for (j = blen - 4096; j >= 0; j -= 4096 ) { | ||||
| 		    uint32_t len = 4096;  | ||||
| 		    ssize_t rlen; | ||||
| 		     | ||||
| 		    if (lseek(fs, j + fw_off, SEEK_SET) < 0) { | ||||
| 			    printf("seek error\n"); | ||||
| 			    return -1; | ||||
| 		    } | ||||
| 		    if (flen - j < 4096) { | ||||
| 			    len = flen - j; | ||||
| 			    memset(ddf->buffer, 0xff, 4096); | ||||
| 		    } | ||||
|    		    rlen = read(fs, ddf->buffer, len); | ||||
| 		    if (rlen < 0 || rlen != len) { | ||||
| 			    printf("file read error %d,%d at %u\n", rlen, errno, j); | ||||
| 			    return -1; | ||||
| 		    } | ||||
| 		    printf ("write %u bytes at %08x\n", len, j); | ||||
|  | ||||
| 		    if ((j & 0xFFFF) == 0 ) | ||||
| 			    printf(" Program  %08x\n",FlashOffset + j); | ||||
| #if 1		     | ||||
| 		    for (i = 0; i < 4096; i += 2) { | ||||
| 			    if (i == 0) { | ||||
| 				    cmd[0] = 0x06;  // WREN | ||||
| 				    err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 				    if (err < 0 )  | ||||
| 					    break; | ||||
| 				     | ||||
| 				    cmd[0] = 0xAD;  // AAI | ||||
| 				    cmd[1] = ((( FlashOffset + j ) >> 16) & 0xFF ); | ||||
| 				    cmd[2] = ((( FlashOffset + j ) >>  8) & 0xFF ); | ||||
| 				    cmd[3] = 0x00; | ||||
| 				    cmd[4] = ddf->buffer[i]; | ||||
| 				    cmd[5] = ddf->buffer[i + 1]; | ||||
| 				    err = flashio(ddf->fd,cmd,6,NULL,0); | ||||
| 			    } else { | ||||
| 				    cmd[0] = 0xAD;  // AAI | ||||
| 				    cmd[1] = ddf->buffer[i]; | ||||
| 				    cmd[2] = ddf->buffer[i + 1]; | ||||
| 				    err = flashio(ddf->fd,cmd,3,NULL,0); | ||||
| 			    } | ||||
| 			    if (err < 0 )  | ||||
| 				    break; | ||||
| 			     | ||||
| 			    while(1) { | ||||
| 				    cmd[0] = 0x05;  // RDRS | ||||
| 				    err = flashio(ddf->fd,cmd,1,&cmd[0],1); | ||||
| 				    if (err < 0 ) break; | ||||
| 				    if ((cmd[0] & 0x01) == 0 ) break; | ||||
| 			    } | ||||
| 			    if (err < 0 )  | ||||
| 				    break; | ||||
| 		    } | ||||
| 		    if (err < 0) | ||||
| 			    break; | ||||
| 		     | ||||
| 		    cmd[0] = 0x04;  // WDIS | ||||
| 		    err = flashio(ddf->fd, cmd, 1, NULL, 0); | ||||
| 		    if (err < 0 )  | ||||
| 			    break; | ||||
| #endif | ||||
| 	    } | ||||
| 	    if (err < 0 ) break; | ||||
| 	     | ||||
| 	    cmd[0] = 0x50;  // EWSR | ||||
| 	    err = flashio(ddf->fd,cmd,1,NULL,0); | ||||
| 	    if (err < 0 ) break; | ||||
| 	     | ||||
| 	    cmd[0] = 0x01;  // WRSR | ||||
| 	    cmd[1] = 0x1C;  // BPx = 0, Lock all blocks | ||||
| 	    err = flashio(ddf->fd,cmd,2,NULL,0); | ||||
|     } while(0); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off) | ||||
| { | ||||
| 	switch (ddf->flash_type) { | ||||
|         case SSTI_SST25VF016B:  | ||||
|         case SSTI_SST25VF032B:  | ||||
| 		return flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off); | ||||
|         case SSTI_SST25VF064C: | ||||
| 		return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off); | ||||
| 	case SPANSION_S25FL116K:  | ||||
| 	case SPANSION_S25FL132K:  | ||||
| 	case SPANSION_S25FL164K:  | ||||
| 		return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off); | ||||
| 	} | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off) | ||||
| { | ||||
| 	off_t off; | ||||
| 	uint32_t len; | ||||
| 	int i, j, rlen; | ||||
| 	uint8_t buf[256], buf2[256]; | ||||
| 	int bl = sizeof(buf); | ||||
| 	 | ||||
| 	off = lseek(fs, 0, SEEK_END); | ||||
| 	if (off < 0) | ||||
| 		return -1; | ||||
| 	len = off - fw_off; | ||||
| 	lseek(fs, fw_off, SEEK_SET); | ||||
| 	if (len > maxlen) { | ||||
| 		printf("file too big\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	printf("flash file len %u, compare to %08x in flash\n", len, addr); | ||||
| 	for (j = 0; j < len; j += bl, addr += bl) { | ||||
| 		if (len - j < bl) | ||||
| 			bl = len - j; | ||||
| 		flashread(ddf->fd, buf, addr, bl); | ||||
| 		rlen = read(fs, buf2, bl); | ||||
| 		if (rlen < 0 || rlen != bl) { | ||||
| 			printf("read error\n"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 			 | ||||
| 		if (memcmp(buf, buf2, bl)) { | ||||
| 			printf("flash differs at %08x (offset %u)\n", addr, j); | ||||
| 			dump(buf, 32); | ||||
| 			dump(buf2, 32); | ||||
| 			return addr; | ||||
| 		} | ||||
| 	} | ||||
| 	printf("flash same as file\n"); | ||||
| 	return -2; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int flash_detect(struct ddflash *ddf) | ||||
| { | ||||
| 	uint8_t cmd = 0x9F; | ||||
| 	uint8_t id[3]; | ||||
| 	 | ||||
| 	int r = flashio(ddf->fd, &cmd, 1, id, 3); | ||||
| 	if (r < 0) | ||||
| 		return r; | ||||
| 	 | ||||
| 	if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x41) { | ||||
| 		ddf->flash_type = SSTI_SST25VF016B;  | ||||
| 		printf("Flash: SSTI  SST25VF016B 16 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x200000;  | ||||
| 	} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4A) { | ||||
| 		ddf->flash_type = SSTI_SST25VF032B;  | ||||
| 		printf("Flash: SSTI  SST25VF032B 32 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x400000;  | ||||
| 	} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4B) { | ||||
| 		ddf->flash_type = SSTI_SST25VF064C;  | ||||
| 		printf("Flash: SSTI  SST25VF064C 64 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x800000;  | ||||
| 	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x15) { | ||||
| 		ddf->flash_type = SPANSION_S25FL116K; | ||||
| 		printf("Flash: SPANSION S25FL116K 16 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x200000;  | ||||
| 	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x16) { | ||||
| 		ddf->flash_type = SPANSION_S25FL132K; | ||||
| 		printf("Flash: SPANSION S25FL132K 32 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x400000;  | ||||
| 	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x17) { | ||||
| 		ddf->flash_type = SPANSION_S25FL164K; | ||||
| 		printf("Flash: SPANSION S25FL164K 64 MBit\n"); | ||||
| 		ddf->sector_size = 4096;  | ||||
| 		ddf->size = 0x800000;  | ||||
| 	} else if (id[0] == 0x1F && id[1] == 0x28) { | ||||
| 		ddf->flash_type = ATMEL_AT45DB642D;  | ||||
| 		printf("Flash: Atmel AT45DB642D  64 MBit\n"); | ||||
| 		ddf->sector_size = 1024;  | ||||
| 		ddf->size = 0x800000;  | ||||
| 	} else { | ||||
| 		printf("Unknown Flash Flash ID = %02x %02x %02x\n", id[0], id[1], id[2]); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (ddf->sector_size) { | ||||
| 		ddf->buffer = malloc(ddf->sector_size); | ||||
| 		//printf("allocated buffer %08x@%08x\n", ddf->sector_size, (uint32_t) ddf->buffer); | ||||
| 		if (!ddf->buffer) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int get_id(struct ddflash *ddf) { | ||||
| 	uint8_t id[4]; | ||||
|  | ||||
| 	if (ioctl(ddf->fd, IOCTL_DDB_ID, &ddf->id) < 0) | ||||
| 		return -1; | ||||
| #if 1 | ||||
| 	printf("%04x %04x %04x %04x %08x %08x\n", | ||||
| 	       ddf->id.vendor, ddf->id.device, | ||||
| 	       ddf->id.subvendor, ddf->id.subdevice, | ||||
| 	       ddf->id.hw, ddf->id.regmap); | ||||
| #endif	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) | ||||
| { | ||||
| 	int fd, fsize, ret = 0; | ||||
| 	off_t off; | ||||
| 	uint32_t p, i; | ||||
| 	uint8_t *buf; | ||||
| 	uint8_t hdr[256]; | ||||
| 	unsigned int devid, version, length; | ||||
| 	unsigned int cid[8]; | ||||
| 	int cids = 0; | ||||
| 	uint32_t maxlen = 1024 * 1024; | ||||
| 	 | ||||
| 	fd = open(fn, O_RDONLY); | ||||
| 	if (fd < 0) { | ||||
| 		printf("%s: not found\n", fn); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	off = lseek(fd, 0, SEEK_END); | ||||
| 	if (off < 0) | ||||
| 		return -1; | ||||
| 	fsize = off; | ||||
| 	if (fsize > maxlen) { | ||||
| 		close(fd); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	lseek(fd, 0, SEEK_SET);	 | ||||
| 	buf = malloc(fsize); | ||||
| 	if (!buf) | ||||
| 		return -1; | ||||
| 	read(fd, buf, fsize); | ||||
| 	close(fd); | ||||
| 	 | ||||
| 	for (p = 0; p < fsize && buf[p]; p++) { | ||||
| 		char *key = &buf[p], *val = NULL; | ||||
|  | ||||
| 		for (; p < fsize && buf[p] != 0x0a; p++) { | ||||
| 			if (buf[p] == ':') { | ||||
| 				buf[p] = 0; | ||||
| 				val = &buf[p + 1]; | ||||
| 			} | ||||
| 		} | ||||
| 		if (val == NULL || p == fsize) | ||||
| 			break; | ||||
| 		buf[p] = 0; | ||||
| 		//printf("%-20s:%s\n", key, val); | ||||
| 		if (!strcasecmp(key, "Devid")) { | ||||
| 			sscanf(val, "%x", &devid); | ||||
| 		} else if (!strcasecmp(key, "Compat")) { | ||||
| 			cids = sscanf(val, "%x,%x,%x,%x,%x,%x,%x,%x", | ||||
| 				      &cid[0], &cid[1], &cid[2], &cid[3], | ||||
| 				      &cid[4], &cid[5], &cid[6], &cid[7]); | ||||
| 			if (cids < 1) | ||||
| 				break; | ||||
| 			for (i = 0; i < cids; i++)  | ||||
| 				if (cid[i] == ddf->id.device) | ||||
| 					break; | ||||
| 			if (i == cids) { | ||||
| 				printf("%s: no compatible id\n", fn); | ||||
| 				ret = -2; /* no compatible ID */ | ||||
| 				goto out; | ||||
| 			} | ||||
| 		} else if (!strcasecmp(key, "Version")) { | ||||
| 			if (strchr(val,'.')) { | ||||
| 				int major = 0, minor = 0; | ||||
| 				sscanf(val,"%d.%d",&major,&minor); | ||||
| 				version = (major << 16) + minor; | ||||
| 			} else | ||||
| 				sscanf(val, "%x", &version); | ||||
| 		} else if (!strcasecmp(key, "Length")) { | ||||
| 			sscanf(val, "%u", &length); | ||||
| 		}  | ||||
| 	} | ||||
| 	p++; | ||||
| 	*fw_off = p; | ||||
| 	printf("devid = %04x\n", devid); | ||||
| 	printf("version = %08x  %08x\n", version, ddf->id.hw); | ||||
| 	printf("length = %u\n", length); | ||||
| 	printf("fsize = %u, p = %u, f-p = %u\n", fsize, p, fsize - p); | ||||
| 	if (devid == ddf->id.device) { | ||||
| 		if (version <= (ddf->id.hw & 0xffffff)) { | ||||
| 			printf("%s: old version\n", fn); | ||||
| 			ret = -3; /* same id but no newer version */ | ||||
| 		} | ||||
| 	} else | ||||
| 		ret = 1; | ||||
|  | ||||
| out: | ||||
| 	free(buf); | ||||
| 	printf("check_fw = %d\n", ret); | ||||
| 	return ret; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| static int update_image(struct ddflash *ddf, char *fn,  | ||||
| 			uint32_t adr, uint32_t len, | ||||
| 			int has_header, int no_change) | ||||
| { | ||||
| 	int fs, res = 0; | ||||
| 	uint32_t fw_off = 0; | ||||
|  | ||||
| 	printf("Check %s\n", fn); | ||||
| 	if (has_header) { | ||||
| 		int ck; | ||||
| 		 | ||||
| 		ck = check_fw(ddf, fn, &fw_off); | ||||
| 		if (ck < 0) | ||||
| 			return ck; | ||||
| 		if (ck == 1 && no_change) | ||||
| 			return 0; | ||||
| 	} | ||||
| 	fs = open(fn, O_RDONLY); | ||||
| 	if (fs < 0 ) { | ||||
| 		printf("File %s not found \n", fn); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	res = flashcmp(ddf, fs, adr, len, fw_off); | ||||
| 	if (res == -2) { | ||||
| 		printf("%s: same as flash\n", fn); | ||||
| 	} | ||||
| 	if (res < 0)  | ||||
| 		goto out; | ||||
| 	res = flashwrite(ddf, fs, adr, len, fw_off); | ||||
| 	if (res == 0) { | ||||
| 		res = flashcmp(ddf, fs, adr, len, fw_off); | ||||
| 		if (res == -2) { | ||||
| 			res = 1; | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| out: | ||||
| 	close(fs); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int fexists(char *fn) | ||||
| { | ||||
| 	struct stat b; | ||||
|  | ||||
| 	return (!stat(fn, &b)); | ||||
| } | ||||
| #include "flash.c" | ||||
|  | ||||
| static int update_flash(struct ddflash *ddf) | ||||
| { | ||||
| @@ -730,6 +178,7 @@ int main(int argc, char **argv) | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	ddf.link = 0; | ||||
| 	flash = flash_detect(&ddf); | ||||
| 	if (flash < 0) | ||||
| 		return -1; | ||||
|   | ||||
| @@ -10,8 +10,10 @@ | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <linux/types.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "flash.h" | ||||
| #include "flash.c" | ||||
|  | ||||
| typedef int (*COMMAND_FUNCTION)(int dev, int argc, char* argv[], uint32_t Flags); | ||||
|  | ||||
| @@ -43,7 +45,7 @@ int ReadFlash(int ddb, int argc, char *argv[], uint32_t Flags) | ||||
| 	Start = strtoul(argv[0],NULL,16); | ||||
| 	Len   = strtoul(argv[1],NULL,16); | ||||
| 	if (argc == 3) { | ||||
| 		fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC); | ||||
| 		fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); | ||||
| 		if (fd < 0) { | ||||
| 			printf("Could not open file %s\n", argv[2]); | ||||
| 			return -1; | ||||
| @@ -51,7 +53,7 @@ int ReadFlash(int ddb, int argc, char *argv[], uint32_t Flags) | ||||
| 	} | ||||
| 	 | ||||
| 	Buffer = malloc(Len); | ||||
| 	if (flashread(ddb, Buffer, Start, Len) < 0) { | ||||
| 	if (flashread(ddb, linknr, Buffer, Start, Len) < 0) { | ||||
| 		printf("flashread error\n"); | ||||
| 		free(Buffer); | ||||
| 		return 0; | ||||
| @@ -81,7 +83,7 @@ int ReadSave(int ddb, int argc, char *argv[], uint32_t Flags) | ||||
| 	Len   = strtoul(argv[1],NULL,16); | ||||
| 		 | ||||
| 	Buffer = malloc(Len); | ||||
| 	if (flashread(ddb, Buffer, Start, Len) < 0) { | ||||
| 	if (flashread(ddb, linknr, Buffer, Start, Len) < 0) { | ||||
| 		printf("flashread error\n"); | ||||
| 		free(Buffer); | ||||
| 		return 0; | ||||
| @@ -108,12 +110,12 @@ int FlashChipEraseAtmel(int dev) | ||||
| 		Cmd[1] = ( (( i ) >> 16) & 0xFF ); | ||||
| 		Cmd[2] = ( (( i ) >>  8) & 0xFF ); | ||||
| 		Cmd[3] = 0x00; | ||||
| 		err = flashio(dev,Cmd,4,NULL,0); | ||||
| 		err = flashio(dev,linknr, Cmd,4,NULL,0); | ||||
| 		if( err < 0 )  | ||||
| 			break; | ||||
| 		while (1) { | ||||
| 			Cmd[0] = 0xD7;  // Read Status register | ||||
| 			err = flashio(dev,Cmd,1,&Cmd[0],1); | ||||
| 			err = flashio(dev,linknr, Cmd,1,&Cmd[0],1); | ||||
| 			if( err < 0 ) break; | ||||
| 			if( (Cmd[0] & 0x80) == 0x80 ) break; | ||||
| 		} | ||||
| @@ -131,25 +133,25 @@ int FlashChipEraseSSTI(int dev) | ||||
| 	 | ||||
| 	do { | ||||
| 		Cmd[0] = 0x50;  // EWSR | ||||
| 		err = flashio(dev,Cmd,1,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,1,NULL,0); | ||||
| 		if( err < 0 ) break; | ||||
| 		 | ||||
| 		Cmd[0] = 0x01;  // WRSR | ||||
| 		Cmd[1] = 0x00;  // BPx = 0, Unlock all blocks | ||||
| 		err = flashio(dev,Cmd,2,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,2,NULL,0); | ||||
| 		if( err < 0 ) break; | ||||
| 		 | ||||
| 		Cmd[0] = 0x06;  // WREN | ||||
| 		err = flashio(dev,Cmd,1,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,1,NULL,0); | ||||
| 		if( err < 0 ) break; | ||||
| 		 | ||||
| 		Cmd[0] = 0x60;  // CHIP Erase | ||||
| 		err = flashio(dev,Cmd,1,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,1,NULL,0); | ||||
| 		if( err < 0 ) break; | ||||
| 		 | ||||
| 		while(1) { | ||||
| 			Cmd[0] = 0x05;  // RDRS | ||||
| 			err = flashio(dev,Cmd,1,&Cmd[0],1); | ||||
| 			err = flashio(dev, linknr, Cmd,1,&Cmd[0],1); | ||||
| 			if( err < 0 ) break; | ||||
| 			if( (Cmd[0] & 0x01) == 0 ) break; | ||||
| 		} | ||||
| @@ -157,12 +159,12 @@ int FlashChipEraseSSTI(int dev) | ||||
| 			break; | ||||
| 		 | ||||
| 		Cmd[0] = 0x50;  // EWSR | ||||
| 		err = flashio(dev,Cmd,1,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,1,NULL,0); | ||||
| 		if( err < 0 ) break; | ||||
| 		 | ||||
| 		Cmd[0] = 0x01;  // WRSR | ||||
| 		Cmd[1] = 0x1C;  // BPx = 0, Lock all blocks | ||||
| 		err = flashio(dev,Cmd,2,NULL,0); | ||||
| 		err = flashio(dev, linknr, Cmd,2,NULL,0); | ||||
| 	} | ||||
| 	while(0); | ||||
| 	 | ||||
| @@ -332,7 +334,7 @@ int flashioc(int dev,int argc, char* argv[],uint32_t Flags) | ||||
|         Buffer[i] = (uint8_t) tmp; | ||||
|     } | ||||
|  | ||||
|     if( flashio(dev,Buffer,WriteLen,Buffer,ReadLen) < 0 ) | ||||
|     if( flashio(dev, linknr, Buffer,WriteLen,Buffer,ReadLen) < 0 ) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| @@ -384,8 +386,8 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags) | ||||
| 	int BufferSize = 0; | ||||
| 	int BlockErase = 0; | ||||
| 	uint32_t FlashOffset = 0x10000; | ||||
| 	int SectorSize = 0; | ||||
| 	int FlashSize = 0; | ||||
| 	uint32_t SectorSize = 0; | ||||
| 	uint32_t FlashSize = 0; | ||||
| 	int ValidateFPGAType = 1; | ||||
| 	int Flash; | ||||
| 	uint32_t Id1, Id2; | ||||
| @@ -402,6 +404,10 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags) | ||||
|         case SPANSION_S25FL116K: SectorSize = 4096; FlashSize = 0x200000; break; | ||||
|         case SPANSION_S25FL132K: SectorSize = 4096; FlashSize = 0x400000; break; | ||||
|         case SPANSION_S25FL164K: SectorSize = 4096; FlashSize = 0x800000; break; | ||||
| 	case WINBOND_W25Q16JV: SectorSize = 4096; FlashSize = 0x200000; break; | ||||
| 	case WINBOND_W25Q32JV: SectorSize = 4096; FlashSize = 0x400000; break; | ||||
| 	case WINBOND_W25Q64JV: SectorSize = 4096; FlashSize = 0x800000; break; | ||||
| 	case WINBOND_W25Q128JV: SectorSize = 4096; FlashSize = 0x1000000; break; | ||||
| 	} | ||||
| 	if (SectorSize == 0)  | ||||
| 		return 0; | ||||
| @@ -476,7 +482,7 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags) | ||||
| 		 | ||||
| 		int fsize = lseek(fh,0,SEEK_END); | ||||
| 		 | ||||
| 		if( fsize > 4000000 || fsize < SectorSize ) | ||||
| 		if( fsize > 5000000 || fsize < SectorSize ) | ||||
| 		{ | ||||
| 			close(fh); | ||||
| 			printf("Invalid File Size \n"); | ||||
| @@ -532,7 +538,7 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags) | ||||
| 					printf("out of memory\n"); | ||||
| 					return 0; | ||||
| 				} | ||||
| 				if (flashread(dev, CmpBuffer, FlashOffset, 0x10000)<0) { | ||||
| 				if (flashread(dev, linknr, CmpBuffer, FlashOffset, 0x10000)<0) { | ||||
| 					printf("Ioctl returns error\n"); | ||||
| 					free(Buffer); | ||||
| 					free(CmpBuffer); | ||||
| @@ -571,6 +577,10 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags) | ||||
|         case SPANSION_S25FL116K:  | ||||
|         case SPANSION_S25FL132K:  | ||||
|         case SPANSION_S25FL164K:  | ||||
| 	case WINBOND_W25Q16JV: | ||||
| 	case WINBOND_W25Q32JV: | ||||
| 	case WINBOND_W25Q64JV: | ||||
| 	case WINBOND_W25Q128JV: | ||||
| 		err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x1C); break; | ||||
| 	} | ||||
| 	 | ||||
| @@ -658,7 +668,7 @@ int FlashVerify(int dev,int argc, char* argv[],uint32_t Flags) | ||||
|         // Place our own header | ||||
|     } | ||||
| #endif | ||||
|     if (flashread(dev, Buffer2, FlashOffset, BufferSize)<0) { | ||||
|     if (flashread(dev, linknr, Buffer2, FlashOffset, BufferSize)<0) { | ||||
| 	    printf("Ioctl returns error\n"); | ||||
| 	    free(Buffer); | ||||
| 	    free(Buffer2); | ||||
| @@ -1110,7 +1120,7 @@ char *GetSerNbr(int dev) | ||||
| 	int i; | ||||
| 	 | ||||
| 	memset(Buffer,0,sizeof(Buffer)); | ||||
| 	if (flashread(dev, Buffer, Start, sizeof(Buffer) - 1)) | ||||
| 	if (flashread(dev, linknr, Buffer, Start, sizeof(Buffer) - 1)) | ||||
| 	{ | ||||
| 		printf("Ioctl returns error\n"); | ||||
| 		return NULL; | ||||
| @@ -1284,10 +1294,10 @@ int lic_erase(int dev, int argc, char* argv[], uint32_t Flags) | ||||
|  | ||||
| static int read_sfpd(int dev, uint8_t adr, uint8_t *val) | ||||
| { | ||||
| 	uint8_t cmd[5] = { 0x5a, 0, 0, adr, 00 };      | ||||
| 	uint8_t cmd[5] = { 0x5a, 0, 0, adr, 0 };      | ||||
| 	int r; | ||||
| 	 | ||||
| 	r = flashio(dev, cmd, 5, val, 1); | ||||
| 	r = flashio(dev, linknr,  cmd, 5, val, 1); | ||||
| 	if (r < 0) | ||||
| 		return r; | ||||
| 	return 0; | ||||
| @@ -1299,13 +1309,24 @@ static int read_sst_id(int dev, uint8_t *id) | ||||
| 	uint8_t buf[9]; | ||||
| 	int r; | ||||
| 	 | ||||
| 	r = flashio(dev, cmd, 2, buf, 9); | ||||
| 	r = flashio(dev, linknr,  cmd, 2, buf, 9); | ||||
| 	if (r < 0) | ||||
| 		return r; | ||||
| 	memcpy(id, buf + 1, 8); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int read_winbd(int dev, uint8_t *val) | ||||
| { | ||||
| 	uint8_t cmd[5] = { 0x4b, 0, 0, 0, 0 };      | ||||
| 	int r; | ||||
| 	 | ||||
| 	r = flashio(dev, linknr,  cmd, 5, val, 8); | ||||
| 	if (r < 0) | ||||
| 		return r; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int read_id(int dev, int argc, char* argv[], uint32_t Flags) | ||||
| { | ||||
| 	int Flash = FlashDetect(dev); | ||||
| @@ -1315,6 +1336,13 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags) | ||||
| 	 | ||||
| 	 | ||||
| 	switch(Flash) { | ||||
| 	case WINBOND_W25Q16JV: | ||||
| 	case WINBOND_W25Q32JV: | ||||
| 	case WINBOND_W25Q64JV: | ||||
| 	case WINBOND_W25Q128JV: | ||||
| 		read_winbd(dev, Id); | ||||
| 		len = 8; | ||||
| 		break; | ||||
|         case SPANSION_S25FL116K: | ||||
|         case SPANSION_S25FL132K: | ||||
|         case SPANSION_S25FL164K: | ||||
|   | ||||
							
								
								
									
										285
									
								
								apps/octonet/ddupdate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								apps/octonet/ddupdate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,285 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
| #include <errno.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <linux/types.h> | ||||
|  | ||||
| #include "flash.h" | ||||
| #include "flash.c" | ||||
|  | ||||
| static int verbose = 0; | ||||
|  | ||||
| static int yesno() | ||||
| { | ||||
| 	char c; | ||||
|  | ||||
| 	printf("\n\nNew firmware available\nReally flash now? y/n\n"); | ||||
| 	fflush(0); | ||||
| 	c = getchar(); | ||||
| 	if (c!='y') { | ||||
| 		printf("\nFlashing aborted.\n\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	printf("\nStarting to flash\n\n"); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int update_flash(struct ddflash *ddf) | ||||
| { | ||||
| 	char *fname, *default_fname; | ||||
| 	int res, stat = 0; | ||||
| 	char *name = 0, *dname; | ||||
| 	 | ||||
| 	switch (ddf->id.device) { | ||||
| 	case 0x300: | ||||
| 	case 0x301: | ||||
| 	case 0x302: | ||||
| 	case 0x307: | ||||
| 		if ((res = update_image(ddf, "/boot/bs.img", 0x4000, 0x1000, 0, 0)) == 1) | ||||
| 			stat |= 4; | ||||
| 		if ((res = update_image(ddf, "/boot/uboot.img", 0xb0000, 0xb0000, 0, 0)) == 1) | ||||
| 			stat |= 2; | ||||
| 		if (fexists("/config/gtl.enabled")) { | ||||
| 			if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1) | ||||
| 				stat |= 1; | ||||
| 			if (res == -1) | ||||
| 				if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1) | ||||
| 					stat |= 1; | ||||
| 		} else if (fexists("/config/gtl.disabled")) { | ||||
| 			if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1) | ||||
| 				stat |= 1; | ||||
| 			if (res == -1) | ||||
| 				if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1) | ||||
| 					stat |= 1; | ||||
| 		} else { | ||||
| 			if (ddf->id.device == 0x0307) { | ||||
| 				if (res == -1) | ||||
| 					if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1) | ||||
| 						stat |= 1; | ||||
| 				if (res == -1) | ||||
| 					if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1) | ||||
| 						stat |= 1; | ||||
| 			} else { | ||||
| 				if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1) | ||||
| 					stat |= 1; | ||||
| 				if (res == -1) | ||||
| 					if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1) | ||||
| 						stat |= 1; | ||||
| 			} | ||||
| 		} | ||||
| #if 1 | ||||
| 		if ( (stat&1) && (ddf->id.hw & 0xffffff) <= 0x010001) {		 | ||||
| 			if (ddf->id.device == 0x0307) { | ||||
| 				if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1) | ||||
| 					stat |= 1; | ||||
| 				if (res == -1) | ||||
| 					if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1) | ||||
| 						stat |= 1; | ||||
| 			} else { | ||||
| 				if ((res = update_image(ddf, "/config/fpga.img", 0x160000, 0x80000, 1, 0)) == 1) | ||||
| 					stat |= 1; | ||||
| 				if (res == -1) | ||||
| 					if ((res = update_image(ddf, "/boot/fpga.img", 0x160000, 0x80000, 1, 0)) == 1) | ||||
| 						stat |= 1; | ||||
| 			 | ||||
| 			} | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		break; | ||||
| 	case 0x320: | ||||
| 		//fname="/boot/DVBNetV1A_DD01_0300.bit"; | ||||
| 		fname="/boot/fpga.img"; | ||||
| 		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1) | ||||
| 			stat |= 1; | ||||
| 		return stat; | ||||
| 		break; | ||||
| 	case 0x322: | ||||
| 		//fname="/boot/DVBNetV1A_DD01_0300.bit"; | ||||
| 		fname="/boot/fpga.img"; | ||||
| 		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1) | ||||
| 			stat |= 1; | ||||
| 		return stat; | ||||
| 		break; | ||||
| 	default: | ||||
| 		fname = ddf->fname; | ||||
| 		default_fname = devid2fname(ddf->id.device, &name); | ||||
| 		if (!fname) | ||||
| 			fname = default_fname; | ||||
| 		if (name) | ||||
| 			printf("Card:     %s\n", name); | ||||
| 		if (ddf->flash_name) | ||||
| 			printf("Flash:    %s\n", ddf->flash_name); | ||||
| 		printf("Version:  %08x\n", ddf->id.hw); | ||||
| 		printf("REGMAP :  %08x\n", ddf->id.regmap); | ||||
| 		if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1) | ||||
| 			stat |= 1; | ||||
| 		return stat; | ||||
| 	} | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int update_link(struct ddflash *ddf) | ||||
| { | ||||
| 	int ret; | ||||
| 	 | ||||
| 	ret = flash_detect(ddf); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	ret = update_flash(ddf); | ||||
|  | ||||
| 	if (ddf->buffer) | ||||
| 		free(ddf->buffer); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int update_card(int ddbnum, char *fname, int force) | ||||
| { | ||||
| 	struct ddflash ddf; | ||||
| 	char ddbname[80]; | ||||
| 	struct ddb_id ddbid; | ||||
| 	int ddb, ret, link, links; | ||||
| 	 | ||||
| 	sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum); | ||||
| 	ddb = open(ddbname, O_RDWR); | ||||
| 	if (ddb < 0) | ||||
| 		return -3; | ||||
| 	ddf.fd = ddb; | ||||
| 	ddf.link = 0; | ||||
| 	ddf.fname = fname; | ||||
| 	ddf.force = force; | ||||
| 	links = 1; | ||||
|  | ||||
| 	for (link = 0; link < links; link++) { | ||||
| 		ddf.link = link; | ||||
| 		if (verbose >= 2) | ||||
| 			printf("Get id card %u link %u\n", ddbnum, link); | ||||
| 		ret = get_id(&ddf); | ||||
| 		if (ret < 0) | ||||
| 			goto out; | ||||
| 		if (!link) { | ||||
| 			switch (ddf.id.device) { | ||||
| 			case 0x20: | ||||
| 				links = 4; | ||||
| 				break; | ||||
| 			case 0x300: | ||||
| 			case 0x301: | ||||
| 			case 0x307: | ||||
| 				links = 2; | ||||
| 				break; | ||||
| 			 | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		//printf("%08x %08x\n", ddf.id.device, ddf.id.subdevice); | ||||
| 		if (ddf.id.device) { | ||||
| 			printf("\n\nUpdate card %s link %u:\n", ddbname, link); | ||||
| 			ret = update_link(&ddf); | ||||
| 			//if (ret < 0) | ||||
| 			//	break; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| out: | ||||
| 	close(ddb); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int usage() | ||||
| { | ||||
| 	printf("ddupdate [OPTION]\n\n" | ||||
| 	       "-n N\n  only update card N (default with N=0)\n\n" | ||||
| 	       "-a \n   update all cards\n\n" | ||||
| 	       "-b file\n  fpga image file override (ignored if -a is used)\n\n" | ||||
| 	       "-f  \n  force  update\n\n" | ||||
| 	       "-v \n   more verbose (up to -v -v -v)\n\n" | ||||
| 		); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	int ddbnum = -1, all = 0, i, force = 0, reboot_len = -1; | ||||
| 	char *fname = 0; | ||||
| 	int ret; | ||||
| 	 | ||||
|         while (1) { | ||||
|                 int option_index = 0; | ||||
| 		int c; | ||||
|                 static struct option long_options[] = { | ||||
| 			{"reboot", optional_argument , NULL, 'r'}, | ||||
| 			{"help", no_argument , NULL, 'h'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
|                 c = getopt_long(argc, argv,  | ||||
| 				"n:havfb:r::", | ||||
| 				long_options, &option_index); | ||||
| 		if (c==-1) | ||||
| 			break; | ||||
|  | ||||
| 		switch (c) { | ||||
| 		case 'b': | ||||
| 			fname = optarg; | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			ddbnum = strtol(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'a': | ||||
| 			all = 1; | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			force = 1; | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			verbose++; | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			if (optarg) | ||||
| 				reboot_len = strtol(optarg, NULL, 0); | ||||
| 			else  | ||||
| 				reboot_len = 40; | ||||
| 			if (!reboot_len) | ||||
| 				reboot(40); | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 			usage(); | ||||
| 			return 0; | ||||
| 		default: | ||||
| 			break; | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("Warning: unused arguments\n"); | ||||
| 	} | ||||
| 	if (!all && (ddbnum < 0)) { | ||||
| 		printf("Select card number or all cards\n\n"); | ||||
| 		usage(); | ||||
| 		return -1; | ||||
| 	} | ||||
| 		 | ||||
| 	if (!all) | ||||
| 		ret = update_card(ddbnum, fname, force); | ||||
| 	else | ||||
| 		for (i = 0; i < 100; i++) { | ||||
| 			ret = update_card(i, 0, 0); | ||||
| 			 | ||||
| 			if (ret == -3)     /* could not open, no more cards! */ | ||||
| 				break;  | ||||
| 			if (ret < 0) | ||||
| 				return i; /* fatal error */  | ||||
| 			if (verbose >= 1) | ||||
| 				printf("card %d up to date\n", i); | ||||
| 		} | ||||
| 	if (reboot_len > 0) | ||||
| 		reboot(reboot_len); | ||||
| 	return 0;  | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -62,4 +62,46 @@ struct ddb_i2c_msg { | ||||
| #define IOCTL_DDB_READ_I2C   _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) | ||||
| #define IOCTL_DDB_WRITE_I2C  _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) | ||||
|  | ||||
| #include "flash.c" | ||||
| enum { | ||||
| 	UNKNOWN_FLASH = 0, | ||||
| 	ATMEL_AT45DB642D = 1, | ||||
| 	SSTI_SST25VF016B = 2, | ||||
| 	SSTI_SST25VF032B = 3, | ||||
| 	SSTI_SST25VF064C = 4, | ||||
| 	SPANSION_S25FL116K = 5, | ||||
| 	SPANSION_S25FL132K = 6, | ||||
| 	SPANSION_S25FL164K = 7, | ||||
| 	WINBOND_W25Q16JV = 8, | ||||
| 	WINBOND_W25Q32JV = 9, | ||||
| 	WINBOND_W25Q64JV = 10, | ||||
| 	WINBOND_W25Q128JV = 11, | ||||
| }; | ||||
|  | ||||
| struct flash_info { | ||||
| 	uint8_t id[3]; | ||||
| 	uint32_t type; | ||||
| 	uint32_t ssize; | ||||
| 	uint32_t fsize; | ||||
| 	char *name; | ||||
| }; | ||||
|  | ||||
| struct ddflash { | ||||
| 	int fd; | ||||
| 	uint32_t link; | ||||
| 	char *fname; | ||||
| 	int force; | ||||
| 	 | ||||
| 	struct ddb_id id; | ||||
| 	uint32_t version; | ||||
|  | ||||
| 	char    *flash_name; | ||||
| 	uint32_t flash_type; | ||||
| 	uint32_t sector_size; | ||||
| 	uint32_t size; | ||||
|  | ||||
| 	uint32_t bufsize; | ||||
| 	uint32_t block_erase; | ||||
|  | ||||
| 	uint8_t *buffer; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -147,7 +147,7 @@ int main(int argc, char **argv) | ||||
| 	if (gold != 0xffffffff) { | ||||
| 		if (gold < 0x3ffff) { | ||||
| 			root = gold2root(gold); | ||||
| 			printf("gold = %llu (0x%05x)   root = %llu (0x%05x)\n", | ||||
| 			printf("gold = %u (0x%05x)   root = %u (0x%05x)\n", | ||||
| 			       gold, gold, root, root); | ||||
| 		} else | ||||
| 			printf("Invalid gold code specified.\n"); | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| #include <fcntl.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <pthread.h> | ||||
| #include <getopt.h> | ||||
|  | ||||
| #include <linux/dvb/mod.h> | ||||
|  | ||||
| @@ -51,33 +52,98 @@ static int get_property(int fd, uint32_t cmd, uint32_t *data) | ||||
|  | ||||
|  | ||||
|  | ||||
| int main() | ||||
| int main(int argc, char*argv[]) | ||||
| { | ||||
| 	int fd; | ||||
| 	struct dvb_mod_params mp; | ||||
| 	struct dvb_mod_channel_params mc; | ||||
| 	uint32_t data; | ||||
| 	int32_t adapter = 0, channel = 0, gain = -1; | ||||
| 	int32_t base = -1, freq = -1, rate = -1; | ||||
| 	char mod_name[128]; | ||||
| 	 | ||||
| 	while (1) { | ||||
| 		int cur_optind = optind ? optind : 1; | ||||
| 		int option_index = 0; | ||||
| 		int c; | ||||
| 		static struct option long_options[] = { | ||||
| 			{"adapter", required_argument, 0, 'a'}, | ||||
| 			{"channel", required_argument, 0, 'c'}, | ||||
| 			{"gain", required_argument, 0, 'g'}, | ||||
| 			{"base", required_argument, 0, 'b'}, | ||||
| 			{"frequency", required_argument, 0, 'f'}, | ||||
| 			{"rate", required_argument, 0, 'r'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
|                 c = getopt_long(argc, argv,  | ||||
| 				"a:c:g:b:f:r:", | ||||
| 				long_options, &option_index); | ||||
| 		if (c==-1) | ||||
| 			break; | ||||
|  | ||||
| 		switch (c) { | ||||
| 		case 'a': | ||||
| 			adapter = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			channel = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'g': | ||||
| 			gain = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'b': | ||||
| 			base = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			freq = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			if (!strcmp(optarg, "DVBT_8")) | ||||
| 				rate = SYS_DVBT_8; | ||||
| 			else if (!strcmp(optarg, "DVBT_7")) | ||||
| 				rate = SYS_DVBT_7; | ||||
| 			else if (!strcmp(optarg, "DVBT_6")) | ||||
| 				rate = SYS_DVBT_6; | ||||
| 			else if (!strcmp(optarg, "ISDBT_6")) | ||||
| 				rate = SYS_ISDBT_6; | ||||
| 			else rate = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	snprintf(mod_name, 127, "/dev/dvb/adapter%d/mod%d", adapter, channel); | ||||
| 	fd = open(mod_name, O_RDONLY); | ||||
| 	 | ||||
| 	if (fd < 0)  { | ||||
| 		printf("Could not open modulator device.\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 		 | ||||
| 	fd = open("/dev/dvb/adapter0/mod0", O_RDONLY); | ||||
| 	 | ||||
| 	/* gain 0-255 */ | ||||
| 	get_property(fd, MODULATOR_GAIN, &data); | ||||
| 	printf("Modulator gain = %u\n", data); | ||||
| 	set_property(fd, MODULATOR_GAIN, 100); | ||||
| 	//get_property(fd, MODULATOR_GAIN, &data); | ||||
| 	//printf("Modulator gain = %u\n", data); | ||||
| 	//set_property(fd, MODULATOR_GAIN, 100); | ||||
|  | ||||
| 	get_property(fd, MODULATOR_GAIN, &data); | ||||
| 	printf("Modulator gain = %u\n", data); | ||||
| 	//get_property(fd, MODULATOR_ATTENUATOR, &data); | ||||
| 	//printf("Modulator attenuator = %u\n", data); | ||||
|  | ||||
| 	get_property(fd, MODULATOR_ATTENUATOR, &data); | ||||
| 	printf("Modulator attenuator = %u\n", data); | ||||
| 	if (gain > 0) | ||||
| 		set_property(fd, MODULATOR_GAIN, gain); | ||||
| 	if (base > 0) | ||||
| 		set_property(fd, MODULATOR_BASE_FREQUENCY, base); | ||||
| 	if (freq > 0) | ||||
| 		set_property(fd, MODULATOR_FREQUENCY, freq); | ||||
| 	if (rate > 0) | ||||
| 		set_property(fd, MODULATOR_OUTPUT_RATE, rate); | ||||
| 	 | ||||
| 	 | ||||
| 	get_property(fd, MODULATOR_STATUS, &data); | ||||
| 	printf("Modulator status = %u\n", data); | ||||
| 	set_property(fd, MODULATOR_STATUS, 2); | ||||
| 	 | ||||
| 	 | ||||
| 	//set_property(fd, MODULATOR_RESET, 0); | ||||
| 	close(fd); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										105
									
								
								apps/tscheck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								apps/tscheck.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| #include <stdio.h> | ||||
| #include <ctype.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <fcntl.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <linux/dvb/dmx.h> | ||||
| #include <linux/dvb/frontend.h> | ||||
| #include <linux/dvb/video.h> | ||||
|  | ||||
| char line_start[16] = ""; | ||||
| char line_end[16]   = "\r"; | ||||
|  | ||||
|  | ||||
| uint32_t cc_errors = 0; | ||||
| uint32_t packets = 0; | ||||
| uint32_t payload_packets = 0; | ||||
| uint32_t packet_errors = 0; | ||||
|  | ||||
| uint8_t cc[8192] = { 0 }; | ||||
|  | ||||
| void proc_ts(int i, uint8_t *buf) | ||||
| { | ||||
| 	uint16_t pid= 0x1fff& ((buf[1] << 8) | buf[2]); | ||||
| 	uint8_t ccin = buf[3] & 0x1f; | ||||
|  | ||||
| 	if( buf[0] == 0x47 && (buf[1] & 0x80) == 0) { | ||||
| 		if( pid != 8191 ) { | ||||
| 			if (ccin & 0x10) { | ||||
| 				if( cc[pid] != 0 ) { | ||||
| 					// TODO: 1 repetition allowed | ||||
| 					if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) )  { | ||||
| 						cc_errors += 1; | ||||
| 						printf("%04x: %u != %u\n", pid, (cc[pid] + 1) & 0x0F, ccin & 0x0F); | ||||
| 					} | ||||
| 				} | ||||
| 				cc[pid] = ccin; | ||||
| 			} | ||||
| 			payload_packets += 1; | ||||
| 		} | ||||
| 	} else | ||||
| 		packet_errors += 1; | ||||
| 	 | ||||
| 	if( (packets & 0x3FFF ) == 0) { | ||||
| 		printf("%s  Packets: %12u non null %12u, errors: %12u, CC errors: %12u%s", | ||||
| 		       line_start, packets, payload_packets, packet_errors, cc_errors, line_end); | ||||
| 		fflush(stdout); | ||||
| 	} | ||||
| 	packets += 1;   | ||||
| } | ||||
|  | ||||
| #define TSBUFSIZE (100*188) | ||||
|  | ||||
| void citest(char* n) | ||||
| { | ||||
| 	uint8_t *buf; | ||||
| 	uint8_t id; | ||||
| 	int i, nts; | ||||
| 	int len; | ||||
| 	int ts=open(n, O_RDONLY); | ||||
| 	buf=(uint8_t *)malloc(TSBUFSIZE); | ||||
| 	 | ||||
| 	 | ||||
| 	while(1) { | ||||
| 		len=read(ts, buf, TSBUFSIZE); | ||||
| 		if (len<0) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (buf[0]!=0x47) { | ||||
| 			read(ts, buf, 1); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (len%188) { /* should not happen */ | ||||
| 			printf("blah\n"); | ||||
| 			continue; | ||||
| 		} | ||||
| 		nts=len/188; | ||||
| 		for (i=0; i<nts; i++) | ||||
| 			proc_ts(i, buf+i*188); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
| 	if( argc < 2 ) | ||||
| 	{ | ||||
| 		printf("tscheck <file>|<device> [<display line>]\n"); | ||||
| 		exit(0); | ||||
| 	} | ||||
| 	if( argc > 2 ) | ||||
| 	{ | ||||
| 		int line = atoi(argv[2]); | ||||
| 		if( line >= 0 && line < 64 ) | ||||
| 		{ | ||||
| 			snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line); | ||||
| 			strncpy(line_end,"\0338",sizeof(line_end)-1); | ||||
| 		} | ||||
| 	} | ||||
| 	citest(argv[1]); | ||||
| } | ||||
|  | ||||
| @@ -1,11 +1,17 @@ | ||||
| EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET | ||||
|  | ||||
| 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 | ||||
| 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 | ||||
| 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 | ||||
|  | ||||
| obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.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 | ||||
|  | ||||
| #mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o | ||||
|  | ||||
| ifneq ($(KERNEL_DVB_CORE),y) | ||||
| obj-$(CONFIG_DVB_OCTONET) += octonet.o | ||||
| endif | ||||
|  | ||||
| EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends | ||||
| EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||||
| NOSTDINC_FLAGS += -I$(SUBDIRS)/frontends -I$(SUBDIRS)/include -I$(SUBDIRS)/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 | ||||
| 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 | ||||
| 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/ | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| # Makefile for the ddbridge device driver | ||||
| # | ||||
|  | ||||
| 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 | ||||
| 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 | ||||
| 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-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 | ||||
| obj-$(CONFIG_DVB_OCTONET) += octonet.o | ||||
| @@ -11,4 +11,5 @@ 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 += --include=dd_compat.h | ||||
|  | ||||
|   | ||||
| @@ -1,24 +1,22 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-ci.c: Digital Devices bridge and DuoFlex CI driver | ||||
|  * | ||||
|  * Copyright (C) 2010-2017 Digital Devices GmbH | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * version 2 only, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| @@ -107,7 +105,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) | ||||
|  | ||||
| 	ddbwritel(ci->port->dev, CI_POWER_ON, | ||||
| 		  CI_CONTROL(ci->nr)); | ||||
| 	msleep(100); | ||||
| 	msleep(300); | ||||
| 	ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, | ||||
| 		  CI_CONTROL(ci->nr)); | ||||
| 	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, | ||||
| @@ -238,7 +236,7 @@ static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) | ||||
|  | ||||
| 	write_creg(ci, 0x01, 0x01); | ||||
| 	write_creg(ci, 0x04, 0x04); | ||||
| 	msleep(20); | ||||
| 	msleep(300); | ||||
| 	write_creg(ci, 0x02, 0x02); | ||||
| 	write_creg(ci, 0x00, 0x04); | ||||
| 	write_creg(ci, 0x18, 0x18); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-hw.c: Digital Devices device information tables | ||||
|  * | ||||
| @@ -18,8 +19,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| @@ -124,6 +124,32 @@ static const struct ddb_regset octopus_i2c_buf = { | ||||
|  | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_regset max_mci = { | ||||
| 	.base = 0x500, | ||||
| 	.num  = 0x01, | ||||
| 	.size = 0x04, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset max_mci_buf = { | ||||
| 	.base = 0x600, | ||||
| 	.num  = 0x01, | ||||
| 	.size = 0x100, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset sdr_mci = { | ||||
| 	.base = 0x260, | ||||
| 	.num  = 0x01, | ||||
| 	.size = 0x04, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset sdr_mci_buf = { | ||||
| 	.base = 0x300, | ||||
| 	.num  = 0x01, | ||||
| 	.size = 0x100, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_regset octopro_input = { | ||||
| 	.base = 0x400, | ||||
| 	.num  = 0x14, | ||||
| @@ -181,6 +207,33 @@ static const struct ddb_regset octopro_gtl = { | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_regset gtl_mini_input = { | ||||
| 	.base = 0x400, | ||||
| 	.num  = 0x14, | ||||
| 	.size = 0x10, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset gtl_mini_idma = { | ||||
| 	.base = 0x800, | ||||
| 	.num  = 0x40, | ||||
| 	.size = 0x10, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset gtl_mini_idma_buf = { | ||||
| 	.base = 0x4000, | ||||
| 	.num  = 0x40, | ||||
| 	.size = 0x100, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regset gtl_mini_gtl = { | ||||
| 	.base = 0xe00, | ||||
| 	.num  = 0x03, | ||||
| 	.size = 0x40, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_regmap octopus_map = { | ||||
| 	.irq_version = 1, | ||||
| 	.irq_base_i2c = 0, | ||||
| @@ -193,9 +246,29 @@ static const struct ddb_regmap octopus_map = { | ||||
| 	.odma = &octopus_odma, | ||||
| 	.odma_buf = &octopus_odma_buf, | ||||
| 	.input = &octopus_input, | ||||
|  | ||||
| 	.output = &octopus_output, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regmap octopus_mci_map = { | ||||
| 	.irq_version = 1, | ||||
| 	.irq_base_i2c = 0, | ||||
| 	.irq_base_idma = 8, | ||||
| 	.irq_base_odma = 16, | ||||
| 	.irq_base_mci = 0, | ||||
| 	.i2c = &octopus_i2c, | ||||
| 	.i2c_buf = &octopus_i2c_buf, | ||||
| 	.idma = &octopus_idma, | ||||
| 	.idma_buf = &octopus_idma_buf, | ||||
| 	.odma = &octopus_odma, | ||||
| 	.odma_buf = &octopus_odma_buf, | ||||
| 	.input = &octopus_input, | ||||
| 	.output = &octopus_output, | ||||
|  | ||||
| 	.mci = &max_mci, | ||||
| 	.mci_buf = &max_mci_buf, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regmap octopro_map = { | ||||
| 	.irq_version = 2, | ||||
| 	.irq_base_i2c = 32, | ||||
| @@ -242,20 +315,40 @@ static const struct ddb_regmap octopus_mod_2_map = { | ||||
| 	.irq_version = 2, | ||||
| 	.irq_base_odma = 64, | ||||
| 	.irq_base_rate = 32, | ||||
| 	.irq_base_mci = 10, | ||||
| 	.output = &octopus_output, | ||||
| 	.odma = &octopus_mod_2_odma, | ||||
| 	.odma_buf = &octopus_mod_2_odma_buf, | ||||
| 	.channel = &octopus_mod_2_channel, | ||||
|  | ||||
| 	.mci = &sdr_mci, | ||||
| 	.mci_buf = &sdr_mci_buf, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regmap octopus_sdr_map = { | ||||
| 	.irq_version = 2, | ||||
| 	.irq_base_odma = 64, | ||||
| 	.irq_base_rate = 32, | ||||
| 	.irq_base_mci = 10, | ||||
| 	.output = &octopus_sdr_output, | ||||
| 	.odma = &octopus_mod_2_odma, | ||||
| 	.odma_buf = &octopus_mod_2_odma_buf, | ||||
| 	.channel = &octopus_mod_2_channel, | ||||
|  | ||||
| 	.mci = &sdr_mci, | ||||
| 	.mci_buf = &sdr_mci_buf, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_regmap gtl_mini = { | ||||
| 	.irq_version = 2, | ||||
| 	.irq_base_i2c = 32, | ||||
| 	.irq_base_idma = 64, | ||||
| 	.irq_base_odma = 128, | ||||
| 	.irq_base_gtl = 8, | ||||
| 	.idma = >l_mini_idma, | ||||
| 	.idma_buf = >l_mini_idma_buf, | ||||
| 	.input = >l_mini_input, | ||||
| 	.gtl = >l_mini_gtl, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
| @@ -468,7 +561,7 @@ static const struct ddb_info ddb_mod_fsm_8 = { | ||||
|  | ||||
| static const struct ddb_info ddb_mod_fsm_4 = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices DVB-C modulator FSM-8", | ||||
| 	.name     = "Digital Devices DVB-C modulator FSM-4", | ||||
| 	.version  = 2, | ||||
| 	.regmap   = &octopus_mod_2_map, | ||||
| 	.port_num = 4, | ||||
| @@ -477,10 +570,51 @@ static const struct ddb_info ddb_mod_fsm_4 = { | ||||
| 	.lostlock_irq = 9, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_sdr = { | ||||
| static const struct ddb_info ddb_mod_fsm = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices SDR", | ||||
| 	.version  = 3, | ||||
| 	.name     = "Digital Devices DVB-C FSM", | ||||
| 	.version  = 2, | ||||
| 	.regmap   = &octopus_mod_2_map, | ||||
| 	.port_num = 0, | ||||
| 	.temp_num = 1, | ||||
| 	.tempmon_irq = 8, | ||||
| 	.lostlock_irq = 9, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_sdr_atv = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices SDR ATV", | ||||
| 	.version  = 16, | ||||
| 	.regmap   = &octopus_sdr_map, | ||||
| 	.port_num = 16, | ||||
| 	.temp_num = 1, | ||||
| 	.tempmon_irq = 8, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_sdr_iq = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices SDR IQ", | ||||
| 	.version  = 17, | ||||
| 	.regmap   = &octopus_sdr_map, | ||||
| 	.port_num = 16, | ||||
| 	.temp_num = 1, | ||||
| 	.tempmon_irq = 8, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_sdr_iq2 = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices SDR IQ2", | ||||
| 	.version  = 17, | ||||
| 	.regmap   = &octopus_sdr_map, | ||||
| 	.port_num = 4, | ||||
| 	.temp_num = 1, | ||||
| 	.tempmon_irq = 8, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_sdr_dvbt = { | ||||
| 	.type     = DDB_MOD, | ||||
| 	.name     = "Digital Devices DVBT", | ||||
| 	.version  = 18, | ||||
| 	.regmap   = &octopus_sdr_map, | ||||
| 	.port_num = 16, | ||||
| 	.temp_num = 1, | ||||
| @@ -508,7 +642,7 @@ static const struct ddb_info ddb_octopro = { | ||||
| static const struct ddb_info ddb_s2_48 = { | ||||
| 	.type     = DDB_OCTOPUS_MAX, | ||||
| 	.name     = "Digital Devices MAX S8 4/8", | ||||
| 	.regmap   = &octopus_map, | ||||
| 	.regmap   = &octopus_mci_map, | ||||
| 	.port_num = 4, | ||||
| 	.i2c_mask = 0x01, | ||||
| 	.board_control = 1, | ||||
| @@ -575,10 +709,24 @@ static const struct ddb_info ddb_c2t2i_8 = { | ||||
| 	.tempmon_irq = 24, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_info ddb_s2x_48 = { | ||||
| 	.type     = DDB_OCTOPUS_MCI, | ||||
| 	.name     = "Digital Devices MAX SX8", | ||||
| 	.regmap   = &octopus_map, | ||||
| 	.regmap   = &octopus_mci_map, | ||||
| 	.port_num = 4, | ||||
| 	.i2c_mask = 0x00, | ||||
| 	.tempmon_irq = 24, | ||||
| 	.mci_ports = 4, | ||||
| 	.mci_type = 0, | ||||
| 	.temp_num = 1, | ||||
| }; | ||||
|  | ||||
| static const struct ddb_info ddb_s2x_48_b = { | ||||
| 	.type     = DDB_OCTOPUS_MCI, | ||||
| 	.name     = "Digital Devices MAX SX8 Basic", | ||||
| 	.regmap   = &octopus_mci_map, | ||||
| 	.port_num = 4, | ||||
| 	.i2c_mask = 0x00, | ||||
| 	.tempmon_irq = 24, | ||||
| @@ -590,7 +738,7 @@ static const struct ddb_info ddb_s2x_48 = { | ||||
| static const struct ddb_info ddb_m4 = { | ||||
| 	.type     = DDB_OCTOPUS_MCI, | ||||
| 	.name     = "Digital Devices MAX M4", | ||||
| 	.regmap   = &octopus_map, | ||||
| 	.regmap   = &octopus_mci_map, | ||||
| 	.port_num = 2, | ||||
| 	.i2c_mask = 0x00, | ||||
| 	.tempmon_irq = 24, | ||||
| @@ -599,6 +747,17 @@ static const struct ddb_info ddb_m4 = { | ||||
| 	.temp_num = 1, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static const struct ddb_info ddb_gtl_mini = { | ||||
| 	.type     = DDB_OCTOPUS, | ||||
| 	.name     = "Digital Devices Octopus GT Mini", | ||||
| 	.regmap   = >l_mini, | ||||
| 	.port_num = 0, | ||||
| 	.i2c_mask = 0x00, | ||||
| 	.ns_num   = 0, | ||||
| }; | ||||
|  | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| @@ -712,22 +871,29 @@ static const struct ddb_device_id ddb_device_ids[] = { | ||||
| 	DDB_DEVID(0x0009, 0x0025, ddb_s2x_48), | ||||
| 	DDB_DEVID(0x0006, 0x0039, ddb_ctv7), | ||||
| 	DDB_DEVID(0x000a, 0x0050, ddb_m4), | ||||
| 	DDB_DEVID(0x000b, 0x0026, ddb_s2x_48_b), | ||||
| 	DDB_DEVID(0x0011, 0x0040, ddb_ci), | ||||
| 	DDB_DEVID(0x0011, 0x0041, ddb_cis), | ||||
| 	DDB_DEVID(0x0012, 0x0042, ddb_ci), | ||||
| 	DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro), | ||||
| 	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 ! */ | ||||
| 	DDB_DEVID(0x0203, 0x0001, ddb_mod), | ||||
| 	DDB_DEVID(0x0210, 0x0004, ddb_mod_fsm), /* dummy entry ! */ | ||||
| 	DDB_DEVID(0x0210, 0x0000, ddb_mod_fsm_4), /* dummy entry ! */ | ||||
| 	DDB_DEVID(0x0210, 0x0001, ddb_mod_fsm_24), | ||||
| 	DDB_DEVID(0x0210, 0x0002, ddb_mod_fsm_16), | ||||
| 	DDB_DEVID(0x0210, 0x0003, ddb_mod_fsm_8), | ||||
| 	DDB_DEVID(0x0220, 0x0001, ddb_sdr), | ||||
| 	DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv), | ||||
| 	DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq), | ||||
| 	DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt), | ||||
| 	DDB_DEVID(0x0223, 0x0001, ddb_sdr_iq2), | ||||
| 	DDB_DEVID(0xffff, 0xffff, ddb_sdr_iq2), | ||||
|  | ||||
| 	/* testing on OctopusNet Pro */ | ||||
| 	DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin), | ||||
| @@ -736,6 +902,8 @@ static const struct ddb_device_id ddb_device_ids[] = { | ||||
| 	DDB_DEVID(0x0323, 0xffff, ddb_none), | ||||
| 	DDB_DEVID(0x0328, 0xffff, ddb_none), | ||||
| 	DDB_DEVID(0x0329, 0xffff, ddb_octopro_hdin), | ||||
|  | ||||
| 	DDB_DEVID(0xffff, 0xffff, ddb_none), | ||||
| }; | ||||
|  | ||||
| const struct ddb_info *get_ddb_info(u16 vendor, u16 device, | ||||
| @@ -748,7 +916,8 @@ const struct ddb_info *get_ddb_info(u16 vendor, u16 device, | ||||
|  | ||||
| 		if (vendor == id->vendor && | ||||
| 		    device == id->device && | ||||
| 		    subvendor == id->subvendor && | ||||
| 		    (subvendor == id->subvendor || | ||||
| 		     id->subvendor == 0xffff) && | ||||
| 		    (subdevice == id->subdevice || | ||||
| 		     id->subdevice == 0xffff)) | ||||
| 			return id->info; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-i2c.c: Digital Devices bridge i2c driver | ||||
|  * | ||||
| @@ -5,6 +6,7 @@ | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  * | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * version 2 only, as published by the Free Software Foundation. | ||||
| @@ -17,8 +19,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| @@ -34,38 +35,35 @@ 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; | ||||
| 	if (val == 0x20000) | ||||
| 		dev_err(dev->dev, "I2C bus errorx\n"); | ||||
| 		dev_err(dev->dev, "I2C bus error\n"); | ||||
| 	if (val) | ||||
| 		return -EIO; | ||||
| 	return 0; | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * ddbridge-i2c.h: Digital Devices bridge i2c driver | ||||
|  * | ||||
|  * Copyright (C) 2010-2017 Digital Devices GmbH | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  * | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
| @@ -17,8 +19,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef _DDBRIDGE_I2C_H_ | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-io.c: Digital Devices bridge I/O functions | ||||
|  * | ||||
| @@ -65,6 +66,8 @@ u32 ddbreadl(struct ddb *dev, u32 adr) | ||||
| 		u32 val, l = (adr >> DDB_LINK_SHIFT) & 3; | ||||
| 		struct ddb_link *link = &dev->link[l]; | ||||
|  | ||||
| 		if (!link->regs) | ||||
| 			return 0; | ||||
| 		spin_lock_irqsave(&link->lock, flags); | ||||
| 		gtlw(link); | ||||
| 		ddblwritel0(link, adr & 0xfffc, link->regs + 0x14); | ||||
| @@ -84,6 +87,8 @@ void ddbwritel(struct ddb *dev, u32 val, u32 adr) | ||||
| 		u32 l = (adr >> DDB_LINK_SHIFT); | ||||
| 		struct ddb_link *link = &dev->link[l]; | ||||
|  | ||||
| 		if (!link->regs) | ||||
| 			return; | ||||
| 		spin_lock_irqsave(&link->lock, flags); | ||||
| 		gtlw(link); | ||||
| 		ddblwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14); | ||||
| @@ -134,8 +139,8 @@ void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count) | ||||
| 	u32 a = p & 3; | ||||
|  | ||||
| 	if (a) { | ||||
| 		val = ddbreadl(dev, p) >> (8 * a); | ||||
| 		while (p & 3 && count) { | ||||
| 		val = ddbreadl(dev, p & ~3) >> (8 * a); | ||||
| 		while ((p & 3) && count) { | ||||
| 			*buf = val & 0xff; | ||||
| 			val >>= 8; | ||||
| 			p++; | ||||
| @@ -172,7 +177,12 @@ void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count) | ||||
|  | ||||
| void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count) | ||||
| { | ||||
| 	return gtlcpyfrom(dev, dst, adr, count); | ||||
| 	/*  The possible 64 bit read in memcpy_fromio produces errors | ||||
| 	    on some platforms, i.e. arm64 rpi4 | ||||
| 	if (unlikely(adr & 0xf0000000)) | ||||
| 		return gtlcpyfrom(dev, dst, adr, count); | ||||
| 	return memcpy_fromio(dst, dev->regs + adr, count); | ||||
|         return memcpy_fromio(dst, dev->regs + adr, count); | ||||
| 	*/ | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										74
									
								
								ddbridge/ddbridge-ioctl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								ddbridge/ddbridge-ioctl.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| #ifndef _DDBRIDGE_IOCTL_H_ | ||||
| #define _DDBRIDGE_IOCTL_H_ | ||||
|  | ||||
| #define DDB_MAGIC 'd' | ||||
|  | ||||
| struct ddb_flashio { | ||||
| 	__u8 *write_buf; | ||||
| 	__u32 write_len; | ||||
| 	__u8 *read_buf; | ||||
| 	__u32 read_len; | ||||
| 	__u32 link; | ||||
| }; | ||||
|  | ||||
| struct ddb_gpio { | ||||
| 	__u32 mask; | ||||
| 	__u32 data; | ||||
| }; | ||||
|  | ||||
| struct ddb_id { | ||||
| 	__u16 vendor; | ||||
| 	__u16 device; | ||||
| 	__u16 subvendor; | ||||
| 	__u16 subdevice; | ||||
| 	__u32 hw; | ||||
| 	__u32 regmap; | ||||
| }; | ||||
|  | ||||
| struct ddb_reg { | ||||
| 	__u32 reg; | ||||
| 	__u32 val; | ||||
| }; | ||||
|  | ||||
| struct ddb_mem { | ||||
| 	__u32  off; | ||||
| 	__u8  *buf; | ||||
| 	__u32  len; | ||||
| }; | ||||
|  | ||||
| struct ddb_mdio { | ||||
| 	__u8   adr; | ||||
| 	__u8   reg; | ||||
| 	__u16  val; | ||||
| }; | ||||
|  | ||||
| struct ddb_i2c_msg { | ||||
| 	__u8   bus; | ||||
| 	__u8   adr; | ||||
| 	__u8  *hdr; | ||||
| 	__u32  hlen; | ||||
| 	__u8  *msg; | ||||
| 	__u32  mlen; | ||||
| }; | ||||
|  | ||||
| struct ddb_mci_msg { | ||||
| 	__u32 link; | ||||
| 	struct mci_command cmd; | ||||
| 	struct mci_result res; | ||||
| }; | ||||
|  | ||||
| #define IOCTL_DDB_FLASHIO    _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) | ||||
| #define IOCTL_DDB_GPIO_IN    _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) | ||||
| #define IOCTL_DDB_GPIO_OUT   _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) | ||||
| #define IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id) | ||||
| #define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) | ||||
| #define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg) | ||||
| #define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) | ||||
| #define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem) | ||||
| #define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) | ||||
| #define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) | ||||
| #define IOCTL_DDB_READ_I2C   _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) | ||||
| #define IOCTL_DDB_WRITE_I2C  _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) | ||||
| #define IOCTL_DDB_MCI_CMD    _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg) | ||||
|  | ||||
| #endif | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-m4.c: Digital Devices MAX M4 driver | ||||
|  * | ||||
| @@ -23,7 +24,6 @@ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-io.h" | ||||
| #include "ddbridge-i2c.h" | ||||
| #include "ddbridge-mci.h" | ||||
|  | ||||
| struct m4_base { | ||||
| @@ -46,7 +46,6 @@ static int stop(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_command cmd; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
|  | ||||
| 	if (!state->started) | ||||
| 		return -1; | ||||
| @@ -62,8 +61,6 @@ static int stop(struct dvb_frontend *fe) | ||||
| static int search_s2(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
| @@ -72,11 +69,12 @@ static int search_s2(struct dvb_frontend *fe) | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBS; | ||||
| 	cmd.dvbs2_search.flags = 3; | ||||
| 	cmd.dvbs2_search.s2_modulation_mask = 3; | ||||
| 	cmd.dvbs2_search.retry = 2; | ||||
| 	cmd.dvbs2_search.retry = 0; | ||||
| 	cmd.dvbs2_search.frequency = p->frequency * 1000; | ||||
| 	cmd.dvbs2_search.symbol_rate = p->symbol_rate; | ||||
| 	cmd.dvbs2_search.scrambling_sequence_index = 0; //p->scrambling_sequence_index; | ||||
| 	cmd.dvbs2_search.input_stream_id = p->stream_id; | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER) | ||||
| 		cmd.dvbs2_search.input_stream_id = p->stream_id; | ||||
| 	cmd.tuner = state->mci.nr; | ||||
| 	cmd.demod = state->mci.tuner; | ||||
| 	cmd.output = state->mci.nr; | ||||
| @@ -90,26 +88,19 @@ static int search_s2(struct dvb_frontend *fe) | ||||
| static int search_c(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBC; | ||||
| 	switch (p->bandwidth_hz) { | ||||
| 	case 6000000: | ||||
| 	if (p->bandwidth_hz <= 6000000) | ||||
| 		cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_6MHZ; | ||||
| 		break; | ||||
| 	case 7000000: | ||||
| 	else if (p->bandwidth_hz <= 7000000) | ||||
| 		cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_7MHZ; | ||||
| 		break; | ||||
| 	default: | ||||
| 	else | ||||
| 		cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_8MHZ; | ||||
| 		break; | ||||
| 	} | ||||
| 	cmd.dvbc_search.retry = 2; | ||||
| 	cmd.dvbc_search.retry = 0; | ||||
| 	cmd.dvbc_search.frequency = p->frequency; | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| @@ -124,8 +115,6 @@ static int search_c(struct dvb_frontend *fe) | ||||
| static int search_t(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
| @@ -146,7 +135,7 @@ static int search_t(struct dvb_frontend *fe) | ||||
| 		cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ; | ||||
| 		break; | ||||
| 	} | ||||
| 	cmd.dvbt_search.retry = 2; | ||||
| 	cmd.dvbt_search.retry = 0; | ||||
| 	cmd.dvbt_search.frequency = p->frequency; | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| @@ -158,15 +147,87 @@ static int search_t(struct dvb_frontend *fe) | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int search_t2(struct dvb_frontend *fe) | ||||
| static int search_isdbs(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_ISDBS; | ||||
| 	cmd.isdbs_search.retry = 0; | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER) { | ||||
| 		cmd.isdbs_search.flags = (p->stream_id & 0xffff0000) ? 0 : 1; | ||||
| 		cmd.isdbs_search.tsid = p->stream_id; | ||||
| 	} | ||||
| 	cmd.isdbs_search.frequency = p->frequency * 1000; | ||||
| 	cmd.tuner = state->mci.nr; | ||||
| 	cmd.demod = state->mci.tuner; | ||||
| 	cmd.output = state->mci.nr; | ||||
|  | ||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	if (stat) | ||||
| 		stop(fe); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int search_isdbc(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_ISDBC; | ||||
| 	cmd.isdbc_search.retry = 0; | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER) { | ||||
| 		cmd.isdbc_search.flags = (p->stream_id & 0xffff0000) ? 0 : 1; | ||||
| 		cmd.isdbc_search.tsid = p->stream_id; | ||||
| 		cmd.isdbc_search.onid = (p->stream_id & 0x10000) >> 16; | ||||
| 	} | ||||
| 	cmd.isdbc_search.bandwidth = MCI_BANDWIDTH_6MHZ; | ||||
| 	cmd.isdbc_search.frequency = p->frequency; | ||||
| 	cmd.demod = state->mci.tuner; | ||||
| 	cmd.output = state->mci.nr; | ||||
|  | ||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	if (stat) | ||||
| 		stop(fe); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int search_j83b(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_J83B; | ||||
| 	cmd.j83b_search.flags = 0; | ||||
| 	cmd.j83b_search.retry = 0; | ||||
| 	cmd.j83b_search.bandwidth = MCI_BANDWIDTH_6MHZ; | ||||
| 	if (p->symbol_rate > 5500000) | ||||
| 		cmd.j83b_search.bandwidth |= MCI_BANDWIDTH_EXTENSION; | ||||
| 	cmd.j83b_search.frequency = p->frequency; | ||||
| 	cmd.demod = state->mci.tuner; | ||||
| 	cmd.output = state->mci.nr; | ||||
|  | ||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	if (stat) | ||||
| 		stop(fe); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int search_t2(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
| 	u32 flags = 0; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBT2; | ||||
| @@ -187,7 +248,7 @@ static int search_t2(struct dvb_frontend *fe) | ||||
| 		cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ; | ||||
| 		break; | ||||
| 	} | ||||
| 	cmd.dvbt2_search.retry = 2; | ||||
| 	cmd.dvbt2_search.retry = 0; | ||||
| 	cmd.dvbt2_search.frequency = p->frequency; | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER) { | ||||
| 		cmd.dvbt2_search.plp = p->stream_id & 0xff; | ||||
| @@ -207,12 +268,9 @@ static int search_t2(struct dvb_frontend *fe) | ||||
| static int search_c2(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
| 	u32 flags = 0; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBC2; | ||||
| @@ -224,7 +282,7 @@ static int search_c2(struct dvb_frontend *fe) | ||||
| 		cmd.dvbc2_search.bandwidth = MCI_BANDWIDTH_8MHZ; | ||||
| 		break; | ||||
| 	} | ||||
| 	cmd.dvbc2_search.retry = 2; | ||||
| 	cmd.dvbc2_search.retry = 0; | ||||
| 	cmd.dvbc2_search.frequency = p->frequency; | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER) { | ||||
| 		cmd.dvbc2_search.plp = p->stream_id & 0xff; | ||||
| @@ -243,12 +301,9 @@ static int search_c2(struct dvb_frontend *fe) | ||||
| static int search_isdbt(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct m4_base *m4_base = (struct m4_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_command cmd; | ||||
| 	int stat; | ||||
| 	u32 flags = 0; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = MCI_CMD_SEARCH_ISDBT; | ||||
| @@ -263,7 +318,7 @@ static int search_isdbt(struct dvb_frontend *fe) | ||||
| 		cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_6MHZ; | ||||
| 		break; | ||||
| 	} | ||||
| 	cmd.isdbt_search.retry = 2; | ||||
| 	cmd.isdbt_search.retry = 0; | ||||
| 	cmd.isdbt_search.frequency = p->frequency; | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| @@ -280,6 +335,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); | ||||
|  | ||||
| @@ -288,6 +344,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: | ||||
| @@ -296,6 +353,9 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 	case SYS_DVBC_ANNEX_A: | ||||
| 		res = search_c(fe); | ||||
| 		break; | ||||
| 	case SYS_DVBC_ANNEX_B: | ||||
| 		res = search_j83b(fe); | ||||
| 		break; | ||||
| 	case SYS_DVBT: | ||||
| 		state->iq_constellation_tap = 5; | ||||
| 		res = search_t(fe); | ||||
| @@ -309,6 +369,13 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 	case SYS_ISDBT: | ||||
| 		res = search_isdbt(fe); | ||||
| 		break; | ||||
| 	case SYS_ISDBS: | ||||
| 		res = search_isdbs(fe); | ||||
| 		break; | ||||
| 	case SYS_DVBC_ANNEX_C: | ||||
| 	case SYS_ISDBC: | ||||
| 		res = search_isdbc(fe); | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| @@ -325,15 +392,23 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) | ||||
| 	struct m4 *state = fe->demodulator_priv; | ||||
| 	struct mci_result res; | ||||
|  | ||||
| 	*status = 0x00; | ||||
| 	if (!state->started) | ||||
| 		return 0; | ||||
| 	stat = ddb_mci_get_status(&state->mci, &res); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	*status = 0x00; | ||||
| 	ddb_mci_get_info(&state->mci); | ||||
| 	stat = ddb_mci_get_info(&state->mci); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	ddb_mci_get_strength(fe); | ||||
| 	if (res.status == M4_DEMOD_WAIT_SIGNAL) | ||||
| 	if (res.status == MCI_DEMOD_WAIT_SIGNAL) | ||||
| 		*status = 0x01; | ||||
| 	if (res.status == M4_DEMOD_LOCKED) { | ||||
| 	else if (res.status == M4_DEMOD_WAIT_TS) | ||||
| 		*status = 0x03; | ||||
| 	else if (res.status == MCI_DEMOD_TIMEOUT) | ||||
| 		*status = FE_TIMEDOUT; | ||||
| 	else if (res.status == MCI_DEMOD_LOCKED) { | ||||
| 		*status = 0x1f; | ||||
| 		ddb_mci_get_snr(fe); | ||||
| 	} | ||||
| @@ -383,7 +458,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; | ||||
| } | ||||
| @@ -397,25 +472,27 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties | ||||
| } | ||||
|  | ||||
| static struct dvb_frontend_ops m4_ops = { | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT, | ||||
| 		    SYS_DVBS, SYS_DVBS2, }, | ||||
| 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C, | ||||
| 		    SYS_ISDBC, SYS_DVBC2, | ||||
| 		    SYS_DVBT, SYS_DVBT2, SYS_ISDBT, | ||||
| 		    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, | ||||
| @@ -439,7 +516,7 @@ static int base_init(struct mci_base *mci_base) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct mci_cfg ddb_max_m4_cfg = { | ||||
| static struct mci_cfg ddb_max_m4_cfg = { | ||||
| 	.type = 0, | ||||
| 	.fe_ops = &m4_ops, | ||||
| 	.base_size = sizeof(struct m4_base), | ||||
| @@ -447,3 +524,8 @@ struct mci_cfg ddb_max_m4_cfg = { | ||||
| 	.init = init, | ||||
| 	.base_init = base_init, | ||||
| }; | ||||
|  | ||||
| struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner) | ||||
| { | ||||
| 	return ddb_mci_attach(input, &ddb_max_m4_cfg, nr, tuner); | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge.c: Digital Devices PCIe bridge driver | ||||
|  * | ||||
| @@ -5,22 +6,19 @@ | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  * | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * version 2 only, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-io.h" | ||||
|  | ||||
| @@ -86,7 +84,7 @@ int pci_irq_vector(struct pci_dev *dev, unsigned int nr) | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| static void __devexit ddb_irq_disable(struct ddb *dev) | ||||
| static void ddb_irq_disable(struct ddb *dev) | ||||
| { | ||||
| 	if (dev->link[0].info->regmap->irq_version == 2) { | ||||
| 		ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL); | ||||
| @@ -116,7 +114,7 @@ static void __devexit ddb_msi_exit(struct ddb *dev) | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void __devexit ddb_irq_exit(struct ddb *dev) | ||||
| static void ddb_irq_exit(struct ddb *dev) | ||||
| { | ||||
| 	ddb_irq_disable(dev); | ||||
| 	if (dev->msi == 2) | ||||
| @@ -141,6 +139,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev) | ||||
| 	ddb_buffers_free(dev); | ||||
|  | ||||
| 	ddb_unmap(dev); | ||||
| 	pci_clear_master(pdev); | ||||
| 	pci_set_drvdata(pdev, NULL); | ||||
| 	pci_disable_device(pdev); | ||||
| } | ||||
| @@ -256,17 +255,9 @@ static int __devinit ddb_irq_init(struct ddb *dev) | ||||
| 			return stat; | ||||
| 		} | ||||
| 	} else { | ||||
| #ifdef DDB_TEST_THREADED | ||||
| 		stat = request_threaded_irq(pci_irq_vector(dev->pdev, 0), | ||||
| 					    dev->pdev->irq, ddb_irq_handler, | ||||
| 					    irq_thread, | ||||
| 					    irq_flag, | ||||
| 					    "ddbridge", (void *)dev); | ||||
| #else | ||||
| 		stat = request_irq(pci_irq_vector(dev->pdev, 0), | ||||
| 				   ddb_irq_handler, | ||||
| 				   irq_flag, "ddbridge", (void *)dev); | ||||
| #endif | ||||
| 		if (stat < 0) | ||||
| 			return stat; | ||||
| 	} | ||||
| @@ -292,9 +283,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
|  | ||||
| 	pci_set_master(pdev); | ||||
|  | ||||
| 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) | ||||
| 		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) | ||||
| 			return -ENODEV; | ||||
| #if (KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE) | ||||
| 	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) | ||||
| 		if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) | ||||
| #else | ||||
| 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | ||||
| 		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | ||||
| 	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { | ||||
| 		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||||
| 	} else | ||||
| #endif | ||||
| 		return -ENODEV; | ||||
|  | ||||
| 	dev = vzalloc(sizeof(*dev)); | ||||
| 	if (!dev) | ||||
| @@ -311,11 +310,11 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
| 	dev->link[0].ids.subvendor = id->subvendor; | ||||
| 	dev->link[0].ids.subdevice = pdev->subsystem_device; | ||||
| 	dev->link[0].ids.devid = (id->device << 16) | id->vendor; | ||||
| 	dev->link[0].ids.revision = pdev->revision; | ||||
|  | ||||
| 	dev->link[0].dev = dev; | ||||
| 	dev->link[0].info = get_ddb_info(id->vendor, id->device, | ||||
| 					 id->subvendor, pdev->subsystem_device); | ||||
| 	dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name); | ||||
|  | ||||
| 	dev->regs_len = pci_resource_len(dev->pdev, 0); | ||||
| 	dev->regs = ioremap(pci_resource_start(dev->pdev, 0), | ||||
| @@ -335,14 +334,12 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
| 	dev->link[0].ids.hwid = ddbreadl(dev, 0); | ||||
| 	dev->link[0].ids.regmapid = ddbreadl(dev, 4); | ||||
|  | ||||
| 	dev_info(dev->dev, "HW %08x REGMAP %08x\n", | ||||
| 		 dev->link[0].ids.hwid, dev->link[0].ids.regmapid); | ||||
| 	if ((dev->link[0].ids.hwid & 0xffffff) < | ||||
| 	    dev->link[0].info->hw_min) { | ||||
| 		u32 min = dev->link[0].info->hw_min; | ||||
|  | ||||
| 		dev_err(dev->dev, "Update firmware to at least version %u.%u to ensure full functionality!\n", | ||||
| 			 (min & 0xff0000) >> 16, min & 0xffff); | ||||
| 			(min & 0xff0000) >> 16, min & 0xffff); | ||||
| 	} | ||||
|  | ||||
| 	if (dev->link[0].info->ns_num) { | ||||
| @@ -353,33 +350,27 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
| 	if (dev->link[0].info->type != DDB_MOD) | ||||
| 		ddbwritel(dev, 0, DMA_BASE_WRITE); | ||||
|  | ||||
| 	if (dev->link[0].info->type == DDB_MOD | ||||
| 	    && dev->link[0].info->version <= 1) { | ||||
| 	if (dev->link[0].info->type == DDB_MOD && | ||||
| 	    dev->link[0].info->version <= 1) { | ||||
| 		if (ddbreadl(dev, 0x1c) == 4) | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0201, 0xdd01, 0x0004); | ||||
| 	} | ||||
| 	if (dev->link[0].info->type == DDB_MOD | ||||
| 	    && dev->link[0].info->version == 2) { | ||||
| 		u32 lic = ddbreadl(dev, 0x1c) & 7; | ||||
|  | ||||
| 		switch (lic) { | ||||
| 		case 0:  | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000); | ||||
| 			break; | ||||
| 		case 1:  | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003); | ||||
| 			break; | ||||
| 		case 3:  | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	if (dev->link[0].info->type == DDB_MOD && | ||||
| 	    dev->link[0].info->version == 2) { | ||||
| 		if (dev->link[0].ids.revision == 1) | ||||
| 			dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004); | ||||
| 		else if ((ddbreadl(dev, 0x1c) & 7) != 7) | ||||
| 			dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004); | ||||
| 	} | ||||
|  | ||||
| 	dev_info(dev->dev, "%s\n", dev->link[0].info->name); | ||||
| 	dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n", | ||||
| 		 dev->link[0].ids.hwid, dev->link[0].ids.regmapid, | ||||
| 		 (dev->link[0].ids.hwid & 0xff0000) >> 16, | ||||
| 		 dev->link[0].ids.hwid & 0xffff); | ||||
|  | ||||
| 	stat = ddb_irq_init(dev); | ||||
| 	if (stat < 0) | ||||
| 		goto fail0; | ||||
| @@ -404,6 +395,12 @@ fail: | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| #ifndef PCI_DEVICE_SUB | ||||
| #define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \ | ||||
| 	.vendor = (vend), .device = (dev), \ | ||||
| 		.subvendor = (subvend), .subdevice = (subdev) | ||||
| #endif | ||||
|  | ||||
| #define DDB_DEVICE_ANY(_device) \ | ||||
| 	{ PCI_DEVICE_SUB(0xdd01, _device, 0xdd01, PCI_ANY_ID) } | ||||
|  | ||||
| @@ -416,13 +413,18 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = { | ||||
| 	DDB_DEVICE_ANY(0x0008), | ||||
| 	DDB_DEVICE_ANY(0x0009), | ||||
| 	DDB_DEVICE_ANY(0x000a), | ||||
| 	DDB_DEVICE_ANY(0x000b), | ||||
| 	DDB_DEVICE_ANY(0x0011), | ||||
| 	DDB_DEVICE_ANY(0x0012), | ||||
| 	DDB_DEVICE_ANY(0x0013), | ||||
| 	DDB_DEVICE_ANY(0x0020), | ||||
| 	DDB_DEVICE_ANY(0x0201), | ||||
| 	DDB_DEVICE_ANY(0x0203), | ||||
| 	DDB_DEVICE_ANY(0x0210), | ||||
| 	DDB_DEVICE_ANY(0x0220), | ||||
| 	DDB_DEVICE_ANY(0x0221), | ||||
| 	DDB_DEVICE_ANY(0x0222), | ||||
| 	DDB_DEVICE_ANY(0x0223), | ||||
| 	DDB_DEVICE_ANY(0x0320), | ||||
| 	DDB_DEVICE_ANY(0x0321), | ||||
| 	DDB_DEVICE_ANY(0x0322), | ||||
| @@ -433,11 +435,51 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = { | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(pci, ddb_id_table); | ||||
|  | ||||
| static pci_ers_result_t ddb_pci_slot_reset(struct pci_dev *dev) | ||||
| { | ||||
| 	pr_info("pci_slot_reset\n"); | ||||
| 	return PCI_ERS_RESULT_RECOVERED; | ||||
| } | ||||
|  | ||||
| static void ddb_pci_resume(struct pci_dev *dev) | ||||
| { | ||||
| 	pr_info("pci_resume\n"); | ||||
| } | ||||
|  | ||||
| static pci_ers_result_t ddb_pci_mmio_enabled(struct pci_dev *pdev) | ||||
| { | ||||
| 	pr_info("pci_mmio_enabled\n"); | ||||
| 	return PCI_ERS_RESULT_NEED_RESET; | ||||
| } | ||||
|  | ||||
| static pci_ers_result_t ddb_pci_error_detected(struct pci_dev *pdev, | ||||
| 					       pci_channel_state_t state) | ||||
| { | ||||
| 	switch (state) { | ||||
| 	case pci_channel_io_frozen: | ||||
| 		return PCI_ERS_RESULT_CAN_RECOVER; | ||||
| 	case pci_channel_io_perm_failure: | ||||
| 		return PCI_ERS_RESULT_DISCONNECT; | ||||
| 	case pci_channel_io_normal: | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 	return PCI_ERS_RESULT_NEED_RESET; | ||||
| } | ||||
|  | ||||
| static const struct pci_error_handlers ddb_error = { | ||||
| 	.error_detected = ddb_pci_error_detected, | ||||
| 	.mmio_enabled = ddb_pci_mmio_enabled, | ||||
| 	.slot_reset = ddb_pci_slot_reset, | ||||
| 	.resume = ddb_pci_resume, | ||||
| }; | ||||
|  | ||||
| static struct pci_driver ddb_pci_driver = { | ||||
| 	.name        = "ddbridge", | ||||
| 	.id_table    = ddb_id_table, | ||||
| 	.probe       = ddb_probe, | ||||
| 	.remove      = ddb_remove, | ||||
| 	.err_handler = &ddb_error, | ||||
| }; | ||||
|  | ||||
| static __init int module_init_ddbridge(void) | ||||
| @@ -446,7 +488,7 @@ static __init int module_init_ddbridge(void) | ||||
|  | ||||
| 	pr_info("Digital Devices PCIE bridge driver " | ||||
| 		DDBRIDGE_VERSION | ||||
| 		", Copyright (C) 2010-17 Digital Devices GmbH\n"); | ||||
| 		", Copyright (C) 2010-19 Digital Devices GmbH\n"); | ||||
| 	stat = ddb_init_ddbridge(); | ||||
| 	if (stat < 0) | ||||
| 		return stat; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-max.c: Digital Devices MAX card line support functions | ||||
|  * | ||||
| @@ -39,6 +40,10 @@ static int old_quattro; | ||||
| module_param(old_quattro, int, 0444); | ||||
| MODULE_PARM_DESC(old_quattro, "old quattro LNB input order "); | ||||
|  | ||||
| static int no_voltage; | ||||
| module_param(no_voltage, int, 0444); | ||||
| MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone)."); | ||||
|  | ||||
| /* MAX LNB interface related functions */ | ||||
|  | ||||
| static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) | ||||
| @@ -60,21 +65,21 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int max_set_input_unlocked(struct dvb_frontend *fe, int in); | ||||
| static int max_set_input(struct dvb_frontend *fe, int in); | ||||
|  | ||||
| static int max_emulate_switch(struct dvb_frontend *fe, | ||||
| 			      u8 *cmd, u32 len) | ||||
| { | ||||
| 	int input; | ||||
|  | ||||
| 	if (len !=4) | ||||
| 	if (len != 4) | ||||
| 		return -1; | ||||
|  | ||||
| 	if ((cmd[0] != 0xe0) || (cmd[1] != 0x10) || (cmd[2] != 0x39)) | ||||
| 		return -1; | ||||
|  | ||||
| 	input = cmd[3] & 3; | ||||
| 	max_set_input_unlocked(fe, input); | ||||
| 	max_set_input(fe, input); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -93,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe, | ||||
| 		return 0; | ||||
|  | ||||
| 	if (fmode == 4) | ||||
| 		max_emulate_switch(fe, cmd->msg, cmd->msg_len); | ||||
| 		if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len)) | ||||
| 			return 0; | ||||
|  | ||||
| 	if (dvb->diseqc_send_master_cmd) | ||||
| 		dvb->diseqc_send_master_cmd(fe, cmd); | ||||
| @@ -163,6 +169,8 @@ static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input, | ||||
| { | ||||
| 	int s = 0; | ||||
|  | ||||
| 	if (no_voltage) | ||||
| 		voltage = SEC_VOLTAGE_OFF; | ||||
| 	if (dev->link[link].lnb.oldvoltage[input] == voltage) | ||||
| 		return 0; | ||||
| 	switch (voltage) { | ||||
| @@ -357,6 +365,29 @@ static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) | ||||
|  | ||||
| static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) | ||||
| { | ||||
| 	struct ddb_input *input = fe->sec_priv; | ||||
| 	struct ddb_port *port = input->port; | ||||
| 	struct ddb *dev = port->dev; | ||||
| 	u32 tag = DDB_LINK_TAG(port->lnr); | ||||
| 	struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; | ||||
| 	u32 fmode = dev->link[port->lnr].lnb.fmode; | ||||
|  | ||||
| 	mutex_lock(&dev->link[port->lnr].lnb.lock); | ||||
| 	switch (fmode) { | ||||
| 	default: | ||||
| 	case 0: | ||||
| 	case 3: | ||||
| 		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input)); | ||||
| 		break; | ||||
| 	case 1: | ||||
| 	case 2: | ||||
| 		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0)); | ||||
| 		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1)); | ||||
| 		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2)); | ||||
| 		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3)); | ||||
| 		break; | ||||
| 	} | ||||
| 	mutex_unlock(&dev->link[port->lnr].lnb.lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -441,7 +472,8 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input) | ||||
| 	tuner = demod & 3; | ||||
| 	if (fmode >= 3) | ||||
| 		tuner = 0; | ||||
| 	dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner); | ||||
| 	dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, | ||||
| 			     demod, tuner, &dvb->set_input); | ||||
| 	if (!dvb->fe) { | ||||
| 		dev_err(dev->dev, "No MXL5XX found!\n"); | ||||
| 		return -ENODEV; | ||||
| @@ -459,44 +491,42 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input) | ||||
| 	dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; | ||||
| 	dvb->fe->ops.diseqc_send_burst = max_send_burst; | ||||
| 	dvb->fe->sec_priv = input; | ||||
| 	dvb->set_input = dvb->fe->ops.set_input; | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	dvb->fe->ops.set_input = max_set_input; | ||||
| #endif | ||||
| 	dvb->input = tuner; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* MAX MCI related functions */ | ||||
|  | ||||
| extern struct mci_cfg ddb_max_sx8_cfg; | ||||
| extern struct mci_cfg ddb_max_m4_cfg; | ||||
| struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner, | ||||
| 				    int (**fn_set_input)(struct dvb_frontend *fe, int input)); | ||||
| struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner); | ||||
|  | ||||
| int ddb_fe_attach_mci(struct ddb_input *input, u32 type) | ||||
| { | ||||
| 	struct ddb *dev = input->port->dev; | ||||
| 	//struct i2c_adapter *i2c = &input->port->i2c->adap; | ||||
| 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; | ||||
| 	struct ddb_port *port = input->port; | ||||
| 	struct ddb_link *link = &dev->link[port->lnr]; | ||||
| 	int demod, tuner; | ||||
| 	struct mci_cfg cfg; | ||||
| 	int fm = fmode; | ||||
|  | ||||
| 	demod = input->nr; | ||||
| 	tuner = demod & 3; | ||||
| 	switch (type) { | ||||
| 	case DDB_TUNER_MCI_SX8: | ||||
| 		cfg = ddb_max_sx8_cfg; | ||||
| 		if (fm >= 3) | ||||
| 			tuner = 0; | ||||
| 		dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input); | ||||
| 		break; | ||||
| 	case DDB_TUNER_MCI_M4: | ||||
| 		fm = 0; | ||||
| 		cfg = ddb_max_m4_cfg; | ||||
| 		dvb->fe = ddb_m4_attach(input, demod, tuner); | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	dvb->fe = ddb_mci_attach(input, &cfg, demod, tuner); | ||||
| 	if (!dvb->fe) { | ||||
| 		dev_err(dev->dev, "No MCI card found!\n"); | ||||
| 		return -ENODEV; | ||||
| @@ -514,8 +544,15 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) | ||||
| 	dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; | ||||
| 	dvb->fe->ops.diseqc_send_burst = max_send_burst; | ||||
| 	dvb->fe->sec_priv = input; | ||||
| 	dvb->set_input = dvb->fe->ops.set_input; | ||||
| 	dvb->fe->ops.set_input = max_set_input; | ||||
| 	switch (type) { | ||||
| 	case DDB_TUNER_MCI_M4: | ||||
| 		break; | ||||
| 	default: | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 		dvb->fe->ops.set_input = max_set_input; | ||||
| #endif | ||||
| 		break; | ||||
| 	} | ||||
| 	dvb->input = tuner; | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * ddbridge-mci.c: Digital Devices microcode interface | ||||
|  * | ||||
| @@ -27,125 +28,189 @@ | ||||
|  | ||||
| static LIST_HEAD(mci_list); | ||||
|  | ||||
| static int mci_reset(struct mci *state) | ||||
| static int mci_reset(struct ddb_link *link) | ||||
| { | ||||
| 	struct ddb_link *link = state->base->link; | ||||
| 	const struct ddb_regmap *regmap = link->info->regmap; | ||||
| 	u32 control; | ||||
| 	u32 status = 0; | ||||
| 	u32 timeout = 40; | ||||
| 	union { | ||||
| 		u32 u[4]; | ||||
| 		char s[16]; | ||||
| 	} version; | ||||
| 	u32 vaddr; | ||||
| 	 | ||||
| 	ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL); | ||||
| 	ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */ | ||||
| 	msleep(300); | ||||
| 	ddblwritel(link, 0, MCI_CONTROL); | ||||
| 	if (!regmap || !regmap->mci) | ||||
| 		return -EINVAL; | ||||
| 	control = regmap->mci->base; | ||||
| 	vaddr = regmap->mci_buf->base + 0xf0; | ||||
|  | ||||
| 	while(1) { | ||||
| 		status = ddblreadl(link, MCI_CONTROL); | ||||
| 	if ((link->info->type == DDB_OCTOPUS_MCI) && | ||||
| 	    (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { | ||||
| 		ddblwritel(link, MCI_CONTROL_RESET, control); | ||||
| 		ddblwritel(link, 0, control + 4); /* 1= no internal init */ | ||||
| 		msleep(300); | ||||
| 	} | ||||
| 	ddblwritel(link, 0, control); | ||||
| 	while (1) { | ||||
| 		status = ddblreadl(link, control); | ||||
| 		if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) | ||||
| 			break; | ||||
| 		if (--timeout == 0) | ||||
| 			break; | ||||
| 		msleep(50); | ||||
| 	} | ||||
| 	if ((status & MCI_CONTROL_READY) == 0 ) | ||||
| 	dev_info(link->dev->dev, "MCI control port @ %08x\n", control); | ||||
|  | ||||
| 	if ((status & MCI_CONTROL_READY) == 0) { | ||||
| 		dev_err(link->dev->dev, "MCI init failed!\n"); | ||||
| 		return -1; | ||||
| 	if (link->ids.device == 0x0009) | ||||
| 		ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); | ||||
| 	} | ||||
| 	version.u[0] = ddblreadl(link, vaddr); | ||||
| 	version.u[1] = ddblreadl(link, vaddr + 4); | ||||
| 	version.u[2] = ddblreadl(link, vaddr + 8); | ||||
| 	version.u[3] = ddblreadl(link, vaddr + 12); | ||||
| 	dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50); | ||||
| 	dev_info(link->dev->dev, "MCI firmware version %s.%d\n", version.s, version.s[15]); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int ddb_mci_config(struct mci *state, u32 config) | ||||
| { | ||||
| 	struct ddb_link *link = state->base->link; | ||||
|  | ||||
| 	if (link->ids.device != 0x0009) | ||||
| 		return -EINVAL; | ||||
| 	ddblwritel(link, config, SX8_TSCONFIG); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int ddb_mci_cmd_raw_unlocked(struct mci *state, | ||||
| static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link, | ||||
| 				    u32 *cmd, u32 cmd_len, | ||||
| 				    u32 *res, u32 res_len) | ||||
| { | ||||
| 	struct ddb_link *link = state->base->link; | ||||
| 	const struct ddb_regmap *regmap = link->info->regmap; | ||||
| 	u32 control, command, result; | ||||
| 	u32 i, val; | ||||
| 	unsigned long stat; | ||||
|  | ||||
| 	val = ddblreadl(link, MCI_CONTROL); | ||||
| 	if (!regmap || ! regmap->mci) | ||||
| 		return -EINVAL; | ||||
| 	control = regmap->mci->base; | ||||
| 	command = regmap->mci_buf->base; | ||||
| 	result = command + MCI_COMMAND_SIZE; | ||||
| 	val = ddblreadl(link, control); | ||||
| 	if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) | ||||
| 		return -EIO; | ||||
| 	if (cmd && cmd_len) | ||||
| 		for (i = 0; i < cmd_len; i++) | ||||
| 			ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); | ||||
| 	val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); | ||||
| 	ddblwritel(link, val, MCI_CONTROL); | ||||
| 			ddblwritel(link, cmd[i], command + i * 4); | ||||
| 	val |= (MCI_CONTROL_START_COMMAND | | ||||
| 		MCI_CONTROL_ENABLE_DONE_INTERRUPT); | ||||
| 	ddblwritel(link, val, control); | ||||
|  | ||||
| 	stat = wait_for_completion_timeout(&state->base->completion, HZ); | ||||
| 	stat = wait_for_completion_timeout(&link->mci_completion, HZ); | ||||
| 	if (stat == 0) { | ||||
| 		printk("MCI timeout\n"); | ||||
| 		return -EIO; | ||||
| 		u32 istat = ddblreadl(link, INTERRUPT_STATUS); | ||||
|  | ||||
| 		dev_err(link->dev->dev, "MCI timeout\n"); | ||||
| 		val = ddblreadl(link, control); | ||||
| 		if (val == 0xffffffff) { | ||||
| 			dev_err(link->dev->dev, | ||||
| 				"Lost PCIe link!\n"); | ||||
| 			return -EIO; | ||||
| 		} else { | ||||
| 			dev_err(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); | ||||
| 		} | ||||
| 	} | ||||
| 	//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false); | ||||
| 	if (res && res_len) | ||||
| 		for (i = 0; i < res_len; i++) | ||||
| 			res[i] = ddblreadl(link, MCI_RESULT + i * 4); | ||||
| 			res[i] = ddblreadl(link, result + i * 4); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int ddb_mci_cmd_unlocked(struct mci *state, | ||||
| 			 struct mci_command *command, | ||||
| 			 struct mci_result *result) | ||||
| int ddb_mci_cmd_link(struct ddb_link *link, | ||||
| 		     struct mci_command *command, | ||||
| 		     struct mci_result *result) | ||||
| { | ||||
| 	u32 *cmd = (u32 *) command; | ||||
| 	u32 *res = (u32 *) result; | ||||
| 	struct mci_result res; | ||||
| 	int stat; | ||||
|  | ||||
| 	return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32), | ||||
| 					res, sizeof(*result)/sizeof(u32)); | ||||
| 	if (!link->mci_ok) | ||||
| 		return -EFAULT; | ||||
| 	if (!result) | ||||
| 		result = &res; | ||||
| 	mutex_lock(&link->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(link, | ||||
| 					(u32 *)command, | ||||
| 					sizeof(*command)/sizeof(u32), | ||||
| 					(u32 *)result, | ||||
| 					sizeof(*result)/sizeof(u32)); | ||||
| 	mutex_unlock(&link->mci_lock); | ||||
| 	if (command && result && (result->status & 0x80)) | ||||
| 		dev_warn(link->dev->dev, | ||||
| 			 "mci_command 0x%02x, error=0x%02x\n", | ||||
| 			 command->command, result->status); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static void mci_handler(void *priv) | ||||
| { | ||||
| 	struct ddb_link *link = (struct ddb_link *) priv; | ||||
|  | ||||
| 	complete(&link->mci_completion); | ||||
| } | ||||
|  | ||||
| int mci_init(struct ddb_link *link) | ||||
| { | ||||
| 	int result; | ||||
| 	 | ||||
| 	mutex_init(&link->mci_lock); | ||||
| 	init_completion(&link->mci_completion); | ||||
| 	result = mci_reset(link); | ||||
| 	if (result < 0) | ||||
| 		return result; | ||||
| 	if (link->ids.device == 0x0009  || link->ids.device == 0x000b) | ||||
| 		ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); | ||||
| 	 | ||||
| 	ddb_irq_set(link->dev, link->nr, | ||||
| 		    link->info->regmap->irq_base_mci, | ||||
| 		    mci_handler, link); | ||||
| 	link->mci_ok = 1; | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val) | ||||
| { | ||||
| 	struct mci_result result; | ||||
| 	struct mci_command command; | ||||
|  | ||||
| 	command.command_word = cmd; | ||||
| 	command.params[0] = val; | ||||
| 	return ddb_mci_cmd_link(link, &command, &result); | ||||
| } | ||||
|  | ||||
| /****************************************************************************/ | ||||
| /****************************************************************************/ | ||||
|  | ||||
| int ddb_mci_cmd(struct mci *state, | ||||
| 		struct mci_command *command, | ||||
| 		struct mci_result *result) | ||||
| { | ||||
| 	int stat; | ||||
| 	 | ||||
| 	mutex_lock(&state->base->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(state, | ||||
| 				 (u32 *)command, sizeof(*command)/sizeof(u32), | ||||
| 				 (u32 *)result, sizeof(*result)/sizeof(u32)); | ||||
| 	mutex_unlock(&state->base->mci_lock); | ||||
| 	return stat; | ||||
| 	return ddb_mci_cmd_link(state->base->link, command, result); | ||||
| } | ||||
|  | ||||
|  | ||||
| int ddb_mci_cmd_raw(struct mci *state, | ||||
| 		    struct mci_command *command, u32 command_len, | ||||
| 		    struct mci_result *result, u32 result_len) | ||||
| { | ||||
| 	struct ddb_link *link = state->base->link; | ||||
| 	int stat; | ||||
|  | ||||
| 	mutex_lock(&state->base->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(state, | ||||
| 	mutex_lock(&link->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(link, | ||||
| 					(u32 *)command, command_len, | ||||
| 					(u32 *)result, result_len); | ||||
| 	mutex_unlock(&state->base->mci_lock); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q) | ||||
| { | ||||
| 	int stat; | ||||
| 	struct mci_command cmd; | ||||
| 	struct mci_result res; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	memset(&res, 0, sizeof(res)); | ||||
| 	cmd.command = MCI_CMD_GET_IQSYMBOL; | ||||
| 	cmd.demod = demod; | ||||
| 	stat = ddb_mci_cmd(mci, &cmd, &res); | ||||
| 	if (!stat) { | ||||
| 		*i = res.iq_symbol.i; | ||||
| 		*q = res.iq_symbol.q; | ||||
| 	} | ||||
| 	mutex_unlock(&link->mci_lock); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| @@ -165,8 +230,8 @@ 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; | ||||
| } | ||||
|  | ||||
| @@ -222,7 +287,7 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 	}; | ||||
| 	const enum fe_code_rate dvbs_fec_lut[8] = { | ||||
| 		FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, | ||||
| 		FEC_NONE, FEC_7_8, FEC_NONE, FEC_NONE, | ||||
| 		FEC_7_8, FEC_7_8, FEC_NONE, FEC_NONE, | ||||
| 	}; | ||||
| 	const enum fe_rolloff ro_lut[8] = { | ||||
| 		ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10, | ||||
| @@ -231,6 +296,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
|  | ||||
| 	p->frequency = | ||||
| 		mci->signal_info.dvbs2_signal_info.frequency; | ||||
| 	p->symbol_rate = | ||||
| 		mci->signal_info.dvbs2_signal_info.symbol_rate; | ||||
| 	switch (p->delivery_system) { | ||||
| 	default: | ||||
| 	case SYS_DVBS: | ||||
| @@ -238,23 +305,33 @@ 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 = | ||||
| 			(mci->signal_info.dvbs2_signal_info.standard == 2)  ? | ||||
| 			SYS_DVBS2 : SYS_DVBS; | ||||
| 		p->inversion = (mci->signal_info.dvbs2_signal_info.roll_off & 0x80) ? | ||||
| 			INVERSION_ON : INVERSION_OFF; | ||||
| 		if (mci->signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 			u32 modcod = (0x7c & pls_code) >> 2; | ||||
| 			u32 modcod; | ||||
|  | ||||
| 			p->delivery_system = SYS_DVBS2; | ||||
| 			p->rolloff = | ||||
| 				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]; | ||||
| 			p->transmission_mode = pls_code; | ||||
| 			p->rolloff = | ||||
| 				ro_lut[mci->signal_info.dvbs2_signal_info.roll_off & 7]; | ||||
| 			p->pilot = (pls_code & 1) ? PILOT_ON : PILOT_OFF; | ||||
| 			if (pls_code & 0x80) { | ||||
| 				/* no suitable values defined in Linux DVB API yet */ | ||||
| 				/* modcod = (0x7f & pls_code) >> 1; */ | ||||
| 				p->fec_inner = FEC_NONE; | ||||
| 				p->modulation = 0; | ||||
| 				if (pls_code >= 250) | ||||
| 					p->pilot = PILOT_ON; | ||||
| 			} else { | ||||
| 				modcod = (0x7c & pls_code) >> 2; | ||||
| 				p->fec_inner = modcod2fec[modcod]; | ||||
| 				p->modulation = modcod2mod[modcod]; | ||||
| 			} | ||||
| 		} else { | ||||
| 			p->delivery_system = SYS_DVBS; | ||||
| 			p->rolloff = ROLLOFF_35; | ||||
| @@ -265,6 +342,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 		break; | ||||
| 	} | ||||
| 	case SYS_DVBC_ANNEX_A: | ||||
| 		p->modulation = | ||||
| 			mci->signal_info.dvbc_signal_info.constellation + 1; | ||||
| 		break; | ||||
| 	case SYS_DVBT: | ||||
| 		break; | ||||
| @@ -275,6 +354,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 	case SYS_ISDBT: | ||||
| 		break; | ||||
| 	} | ||||
| 	/* post is correct, we cannot provide both pre and post at the same time  */ | ||||
| 	/* set pre and post the same for now */ | ||||
| 	p->pre_bit_error.len = 1; | ||||
| 	p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 	p->pre_bit_error.stat[0].uvalue = | ||||
| @@ -285,6 +366,16 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 	p->pre_bit_count.stat[0].uvalue = | ||||
| 		mci->signal_info.dvbs2_signal_info.ber_denominator; | ||||
|  | ||||
| 	p->post_bit_error.len = 1; | ||||
| 	p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 	p->post_bit_error.stat[0].uvalue = | ||||
| 		mci->signal_info.dvbs2_signal_info.ber_numerator; | ||||
|  | ||||
| 	p->post_bit_count.len = 1; | ||||
| 	p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 	p->post_bit_count.stat[0].uvalue = | ||||
| 		mci->signal_info.dvbs2_signal_info.ber_denominator; | ||||
|  | ||||
| 	p->block_error.len = 1; | ||||
| 	p->block_error.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 	p->block_error.stat[0].uvalue = | ||||
| @@ -293,22 +384,15 @@ 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; | ||||
| 	p->strength.stat[0].svalue = | ||||
| 	p->strength.stat[0].svalue = (s64) | ||||
| 		mci->signal_info.dvbs2_signal_info.channel_power * 10; | ||||
| } | ||||
|  | ||||
| static void mci_handler(void *priv) | ||||
| { | ||||
| 	struct mci_base *base = (struct mci_base *)priv; | ||||
|  | ||||
| 	complete(&base->completion); | ||||
| } | ||||
|  | ||||
| static struct mci_base *match_base(void *key) | ||||
| { | ||||
| 	struct mci_base *p; | ||||
| @@ -319,13 +403,8 @@ static struct mci_base *match_base(void *key) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static int probe(struct mci *state) | ||||
| { | ||||
| 	mci_reset(state); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner) | ||||
| struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, | ||||
| 				    struct mci_cfg *cfg, int nr, int tuner) | ||||
| { | ||||
| 	struct ddb_port *port = input->port; | ||||
| 	struct ddb *dev = port->dev; | ||||
| @@ -349,12 +428,11 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg | ||||
| 		base->key = key; | ||||
| 		base->count = 1; | ||||
| 		base->link = link; | ||||
| 		mutex_init(&base->mci_lock); | ||||
| 		link->mci_base = base; | ||||
| 		mutex_init(&base->tuner_lock); | ||||
| 		ddb_irq_set(dev, link->nr, 0, mci_handler, base); | ||||
| 		init_completion(&base->completion); | ||||
| 		state->base = base; | ||||
| 		if (probe(state) < 0) { | ||||
|  | ||||
| 		if (!link->mci_ok) { | ||||
| 			kfree(base); | ||||
| 			goto fail; | ||||
| 		} | ||||
| @@ -367,6 +445,7 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg | ||||
| 	state->nr = nr; | ||||
| 	state->demod = nr; | ||||
| 	state->tuner = tuner; | ||||
| 	state->input = input; | ||||
| 	if (cfg->init) | ||||
| 		cfg->init(state); | ||||
| 	return &state->fe; | ||||
|   | ||||
| @@ -39,11 +39,6 @@ | ||||
| #define MIC_INTERFACE_OUT       (0x0680) | ||||
| #define MIC_INTERFACE_VER       (0x06F0) | ||||
|  | ||||
|  | ||||
| #define MCI_CONTROL                         (0x500) | ||||
| #define MCI_COMMAND                         (0x600) | ||||
| #define MCI_RESULT                          (0x680) | ||||
|  | ||||
| #define MCI_COMMAND_SIZE                    (0x80) | ||||
| #define MCI_RESULT_SIZE                     (0x80) | ||||
|  | ||||
| @@ -93,29 +88,42 @@ | ||||
|  | ||||
| /********************************************************/ | ||||
|  | ||||
| #define SX8_DEMOD_STOPPED        (0) | ||||
| #define SX8_DEMOD_IQ_MODE        (1) | ||||
| #define SX8_DEMOD_WAIT_SIGNAL    (2) | ||||
| #define SX8_DEMOD_WAIT_MATYPE    (3) | ||||
| #define SX8_DEMOD_TIMEOUT        (14) | ||||
| #define SX8_DEMOD_LOCKED         (15) | ||||
| #define MCI_DEMOD_STOPPED        (0) | ||||
| #define MCI_DEMOD_WAIT_SIGNAL    (2) | ||||
| #define MCI_DEMOD_TIMEOUT        (14) | ||||
| #define MCI_DEMOD_LOCKED         (15) | ||||
|  | ||||
| #define M4_DEMOD_STOPPED         (0) | ||||
| #define M4_DEMOD_WAIT_SIGNAL     (1) | ||||
| #define M4_DEMOD_TIMEOUT         (14) | ||||
| #define M4_DEMOD_LOCKED          (15) | ||||
| #define SX8_DEMOD_IQ_MODE        (1) | ||||
| #define SX8_DEMOD_WAIT_MATYPE    (3) | ||||
|  | ||||
| #define M4_DEMOD_WAIT_TS         (6) | ||||
| #define M4_DEMOD_C2SCAN          (16) | ||||
|  | ||||
| #define MCI_STATUS_OK                 (0x00) | ||||
| #define MCI_STATUS_UNSUPPORTED        (0x80) | ||||
| #define MCI_STATUS_BUSY               (0xFA) | ||||
| #define MCI_STATUS_HARDWARE_ERROR     (0xFB) | ||||
| #define MCI_STATUS_INVALID_PARAMETER  (0xFC) | ||||
| #define MCI_STATUS_RETRY              (0xFD) | ||||
| #define MCI_STATUS_NOT_READY          (0xFE) | ||||
| #define MCI_STATUS_ERROR              (0xFF) | ||||
|  | ||||
| #define MCI_CMD_STOP             (0x01) | ||||
| #define MCI_CMD_GETSTATUS        (0x02) | ||||
| #define MCI_CMD_GETSIGNALINFO    (0x03) | ||||
| #define MCI_CMD_RFPOWER          (0x04) | ||||
| //#define MCI_CMD_RFPOWER          (0x04) | ||||
|  | ||||
| #define MCI_CMD_SEARCH_DVBS     (0x10) | ||||
| #define MCI_CMD_SEARCH_ISDBS    (0x11) | ||||
|  | ||||
| #define MCI_CMD_SEARCH_DVBC     (0x20) | ||||
| #define MCI_CMD_SEARCH_DVBT     (0x21) | ||||
| #define MCI_CMD_SEARCH_DVBT2    (0x22) | ||||
| #define MCI_CMD_SEARCH_DVBC2    (0x23) | ||||
|  | ||||
| #define MCI_CMD_SEARCH_ISDBT    (0x24) | ||||
| #define MCI_CMD_SEARCH_ISDBC    (0x25) | ||||
| #define MCI_CMD_SEARCH_J83B     (0x26) | ||||
|  | ||||
| #define MCI_CMD_GET_IQSYMBOL     (0x30) | ||||
|  | ||||
| @@ -126,13 +134,7 @@ | ||||
| #define MCI_BANDWIDTH_7MHZ       (7) | ||||
| #define MCI_BANDWIDTH_8MHZ       (8) | ||||
|  | ||||
| #define M4_MODE_DVBSX            (2) | ||||
| #define M4_MODE_DVBC             (3) | ||||
| #define M4_MODE_DVBT             (4) | ||||
| #define M4_MODE_DVBT2            (5) | ||||
| #define M4_MODE_DVBC2            (6) | ||||
| #define M4_MODE_ISDBT            (7) | ||||
|  | ||||
| #define SX8_CMD_GETBIST          (0x0F) | ||||
| #define SX8_CMD_INPUT_ENABLE     (0x40) | ||||
| #define SX8_CMD_INPUT_DISABLE    (0x41) | ||||
| #define SX8_CMD_START_IQ         (0x42) | ||||
| @@ -140,18 +142,174 @@ | ||||
| #define SX8_CMD_ENABLE_IQOUTPUT  (0x44) | ||||
| #define SX8_CMD_DISABLE_IQOUTPUT (0x45) | ||||
|  | ||||
| #define M4_CMD_GET_T2_L1INFO      (0x50) | ||||
| #define M4_CMD_GET_C2_L1P2        (0x50) | ||||
| #define M4_CMD_GET_L1INFO         (0x50) | ||||
| #define M4_CMD_GET_IDS            (0x51) | ||||
| #define M4_CMD_GET_DVBT_TPS       (0x52) | ||||
| #define MCI_CMD_GET_BBHEADER      (0x53) | ||||
| #define M4_CMD_GET_ISDBT_TMCC     (0x54) | ||||
| #define M4_CMD_GET_ISDBS_TMCC     (0x55) | ||||
| #define M4_CMD_GET_ISDBC_TSMF     (0x56) | ||||
|  | ||||
| #define MCI_STATUS_OK             (0x00) | ||||
| #define MCI_STATUS_UNSUPPORTED    (0x80) | ||||
| #define MCI_STATUS_RETRY          (0xFD) | ||||
| #define MCI_STATUS_NOT_READY      (0xFE) | ||||
| #define MCI_STATUS_ERROR          (0xFF) | ||||
| #define M4_CMD_GET_BBHEADER       (MCI_CMD_GET_BBHEADER) | ||||
|  | ||||
| #define M4_L1INFO_SEL_PRE         (0) | ||||
| #define M4_L1INFO_SEL_DSINFO      (1) | ||||
| #define M4_L1INFO_SEL_PLPINFO     (2) | ||||
| #define M4_L1INFO_SEL_PLPINFO_C   (3) | ||||
| #define M4_L1INFO_SEL_SETID       (0x80) | ||||
|  | ||||
| #define MCI_BANDWIDTH_EXTENSION  (0x80)   // currently used only for J83B in Japan | ||||
|  | ||||
| #define M4_MODE_DVBSX            (2) | ||||
| #define M4_MODE_DVBC             (3) | ||||
| #define M4_MODE_DVBT             (4) | ||||
| #define M4_MODE_DVBT2            (5) | ||||
| #define M4_MODE_DVBC2            (6) | ||||
| #define M4_MODE_J83B             (7) | ||||
| #define M4_MODE_ISDBT            (8) | ||||
| #define M4_MODE_ISDBC            (9) | ||||
| #define M4_MODE_ISDBS            (10) | ||||
|  | ||||
| #define M4_DVBC_CONSTELLATION_16QAM  (0) | ||||
| #define M4_DVBC_CONSTELLATION_32QAM  (1) | ||||
| #define M4_DVBC_CONSTELLATION_64QAM  (2)  // also valid for J83B and ISDB-C | ||||
| #define M4_DVBC_CONSTELLATION_128QAM (3) | ||||
| #define M4_DVBC_CONSTELLATION_256QAM (4)  // also valid for J83B and ISDB-C | ||||
|  | ||||
| #define M4_SIGNALINFO_FLAG_CHANGE (0x01) | ||||
| #define M4_SIGNALINFO_FLAG_EWS    (0x02) | ||||
|  | ||||
| #define SX8_ROLLOFF_35  0 | ||||
| #define SX8_ROLLOFF_25  1 | ||||
| #define SX8_ROLLOFF_20  2 | ||||
| #define SX8_ROLLOFF_15  5 | ||||
| #define SX8_ROLLOFF_10  3 | ||||
| #define SX8_ROLLOFF_05  4 | ||||
|  | ||||
| #define MCI_SUCCESS(status)     ((status & MCI_STATUS_UNSUPPORTED) == 0) | ||||
|  | ||||
| /********************************************************/ | ||||
|  | ||||
| #define MOD_SETUP_CHANNELS        (0x60) | ||||
| #define MOD_SETUP_OUTPUT          (0x61) | ||||
| #define MOD_SETUP_STREAM          (0x62) | ||||
| #define MOD_SET_STREAM_CHANNEL    (0x63) | ||||
|  | ||||
| #define MOD_SETUP_FLAG_FIRST      (0x01) | ||||
| #define MOD_SETUP_FLAG_LAST       (0x02) | ||||
| #define MOD_SETUP_FLAG_VALID      (0x80) | ||||
|  | ||||
| #define MOD_STANDARD_GENERIC      (0x00) | ||||
| #define MOD_STANDARD_DVBT_8       (0x01) | ||||
| #define MOD_STANDARD_DVBT_7       (0x02) | ||||
| #define MOD_STANDARD_DVBT_6       (0x03) | ||||
| #define MOD_STANDARD_DVBT_5       (0x04) | ||||
|  | ||||
| #define MOD_STANDARD_DVBC_8       (0x08) | ||||
| #define MOD_STANDARD_DVBC_7       (0x09) | ||||
| #define MOD_STANDARD_DVBC_6       (0x0A) | ||||
|  | ||||
| #define MOD_STANDARD_J83A_8       (MOD_STANDARD_DVBC_8) | ||||
| #define MOD_STANDARD_J83A_7       (MOD_STANDARD_DVBC_7) | ||||
| #define MOD_STANDARD_J83A_6       (MOD_STANDARD_DVBC_6) | ||||
|  | ||||
| #define MOD_STANDARD_J83B_QAM64   (0x0B) | ||||
| #define MOD_STANDARD_J83B_QAM256  (0x0C) | ||||
|  | ||||
| #define MOD_STANDARD_ISDBC_QAM64  (0x0D) | ||||
| #define MOD_STANDARD_ISDBC_QAM256 (0x0E) | ||||
|  | ||||
| #define MOD_STANDARD_J83C_QAM64   (MOD_STANDARD_ISDBC_QAM64 ) | ||||
| #define MOD_STANDARD_J83C_QAM256  (MOD_STANDARD_ISDBC_QAM256) | ||||
|  | ||||
| #define MOD_CONNECTOR_OFF         (0x00) | ||||
| #define MOD_CONNECTOR_F           (0x01) | ||||
| #define MOD_CONNECTOR_SMA         (0x02) | ||||
|  | ||||
| #define MOD_UNIT_DBUV             (0x00) | ||||
| #define MOD_UNIT_DBM              (0x01) | ||||
|  | ||||
| #define MOD_FORMAT_DEFAULT        (0x00) | ||||
| #define MOD_FORMAT_IQ16           (0x01) | ||||
| #define MOD_FORMAT_IQ8            (0x02) | ||||
| #define MOD_FORMAT_IDX8           (0x03) | ||||
| #define MOD_FORMAT_TS             (0x04) | ||||
|  | ||||
| #define MOD_DVBT_FFT_8K           (0x01) | ||||
| #define MOD_DVBT_GI_1_32          (0x00) | ||||
| #define MOD_DVBT_GI_1_16          (0x01) | ||||
| #define MOD_DVBT_GI_1_8           (0x02) | ||||
| #define MOD_DVBT_GI_1_4           (0x03) | ||||
|  | ||||
| #define MOD_DVBT_PR_1_2           (0x00) | ||||
| #define MOD_DVBT_PR_2_3           (0x01) | ||||
| #define MOD_DVBT_PR_3_4           (0x02) | ||||
| #define MOD_DVBT_PR_5_6           (0x03) | ||||
| #define MOD_DVBT_PR_7_8           (0x04) | ||||
|  | ||||
| #define MOD_DVBT_QPSK             (0x00) | ||||
| #define MOD_DVBT_16QAM            (0x01) | ||||
| #define MOD_DVBT_64QAM            (0x02) | ||||
|  | ||||
| #define MOD_QAM_DVBC_16           (0x00) | ||||
| #define MOD_QAM_DVBC_32           (0x01) | ||||
| #define MOD_QAM_DVBC_64           (0x02) | ||||
| #define MOD_QAM_DVBC_128          (0x03) | ||||
| #define MOD_QAM_DVBC_256          (0x04) | ||||
|  | ||||
| #define MOD_QAM_J83B_64           (0x05) | ||||
| #define MOD_QAM_J83B_256          (0x06) | ||||
|  | ||||
| #define MOD_QAM_GENERIC           (0x07) | ||||
|  | ||||
| #define MOD_QAM_ISDBC_64          (0x08) | ||||
| #define MOD_QAM_ISDBC_256         (0x09) | ||||
|  | ||||
| #define CMD_GET_SERIALNUMBER    (0xF0) | ||||
| #define CMD_EXPORT_LICENSE      (0xF0) | ||||
|  | ||||
| struct mod_setup_channels { | ||||
| 	u8   flags; | ||||
| 	u8   standard; | ||||
| 	u8   num_channels; | ||||
| 	u8   rsvd; | ||||
| 	u32  frequency; | ||||
| 	u32  offset;            /* used only when Standard == 0 */ | ||||
| 	u32  bandwidth;         /* used only when Standard == 0 */ | ||||
| }; | ||||
|  | ||||
| struct mod_ofdm_parameter { | ||||
| 	u8   fft_size;           /* 0 = 2K, 1 = 8K  (2K not yet supported) */ | ||||
| 	u8   guard_interval;     /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4  (DVB-T Encoding) */ | ||||
| 	u8   puncture_rate;      /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8  (DVB-T Encoding) */ | ||||
| 	u8   constellation;      /* MOD_DVBT_QPSK, MOD_DVBT_16QAM, MOD_DVBT_64QAM */ | ||||
| 	u8   rsvd2[2];           /* Reserved for DVB-T hierarchical */ | ||||
| 	u16  cell_identifier; | ||||
| }; | ||||
|  | ||||
| struct mod_qam_parameter { | ||||
| 	u8   modulation; | ||||
| 	u8   rolloff;           /* Legal values:  12,13,15,18 */ | ||||
| }; | ||||
|  | ||||
| struct mod_setup_stream { | ||||
| 	u8   standard; | ||||
| 	u8   stream_format; | ||||
| 	u8   rsvd1[2]; | ||||
| 	u32  symbol_rate;        /* only used when Standard doesn't define a fixed symbol rate */ | ||||
| 	union { | ||||
| 		struct mod_ofdm_parameter ofdm; | ||||
| 		struct mod_qam_parameter qam; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| struct mod_setup_output { | ||||
| 	u8   connector;         /* 0 = OFF, 1 = F, 2 = SMA */ | ||||
| 	u8   num_channels;      /* max active channels, determines max power for each channel. */ | ||||
| 	u8   unit;              /* 0 = dBµV, 1 = dBm, */ | ||||
| 	u8   rsvd; | ||||
| 	s16  channel_power; | ||||
| }; | ||||
|  | ||||
| /********************************************************/ | ||||
|  | ||||
| @@ -164,13 +322,22 @@ struct mci_command { | ||||
| 			u8 demod; | ||||
| 			u8 output; | ||||
| 		}; | ||||
| 		struct { | ||||
| 			u8 mod_command; | ||||
| 			u8 mod_channel; | ||||
| 			u8 mod_stream; | ||||
| 			u8 mod_rsvd1; | ||||
| 		}; | ||||
| 	}; | ||||
| 	union { | ||||
| 		u32 params[31]; | ||||
| 		u8  params8[31*4]; | ||||
| 		struct { | ||||
| 			u8  flags;    /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled, 7: InputStreamID*/ | ||||
|                         /* Bit 0 : QPSK, 1: 8PSK/8APSK, 2 : 16APSK, 3: 32APSK, 4: 64APSK, 5: 128APSK, 6: 256APSK */ | ||||
| 			u8  s2_modulation_mask; | ||||
| 			u8  flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled, | ||||
| 				      5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */ | ||||
| 			u8  s2_modulation_mask; /* Bit 0 : QPSK, 1: 8PSK/8APSK, | ||||
| 						   2 : 16APSK, 3: 32APSK, 4: 64APSK, | ||||
| 						   5: 128APSK, 6: 256APSK */ | ||||
| 			u8  rsvd1; | ||||
| 			u8  retry; | ||||
| 			u32 frequency; | ||||
| @@ -179,8 +346,21 @@ struct mci_command { | ||||
| 			u8  rsvd2[3]; | ||||
| 			u32 scrambling_sequence_index; | ||||
| 			u32 frequency_range; | ||||
| 			u8  channel_bonding_config; /* Bit 7: IsSlave,  Bit 5..4: MasterDemod, | ||||
| 						       bit 0:  Num channels - 2. | ||||
| 						       (must be set on all channels to same value) */ | ||||
| 		} dvbs2_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags;  /* Bit 0:  0 = TSID is Transport Stream ID, 1 = TSID is relative stream number */ | ||||
| 			u8   rsvd1[2]; | ||||
| 			u8   retry; | ||||
| 			u32  frequency; | ||||
| 			u32  rsvd2; | ||||
| 			u16  rsvd3; | ||||
| 			u16  tsid; | ||||
| 		} isdbs_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags; | ||||
| 			u8   bandwidth; | ||||
| @@ -228,6 +408,30 @@ struct mci_command { | ||||
| 			u32  frequency; | ||||
| 		} isdbt_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags; /* Bit 0:  0 = TSID is Transport Stream ID, 1 = TSID is relative stream number */ | ||||
| 			/* Bit 2..1:  0 = force single, 1 = force multi, 2 = auto detect */ | ||||
| 			u8   bandwidth; | ||||
| 			u8   rsvd1; | ||||
| 			u8   retry; | ||||
| 			u32  frequency; | ||||
| 			u32  rsvd2; | ||||
| 			u16  onid; | ||||
| 			u16  tsid; | ||||
| 		} isdbc_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags; | ||||
| 			u8   bandwidth; | ||||
| 			u8   rsvd1; | ||||
| 			u8   retry; | ||||
| 			u32  frequency; | ||||
| 		} j83b_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags; /*  Bit 0 : 1 = short info (1st 4 Bytes) */ | ||||
| 		} get_signalinfo; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   tap; | ||||
| 			u8   rsvd; | ||||
| @@ -235,32 +439,47 @@ struct mci_command { | ||||
| 		} get_iq_symbol; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags;              /*  Bit 0 : 0 = VTM, 1 = SCAN.  Bit 1: Set Gain */ | ||||
| 			u8   flags; /*  Bit 0 : 0 = VTM/SDR, 1 = SCAN, | ||||
| 					     Bit 1: 1 = Disable AGC, | ||||
| 					     Bit 2: 1 = Set Gain.   */ | ||||
| 			u8   roll_off; | ||||
| 			u8   rsvd1; | ||||
| 			u8   rsvd2; | ||||
| 			u32  frequency; | ||||
| 			u32  symbol_rate;         /* Only in VTM mode. */ | ||||
| 			u16  gain; | ||||
| 			u32  symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ | ||||
| 			u8   gain;         /* Gain in 0.25 dB Steps */ | ||||
| 			/* Frequency, symbolrate and gain can be schanged while running */ | ||||
| 		} sx8_start_iq; | ||||
|  | ||||
| 		struct { | ||||
| 			/* Bit 1:0 = STVVGLNA Gain.  0 = AGC, 1 = 0dB, | ||||
| 			   2 = Minimum, 3 = Maximum */ | ||||
| 			u8     flags;  | ||||
| 			u8   flags; | ||||
| 			/*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||
| 			     2 = Medium, 3 = Maximum gain {~ 15dB} | ||||
| 			     Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) | ||||
| 			     Bit 4: Set RF Gain | ||||
| 			     Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) | ||||
| 			     Bit 7: Optimize RF Gain and freeze for FFT */ | ||||
| 			u8   rf_gain;       /*   0 .. 50 dB */ | ||||
| 		} sx8_input_enable; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   Offset;        // Offset into list, must be multiple of 64 | ||||
| 			u8   Select;        // 0 = Slices, 1 = PLPs  (C2 Only) | ||||
| 			u8   DataSlice;     // DataSlice to get PLPList (C2 Only) | ||||
| 			u8   offset;        /* Offset into list, must be multiple of 64 */ | ||||
| 			u8   select;        /* 0 = Slices, 1 = PLPs  (C2 Only) */ | ||||
| 			u8   data_slice;    /* DataSlice to get PLPList (C2 Only) */ | ||||
| 		} get_ids; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   select;        // 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID | ||||
| 			u8   id;            // DataSliceID, PLPId  | ||||
| 			u8   select;        /* 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID */ | ||||
| 			u8   id;            /* DataSliceID, PLPId */ | ||||
| 		} get_l1_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   select;        /* 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 */ | ||||
| 		} get_bb_header; | ||||
|  | ||||
| 		struct mod_setup_channels mod_setup_channels[4]; | ||||
| 		struct mod_setup_stream mod_setup_stream; | ||||
| 		struct mod_setup_output mod_setup_output; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| @@ -273,13 +492,32 @@ struct mci_result { | ||||
| 			u16 time; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	union { | ||||
| 		u32 result[27]; | ||||
| 		u8 result8[27 * 4]; | ||||
| 		struct { | ||||
| 			u8  Rsvd0[3]; | ||||
| 			u8  Flags; | ||||
|  | ||||
| 			u32 frequency;          /* actual frequency in Hz */ | ||||
| 			u32 rsvd1; | ||||
| 			s16 channel_power;      /* channel power in dBm x 100 */ | ||||
| 			s16 rsvd2; | ||||
| 			s16 signal_to_noise;    /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ | ||||
| 			u16 signal_loss_counter;/* Counts signal losses and automatic retunes */ | ||||
| 			u32 rsvd4; | ||||
| 			u32 ber_numerator;      /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ | ||||
| 			u32 ber_denominator; | ||||
| 			u32 ber_rsvd1;          /* Place holder for modulation bit error rate */ | ||||
| 			u32 ber_rsvd2; | ||||
| 		} common_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  standard; /* 1 = DVB-S, 2 = DVB-S2X */ | ||||
| 			u8  pls_code; /* puncture rate for DVB-S */ | ||||
| 			u8  roll_off;           /* 2-0: rolloff */ | ||||
| 			u8  rsvd; | ||||
| 			u8  pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */ | ||||
| 			u8  roll_off; /* 2-0: rolloff, 7: spectrum inversion */ | ||||
| 			u8  flags; | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 symbol_rate;       /* actual symbolrate in Hz */ | ||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||
| @@ -292,8 +530,24 @@ struct mci_result { | ||||
| 		} dvbs2_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  modulation; | ||||
| 			u8  rsvd1[3]; | ||||
| 			u8  modcod; | ||||
| 			u8  rsvd0[2]; | ||||
| 			u8  flags;             /* Bit 0: TMCC changed, Bit 1: EWS */ | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 symbol_rate;       /* actual symbolrate in Hz */ | ||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||
| 			s16 band_power;        /*/ band power in dBm x 100 */ | ||||
| 			s16 signal_to_noise;   /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;     /* Counter for packet errors. (set to 0 on Start command) */ | ||||
| 			u32 ber_numerator;     /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ | ||||
| 			u32 ber_denominator; | ||||
| 		} isdbs_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  constellation; | ||||
| 			u8  rsvd0[2]; | ||||
| 			u8  flags; | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 symbol_rate;       /* actual symbolrate in Hz */ | ||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||
| @@ -306,9 +560,10 @@ struct mci_result { | ||||
| 		} dvbc_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  tps_25_32;         /* Constellation (2), Hierarchy (3), Coderate HP (3) */ | ||||
| 			u8  tps_33_39;         /* Coderate LP (3), Guardinterval (2), FFT (2), 0 (1) */ | ||||
| 			u16 tps_cell_id;       /* Cell Identifier */ | ||||
| 			u8  modulation1;        // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High | ||||
| 			u8  modulation2;        // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode | ||||
| 			u8  rsvd0; | ||||
| 			u8  flags; | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 rsvd1; | ||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||
| @@ -321,7 +576,8 @@ struct mci_result { | ||||
| 		} dvbt_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u32 rsvd0; | ||||
| 			u8  rsvd0[3]; | ||||
| 			u8  flags; | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 rsvd1; | ||||
| 			s16 channel_power;      /* channel power in dBm x 100 */ | ||||
| @@ -333,8 +589,9 @@ struct mci_result { | ||||
| 			u32 ber_denominator; | ||||
| 		} dvbt2_signal_info; | ||||
|  | ||||
| 		struct {  // Work in Progress | ||||
| 			u32 rsvd0     ;        // Cell Identifier | ||||
| 		struct { | ||||
| 			u8  rsvd0[3]; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 rsvd1;             // | ||||
| @@ -348,7 +605,8 @@ struct mci_result { | ||||
| 		} dvbc2_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u32 rsvd0; | ||||
| 			u8  rsvd0[3]; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 rsvd1;             // | ||||
| @@ -357,24 +615,119 @@ struct mci_result { | ||||
| 			s16 signal_to_noise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;      // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 ber_numerator;      // Bit error rate: PreRS  | ||||
| 			u32 ber_numerator;     // Bit error rate: PreRS Segment A | ||||
| 			u32 ber_denominator; | ||||
| 			 | ||||
| 			u8  tmcc_info[13];      // TMCC B20 - B121 | ||||
| 			u32 ber_rsvd1;          // Place holder for modulation bit error rate | ||||
| 			u32 ber_rsvd2; | ||||
| 			u32 ber_numeratorB;     // Bit error rate: PreRS Segment B | ||||
| 			u32 ber_numeratorC;     // Bit error rate: PreRS Segment C | ||||
| 		} isdbt_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  constellation; | ||||
| 			u8  rsvd0[2]; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 symbol_rate;       // actual symbolrate in Hz | ||||
| 			s16 channel_power;     // channel power in dBm x 100 | ||||
| 			s16 band_power;        // band power in dBm x 100 | ||||
| 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;     // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 ber_numerator;     // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 ber_denominator; | ||||
| 		} isdbc_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  constellation; | ||||
| 			u8  interleaving; | ||||
| 			u8  rsvd0; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 symbol_rate;        // actual symbolrate in Hz | ||||
| 			s16 channel_power;      // channel power in dBm x 100 | ||||
| 			s16 band_power;         // band power in dBm x 100 | ||||
| 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;      // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 ber_numerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 ber_denominator; | ||||
| 		} j83b_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			s16 i; | ||||
| 			s16 q; | ||||
| 		} iq_symbol; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  t2_l1_pre[37]; | ||||
| 			u8  t2_l1_post[15]; | ||||
| 			u8  t2_l1_post_d[19]; | ||||
| 			u8  t2_l1_post_c[19]; | ||||
| 			u8   tps_info[7]; | ||||
| 			// u16 tps_cell_id; | ||||
| 		} dvbt_tps_info; | ||||
|  | ||||
| 		struct { | ||||
| 			struct  { | ||||
| 				u8 type; | ||||
| 				u8 BWExtension; | ||||
| 				u8 S1; | ||||
| 				u8 S2; | ||||
| 				u8 L1RepetitionFlag; | ||||
| 				u8 GuardInterval; | ||||
| 				u8 PAPR; | ||||
| 				u8 L1Mod; | ||||
| 				u8 L1Cod; | ||||
| 				u8 L1FECType; | ||||
| 				u8 L1PostSize[3]; | ||||
| 				u8 L1PostInfoSize[3]; | ||||
| 				u8 PilotPattern; | ||||
| 				u8 TXIDAvailabilty; | ||||
| 				u8 CellID[2]; | ||||
| 				u8 NetworkID[2]; | ||||
| 				u8 T2SystemID[2]; | ||||
| 				u8 NumT2Frames; | ||||
| 				u8 NumDataSymbols[2]; | ||||
| 				u8 RegenFlag; | ||||
| 				u8 L1PostExtension; | ||||
| 				u8 NumRF; | ||||
| 				u8 CurrentRFIndex; | ||||
| 				u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit | ||||
| 				u8 CRC32[4]; | ||||
| 			} dvbt2_l1_pre; | ||||
|  | ||||
| 			struct  { | ||||
| 				u8 SubSlicesPerFrame[2]; | ||||
| 				u8 NumPLP; | ||||
| 				u8 NumAux; | ||||
| 				u8 AuxConfigRFU; | ||||
| 				u8 RFIndex; | ||||
| 				u8 Frequency[4]; | ||||
| 				u8 FEFType; | ||||
| 				u8 FEFLength[3]; | ||||
| 				u8 FEFInterval; | ||||
| 			} dvbt2_l1_post; | ||||
| 		} dvbt2_l1_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8 PLPID; | ||||
| 			u8 Type; | ||||
| 			u8 PayloadType; | ||||
| 			u8 FFFlag; | ||||
| 			u8 FirstRFIndex; | ||||
| 			u8 FirstFrameIndex; | ||||
| 			u8 GroupID; | ||||
| 			u8 Cod; | ||||
| 			u8 Mod; | ||||
| 			u8 Rotation; | ||||
| 			u8 FECType; | ||||
| 			u8 NumBlocksMax[2]; | ||||
| 			u8 FrameInterval; | ||||
| 			u8 TimeILLength; | ||||
| 			u8 TimeILType; | ||||
| 			u8 InBandAFlag; | ||||
| 			u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2];  // 1,11,2,1,1 | ||||
| 		} dvbt2_plp_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  NetworkID[2]; | ||||
| 			u8  C2SystemID[2]; | ||||
| @@ -421,7 +774,7 @@ struct mci_result { | ||||
| 			u8  PayloadType; | ||||
| 			u8  GroupID; | ||||
| 			u8  Start[2]; | ||||
| 			u8  FEC_Type; | ||||
| 			u8  FECType; | ||||
| 			u8  Mod; | ||||
| 			u8  Cod; | ||||
| 			u8  PSISIReprocessing; | ||||
| @@ -429,10 +782,88 @@ struct mci_result { | ||||
| 			u8  OrginalNetworkID[2]; | ||||
| 			u8  Reserved1; | ||||
| 		} DVBC2_PLPInfo; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  valid; | ||||
| 			u8  matype_1; | ||||
| 			u8  matype_2; | ||||
| 			u8  upl[2]; | ||||
| 			u8  dfl[2]; | ||||
| 			u8  sync; | ||||
| 			u8  syncd[2]; | ||||
| 			u8  rsvd; | ||||
| 			u8  issy[3]; | ||||
| 			u8  min_input_stream_id; | ||||
| 			u8  max_input_stream_id; | ||||
| 		} bb_header; | ||||
|  | ||||
| 		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 | ||||
| 		} ISDBT_TMCCInfo; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   Change;  // 5 bits, increments with every change | ||||
| 			struct { | ||||
| 				u8 ModCod;    // 4 bits | ||||
| 				u8 NumSlots;  // 6 bits | ||||
| 			} Mode[4]; | ||||
| 			u8   RelTSID[24];  // bit 6..4 Relative TSID for slot i*2 + 1, bit 2..0 Relative TSID for slot i*2 + 2 | ||||
| 			struct { | ||||
| 				u8 highByte; | ||||
| 				u8 lowByte; | ||||
| 			} TSID[8]; | ||||
| 			u8   Flags;  // Bit 5: EWS flag, bit 4: Site Diversity flag, bit 3..1: Site Diversity information, bit 0: Extension flag | ||||
| 			u8   Extension[8];   // 61 bits, right aligned | ||||
| 		} ISDBS_TMCCInfo; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  cut; | ||||
| 			u8  avs_code; | ||||
| 			u8  temperature; | ||||
| 			u8  rsvd[13]; | ||||
| 		} sx8_bist; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   status; | ||||
| 			u8   offset; | ||||
| 			u8   length; | ||||
| 			u8   rsvd2; | ||||
| 			u32  rsvd3[2]; | ||||
| 			u8   data[96]; | ||||
| 		} SX8_packet_filter_status; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   version;  /* 0 = none, 1 = SX8 */ | ||||
| 			u8   flags;    /* Bit 0: 1 = Tuner Valid, Bit 1: 1 = Output Valid */ | ||||
| 			u8   tuner; | ||||
| 			u8   output; | ||||
| 		} extended_status; | ||||
|  | ||||
| 		struct { | ||||
| 		        u8   reserved; | ||||
| 		        u8   serial_number[17]; | ||||
| 		} serial_number; | ||||
|  | ||||
| 		struct { | ||||
| 		        u8   flags; | ||||
| 		        u8   serial_number[17]; | ||||
| 		        u16  code; | ||||
| 		        u8   ID[8]; | ||||
| 		        u8   LK[24]; | ||||
| 		} license; | ||||
|  | ||||
| 	}; | ||||
| 	u32 version[4]; | ||||
| 	u32 version[3]; | ||||
| 	u8  version_rsvd; | ||||
| 	u8  version_major; | ||||
| 	u8  version_minor; | ||||
| 	u8  version_sub; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Helper Macros */ | ||||
|  | ||||
| /* DVB-T2 L1-Pre Signalling Data   ( ETSI EN 302 755 V1.4.1 Chapter 7.2.2 ) */ | ||||
| @@ -467,7 +898,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) | ||||
| @@ -502,20 +933,21 @@ struct mci_result { | ||||
| #define L1POST_STATIC_FLAG(p)              (((p)[18] >> 1) & 0x01) | ||||
| #define L1POST_STATIC_PADDING_FLAG(p)      (((p)[18] >> 1) & 0x01) | ||||
|  | ||||
| #ifdef __KERNEL__ | ||||
|  | ||||
| struct mci_base { | ||||
| 	struct list_head     mci_list; | ||||
| 	void                *key; | ||||
| 	struct ddb_link     *link; | ||||
| 	struct completion    completion; | ||||
| 	struct i2c_adapter  *i2c; | ||||
| 	struct mutex         i2c_lock; | ||||
| //	struct completion    completion; | ||||
| 	struct mutex         tuner_lock; | ||||
| 	struct mutex         mci_lock; | ||||
| //	struct mutex         mci_lock; | ||||
| 	int                  count; | ||||
| 	int                  type; | ||||
| }; | ||||
|  | ||||
| struct mci { | ||||
| 	struct ddb_io       *input; | ||||
| 	struct mci_base     *base; | ||||
| 	struct dvb_frontend  fe; | ||||
| 	int                  nr; | ||||
| @@ -535,13 +967,15 @@ struct mci_cfg { | ||||
| }; | ||||
|  | ||||
| int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result); | ||||
| int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len, | ||||
| 		    struct mci_result *result, u32 result_len); | ||||
| int ddb_mci_config(struct mci *state, u32 config); | ||||
| int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result); | ||||
| int ddb_mci_get_status(struct mci *mci, struct mci_result *res); | ||||
| int ddb_mci_get_snr(struct dvb_frontend *fe); | ||||
| 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); | ||||
| int mci_init(struct ddb_link *link); | ||||
| int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ddbridge-modulator.c: Digital Devices modulator cards | ||||
|  * | ||||
|  * Copyright (C) 2010-2017 Digital Devices GmbH | ||||
|  * Copyright (C) 2010-2018 Digital Devices GmbH | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  * | ||||
| @@ -23,8 +23,13 @@ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-io.h" | ||||
| #include "ddbridge-ioctl.h" | ||||
|  | ||||
| #ifdef KERNEL_DVB_CORE | ||||
| #include "../include/linux/dvb/mod.h" | ||||
| #else | ||||
| #include <linux/dvb/mod.h> | ||||
| #endif | ||||
| #include <linux/gcd.h> | ||||
|  | ||||
| /****************************************************************************/ | ||||
| @@ -164,11 +169,6 @@ static void mod_calc_rateinc(struct ddb_mod *mod) | ||||
| { | ||||
| 	u32 ri; | ||||
|  | ||||
| 	dev_info(mod->port->dev->dev, | ||||
| 		 "ibitrate %llu\n", mod->ibitrate); | ||||
| 	dev_info(mod->port->dev->dev, | ||||
| 		 "obitrate %llu\n", mod->obitrate); | ||||
|  | ||||
| 	if (mod->ibitrate != 0) { | ||||
| 		u64 d = mod->obitrate - mod->ibitrate; | ||||
|  | ||||
| @@ -195,6 +195,48 @@ static int mod_calc_obitrate(struct ddb_mod *mod) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mod_set_stream(struct ddb_output *output) | ||||
| { | ||||
| 	struct ddb *dev = output->port->dev; | ||||
| 	u32 stream = output->nr; | ||||
| 	struct ddb_mod *mod = &dev->mod[output->nr]; | ||||
| 	struct ddb_link *link = &dev->link[0]; | ||||
| 	struct mci_result res; | ||||
| 	u32 channel; | ||||
| 	struct mci_command cmd = { | ||||
| 		.mod_command = MOD_SETUP_STREAM, | ||||
| 		.mod_channel = stream, | ||||
| 		.mod_stream = stream, | ||||
| 		.mod_setup_stream = { | ||||
| 			.standard = MOD_STANDARD_DVBC_8, | ||||
| 			.symbol_rate = mod->symbolrate, | ||||
| 			.qam = { | ||||
| 				.modulation = mod->modulation - 1, | ||||
| 				.rolloff = 13, | ||||
| 			} | ||||
| 		}, | ||||
| 	}; | ||||
| 	if (dev->link[0].info->version != 2) | ||||
| 		return 0; | ||||
| 	if (dev->link[0].ids.revision != 1) | ||||
| 		return 0; | ||||
| 	if ((dev->link[0].ids.hwid & 0xffffff) < 9065) | ||||
| 		return 0; | ||||
| 	if (!mod->frequency && !mod->symbolrate && !mod->modulation) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (mod->frequency) | ||||
| 		channel = (mod->frequency - 114000000) / 8000000; | ||||
| 	if (!mod->symbolrate) | ||||
| 		mod->symbolrate = 6900000; | ||||
| 	if (!mod->modulation) | ||||
| 		mod->modulation = 5; | ||||
| 	cmd.mod_channel = channel; | ||||
| 	cmd.mod_setup_stream.symbol_rate = mod->symbolrate; | ||||
| 	cmd.mod_setup_stream.qam.modulation = mod->modulation - 1; | ||||
| 	return ddb_mci_cmd_link(link, &cmd, &res); | ||||
| } | ||||
|  | ||||
| static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate) | ||||
| { | ||||
| 	struct ddb *dev = mod->port->dev; | ||||
| @@ -210,6 +252,7 @@ static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate) | ||||
| 	} | ||||
| 	mod->symbolrate = srate; | ||||
| 	mod_calc_obitrate(mod); | ||||
| 	mod_set_stream(mod->port->output); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -227,6 +270,7 @@ static int mod_set_modulation(struct ddb_mod *mod, | ||||
| 		ddbwritel(dev, qamtab[modulation], | ||||
| 			  CHANNEL_SETTINGS(mod->port->nr)); | ||||
| 	mod_calc_obitrate(mod); | ||||
| 	mod_set_stream(mod->port->output); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -241,6 +285,7 @@ static int mod_set_frequency(struct ddb_mod *mod, u32 frequency) | ||||
| 	if ((freq < 114) || (freq > 874)) | ||||
| 		return -EINVAL; | ||||
| 	mod->frequency = frequency; | ||||
| 	mod_set_stream(mod->port->output); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -292,7 +337,7 @@ int ddbridge_mod_output_start(struct ddb_output *output) | ||||
| 	struct ddb_mod *mod = &dev->mod[output->nr]; | ||||
| 	u32 Symbolrate = mod->symbolrate; | ||||
|  | ||||
| 	if (dev->link[0].info->version < 3) | ||||
| 	if (dev->link[0].info->version < 16) | ||||
| 		mod_calc_rateinc(mod); | ||||
|  | ||||
| 	mod->LastInPacketCount = 0; | ||||
| @@ -311,7 +356,7 @@ int ddbridge_mod_output_start(struct ddb_output *output) | ||||
| 	mod->State = CM_STARTUP; | ||||
| 	mod->StateCounter = CM_STARTUP_DELAY; | ||||
|  | ||||
| 	if (dev->link[0].info->version == 3) | ||||
| 	if (dev->link[0].info->version >= 16) | ||||
| 		mod->Control = 0xfffffff0 & | ||||
| 			ddbreadl(dev, CHANNEL_CONTROL(output->nr)); | ||||
| 	else | ||||
| @@ -322,14 +367,27 @@ int ddbridge_mod_output_start(struct ddb_output *output) | ||||
| 		  CHANNEL_CONTROL(output->nr)); | ||||
| 	udelay(10); | ||||
| 	ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); | ||||
|  | ||||
| 	if (dev->link[0].info->version == 2) { | ||||
| 	switch (dev->link[0].info->version) { | ||||
| 	case 2: | ||||
| 	{ | ||||
| 		u32 Output = (mod->frequency - 114000000) / 8000000; | ||||
| 		u32 KF = Symbolrate; | ||||
| 		u32 LF = 9000000UL; | ||||
| 		u32 d = gcd(KF, LF); | ||||
| 		u32 checkLF; | ||||
|  | ||||
| 		if ((dev->link[0].ids.revision == 1)) { | ||||
| 			if ((dev->link[0].info->version == 2)) { | ||||
| 				if ((dev->link[0].ids.hwid & 0xffffff) >= 9065) { | ||||
| 					mod->Control |= CHANNEL_CONTROL_ENABLE_DVB; | ||||
| 					break; | ||||
| 				} | ||||
| 			} else { | ||||
| 				mod->Control |= CHANNEL_CONTROL_ENABLE_DVB; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel)); | ||||
| 		ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel)); | ||||
|  | ||||
| @@ -356,18 +414,23 @@ int ddbridge_mod_output_start(struct ddb_output *output) | ||||
| 					   CHANNEL_CONTROL_CMD_SETUP)) | ||||
| 			return -EINVAL; | ||||
| 		mod->Control |= CHANNEL_CONTROL_ENABLE_DVB; | ||||
| 	} else if (dev->link[0].info->version <= 1) { | ||||
| 		break; | ||||
| 	} | ||||
| 	case 0: | ||||
| 	case 1: | ||||
| 		/* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ | ||||
| 		/* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ | ||||
| 		ddbwritel(dev, qamtab[mod->modulation], | ||||
| 			  CHANNEL_SETTINGS(output->nr)); | ||||
| 		mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ | | ||||
| 				 CHANNEL_CONTROL_ENABLE_DVB); | ||||
| 	} else if (dev->link[0].info->version == 3) { | ||||
| 		break; | ||||
| 	default: | ||||
| 		mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ | | ||||
| 				 CHANNEL_CONTROL_ENABLE_DVB); | ||||
| 		break; | ||||
| 	} | ||||
| 	if (dev->link[0].info->version < 3) { | ||||
| 	if (dev->link[0].info->version < 16) { | ||||
| 		mod_set_rateinc(dev, output->nr); | ||||
| 		mod_set_incs(output); | ||||
| 	} | ||||
| @@ -435,7 +498,7 @@ static int mod_setup_max2871(struct ddb *dev, u32 *reg) | ||||
|  | ||||
| 			if (j == 4) | ||||
| 				val &= 0xFFFFFEDF; | ||||
| 			status = mod_write_max2871(dev, reg[j]); | ||||
| 			status = mod_write_max2871(dev, val); | ||||
| 			if (status) | ||||
| 				break; | ||||
| 			msleep(30); | ||||
| @@ -511,11 +574,11 @@ static int mod_fsm_setup(struct ddb *dev, u32 MaxUsedChannels) | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| static int mod_set_vga(struct ddb *dev, u32 Gain) | ||||
| static int mod_set_vga(struct ddb *dev, u32 gain) | ||||
| { | ||||
| 	if (Gain > 255) | ||||
| 	if (gain > 255) | ||||
| 		return -EINVAL; | ||||
| 	ddbwritel(dev, Gain, RF_VGA); | ||||
| 	ddbwritel(dev, gain, RF_VGA); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -622,7 +685,61 @@ static int mod_set_attenuator(struct ddb *dev, u32 Value) | ||||
| { | ||||
| 	if (Value > 31) | ||||
| 		return -EINVAL; | ||||
| 	ddbwritel(dev, Value, RF_ATTENUATOR); | ||||
| 	if (dev->link[0].ids.revision == 1) { | ||||
| 		struct ddb_link *link = &dev->link[0]; | ||||
| 		struct mci_result res; | ||||
| 		struct mci_command cmd = { | ||||
| 			.mod_command = MOD_SETUP_OUTPUT, | ||||
| 			.mod_channel = 0, | ||||
| 			.mod_stream = 0, | ||||
| 			.mod_setup_output = { | ||||
| 				.connector = MOD_CONNECTOR_F, | ||||
| 				.num_channels = dev->link[0].info->port_num, | ||||
| 				.unit = MOD_UNIT_DBUV, | ||||
| 				.channel_power = 9000 - Value * 100, | ||||
| 			}, | ||||
| 		}; | ||||
| 		if (!link->mci_ok) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 		return ddb_mci_cmd_link(link, &cmd, &res); | ||||
| 	} else | ||||
| 		ddbwritel(dev, Value, RF_ATTENUATOR); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mod_set_sdr_attenuator(struct ddb *dev, u32 value) | ||||
| { | ||||
| 	u32 control; | ||||
| 	 | ||||
| 	if (value > 31) | ||||
| 		return -EINVAL; | ||||
| 	control = ddbreadl(dev, SDR_CONTROL); | ||||
| 	if (control & 0x01000000) { | ||||
| 		ddbwritel(dev, 0x03, SDR_CONTROL); | ||||
| 	} else { | ||||
| 		ddbwritel(dev, value, RF_ATTENUATOR); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mod_set_sdr_gain(struct ddb *dev, u32 gain) | ||||
| { | ||||
| 	u32 control = ddbreadl(dev, SDR_CONTROL); | ||||
|  | ||||
| 	if (control & 0x01000000) { | ||||
| 		if (gain > 511) | ||||
| 			return -EINVAL; | ||||
| 		ddbwritel(dev, 0x03, SDR_CONTROL); | ||||
| 		ddbwritel(dev, gain, SDR_GAIN_F); | ||||
| 		if (gain > 255) | ||||
| 			gain = 255; | ||||
| 		ddbwritel(dev, gain, SDR_GAIN_SMA); | ||||
| 	} else { | ||||
| 		if (gain > 255) | ||||
| 			return -EINVAL; | ||||
| 		ddbwritel(dev, gain, SDR_GAIN_F); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -1423,7 +1540,9 @@ static int mod3_set_base_frequency(struct ddb *dev, u32 frequency) | ||||
|  | ||||
| 	if (frequency % 1000) | ||||
| 		return -EINVAL; | ||||
| 	if ((frequency < 114000000) || (frequency > 874000000)) | ||||
| 	if (frequency < 114000000) | ||||
| 		return -EINVAL; | ||||
| 	if (frequency > 1874000000) | ||||
| 		return -EINVAL; | ||||
| 	dev->mod_base.frequency = frequency; | ||||
| 	tmp = frequency; | ||||
| @@ -1445,7 +1564,8 @@ static void mod3_set_cfcw(struct ddb_mod *mod, u32 f) | ||||
| 	tmp = ((s64) (freq - dcf)) << 32; | ||||
| 	tmp = div64_s64(tmp, srdac); | ||||
| 	cfcw = (u32) tmp; | ||||
| 	dev_info(dev->dev, "f=%u cfcw = %08x nr = %u\n", f, cfcw, mod->port->nr); | ||||
| 	dev_info(dev->dev, "f=%u cfcw = %08x dcf = %08x, nr = %u\n", | ||||
| 		 f, cfcw, dcf, mod->port->nr); | ||||
| 	ddbwritel(dev, cfcw, SDR_CHANNEL_CFCW(mod->port->nr)); | ||||
| } | ||||
|  | ||||
| @@ -1476,12 +1596,111 @@ static int mod3_set_ari(struct ddb_mod *mod, u32 rate) | ||||
| } | ||||
|  | ||||
|  | ||||
| static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate) | ||||
| { | ||||
| 	struct ddb *dev = mod->port->dev; | ||||
| 	u32 cic, inc, bypass = 0; | ||||
|  | ||||
| 	switch (rate) { | ||||
| 		/* 2^31 * freq*4*cic / 245.76Mhz */ | ||||
| 	case SYS_DVBT_6: | ||||
| 		inc = 0x72492492; | ||||
| 		cic = 8; | ||||
| 		break; | ||||
| 	case SYS_DVBT_7: | ||||
| 		inc = 1957341867; | ||||
| 		cic = 7; | ||||
| 		break; | ||||
| 	case SYS_DVBT_8: | ||||
| 		//rate = 8126984; | ||||
| 		inc = 1917396114; | ||||
| 		cic = 6; | ||||
| 		break; | ||||
| 	case SYS_DVBC_6900: | ||||
| 		inc = 0x73000000; //1929379840; | ||||
| 		cic = 8; | ||||
| 		break; | ||||
| 	case 9: | ||||
| 		inc = 0x47e00000; //1929379840; | ||||
| 		cic = 10; | ||||
| 		bypass = 2; | ||||
| 		break; | ||||
|  | ||||
| 	case SYS_J83B_64_6: /* 5056941  */ | ||||
| 		inc = 0x695a5a1d; | ||||
| 		cic = 10; | ||||
| 		break; | ||||
| 	case SYS_J83B_256_6: /* 5360537  */ | ||||
| 		inc = 0x6fad87da; | ||||
| 		cic = 10; | ||||
| 		break; | ||||
| 		 | ||||
| 	case SYS_ISDBT_6: | ||||
| 		inc = 0x7684BD82; //1988410754; | ||||
| 		cic = 7; | ||||
| 		break; | ||||
| 	case SYS_DVB_22: | ||||
| 		inc = 0x72955555; // 1922389333; | ||||
| 		cic = 5; | ||||
| 		bypass = 2; | ||||
| 		break; | ||||
| 	case SYS_DVB_24: | ||||
| 		inc = 0x7d000000; | ||||
| 		cic = 5; | ||||
| 		bypass = 2; | ||||
| 		break; | ||||
| 	case SYS_DVB_30: | ||||
| 		inc = 0x7d000000; | ||||
| 		cic = 4; | ||||
| 		bypass = 2; | ||||
| 		break; | ||||
| 	case SYS_ISDBS_2886: | ||||
| 		inc = 0x78400000; | ||||
| 		cic = 4; | ||||
| 		bypass = 2; | ||||
| 		break; | ||||
| 	default: | ||||
| 	{ | ||||
| 		u64 a; | ||||
| 				 | ||||
| 		if (rate < 1000000) | ||||
| 			return -EINVAL; | ||||
| 		if (rate > 30720000) | ||||
| 			return -EINVAL; | ||||
|  | ||||
| 		bypass = 2; | ||||
| 		if (rate > 24576000) | ||||
| 			cic = 4; | ||||
| 		else if (rate > 20480000) | ||||
| 			cic = 5; | ||||
| 		else if (rate > 17554286) | ||||
| 			cic = 6; | ||||
| 		else if (rate > 15360000) | ||||
| 			cic = 7; | ||||
| 		else | ||||
| 			cic = 8; | ||||
| 		a = (1ULL << 31) * rate * 2 * cic; | ||||
| 		inc = div_s64(a, 245760000); | ||||
| 		break; | ||||
| 	} | ||||
| 	} | ||||
| 	dev_info(dev->dev, "inc = %08x, cic = %u, bypass = %u\n", inc, cic, bypass); | ||||
| 	ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr)); | ||||
| 	ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4), | ||||
| 		  SDR_CHANNEL_CONFIG(mod->port->nr)); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| { | ||||
| 	switch (tvp->cmd) { | ||||
| 	case MODULATOR_OUTPUT_ARI: | ||||
| 		return mod3_set_ari(mod, tvp->u.data); | ||||
|  | ||||
| 	case MODULATOR_OUTPUT_RATE: | ||||
| 		return mod3_set_sample_rate(mod, tvp->u.data); | ||||
|  | ||||
| 	case MODULATOR_FREQUENCY: | ||||
| 		return mod3_set_frequency(mod, tvp->u.data); | ||||
|  | ||||
| @@ -1489,17 +1708,18 @@ static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| 		return mod3_set_base_frequency(mod->port->dev, tvp->u.data); | ||||
|  | ||||
| 	case MODULATOR_ATTENUATOR: | ||||
| 		return mod_set_attenuator(mod->port->dev, tvp->u.data); | ||||
| 		return mod_set_sdr_attenuator(mod->port->dev, tvp->u.data); | ||||
|  | ||||
| 	case MODULATOR_GAIN: | ||||
| 		return mod_set_vga(mod->port->dev, tvp->u.data); | ||||
| 		return mod_set_sdr_gain(mod->port->dev, tvp->u.data); | ||||
|  | ||||
| 	} | ||||
| 	return -EINVAL; | ||||
| } | ||||
|  | ||||
| static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| { | ||||
| 	if (mod->port->dev->link[0].info->version == 3) | ||||
| 	if (mod->port->dev->link[0].info->version >= 16) | ||||
| 		return mod3_prop_proc(mod, tvp); | ||||
| 	switch (tvp->cmd) { | ||||
| 	case MODULATOR_SYMBOL_RATE: | ||||
| @@ -1515,7 +1735,11 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| 		return mod_set_attenuator(mod->port->dev, tvp->u.data); | ||||
|  | ||||
| 	case MODULATOR_INPUT_BITRATE: | ||||
| #ifdef KERNEL_DVB_CORE | ||||
| 		return mod_set_ibitrate(mod, *(u64 *) &tvp->u.buffer.data[0]); | ||||
| #else | ||||
| 		return mod_set_ibitrate(mod, tvp->u.data64); | ||||
| #endif | ||||
|  | ||||
| 	case MODULATOR_GAIN: | ||||
| 		if (mod->port->dev->link[0].info->version == 2) | ||||
| @@ -1541,15 +1765,37 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mod_prop_get3(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| { | ||||
| 	struct ddb *dev = mod->port->dev; | ||||
|  | ||||
| 	switch (tvp->cmd) { | ||||
| 	case MODULATOR_INFO: | ||||
| 		tvp->u.data = dev->link[0].info->version; | ||||
| 		return 0; | ||||
| 	case MODULATOR_GAIN: | ||||
| 		tvp->u.data = 0xff & ddbreadl(dev, RF_VGA); | ||||
| 		return 0; | ||||
| 	default: | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp) | ||||
| { | ||||
| 	struct ddb *dev = mod->port->dev; | ||||
|  | ||||
| 	if (mod->port->dev->link[0].info->version >= 16) | ||||
| 		return mod_prop_get3(mod, tvp); | ||||
| 	if (mod->port->dev->link[0].info->version != 2) | ||||
| 		return -1; | ||||
| 	switch (tvp->cmd) { | ||||
| 	case MODULATOR_INFO: | ||||
| 		tvp->u.data = 2; | ||||
| 		return 0; | ||||
|  | ||||
| 	case MODULATOR_GAIN: | ||||
| 		tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);; | ||||
| 		tvp->u.data = 0xff & ddbreadl(dev, RF_VGA); | ||||
| 		return 0; | ||||
|  | ||||
| 	case MODULATOR_ATTENUATOR: | ||||
| @@ -1592,7 +1838,8 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) | ||||
| 		(struct dtv_properties __user *) parg; | ||||
| 	int i, ret = 0; | ||||
|  | ||||
| 	if (dev->link[0].info->version == 3 && cmd != FE_SET_PROPERTY) | ||||
| 	if (dev->link[0].info->version >= 16 && | ||||
| 	    (cmd != FE_SET_PROPERTY && cmd != IOCTL_DDB_MCI_CMD)) | ||||
| 		return -EINVAL; | ||||
| 	mutex_lock(&dev->ioctl_mutex); | ||||
| 	switch (cmd) { | ||||
| @@ -1684,6 +1931,27 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) | ||||
| 		mod->pcr_correction = cp->pcr_correction; | ||||
| 		break; | ||||
| 	} | ||||
| 	case IOCTL_DDB_MCI_CMD: | ||||
| 	{ | ||||
| 		struct ddb_mci_msg *msg =  | ||||
| 			(struct ddb_mci_msg __user *) parg; | ||||
| 		struct ddb_link *link; | ||||
|  | ||||
| 		if (dev->link[0].ids.revision != 1) | ||||
| 			break; | ||||
|  | ||||
|  		if (msg->link > 3) { | ||||
| 			ret = -EFAULT; | ||||
| 			break; | ||||
| 		} | ||||
| 		link = &dev->link[msg->link]; | ||||
| 		if (!link->mci_ok) { | ||||
| 			ret = -EFAULT; | ||||
| 			break; | ||||
| 		} | ||||
| 		ret = ddb_mci_cmd_link(link, &msg->cmd, &msg->res); | ||||
| 		break; | ||||
| 	} | ||||
| 	default: | ||||
| 		ret = -EINVAL; | ||||
| 		break; | ||||
| @@ -1692,6 +1960,18 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int mod_init_2_1(struct ddb *dev, u32 Frequency) | ||||
| { | ||||
| 	int i, streams = dev->link[0].info->port_num; | ||||
|  | ||||
| 	dev->mod_base.frequency = Frequency; | ||||
| 	for (i = 0; i < streams; i++) { | ||||
| 		struct ddb_mod *mod = &dev->mod[i]; | ||||
| 		mod->port = &dev->port[i]; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mod_init_2(struct ddb *dev, u32 Frequency) | ||||
| { | ||||
| 	int i, status, streams = dev->link[0].info->port_num; | ||||
| @@ -1776,7 +2056,7 @@ static int rfdac_init(struct ddb *dev) | ||||
| 	} | ||||
| 	if (tmp & 0x80) | ||||
| 		return -1; | ||||
| 	dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	ddbwritel(dev, RFDAC_CMD_RESET, RFDAC_CONTROL); | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		msleep(20); | ||||
| @@ -1786,7 +2066,7 @@ static int rfdac_init(struct ddb *dev) | ||||
| 	} | ||||
| 	if (tmp & 0x80) | ||||
| 		return -1; | ||||
| 	dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	ddbwritel(dev, RFDAC_CMD_SETUP, RFDAC_CONTROL); | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		msleep(20); | ||||
| @@ -1796,7 +2076,7 @@ static int rfdac_init(struct ddb *dev) | ||||
| 	} | ||||
| 	if (tmp & 0x80) | ||||
| 		return -1; | ||||
| 	dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	ddbwritel(dev, 0x01, JESD204B_BASE); | ||||
| 	for (i = 0; i < 400; i++) { | ||||
| 		msleep(20); | ||||
| @@ -1804,7 +2084,7 @@ static int rfdac_init(struct ddb *dev) | ||||
| 		if ((tmp & 0xc0000000) == 0xc0000000) | ||||
| 			break; | ||||
| 	} | ||||
| 	dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp); | ||||
| 	if ((tmp & 0xc0000000) != 0xc0000000) | ||||
| 		return -1; | ||||
| 	return 0; | ||||
| @@ -1847,21 +2127,79 @@ static int mod_init_3(struct ddb *dev, u32 Frequency) | ||||
| 		ddbwritel(dev, 0x00002000, SDR_CHANNEL_FM1GAIN(i)); | ||||
| 		ddbwritel(dev, 0x00001000, SDR_CHANNEL_FM2GAIN(i)); | ||||
| 	} | ||||
| 	mod_set_attenuator(dev, 0); | ||||
| 	mod_set_vga(dev, 64); | ||||
| 	mod_set_sdr_attenuator(dev, 0); | ||||
| 	mod_set_sdr_gain(dev, 64); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int mod_init_sdr_iq(struct ddb *dev) | ||||
| { | ||||
| 	int streams = dev->link[0].info->port_num; | ||||
| 	int i, ret = 0; | ||||
|  | ||||
| 	ret = mod_setup_max2871(dev, max2871_sdr); | ||||
| 	if (ret) | ||||
| 		dev_err(dev->dev, "PLL setup failed\n"); | ||||
| 	ret = rfdac_init(dev); | ||||
| 	if (ret) | ||||
| 		ret = rfdac_init(dev); | ||||
| 	if (ret) | ||||
| 		dev_err(dev->dev, "RFDAC setup failed\n"); | ||||
| 	 | ||||
| 	ddbwritel(dev, 0x01, 0x240); | ||||
|  | ||||
|  | ||||
| 	//mod3_set_base_frequency(dev, 602000000); | ||||
| 	dev->mod_base.frequency = 570000000; | ||||
| 	for (i = 0; i < streams; i++) { | ||||
| 		struct ddb_mod *mod = &dev->mod[i]; | ||||
|  | ||||
| 		mod->port = &dev->port[i]; | ||||
| 		if (dev->link[0].ids.revision != 1) | ||||
| 			ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i)); | ||||
| 	} | ||||
| 	if (dev->link[0].ids.revision == 1) | ||||
| 		return ret; | ||||
| 	mod_set_sdr_attenuator(dev, 0); | ||||
| 	udelay(10); | ||||
| 	mod_set_sdr_gain(dev, 120); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int ddbridge_mod_init(struct ddb *dev) | ||||
| { | ||||
| 	dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision); | ||||
| 	if (dev->link[0].ids.revision == 1) { | ||||
| 		switch (dev->link[0].info->version) { | ||||
| 		case 0: | ||||
| 		case 1: | ||||
| 			return mod_init_1(dev, 722000000); | ||||
| 		case 2: /* FSM */ | ||||
| 			if ((dev->link[0].ids.hwid & 0xffffff) >= 9065) | ||||
| 				return mod_init_2_1(dev, 114000000); | ||||
| 			return mod_init_2(dev, 114000000); | ||||
| 		case 16: /* PAL */ | ||||
| 			return mod_init_3(dev, 503250000); | ||||
| 		case 17: /* raw IQ */ | ||||
| 		case 18: /* IQ+FFT */ | ||||
| 			return mod_init_sdr_iq(dev); | ||||
| 		default: | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	switch (dev->link[0].info->version) { | ||||
| 	case 0: | ||||
| 	case 1: | ||||
| 		return mod_init_1(dev, 722000000); | ||||
| 	case 2: | ||||
| 	case 2: /* FSM */ | ||||
| 		return mod_init_2(dev, 114000000); | ||||
| 	case 3: | ||||
| 	case 16: /* PAL */ | ||||
| 		return mod_init_3(dev, 503250000); | ||||
| 	case 17: /* raw IQ */ | ||||
| 		return mod_init_sdr_iq(dev); | ||||
| 	case 18: /* IQ+FFT */ | ||||
| 		return mod_init_sdr_iq(dev); | ||||
| 	default: | ||||
| 		return -1; | ||||
| 	} | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| /* | ||||
|  * ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming | ||||
|  * | ||||
|  * Copyright (C) 2010-2017Marcus Metzler <mocm@metzlerbros.de> | ||||
|  * Copyright (C) 2010-2017 Digital Devices GmbH | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  *                         Digital Devices GmbH | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
| @@ -44,7 +44,7 @@ static u16 calc_pcs16(struct dvb_ns_params *p, int ipv) | ||||
| 	u32 sum = 0, i; | ||||
| 	u16 pcs; | ||||
|  | ||||
| 	for (i = 0; i < ipv ? 16 : 4; i += 2) { | ||||
| 	for (i = 0; i < (ipv ? 16 : 4); i += 2) { | ||||
| 		sum += (p->sip[i] << 8) | p->sip[i + 1]; | ||||
| 		sum += (p->dip[i] << 8) | p->dip[i + 1]; | ||||
| 	} | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -232,6 +232,7 @@ | ||||
|  | ||||
| #define TS_CONTROL(_io)         ((_io)->regs + 0x00) | ||||
| #define TS_CONTROL2(_io)        ((_io)->regs + 0x04) | ||||
| #define TS_STAT(_io)            ((_io)->regs + 0x08) | ||||
|  | ||||
| #define TS_INPUT_CONTROL_ENABLE     (0x00000001) | ||||
| #define TS_INPUT_CONTROL_RESET      (0x00000002) | ||||
| @@ -259,8 +260,8 @@ | ||||
| #define LNB_CMD_DISEQC 6 | ||||
| #define LNB_CMD_SCIF   7 | ||||
|  | ||||
| #define LNB_BUSY  BIT_ULL(4) | ||||
| #define LNB_TONE  BIT_ULL(15) | ||||
| #define LNB_BUSY  (1ULL << 4) | ||||
| #define LNB_TONE  (1ULL << 15) | ||||
|  | ||||
| #define LNB_INTERRUPT_BASE      4 | ||||
|  | ||||
| @@ -407,7 +408,6 @@ | ||||
|  | ||||
| /* Attenuator/VGA */ | ||||
|  | ||||
| #define RF_ATTENUATOR   (0xD8) | ||||
| #define RF_ATTENUATOR   (0xD8) | ||||
| /*  0x00 =  0 dB | ||||
|  *  0x01 =  1 dB | ||||
| @@ -643,3 +643,10 @@ | ||||
| 	 0								\ | ||||
| 		) | ||||
|  | ||||
| /* SDR_CONTROL */ | ||||
|  | ||||
| #define SDR_CONTROL    (0xd0) | ||||
| #define SDR_GAIN_SMA   (0xd4) | ||||
| #define SDR_ATTENUATER (0xd8) | ||||
| #define SDR_GAIN_F     (0xdc) | ||||
|  | ||||
|   | ||||
| @@ -23,11 +23,28 @@ | ||||
|  | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-io.h" | ||||
| #include "ddbridge-i2c.h" | ||||
| #include "ddbridge-mci.h" | ||||
|  | ||||
| static int default_mod = 3; | ||||
| module_param(default_mod, int, 0444); | ||||
| MODULE_PARM_DESC(default_mod, "default modulations enabled, default is  3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); | ||||
|  | ||||
| static int direct_mode; | ||||
| module_param(direct_mode, int, 0444); | ||||
| MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate."); | ||||
|  | ||||
| static u32 sx8_tuner_flags; | ||||
| module_param(sx8_tuner_flags, int, 0664); | ||||
| MODULE_PARM_DESC(sx8_tuner_flags, "Change SX8 tuner flags."); | ||||
|  | ||||
| static u32 sx8_tuner_gain; | ||||
| module_param(sx8_tuner_gain, int, 0664); | ||||
| MODULE_PARM_DESC(sx8_tuner_gain, "Change SX8 tuner gain."); | ||||
|  | ||||
| static const u32 MCLK = (1550000000 / 12); | ||||
| static const u32 MAX_LDPC_BITRATE = (720000000); | ||||
|  | ||||
| /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ | ||||
| static const u32 MAX_LDPC_BITRATE = (720000000 + 2000000); | ||||
| static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); | ||||
|  | ||||
| #define SX8_TUNER_NUM 4 | ||||
| @@ -38,24 +55,19 @@ struct sx8_base { | ||||
| 	struct mci_base      mci_base; | ||||
|  | ||||
| 	u8                   tuner_use_count[SX8_TUNER_NUM]; | ||||
| 	u32                  gain_mode[SX8_TUNER_NUM]; | ||||
|  | ||||
| 	u32                  used_ldpc_bitrate[SX8_DEMOD_NUM]; | ||||
| 	u8                   demod_in_use[SX8_DEMOD_NUM]; | ||||
| 	u32                  iq_mode; | ||||
| 	u32                  burst_size; | ||||
| 	u32                  direct_mode; | ||||
| }; | ||||
|  | ||||
| struct sx8 { | ||||
| 	struct mci           mci; | ||||
| 	struct mutex         lock; | ||||
|  | ||||
| 	int                  first_time_lock; | ||||
| 	int                  started; | ||||
|  | ||||
| 	u32                  bb_mode; | ||||
| 	u32                  local_frequency; | ||||
| 	 | ||||
| 	int                  iq_started; | ||||
| }; | ||||
|  | ||||
| static const u8 dvbs2_bits_per_symbol[] = { | ||||
| @@ -107,62 +119,120 @@ static void release(struct dvb_frontend *fe) | ||||
| 	kfree(state); | ||||
| } | ||||
|  | ||||
| static int ddb_mci_tsconfig(struct mci *state, u32 config) | ||||
| { | ||||
| 	struct ddb_link *link = state->base->link; | ||||
|  | ||||
| 	if (link->ids.device != 0x0009  && link->ids.device != 0x000b) | ||||
| 		return -EINVAL; | ||||
| 	ddblwritel(link, config, SX8_TSCONFIG); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int read_status(struct dvb_frontend *fe, enum fe_status *status) | ||||
| { | ||||
| 	int stat; | ||||
| 	int stat = 0; | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	struct mci_result res; | ||||
|  | ||||
| 	*status = 0x00; | ||||
| 	mutex_lock(&state->lock); | ||||
| 	if (!state->started && !state->iq_started) | ||||
| 		goto unlock; | ||||
| 	stat = ddb_mci_get_status(&state->mci, &res); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	*status = 0x00; | ||||
| 		goto unlock; | ||||
| 	ddb_mci_get_info(&state->mci); | ||||
| 	if (res.status == SX8_DEMOD_WAIT_MATYPE) | ||||
| 		*status = 0x0f; | ||||
| 	if (res.status == SX8_DEMOD_LOCKED) { | ||||
| 		*status = 0x1f; | ||||
| 		if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = | ||||
| 				p->symbol_rate * | ||||
| 				dvbs2_bits_per_symbol[ | ||||
| 					state->mci.signal_info. | ||||
| 					dvbs2_signal_info.pls_code]; | ||||
| 		} else  | ||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; | ||||
| 	} | ||||
| 	if (stat) | ||||
| 		goto unlock; | ||||
| 	if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { | ||||
| 		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | | ||||
| 			FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||||
| 		if (res.status == MCI_DEMOD_LOCKED) { | ||||
| 			mutex_lock(&mci_base->tuner_lock); | ||||
| 			if (state->first_time_lock && state->started) { | ||||
| 				if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 					sx8_base->used_ldpc_bitrate[state->mci.nr] = | ||||
| 						p->symbol_rate * | ||||
| 						dvbs2_bits_per_symbol[ | ||||
| 							state->mci.signal_info. | ||||
| 							dvbs2_signal_info.pls_code]; | ||||
| 				} else | ||||
| 					sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; | ||||
| 				state->first_time_lock = 0; | ||||
| 			} | ||||
| 			mutex_unlock(&mci_base->tuner_lock); | ||||
| 		} | ||||
| 	} else if (res.status == MCI_DEMOD_TIMEOUT) | ||||
| 		*status = FE_TIMEDOUT; | ||||
| 	else if (res.status >= SX8_DEMOD_WAIT_MATYPE) | ||||
| 		*status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||||
| unlock: | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) | ||||
| static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on, | ||||
| 			 u8 flags, u8 gain) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||
| 	struct mci_command cmd; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; | ||||
| 	cmd.sx8_input_enable.flags = sx8_base->gain_mode[state->mci.tuner]; | ||||
| 	cmd.sx8_input_enable.flags = flags; | ||||
| 	cmd.sx8_input_enable.rf_gain = gain; | ||||
| 	return ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| } | ||||
|  | ||||
| static int stop_iq(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||
| 	struct mci_command cmd; | ||||
| 	u32 input = state->mci.tuner; | ||||
|  | ||||
| 	if (!state->iq_started) | ||||
| 		return -1; | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = SX8_CMD_STOP_IQ; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| 	ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL); | ||||
|  | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	sx8_base->tuner_use_count[input]--; | ||||
|         if (!sx8_base->tuner_use_count[input]) | ||||
| 		mci_set_tuner(fe, input, 0, 0, 0); | ||||
| 	if (state->mci.demod != SX8_DEMOD_NONE) { | ||||
| 		sx8_base->demod_in_use[state->mci.demod] = 0; | ||||
| 		state->mci.demod = SX8_DEMOD_NONE; | ||||
| 	} | ||||
| 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	sx8_base->iq_mode = 0; | ||||
| 	state->iq_started = 0; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int stop(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||
| 	struct mci_command cmd; | ||||
| 	u32 input = state->mci.tuner; | ||||
| 	u32 input; | ||||
|  | ||||
| 	input = state->mci.tuner; | ||||
| 	if (!state->started) | ||||
| 		return -1; | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	if (state->mci.demod != SX8_DEMOD_NONE) { | ||||
| 		memset(&cmd, 0, sizeof(cmd)); | ||||
| 		cmd.command = MCI_CMD_STOP; | ||||
| 		cmd.demod = state->mci.demod; | ||||
| 		ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| @@ -171,24 +241,29 @@ static int stop(struct dvb_frontend *fe) | ||||
| 			cmd.demod = state->mci.demod; | ||||
| 			cmd.output = 0; | ||||
| 			ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 			ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); | ||||
| 			ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL); | ||||
| 		} | ||||
| 	} | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	sx8_base->tuner_use_count[input]--; | ||||
|         if (!sx8_base->tuner_use_count[input]) | ||||
| 		mci_set_tuner(fe, input, 0); | ||||
| 		mci_set_tuner(fe, input, 0, 0, 0); | ||||
| 	if (state->mci.demod != SX8_DEMOD_NONE) { | ||||
| 		sx8_base->demod_in_use[state->mci.demod] = 0; | ||||
| 		state->mci.demod = SX8_DEMOD_NONE; | ||||
| 	} | ||||
| 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | ||||
| 	sx8_base->iq_mode = 0; | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	state->started = 0; | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static const u8 ro_lut[8] = { | ||||
| 	8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0, | ||||
| 	8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0, | ||||
| }; | ||||
|  | ||||
| static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| @@ -202,7 +277,14 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| 	u32 input = state->mci.tuner; | ||||
| 	u32 bits_per_symbol = 0; | ||||
| 	int i = -1, stat = 0; | ||||
| 	struct ddb_link *link = state->mci.base->link; | ||||
|  | ||||
| 	if (link->ids.device == 0x000b) { | ||||
| 		/* Mask out higher modulations and MIS for Basic | ||||
| 		   or search command will fail */ | ||||
| 		modmask &= 3; | ||||
| 		p->stream_id = NO_STREAM_ID_FILTER; | ||||
| 	} | ||||
| 	if (p->symbol_rate >= MCLK / 2) | ||||
| 		flags &= ~1; | ||||
| 	if ((flags & 3) == 0) | ||||
| @@ -217,14 +299,13 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| 			bits_per_symbol++; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	if (sx8_base->iq_mode) { | ||||
| 		stat = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	} | ||||
|  | ||||
| 	if (sx8_base->direct_mode) { | ||||
| 	if (direct_mode) { | ||||
| 		if (p->symbol_rate >= MCLK / 2) { | ||||
| 			if (state->mci.nr < 4) | ||||
| 				i = state->mci.nr; | ||||
| @@ -237,7 +318,6 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| 			if (sx8_base->demod_in_use[i]) | ||||
| 				used_demods++; | ||||
| 		} | ||||
| 		printk("used_ldpc_bitrate = %u\n", used_ldpc_bitrate); | ||||
| 		if ((used_ldpc_bitrate >= MAX_LDPC_BITRATE)  || | ||||
| 		    ((ts_config & SX8_TSCONFIG_MODE_MASK) > | ||||
| 		     SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) { | ||||
| @@ -254,9 +334,8 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		 | ||||
| 		modmask &= ((1 << (bits_per_symbol - 1)) - 1); | ||||
| 		if( ((flags & 0x02) != 0)  &&  (modmask == 0)) { | ||||
| 		if (((flags & 0x02) != 0) && (modmask == 0)) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| @@ -274,7 +353,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
|         state->mci.demod = i; | ||||
|  | ||||
|         if (!sx8_base->tuner_use_count[input]) | ||||
| 		mci_set_tuner(fe, input, 1); | ||||
| 		mci_set_tuner(fe, input, 1, sx8_tuner_flags, sx8_tuner_gain); | ||||
| 	sx8_base->tuner_use_count[input]++; | ||||
| 	sx8_base->iq_mode = (ts_config > 1); | ||||
| unlock: | ||||
| @@ -282,20 +361,26 @@ unlock: | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	 | ||||
| 	if (sx8_base->iq_mode) { | ||||
| 		cmd.command = SX8_CMD_ENABLE_IQOUTPUT; | ||||
| 		cmd.demod = state->mci.demod; | ||||
| 		cmd.output = 0; | ||||
| 		cmd.output = p->stream_id & 0x0f; | ||||
| 		ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 		ddb_mci_config(&state->mci, ts_config); | ||||
| 		ddb_mci_tsconfig(&state->mci, ts_config); | ||||
| 	} | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) | ||||
| 	if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000)) | ||||
| 		flags |= 0x80; | ||||
| 	printk("frontend %u: tuner=%u demod=%u\n", state->mci.nr, state->mci.tuner, state->mci.demod); | ||||
| 	//printk("bw %u\n", p->bandwidth_hz); | ||||
| 	if (p->bandwidth_hz && (p->bandwidth_hz < 20000)) { | ||||
| 		flags |= 0x40; | ||||
| 		/* +/- range, so multiply bandwidth_hz (actually in kHz) by 500 */ | ||||
| 		cmd.dvbs2_search.frequency_range = p->bandwidth_hz * 500; | ||||
| 		//printk("range %u\n", cmd.dvbs2_search.frequency_range); | ||||
| 	} | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBS; | ||||
| 	cmd.dvbs2_search.flags = flags; | ||||
| 	cmd.dvbs2_search.s2_modulation_mask = modmask; | ||||
| 	cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7]; | ||||
| 	cmd.dvbs2_search.retry = 2; | ||||
| 	cmd.dvbs2_search.frequency = p->frequency * 1000; | ||||
| 	cmd.dvbs2_search.symbol_rate = p->symbol_rate; | ||||
| @@ -305,9 +390,13 @@ unlock: | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| 	cmd.output = state->mci.nr; | ||||
| 	if (p->stream_id == 0x80000000) | ||||
| 	if ((p->stream_id != NO_STREAM_ID_FILTER)  && | ||||
| 	    (p->stream_id & 0x80000000)) | ||||
| 		cmd.output |= 0x80; | ||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	state->started = 1; | ||||
| 	state->first_time_lock = 1; | ||||
| 	state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; | ||||
| 	if (stat) | ||||
| 		stop(fe); | ||||
| 	return stat; | ||||
| @@ -315,7 +404,7 @@ unlock: | ||||
|  | ||||
|  | ||||
| static int start_iq(struct dvb_frontend *fe, u32 flags, | ||||
| 		    u32 roll_off, u32 ts_config) | ||||
| 		    u32 ts_config) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| @@ -327,59 +416,79 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | ||||
| 	int i, stat = 0; | ||||
|  | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	if (sx8_base->iq_mode) { | ||||
| 		stat = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	if (!state->iq_started) { | ||||
| 		if (sx8_base->iq_mode) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		for (i = 0; i < SX8_DEMOD_NUM; i++) | ||||
| 			if (sx8_base->demod_in_use[i]) | ||||
| 				used_demods++; | ||||
| 		if (used_demods > 0) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		state->mci.demod = 0; | ||||
| 		sx8_base->tuner_use_count[input]++; | ||||
| 		sx8_base->iq_mode = 2; | ||||
| 		mci_set_tuner(fe, input, 1, flags & 0xff, 0x40); | ||||
| 	} else { | ||||
| 		if ((state->iq_started & 0x07) != state->mci.nr) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 	} | ||||
| 	for (i = 0; i < SX8_DEMOD_NUM; i++) | ||||
| 		if (sx8_base->demod_in_use[i]) | ||||
| 			used_demods++; | ||||
|         if (used_demods > 0) { | ||||
| 		stat = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	} | ||||
|         state->mci.demod = 0; | ||||
|         if (!sx8_base->tuner_use_count[input]) | ||||
| 		mci_set_tuner(fe, input, 1); | ||||
| 	sx8_base->tuner_use_count[input]++; | ||||
| 	sx8_base->iq_mode = (ts_config > 1); | ||||
| unlock: | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	 | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.command = SX8_CMD_START_IQ; | ||||
| 	cmd.sx8_start_iq.flags = flags; | ||||
| 	cmd.sx8_start_iq.roll_off = roll_off; | ||||
| 	cmd.sx8_start_iq.flags = (flags >> 16) & 0xff; | ||||
| 	cmd.sx8_start_iq.roll_off = 5; | ||||
| 	//cmd.sx8_start_iq.roll_off = ro_lut[p->rolloff & 7]; | ||||
| 	cmd.sx8_start_iq.frequency = p->frequency * 1000; | ||||
| 	cmd.sx8_start_iq.symbol_rate = p->symbol_rate; | ||||
| 	cmd.sx8_start_iq.gain = (flags >> 8) & 0xff; | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	cmd.demod = state->mci.demod; | ||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||
| 	state->iq_started = 8 | state->mci.nr; | ||||
| 	state->first_time_lock = 1; | ||||
| 	state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; | ||||
| 	if (stat) | ||||
| 		stop(fe); | ||||
| 	ddb_mci_config(&state->mci, ts_config); | ||||
| 		stop_iq(fe); | ||||
| 	ddb_mci_tsconfig(&state->mci, ts_config); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static int set_lna(struct dvb_frontend *fe) | ||||
| { | ||||
| 	printk("set_lna\n"); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int set_parameters(struct dvb_frontend *fe) | ||||
| { | ||||
| 	int stat = 0; | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi; | ||||
| 	u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi, ts_mode = 0; | ||||
|  | ||||
| 	stop(fe); | ||||
| 	isi = p->stream_id; | ||||
| 	if (isi != NO_STREAM_ID_FILTER) { | ||||
| 		iq_mode = (isi & 0x30000000) >> 28; | ||||
| 		ts_mode = (isi & 0x03000000) >> 24; | ||||
| 	} | ||||
| 	state->mci.input->con = ts_mode << 8; | ||||
| 	if (iq_mode) | ||||
| 		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop(fe); | ||||
| 	if (iq_mode < 2) { | ||||
| 		u32 mask; | ||||
|  | ||||
| 		stop_iq(fe); | ||||
| 		switch (p->modulation) { | ||||
| 		case APSK_256: | ||||
| 			mask = 0x7f; | ||||
| @@ -397,18 +506,14 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 			mask = 0x07; | ||||
| 			break; | ||||
| 		default: | ||||
| 			mask = 0x03; | ||||
| 			mask = default_mod; | ||||
| 			break; | ||||
| 		} | ||||
| 		stat = start(fe, 3, mask, ts_config); | ||||
| 	} else { | ||||
| 		stat = start_iq(fe, iq_mode & 1, 4, ts_config); | ||||
| 	} | ||||
| 	if (!stat) { | ||||
| 		state->started = 1; | ||||
| 		state->first_time_lock = 1; | ||||
| 		state->mci.signal_info.status = SX8_DEMOD_WAIT_SIGNAL; | ||||
| 		stat = start_iq(fe, isi & 0xffffff, ts_config); | ||||
| 	} | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| @@ -433,7 +538,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; | ||||
| } | ||||
| @@ -443,20 +548,29 @@ static int set_input(struct dvb_frontend *fe, int input) | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
|  | ||||
| 	printk("fe %u, set input = %u\n", state->mci.nr, input); | ||||
| 	if (input >= SX8_TUNER_NUM) | ||||
| 		return -EINVAL; | ||||
| 	if (state->mci.tuner == input) | ||||
| 		return 0; | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop_iq(fe); | ||||
| 	stop(fe); | ||||
| 	state->mci.tuner = p->input = input; | ||||
| 	printk("fe %u, input = %u\n", state->mci.nr, input); | ||||
| 	state->mci.tuner = input; | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	p->input = input; | ||||
| #endif | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int sleep(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
|  | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop_iq(fe); | ||||
| 	stop(fe); | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -470,13 +584,12 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties | ||||
|  | ||||
| static struct dvb_frontend_ops sx8_ops = { | ||||
| 	.delsys = { SYS_DVBS, SYS_DVBS2 }, | ||||
| 	.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 | | ||||
| @@ -490,7 +603,11 @@ static struct dvb_frontend_ops sx8_ops = { | ||||
| 	.tune                           = tune, | ||||
| 	.release                        = release, | ||||
| 	.read_status                    = read_status, | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */ | ||||
| 	.set_input                      = set_input, | ||||
| #endif | ||||
| 	.set_lna                        = set_lna, | ||||
| 	.sleep                          = sleep, | ||||
| }; | ||||
|  | ||||
| @@ -499,8 +616,11 @@ static int init(struct mci *mci) | ||||
| 	struct sx8 *state = (struct sx8 *) mci; | ||||
|  | ||||
| 	state->mci.demod = SX8_DEMOD_NONE; | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	mci->fe.ops.xbar[1] = mci->nr; | ||||
| 	mci->fe.dtv_property_cache.input = mci->tuner; | ||||
| #endif | ||||
| 	mutex_init(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -511,7 +631,7 @@ static int base_init(struct mci_base *mci_base) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct mci_cfg ddb_max_sx8_cfg = { | ||||
| static struct mci_cfg ddb_max_sx8_cfg = { | ||||
| 	.type = 0, | ||||
| 	.fe_ops = &sx8_ops, | ||||
| 	.base_size = sizeof(struct sx8_base), | ||||
| @@ -519,3 +639,10 @@ struct mci_cfg ddb_max_sx8_cfg = { | ||||
| 	.init = init, | ||||
| 	.base_init = base_init, | ||||
| }; | ||||
|  | ||||
| struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner, | ||||
| 				    int (**fn_set_input)(struct dvb_frontend *fe, int input)) | ||||
| { | ||||
| 	*fn_set_input = set_input; | ||||
| 	return ddb_mci_attach(input, &ddb_max_sx8_cfg, nr, tuner); | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * ddbridge.h: Digital Devices PCIe bridge driver | ||||
|  * | ||||
|  * Copyright (C) 2010-2017 Digital Devices GmbH | ||||
|  *                         Ralph Metzler <rmetzler@digitaldevices.de> | ||||
|  *                         Marcus Metzler <mocm@metzlerbros.de> | ||||
|  *                         Ralph Metzler <rjkm@metzlerbros.de> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
| @@ -14,18 +16,13 @@ | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, point your browser to | ||||
|  * http://www.gnu.org/copyleft/gpl.html | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef _DDBRIDGE_H_ | ||||
| #define _DDBRIDGE_H_ | ||||
|  | ||||
| #define DDB_USE_WORK | ||||
| /*#define DDB_TEST_THREADED*/ | ||||
|  | ||||
| #include <linux/version.h> | ||||
|  | ||||
| #if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE) | ||||
| @@ -60,22 +57,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" | ||||
| @@ -116,6 +111,7 @@ struct ddb_regmap { | ||||
| 	u32 irq_base_odma; | ||||
| 	u32 irq_base_gtl; | ||||
| 	u32 irq_base_rate; | ||||
| 	u32 irq_base_mci; | ||||
|  | ||||
| 	const struct ddb_regset *i2c; | ||||
| 	const struct ddb_regset *i2c_buf; | ||||
| @@ -129,6 +125,9 @@ struct ddb_regmap { | ||||
|  | ||||
| 	const struct ddb_regset *channel; | ||||
| 	const struct ddb_regset *gtl; | ||||
|  | ||||
| 	const struct ddb_regset *mci; | ||||
| 	const struct ddb_regset *mci_buf; | ||||
| }; | ||||
|  | ||||
| struct ddb_ids { | ||||
| @@ -141,6 +140,7 @@ struct ddb_ids { | ||||
| 	u32 regmapid; | ||||
| 	u32 devid; | ||||
| 	u32 mac; | ||||
| 	u8 revision; | ||||
| }; | ||||
|  | ||||
| struct ddb_info { | ||||
| @@ -202,11 +202,7 @@ struct ddb_dma { | ||||
| 	u32                    div; | ||||
| 	u32                    bufval; | ||||
|  | ||||
| #ifdef DDB_USE_WORK | ||||
| 	struct work_struct     work; | ||||
| #else | ||||
| 	struct tasklet_struct  tasklet; | ||||
| #endif | ||||
| 	spinlock_t             lock; /* DMA lock */ | ||||
| 	wait_queue_head_t      wq; | ||||
| 	int                    running; | ||||
| @@ -214,6 +210,10 @@ struct ddb_dma { | ||||
| 	u32                    ctrl; | ||||
| 	u32                    cbuf; | ||||
| 	u32                    coff; | ||||
|  | ||||
| 	u32                    stall_count; | ||||
| 	u32                    packet_loss; | ||||
| 	u32                    unaligned; | ||||
| }; | ||||
|  | ||||
| struct ddb_dvb { | ||||
| @@ -235,7 +235,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); | ||||
| @@ -253,6 +253,7 @@ struct ddb_io { | ||||
| 	struct ddb_port       *port; | ||||
| 	u32                    nr; | ||||
| 	u32                    regs; | ||||
| 	u32                    con; | ||||
| 	struct ddb_dma        *dma; | ||||
| 	struct ddb_io         *redo; | ||||
| 	struct ddb_io         *redi; | ||||
| @@ -404,7 +405,7 @@ struct ddb_lnb { | ||||
| }; | ||||
|  | ||||
| struct ddb_irq { | ||||
| 	void                   (*handler)(void *); | ||||
| 	void                   (*handler)(void *data); | ||||
| 	void                   *data; | ||||
| }; | ||||
|  | ||||
| @@ -423,6 +424,11 @@ struct ddb_link { | ||||
| 	int                    over_temperature_error; | ||||
| 	u8                     temp_tab[11]; | ||||
| 	struct ddb_irq         irq[256]; | ||||
|  | ||||
| 	struct mci_base        *mci_base; | ||||
| 	struct completion      mci_completion; | ||||
| 	struct mutex           mci_lock; | ||||
| 	int                    mci_ok; | ||||
| }; | ||||
|  | ||||
| struct ddb { | ||||
| @@ -449,7 +455,7 @@ struct ddb { | ||||
| 	struct ddb_dma         odma[DDB_MAX_OUTPUT]; | ||||
|  | ||||
| 	struct device         *ddb_dev; | ||||
| 	u32                    ddb_dev_users; | ||||
| 	atomic_t               ddb_dev_users; | ||||
| 	u32                    nr; | ||||
| 	u8                     iobuf[1028]; | ||||
|  | ||||
| @@ -524,7 +530,7 @@ struct DDMOD_FLASH { | ||||
|  | ||||
| int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len); | ||||
|  | ||||
| #define DDBRIDGE_VERSION "0.9.34" | ||||
| #define DDBRIDGE_VERSION "0.9.38" | ||||
|  | ||||
| /* linked function prototypes */ | ||||
|  | ||||
| @@ -538,7 +544,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); | ||||
|   | ||||
| @@ -26,6 +26,9 @@ | ||||
| #include <linux/net.h> | ||||
| #include "dvb_netstream.h" | ||||
| 
 | ||||
| int ddb_dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||||
| 		     int (*func)(struct file *file, unsigned int cmd, void *arg)); | ||||
| 
 | ||||
| static ssize_t ns_write(struct file *file, const char *buf, | ||||
| 			size_t count, loff_t *ppos) | ||||
| { | ||||
| @@ -211,7 +214,7 @@ static int do_ioctl(struct file *file, unsigned int cmd, void *parg) | ||||
| static long ns_ioctl(struct file *file, | ||||
| 		     unsigned int cmd, unsigned long arg) | ||||
| { | ||||
| 	return dvb_usercopy(file, cmd, arg, do_ioctl); | ||||
| 	return ddb_dvb_usercopy(file, cmd, arg, do_ioctl); | ||||
| } | ||||
| 
 | ||||
| static const struct file_operations ns_fops = { | ||||
| @@ -245,7 +248,7 @@ int dvb_netstream_init(struct dvb_adapter *dvb_adapter, | ||||
| 	INIT_LIST_HEAD(&ns->nssl); | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(dvb_netstream_init); | ||||
| //EXPORT_SYMBOL(dvb_netstream_init);
 | ||||
| 
 | ||||
| void dvb_netstream_release(struct dvb_netstream *ns) | ||||
| { | ||||
| @@ -256,4 +259,4 @@ void dvb_netstream_release(struct dvb_netstream *ns) | ||||
| 	} | ||||
| 	dvb_unregister_device(ns->dvbdev); | ||||
| } | ||||
| EXPORT_SYMBOL(dvb_netstream_release); | ||||
| //EXPORT_SYMBOL(dvb_netstream_release);
 | ||||
| @@ -36,9 +36,9 @@ | ||||
| #include <linux/socket.h> | ||||
| #include <linux/in.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <linux/dvb/ns.h> | ||||
| #include "ns.h" | ||||
| 
 | ||||
| #include "dvbdev.h" | ||||
| #include <media/dvbdev.h> | ||||
| 
 | ||||
| #define DVBNS_MAXPIDS 32 | ||||
| 
 | ||||
							
								
								
									
										76
									
								
								ddbridge/ns.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								ddbridge/ns.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| #ifndef _UAPI_DVBNS_H_ | ||||
| #define _UAPI_DVBNS_H_ | ||||
|  | ||||
| #include <linux/types.h> | ||||
|  | ||||
| struct dvb_ns_params { | ||||
| 	__u8     smac[6]; | ||||
| 	__u8     dmac[6]; | ||||
| 	__u8     sip[16]; | ||||
| 	__u8     dip[16]; | ||||
| 	__u16    sport; | ||||
| 	__u16    dport; | ||||
| 	__u16    sport2; | ||||
| 	__u16    dport2; | ||||
| 	__u8     ssrc[8]; | ||||
| 	__u8     flags; | ||||
| 	__u8     qos; | ||||
| 	__u16    vlan; | ||||
| 	__u8     ttl; | ||||
| }; | ||||
|  | ||||
| #define DVB_NS_IPV6    0x01 | ||||
| #define DVB_NS_RTP     0x02 | ||||
| #define DVB_NS_RTCP    0x04 | ||||
| #define DVB_NS_RTP_TO  0x08 | ||||
| #define DVB_NS_VLAN    0x10 | ||||
|  | ||||
| struct dvb_ns_rtcp { | ||||
| 	__u8    *msg; | ||||
| 	__u16    len; | ||||
| }; | ||||
|  | ||||
| struct dvb_ns_packet { | ||||
| 	__u8    *buf; | ||||
| 	__u8     count; | ||||
| }; | ||||
|  | ||||
| struct dvb_nsd_ts { | ||||
| 	__u16    pid; | ||||
| 	__u16    num; | ||||
| 	__u16    input; | ||||
| 	__u16    timeout; | ||||
| 	__u16    len; | ||||
| 	__u8    *ts; | ||||
| 	__u8     mode; | ||||
| 	__u8     table; | ||||
|  | ||||
| 	__u8	 filter_mask; | ||||
|  	__u8     section; | ||||
| 	__u16	 section_id; | ||||
| }; | ||||
|  | ||||
| struct dvb_ns_cap { | ||||
| 	__u8     streams_max; | ||||
| 	__u8     reserved[127]; | ||||
| }; | ||||
|  | ||||
| #define NS_SET_NET               _IOW('o', 192, struct dvb_ns_params) | ||||
| #define NS_START                 _IO('o', 193) | ||||
| #define NS_STOP                  _IO('o', 194) | ||||
| #define NS_SET_PID               _IOW('o', 195, __u16) | ||||
| #define NS_SET_PIDS              _IOW('o', 196, __u8 *) | ||||
| #define NS_SET_RTCP_MSG          _IOW('o', 197, struct dvb_ns_rtcp) | ||||
|  | ||||
| #define NSD_START_GET_TS         _IOWR('o', 198, struct dvb_nsd_ts) | ||||
| #define NSD_STOP_GET_TS          _IOWR('o', 199, struct dvb_nsd_ts) | ||||
| #define NSD_CANCEL_GET_TS        _IO('o', 200) | ||||
| #define NSD_POLL_GET_TS          _IOWR('o', 201, struct dvb_nsd_ts) | ||||
|  | ||||
| #define NS_SET_PACKETS           _IOW('o', 202, struct dvb_ns_packet) | ||||
| #define NS_INSERT_PACKETS	 _IOW('o', 203, __u8) | ||||
| #define NS_SET_CI	         _IOW('o', 204, __u8) | ||||
|  | ||||
| #define NS_GET_CAP               _IOR('o', 204, struct dvb_ns_cap)) | ||||
|  | ||||
| #endif /*_UAPI_DVBNS_H_*/ | ||||
| @@ -7,7 +7,7 @@ is currently considered experimental. | ||||
|  | ||||
| Supported hardware: | ||||
|  | ||||
| Cine V7A                  (>=1.7 FW) | ||||
| cineS2 V7A                (>=1.7 FW) | ||||
| OctopusCI S2 Pro Advanced (>=1.7 FW) | ||||
| Duoflex S2 v4 Advanced    (TBA) | ||||
| MaxSX8                    (NOT the MAXS8!) | ||||
|   | ||||
							
								
								
									
										13
									
								
								docs/firmware
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								docs/firmware
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| Firmware update: | ||||
|  | ||||
| Copy the firmware file to the dddvb/apps/ directory and | ||||
| execute "./flashprog". | ||||
|  | ||||
| The program will try to identify the card version and | ||||
| check if it finds the corresponding firmware file. | ||||
| It will then prompt you to confirm to proceed | ||||
| with the flashing procedure. | ||||
|  | ||||
| After the update the system needs a power cycle. | ||||
|  | ||||
|  | ||||
							
								
								
									
										27
									
								
								docs/iq_samples
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								docs/iq_samples
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| ~The Max SX8 can provide IQ samples in real time. | ||||
|  | ||||
| They are 8 bit signed values embedded in TS packets with PID 0x200. | ||||
|  | ||||
| API: | ||||
|  | ||||
| Currently DTV_STREAM_ID is misused. | ||||
|  | ||||
| 0x10000000 - symbols (locked and tracked) at symbol rate | ||||
| 0x20000000 - samples at symbol rate | ||||
|              (fixed at ADC rate (1550/24=64.583... MHz) if 0x00010000 is set) | ||||
|              Max. sample rate is 64.583333 MHz. | ||||
|  | ||||
| 0x00xx0000 - flags | ||||
| 	     Bit 0 : 0 = VTM/SDR, 1 = SCAN, | ||||
| 	     Bit 1: 1 = Disable channel AGC, | ||||
| 	     Bit 2: 1 = Set Gain.  | ||||
|  | ||||
| 0x0000xx00 - xx=gain | ||||
|  | ||||
| 0x000000xx - xx=flags | ||||
| 	     Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||
| 	                           2 = Medium, 3 = Maximum gain {~ 15dB} | ||||
| 	     Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) | ||||
| 	     Bit 4: Set RF Gain | ||||
| 	     Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) | ||||
| 	     Bit 7: Optimize RF Gain and freeze for FFT | ||||
| @@ -28,3 +28,7 @@ devices in any way. | ||||
| adapter_alloc=3 is rcommended when using redirect | ||||
| The ci device will then show up in the same adapter directory and most | ||||
| software will then assume it belongs to the frontend in the same directory. | ||||
|  | ||||
|  | ||||
| Redirect between cards in different IOMMU groups will not work! | ||||
| Disable IOMMU if you have this problem. | ||||
| @@ -1,7 +1,34 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0-only | ||||
| # | ||||
| # 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 | ||||
| @@ -18,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. | ||||
| @@ -31,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. | ||||
| @@ -40,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. | ||||
|   | ||||
| @@ -1,12 +1,15 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| # 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_netstream.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$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core | ||||
|   | ||||
| @@ -6,7 +6,9 @@ dvb-net-$(CONFIG_DVB_NET) := dvb_net.o | ||||
|  | ||||
| dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\ | ||||
| 		 dvb_ca_en50221.o dvb_frontend.o 		\ | ||||
| 		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o       \ | ||||
| 		 dvb_netstream.o | ||||
| 		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o | ||||
|  | ||||
| obj-$(CONFIG_DVB_CORE) += dvb-core.o | ||||
|  | ||||
| ccflags-y += -Idrivers/media/dvb-core/ | ||||
| ccflags-y += --include=dd_compat.h | ||||
|   | ||||
| @@ -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,7 +28,10 @@ | ||||
| #include <linux/ioctl.h> | ||||
| #include <linux/wait.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include "dmxdev.h" | ||||
| #include <media/dmxdev.h> | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| #include <media/dvb_vb2.h> | ||||
| #endif | ||||
|  | ||||
| static int debug; | ||||
|  | ||||
| @@ -127,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__); | ||||
|  | ||||
| @@ -138,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) { | ||||
| @@ -158,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--; | ||||
| 	} | ||||
|  | ||||
| @@ -195,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; | ||||
| @@ -380,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; | ||||
| 	} | ||||
| @@ -396,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) | ||||
| @@ -413,9 +475,13 @@ 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; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 	struct dvb_vb2_ctx *ctx; | ||||
| #endif | ||||
| 	struct dvb_ringbuffer *buffer; | ||||
| 	int ret; | ||||
|  | ||||
| @@ -425,19 +491,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); | ||||
| @@ -584,7 +671,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; | ||||
| @@ -592,7 +679,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; | ||||
|  | ||||
| @@ -683,7 +769,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) | ||||
| 			ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, | ||||
| 								   secfeed, | ||||
| 								   dvb_dmxdev_section_callback); | ||||
| 			if (ret < 0) { | ||||
| 			if (!*secfeed) { | ||||
| 				pr_err("DVB (%s): could not alloc feed\n", | ||||
| 				       __func__); | ||||
| 				return ret; | ||||
| @@ -776,7 +862,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)) | ||||
| @@ -796,6 +892,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); | ||||
| @@ -1083,8 +1184,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); | ||||
| @@ -1097,30 +1246,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; | ||||
| @@ -1145,10 +1334,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 = { | ||||
| @@ -1177,8 +1370,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); | ||||
| @@ -1191,31 +1407,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, | ||||
| @@ -1225,6 +1468,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 = { | ||||
| @@ -1236,6 +1482,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; | ||||
| @@ -1243,7 +1490,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_ */ | ||||
| @@ -1,3 +1,4 @@ | ||||
|  // SPDX-License-Identifier: GPL-2.0-or-later | ||||
| /* | ||||
|  * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces | ||||
|  * | ||||
| @@ -11,18 +12,6 @@ | ||||
|  * | ||||
|  * Copyright (C) 1999-2002 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 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 | ||||
|  */ | ||||
|  | ||||
| #define pr_fmt(fmt) "dvb_ca_en50221: " fmt | ||||
| @@ -31,10 +20,13 @@ | ||||
| #include <linux/slab.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/version.h> | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) | ||||
| #include <linux/nospec.h> | ||||
| #endif | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/version.h> | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) | ||||
| #include <linux/sched/signal.h> | ||||
| #else | ||||
| @@ -42,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; | ||||
|  | ||||
| @@ -202,16 +194,16 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); | ||||
| static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, | ||||
| 				    u8 *ebuf, int ecount); | ||||
| static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, | ||||
| 				     u8 *ebuf, int ecount); | ||||
| 				     u8 *ebuf, int ecount, u8 flags); | ||||
|  | ||||
| /** | ||||
|  * Safely find needle in haystack. | ||||
|  * findstr - Safely find needle in haystack. | ||||
|  * | ||||
|  * @haystack: Buffer to look in. | ||||
|  * @hlen: Number of bytes in haystack. | ||||
|  * @needle: Buffer to find. | ||||
|  * @nlen: Number of bytes in needle. | ||||
|  * @return Pointer into haystack needle was found at, or NULL if not found. | ||||
|  * return: Pointer into haystack needle was found at, or NULL if not found. | ||||
|  */ | ||||
| static char *findstr(char *haystack, int hlen, char *needle, int nlen) | ||||
| { | ||||
| @@ -231,7 +223,7 @@ static char *findstr(char *haystack, int hlen, char *needle, int nlen) | ||||
| /* ************************************************************************** */ | ||||
| /* EN50221 physical interface functions */ | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  * dvb_ca_en50221_check_camstatus - Check CAM status. | ||||
|  */ | ||||
| static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) | ||||
| @@ -280,9 +272,9 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot on interface. | ||||
|  * @waitfor: Flags to wait for. | ||||
|  * @timeout_ms: Timeout in milliseconds. | ||||
|  * @timeout_hz: Timeout in milliseconds. | ||||
|  * | ||||
|  * @return 0 on success, nonzero on error. | ||||
|  * return: 0 on success, nonzero on error. | ||||
|  */ | ||||
| static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, | ||||
| 					 u8 waitfor, int timeout_hz) | ||||
| @@ -330,7 +322,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot id. | ||||
|  * | ||||
|  * @return 0 on success, nonzero on failure. | ||||
|  * return: 0 on success, nonzero on failure. | ||||
|  */ | ||||
| static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) | ||||
| { | ||||
| @@ -385,7 +377,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) | ||||
| 	ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 	ret = dvb_ca_en50221_write_data(ca, slot, buf, 2); | ||||
| 	ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW); | ||||
| 	if (ret != 2) | ||||
| 		return -EIO; | ||||
| 	ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); | ||||
| @@ -402,11 +394,11 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot id. | ||||
|  * @address: Address to read from. Updated. | ||||
|  * @tupleType: Tuple id byte. Updated. | ||||
|  * @tupleLength: Tuple length. Updated. | ||||
|  * @tuple_type: Tuple id byte. Updated. | ||||
|  * @tuple_length: Tuple length. Updated. | ||||
|  * @tuple: Dest buffer for tuple (must be 256 bytes). Updated. | ||||
|  * | ||||
|  * @return 0 on success, nonzero on error. | ||||
|  * return: 0 on success, nonzero on error. | ||||
|  */ | ||||
| static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, | ||||
| 				     int *address, int *tuple_type, | ||||
| @@ -460,7 +452,7 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot id. | ||||
|  * | ||||
|  * @return 0 on success, <0 on failure. | ||||
|  * return: 0 on success, <0 on failure. | ||||
|  */ | ||||
| static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) | ||||
| { | ||||
| @@ -637,10 +629,11 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot to read from. | ||||
|  * @ebuf: If non-NULL, the data will be written to this buffer. If NULL, | ||||
|  * the data will be added into the buffering system as a normal fragment. | ||||
|  *	  the data will be added into the buffering system as a normal | ||||
|  *	  fragment. | ||||
|  * @ecount: Size of ebuf. Ignored if ebuf is NULL. | ||||
|  * | ||||
|  * @return Number of bytes read, or < 0 on error | ||||
|  * return: Number of bytes read, or < 0 on error | ||||
|  */ | ||||
| static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, | ||||
| 				    u8 *ebuf, int ecount) | ||||
| @@ -789,21 +782,21 @@ exit: | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot to write to. | ||||
|  * @ebuf: The data in this buffer is treated as a complete link-level packet to | ||||
|  * be written. | ||||
|  * @count: Size of ebuf. | ||||
|  * @buf: The data in this buffer is treated as a complete link-level packet to | ||||
|  *	 be written. | ||||
|  * @bytes_write: Size of ebuf. | ||||
|  * | ||||
|  * @return Number of bytes written, or < 0 on error. | ||||
|  * return: Number of bytes written, or < 0 on error. | ||||
|  */ | ||||
| static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, | ||||
| 				     u8 *buf, int bytes_write) | ||||
| 				     u8 *buf, int bytes_write, u8 flags) | ||||
| { | ||||
| 	struct dvb_ca_slot *sl = &ca->slot_info[slot]; | ||||
| 	int status; | ||||
| 	int i; | ||||
|  | ||||
| 	dprintk("%s\n", __func__); | ||||
|  | ||||
| 	flags=0; | ||||
| 	/* sanity check */ | ||||
| 	if (bytes_write > sl->link_buf_size) | ||||
| 		return -EINVAL; | ||||
| @@ -831,7 +824,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, | ||||
|  | ||||
| 	/* OK, set HC bit */ | ||||
| 	status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, | ||||
| 					    IRQEN | CMDREG_HC); | ||||
| 					    IRQEN | CMDREG_HC | flags); | ||||
| 	if (status) | ||||
| 		goto exit; | ||||
|  | ||||
| @@ -901,7 +894,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, | ||||
| 		buf[0], (buf[1] & 0x80) == 0, bytes_write); | ||||
|  | ||||
| exit: | ||||
| 	ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); | ||||
| 	ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | flags); | ||||
|  | ||||
| exitnowrite: | ||||
| 	return status; | ||||
| @@ -938,7 +931,7 @@ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) | ||||
| /** | ||||
|  * dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @pubca: CA instance. | ||||
|  * @slot: Slot concerned. | ||||
|  * @change_type: One of the DVB_CA_CAMCHANGE_* values. | ||||
|  */ | ||||
| @@ -968,7 +961,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); | ||||
| /** | ||||
|  * dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @pubca: CA instance. | ||||
|  * @slot: Slot concerned. | ||||
|  */ | ||||
| void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot) | ||||
| @@ -988,7 +981,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); | ||||
| /** | ||||
|  * dvb_ca_en50221_frda_irq - An FR or DA IRQ has occurred. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @pubca: CA instance. | ||||
|  * @slot: Slot concerned. | ||||
|  */ | ||||
| void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot) | ||||
| @@ -1020,7 +1013,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq); | ||||
| /* EN50221 thread functions */ | ||||
|  | ||||
| /** | ||||
|  * Wake up the DVB CA thread | ||||
|  * dvb_ca_en50221_thread_wakeup - Wake up the DVB CA thread | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  */ | ||||
| @@ -1034,7 +1027,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Update the delay used by the thread. | ||||
|  * dvb_ca_en50221_thread_update_delay - Update the delay used by the thread. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  */ | ||||
| @@ -1092,11 +1085,11 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Poll if the CAM is gone. | ||||
|  * dvb_ca_en50221_poll_cam_gone - Poll if the CAM is gone. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot to process. | ||||
|  * @return: 0 .. no change | ||||
|  * return:: 0 .. no change | ||||
|  *          1 .. CAM state changed | ||||
|  */ | ||||
|  | ||||
| @@ -1123,7 +1116,8 @@ static int dvb_ca_en50221_poll_cam_gone(struct dvb_ca_private *ca, int slot) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Thread state machine for one CA slot to perform the data transfer. | ||||
|  * dvb_ca_en50221_thread_state_machine - Thread state machine for one CA slot | ||||
|  *	to perform the data transfer. | ||||
|  * | ||||
|  * @ca: CA instance. | ||||
|  * @slot: Slot to process. | ||||
| @@ -1274,8 +1268,8 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca, | ||||
| 		ca->pub->slot_ts_enable(ca->pub, slot); | ||||
| 		sl->slot_state = DVB_CA_SLOTSTATE_RUNNING; | ||||
| 		dvb_ca_en50221_thread_update_delay(ca); | ||||
| 		pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", | ||||
| 		       ca->dvbdev->adapter->num); | ||||
| 		pr_info("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", | ||||
| 			ca->dvbdev->adapter->num); | ||||
| 		break; | ||||
|  | ||||
| 	case DVB_CA_SLOTSTATE_RUNNING: | ||||
| @@ -1317,7 +1311,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca, | ||||
| 	mutex_unlock(&sl->slot_lock); | ||||
| } | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  * Kernel thread which monitors CA slots for CAM changes, and performs data | ||||
|  * transfers. | ||||
|  */ | ||||
| @@ -1354,15 +1348,15 @@ static int dvb_ca_en50221_thread(void *data) | ||||
| /* EN50221 IO interface functions */ | ||||
|  | ||||
| /** | ||||
|  * Real ioctl implementation. | ||||
|  * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. | ||||
|  * dvb_ca_en50221_io_do_ioctl - Real ioctl implementation. | ||||
|  * | ||||
|  * @inode: Inode concerned. | ||||
|  * @file: File concerned. | ||||
|  * @cmd: IOCTL command. | ||||
|  * @arg: Associated argument. | ||||
|  * @parg: Associated argument. | ||||
|  * | ||||
|  * @return 0 on success, <0 on error. | ||||
|  * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. | ||||
|  * | ||||
|  * return: 0 on success, <0 on error. | ||||
|  */ | ||||
| static int dvb_ca_en50221_io_do_ioctl(struct file *file, | ||||
| 				      unsigned int cmd, void *parg) | ||||
| @@ -1411,11 +1405,13 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file, | ||||
| 		struct dvb_ca_slot *sl; | ||||
|  | ||||
| 		slot = info->num; | ||||
| 		if ((slot > ca->slot_count) || (slot < 0)) { | ||||
| 		if ((slot >= ca->slot_count) || (slot < 0)) { | ||||
| 			err = -EINVAL; | ||||
| 			goto out_unlock; | ||||
| 		} | ||||
|  | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) | ||||
| 		slot = array_index_nospec(slot, ca->slot_count); | ||||
| #endif | ||||
| 		info->type = CA_CI_LINK; | ||||
| 		info->flags = 0; | ||||
| 		sl = &ca->slot_info[slot]; | ||||
| @@ -1439,14 +1435,13 @@ out_unlock: | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Wrapper for ioctl implementation. | ||||
|  * dvb_ca_en50221_io_ioctl - Wrapper for ioctl implementation. | ||||
|  * | ||||
|  * @inode: Inode concerned. | ||||
|  * @file: File concerned. | ||||
|  * @cmd: IOCTL command. | ||||
|  * @arg: Associated argument. | ||||
|  * | ||||
|  * @return 0 on success, <0 on error. | ||||
|  * return: 0 on success, <0 on error. | ||||
|  */ | ||||
| static long dvb_ca_en50221_io_ioctl(struct file *file, | ||||
| 				    unsigned int cmd, unsigned long arg) | ||||
| @@ -1455,14 +1450,14 @@ static long dvb_ca_en50221_io_ioctl(struct file *file, | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implementation of write() syscall. | ||||
|  * dvb_ca_en50221_io_write - Implementation of write() syscall. | ||||
|  * | ||||
|  * @file: File structure. | ||||
|  * @buf: Source buffer. | ||||
|  * @count: Size of source buffer. | ||||
|  * @ppos: Position in file (ignored). | ||||
|  * | ||||
|  * @return Number of bytes read, or <0 on error. | ||||
|  * return: Number of bytes read, or <0 on error. | ||||
|  */ | ||||
| static ssize_t dvb_ca_en50221_io_write(struct file *file, | ||||
| 				       const char __user *buf, size_t count, | ||||
| @@ -1495,6 +1490,11 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, | ||||
| 		return -EFAULT; | ||||
| 	buf += 2; | ||||
| 	count -= 2; | ||||
| 	if (slot >= ca->slot_count) | ||||
| 		return -EINVAL; | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) | ||||
| 	slot = array_index_nospec(slot, ca->slot_count); | ||||
| #endif | ||||
| 	sl = &ca->slot_info[slot]; | ||||
|  | ||||
| 	/* check if the slot is actually running */ | ||||
| @@ -1533,7 +1533,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, | ||||
|  | ||||
| 			mutex_lock(&sl->slot_lock); | ||||
| 			status = dvb_ca_en50221_write_data(ca, slot, fragbuf, | ||||
| 							   fraglen + 2); | ||||
| 							   fraglen + 2, 0); | ||||
| 			mutex_unlock(&sl->slot_lock); | ||||
| 			if (status == (fraglen + 2)) { | ||||
| 				written = 1; | ||||
| @@ -1557,7 +1557,7 @@ exit: | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  * Condition for waking up in dvb_ca_en50221_io_read_condition | ||||
|  */ | ||||
| static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, | ||||
| @@ -1607,14 +1607,14 @@ nextslot: | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implementation of read() syscall. | ||||
|  * dvb_ca_en50221_io_read - Implementation of read() syscall. | ||||
|  * | ||||
|  * @file: File structure. | ||||
|  * @buf: Destination buffer. | ||||
|  * @count: Size of destination buffer. | ||||
|  * @ppos: Position in file (ignored). | ||||
|  * | ||||
|  * @return Number of bytes read, or <0 on error. | ||||
|  * return: Number of bytes read, or <0 on error. | ||||
|  */ | ||||
| static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, | ||||
| 				      size_t count, loff_t *ppos) | ||||
| @@ -1718,12 +1718,12 @@ exit: | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implementation of file open syscall. | ||||
|  * dvb_ca_en50221_io_open - Implementation of file open syscall. | ||||
|  * | ||||
|  * @inode: Inode concerned. | ||||
|  * @file: File concerned. | ||||
|  * | ||||
|  * @return 0 on success, <0 on failure. | ||||
|  * return: 0 on success, <0 on failure. | ||||
|  */ | ||||
| static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) | ||||
| { | ||||
| @@ -1768,12 +1768,12 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implementation of file close syscall. | ||||
|  * dvb_ca_en50221_io_release - Implementation of file close syscall. | ||||
|  * | ||||
|  * @inode: Inode concerned. | ||||
|  * @file: File concerned. | ||||
|  * | ||||
|  * @return 0 on success, <0 on failure. | ||||
|  * return: 0 on success, <0 on failure. | ||||
|  */ | ||||
| static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | ||||
| { | ||||
| @@ -1797,35 +1797,38 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implementation of poll() syscall. | ||||
|  * dvb_ca_en50221_io_poll - Implementation of poll() syscall. | ||||
|  * | ||||
|  * @file: File concerned. | ||||
|  * @wait: poll wait table. | ||||
|  * | ||||
|  * @return Standard poll mask. | ||||
|  * return: Standard poll mask. | ||||
|  */ | ||||
| static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) | ||||
| typedef unsigned int __poll_t; | ||||
| #define EPOLLIN POLLIN | ||||
| #endif | ||||
| static __poll_t dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) | ||||
| { | ||||
| 	struct dvb_device *dvbdev = file->private_data; | ||||
| 	struct dvb_ca_private *ca = dvbdev->priv; | ||||
| 	unsigned int mask = 0; | ||||
| 	__poll_t mask = 0; | ||||
| 	int slot; | ||||
| 	int result = 0; | ||||
|  | ||||
| 	dprintk("%s\n", __func__); | ||||
|  | ||||
| 	poll_wait(file, &ca->wait_queue, wait); | ||||
|  | ||||
| 	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) | ||||
| 		mask |= POLLIN; | ||||
| 		mask |= EPOLLIN; | ||||
|  | ||||
| 	/* if there is something, return now */ | ||||
| 	if (mask) | ||||
| 		return mask; | ||||
|  | ||||
| 	/* wait for something to happen */ | ||||
| 	poll_wait(file, &ca->wait_queue, wait); | ||||
|  | ||||
| 	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) | ||||
| 		mask |= POLLIN; | ||||
| 		mask |= EPOLLIN; | ||||
|  | ||||
| 	return mask; | ||||
| } | ||||
| @@ -1856,14 +1859,14 @@ static const struct dvb_device dvbdev_ca = { | ||||
| /* Initialisation/shutdown functions */ | ||||
|  | ||||
| /** | ||||
|  * Initialise a new DVB CA EN50221 interface device. | ||||
|  * dvb_ca_en50221_init - Initialise a new DVB CA EN50221 interface device. | ||||
|  * | ||||
|  * @dvb_adapter: DVB adapter to attach the new CA device to. | ||||
|  * @ca: The dvb_ca instance. | ||||
|  * @pubca: The dvb_ca instance. | ||||
|  * @flags: Flags describing the CA device (DVB_CA_FLAG_*). | ||||
|  * @slot_count: Number of slots supported. | ||||
|  * | ||||
|  * @return 0 on success, nonzero on failure | ||||
|  * return: 0 on success, nonzero on failure | ||||
|  */ | ||||
| int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | ||||
| 			struct dvb_ca_en50221 *pubca, int flags, int slot_count) | ||||
| @@ -1948,10 +1951,9 @@ exit: | ||||
| EXPORT_SYMBOL(dvb_ca_en50221_init); | ||||
|  | ||||
| /** | ||||
|  * Release a DVB CA EN50221 interface device. | ||||
|  * dvb_ca_en50221_release - Release a DVB CA EN50221 interface device. | ||||
|  * | ||||
|  * @ca_dev: The dvb_device_t instance for the CA device. | ||||
|  * @ca: The associated dvb_ca instance. | ||||
|  * @pubca: The associated dvb_ca instance. | ||||
|  */ | ||||
| void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) | ||||
| { | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
| 	/* | ||||
| @@ -568,7 +553,7 @@ static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h) | ||||
| 		h->priv->ule_sndu_type_1 = 1; | ||||
| 		h->ts_remain -= 1; | ||||
| 		h->from_where += 1; | ||||
| 		/* fallthrough */ | ||||
| 		fallthrough; | ||||
| 	case 0: | ||||
| 		h->new_ts = 1; | ||||
| 		h->ts += TS_SZ; | ||||
| @@ -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; | ||||
| 		} | ||||
| @@ -783,6 +767,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) | ||||
| 	int ret; | ||||
| 	struct dvb_net_ule_handle h = { | ||||
| 		.dev = dev, | ||||
| 		.priv = netdev_priv(dev), | ||||
| 		.ethh = NULL, | ||||
| 		.buf = buf, | ||||
| 		.buf_len = buf_len, | ||||
| 		.skipped = 0L, | ||||
| @@ -792,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 | ||||
| 	}; | ||||
|  | ||||
| 	/* | ||||
| @@ -868,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); | ||||
| @@ -901,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; | ||||
|  | ||||
| @@ -1009,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 | ||||
| 	 */ | ||||
| @@ -1022,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; | ||||
| @@ -1035,7 +1018,7 @@ static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||||
|  | ||||
| static int dvb_net_filter_sec_set(struct net_device *dev, | ||||
| 		   struct dmx_section_filter **secfilter, | ||||
| 		   u8 *mac, u8 *mac_mask) | ||||
| 		   const u8 *mac, u8 *mac_mask) | ||||
| { | ||||
| 	struct dvb_net_priv *priv = netdev_priv(dev); | ||||
| 	int ret; | ||||
| @@ -1079,7 +1062,7 @@ static int dvb_net_feed_start(struct net_device *dev) | ||||
| 	int ret = 0, i; | ||||
| 	struct dvb_net_priv *priv = netdev_priv(dev); | ||||
| 	struct dmx_demux *demux = priv->demux; | ||||
| 	unsigned char *mac = (unsigned char *) dev->dev_addr; | ||||
| 	const unsigned char *mac = (unsigned char *) dev->dev_addr; | ||||
|  | ||||
| 	netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode); | ||||
| 	mutex_lock(&priv->mutex); | ||||
| @@ -1299,8 +1282,11 @@ static int dvb_net_set_mac (struct net_device *dev, void *p) | ||||
| 	struct dvb_net_priv *priv = netdev_priv(dev); | ||||
| 	struct sockaddr *addr=p; | ||||
|  | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) | ||||
| 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||||
|  | ||||
| #else | ||||
| 	eth_hw_addr_set(dev, addr->sa_data); | ||||
| #endif | ||||
| 	if (netif_running(dev)) | ||||
| 		schedule_work(&priv->restart_net_feed_wq); | ||||
|  | ||||
| @@ -1398,8 +1384,11 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) | ||||
| 			 dvbnet->dvbdev->adapter->num, if_num); | ||||
|  | ||||
| 	net->addr_len = 6; | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) | ||||
| 	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); | ||||
|  | ||||
| #else | ||||
| 	eth_hw_addr_set(net, dvbnet->dvbdev->adapter->proposed_mac); | ||||
| #endif | ||||
| 	dvbnet->device[if_num] = net; | ||||
|  | ||||
| 	priv = netdev_priv(net); | ||||
|   | ||||
| @@ -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 | ||||
| @@ -115,7 +115,7 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) | ||||
| void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) | ||||
| { | ||||
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) | ||||
| 	rbuf->pread = &rbuf->pwrite; | ||||
| 	rbuf->pread = rbuf->pwrite; | ||||
| #else | ||||
| 	/* dvb_ringbuffer_flush() counts as read operation | ||||
| 	 * smp_load_acquire() to load write pointer | ||||
| @@ -391,7 +391,9 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* | ||||
| 		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; | ||||
| 	} | ||||
|  | ||||
| 	consumed = (idx - rbuf->pread) % rbuf->size; | ||||
| 	consumed = idx - rbuf->pread; | ||||
| 	if (consumed < 0) | ||||
| 		consumed += rbuf->size; | ||||
|  | ||||
| 	while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { | ||||
|  | ||||
|   | ||||
							
								
								
									
										442
									
								
								dvb-core/dvb_vb2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								dvb-core/dvb_vb2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,442 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * dvb-vb2.c - dvb-vb2 | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #include <linux/err.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/mm.h> | ||||
|  | ||||
| #include <media/dvbdev.h> | ||||
| #include <media/dvb_vb2.h> | ||||
|  | ||||
| #define DVB_V2_MAX_SIZE		(4096 * 188) | ||||
|  | ||||
| static int vb2_debug; | ||||
| module_param(vb2_debug, int, 0644); | ||||
|  | ||||
| #define dprintk(level, fmt, arg...)					      \ | ||||
| 	do {								      \ | ||||
| 		if (vb2_debug >= level)					      \ | ||||
| 			pr_info("vb2: %s: " fmt, __func__, ## arg); \ | ||||
| 	} while (0) | ||||
|  | ||||
| static int _queue_setup(struct vb2_queue *vq, | ||||
| 			unsigned int *nbuffers, unsigned int *nplanes, | ||||
| 			unsigned int sizes[], struct device *alloc_devs[]) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq); | ||||
|  | ||||
| 	ctx->buf_cnt = *nbuffers; | ||||
| 	*nplanes = 1; | ||||
| 	sizes[0] = ctx->buf_siz; | ||||
|  | ||||
| 	/* | ||||
| 	 * videobuf2-vmalloc allocator is context-less so no need to set | ||||
| 	 * alloc_ctxs array. | ||||
| 	 */ | ||||
|  | ||||
| 	dprintk(3, "[%s] count=%d, size=%d\n", ctx->name, | ||||
| 		*nbuffers, sizes[0]); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int _buffer_prepare(struct vb2_buffer *vb) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 	unsigned long size = ctx->buf_siz; | ||||
|  | ||||
| 	if (vb2_plane_size(vb, 0) < size) { | ||||
| 		dprintk(1, "[%s] data will not fit into plane (%lu < %lu)\n", | ||||
| 			ctx->name, vb2_plane_size(vb, 0), size); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	vb2_set_plane_payload(vb, 0, size); | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void _buffer_queue(struct vb2_buffer *vb) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 	struct dvb_buffer *buf = container_of(vb, struct dvb_buffer, vb); | ||||
| 	unsigned long flags = 0; | ||||
|  | ||||
| 	spin_lock_irqsave(&ctx->slock, flags); | ||||
| 	list_add_tail(&buf->list, &ctx->dvb_q); | ||||
| 	spin_unlock_irqrestore(&ctx->slock, flags); | ||||
|  | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
| } | ||||
|  | ||||
| static int _start_streaming(struct vb2_queue *vq, unsigned int count) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq); | ||||
|  | ||||
| 	dprintk(3, "[%s] count=%d\n", ctx->name, count); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void _stop_streaming(struct vb2_queue *vq) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq); | ||||
| 	struct dvb_buffer *buf; | ||||
| 	unsigned long flags = 0; | ||||
|  | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	spin_lock_irqsave(&ctx->slock, flags); | ||||
| 	while (!list_empty(&ctx->dvb_q)) { | ||||
| 		buf = list_entry(ctx->dvb_q.next, | ||||
| 				 struct dvb_buffer, list); | ||||
| 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||||
| 		list_del(&buf->list); | ||||
| 	} | ||||
| 	spin_unlock_irqrestore(&ctx->slock, flags); | ||||
| } | ||||
|  | ||||
| static void _dmxdev_lock(struct vb2_queue *vq) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq); | ||||
|  | ||||
| 	mutex_lock(&ctx->mutex); | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
| } | ||||
|  | ||||
| static void _dmxdev_unlock(struct vb2_queue *vq) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq); | ||||
|  | ||||
| 	if (mutex_is_locked(&ctx->mutex)) | ||||
| 		mutex_unlock(&ctx->mutex); | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
| } | ||||
|  | ||||
| static const struct vb2_ops dvb_vb2_qops = { | ||||
| 	.queue_setup		= _queue_setup, | ||||
| 	.buf_prepare		= _buffer_prepare, | ||||
| 	.buf_queue		= _buffer_queue, | ||||
| 	.start_streaming	= _start_streaming, | ||||
| 	.stop_streaming		= _stop_streaming, | ||||
| 	.wait_prepare		= _dmxdev_unlock, | ||||
| 	.wait_finish		= _dmxdev_lock, | ||||
| }; | ||||
|  | ||||
| static void _fill_dmx_buffer(struct vb2_buffer *vb, void *pb) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 	struct dmx_buffer *b = pb; | ||||
|  | ||||
| 	b->index = vb->index; | ||||
| 	b->length = vb->planes[0].length; | ||||
| 	b->bytesused = vb->planes[0].bytesused; | ||||
| 	b->offset = vb->planes[0].m.offset; | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
| } | ||||
|  | ||||
| static int _fill_vb2_buffer(struct vb2_buffer *vb, struct vb2_plane *planes) | ||||
| { | ||||
| 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
|  | ||||
| 	planes[0].bytesused = 0; | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static const struct vb2_buf_ops dvb_vb2_buf_ops = { | ||||
| 	.fill_user_buffer	= _fill_dmx_buffer, | ||||
| 	.fill_vb2_buffer	= _fill_vb2_buffer, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Videobuf operations | ||||
|  */ | ||||
| int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking) | ||||
| { | ||||
| 	struct vb2_queue *q = &ctx->vb_q; | ||||
| 	int ret; | ||||
|  | ||||
| 	memset(ctx, 0, sizeof(struct dvb_vb2_ctx)); | ||||
| 	q->type = DVB_BUF_TYPE_CAPTURE; | ||||
| 	/**capture type*/ | ||||
| 	q->is_output = 0; | ||||
| 	/**only mmap is supported currently*/ | ||||
| 	q->io_modes = VB2_MMAP; | ||||
| 	q->drv_priv = ctx; | ||||
| 	q->buf_struct_size = sizeof(struct dvb_buffer); | ||||
| 	q->min_buffers_needed = 1; | ||||
| 	q->ops = &dvb_vb2_qops; | ||||
| 	q->mem_ops = &vb2_vmalloc_memops; | ||||
| 	q->buf_ops = &dvb_vb2_buf_ops; | ||||
| 	q->num_buffers = 0; | ||||
| 	ret = vb2_core_queue_init(q); | ||||
| 	if (ret) { | ||||
| 		ctx->state = DVB_VB2_STATE_NONE; | ||||
| 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	mutex_init(&ctx->mutex); | ||||
| 	spin_lock_init(&ctx->slock); | ||||
| 	INIT_LIST_HEAD(&ctx->dvb_q); | ||||
|  | ||||
| 	strscpy(ctx->name, name, DVB_VB2_NAME_MAX); | ||||
| 	ctx->nonblocking = nonblocking; | ||||
| 	ctx->state = DVB_VB2_STATE_INIT; | ||||
|  | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_release(struct dvb_vb2_ctx *ctx) | ||||
| { | ||||
| 	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q; | ||||
|  | ||||
| 	if (ctx->state & DVB_VB2_STATE_INIT) | ||||
| 		vb2_core_queue_release(q); | ||||
|  | ||||
| 	ctx->state = DVB_VB2_STATE_NONE; | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx) | ||||
| { | ||||
| 	struct vb2_queue *q = &ctx->vb_q; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vb2_core_streamon(q, q->type); | ||||
| 	if (ret) { | ||||
| 		ctx->state = DVB_VB2_STATE_NONE; | ||||
| 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	ctx->state |= DVB_VB2_STATE_STREAMON; | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx) | ||||
| { | ||||
| 	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q; | ||||
| 	int ret; | ||||
|  | ||||
| 	ctx->state &= ~DVB_VB2_STATE_STREAMON; | ||||
| 	ret = vb2_core_streamoff(q, q->type); | ||||
| 	if (ret) { | ||||
| 		ctx->state = DVB_VB2_STATE_NONE; | ||||
| 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx) | ||||
| { | ||||
| 	return (ctx->state & DVB_VB2_STATE_STREAMON); | ||||
| } | ||||
|  | ||||
| int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, | ||||
| 			const unsigned char *src, int len, | ||||
| 			enum dmx_buffer_flags *buffer_flags) | ||||
| { | ||||
| 	unsigned long flags = 0; | ||||
| 	void *vbuf = NULL; | ||||
| 	int todo = len; | ||||
| 	unsigned char *psrc = (unsigned char *)src; | ||||
| 	int ll = 0; | ||||
|  | ||||
| 	/* | ||||
| 	 * normal case: This func is called twice from demux driver | ||||
| 	 * one with valid src pointer, second time with NULL pointer | ||||
| 	 */ | ||||
| 	if (!src || !len) | ||||
| 		return 0; | ||||
| 	spin_lock_irqsave(&ctx->slock, flags); | ||||
| 	if (buffer_flags && *buffer_flags) { | ||||
| 		ctx->flags |= *buffer_flags; | ||||
| 		*buffer_flags = 0; | ||||
| 	} | ||||
| 	while (todo) { | ||||
| 		if (!ctx->buf) { | ||||
| 			if (list_empty(&ctx->dvb_q)) { | ||||
| 				dprintk(3, "[%s] Buffer overflow!!!\n", | ||||
| 					ctx->name); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			ctx->buf = list_entry(ctx->dvb_q.next, | ||||
| 					      struct dvb_buffer, list); | ||||
| 			ctx->remain = vb2_plane_size(&ctx->buf->vb, 0); | ||||
| 			ctx->offset = 0; | ||||
| 		} | ||||
|  | ||||
| 		if (!dvb_vb2_is_streaming(ctx)) { | ||||
| 			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR); | ||||
| 			list_del(&ctx->buf->list); | ||||
| 			ctx->buf = NULL; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		/* Fill buffer */ | ||||
| 		ll = min(todo, ctx->remain); | ||||
| 		vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0); | ||||
| 		memcpy(vbuf + ctx->offset, psrc, ll); | ||||
| 		todo -= ll; | ||||
| 		psrc += ll; | ||||
|  | ||||
| 		ctx->remain -= ll; | ||||
| 		ctx->offset += ll; | ||||
|  | ||||
| 		if (ctx->remain == 0) { | ||||
| 			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); | ||||
| 			list_del(&ctx->buf->list); | ||||
| 			ctx->buf = NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (ctx->nonblocking && ctx->buf) { | ||||
| 		vb2_set_plane_payload(&ctx->buf->vb, 0, ll); | ||||
| 		vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); | ||||
| 		list_del(&ctx->buf->list); | ||||
| 		ctx->buf = NULL; | ||||
| 	} | ||||
| 	spin_unlock_irqrestore(&ctx->slock, flags); | ||||
|  | ||||
| 	if (todo) | ||||
| 		dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo); | ||||
| 	else | ||||
| 		dprintk(3, "[%s]\n", ctx->name); | ||||
|  | ||||
| 	dprintk(3, "[%s] %d bytes are copied\n", ctx->name, len - todo); | ||||
| 	return (len - todo); | ||||
| } | ||||
|  | ||||
| int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	/* Adjust size to a sane value */ | ||||
| 	if (req->size > DVB_V2_MAX_SIZE) | ||||
| 		req->size = DVB_V2_MAX_SIZE; | ||||
|  | ||||
| 	/* FIXME: round req->size to a 188 or 204 multiple */ | ||||
|  | ||||
| 	ctx->buf_siz = req->size; | ||||
| 	ctx->buf_cnt = req->count; | ||||
| 	ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, 0, &req->count); | ||||
| 	if (ret) { | ||||
| 		ctx->state = DVB_VB2_STATE_NONE; | ||||
| 		dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name, | ||||
| 			ctx->buf_cnt, ctx->buf_siz, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	ctx->state |= DVB_VB2_STATE_REQBUFS; | ||||
| 	dprintk(3, "[%s] count=%d size=%d\n", ctx->name, | ||||
| 		ctx->buf_cnt, ctx->buf_siz); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) | ||||
| { | ||||
| 	vb2_core_querybuf(&ctx->vb_q, b->index, b); | ||||
| 	dprintk(3, "[%s] index=%d\n", ctx->name, b->index); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp) | ||||
| { | ||||
| 	struct vb2_queue *q = &ctx->vb_q; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index, | ||||
| 			      0, exp->flags); | ||||
| 	if (ret) { | ||||
| 		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name, | ||||
| 			exp->index, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	dprintk(3, "[%s] index=%d fd=%d\n", ctx->name, exp->index, exp->fd); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL); | ||||
| 	if (ret) { | ||||
| 		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name, | ||||
| 			b->index, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	dprintk(5, "[%s] index=%d\n", ctx->name, b->index); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking); | ||||
| 	if (ret) { | ||||
| 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	spin_lock_irqsave(&ctx->slock, flags); | ||||
| 	b->count = ctx->count++; | ||||
| 	b->flags = ctx->flags; | ||||
| 	ctx->flags = 0; | ||||
| 	spin_unlock_irqrestore(&ctx->slock, flags); | ||||
|  | ||||
| 	dprintk(5, "[%s] index=%d, count=%d, flags=%d\n", | ||||
| 		ctx->name, b->index, ctx->count, b->flags); | ||||
|  | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vb2_mmap(&ctx->vb_q, vma); | ||||
| 	if (ret) { | ||||
| 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	dprintk(3, "[%s] ret=%d\n", ctx->name, ret); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file, | ||||
| 		      poll_table *wait) | ||||
| { | ||||
| 	dprintk(3, "[%s]\n", ctx->name); | ||||
| 	return vb2_core_poll(&ctx->vb_q, file, wait); | ||||
| } | ||||
|  | ||||
| @@ -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,26 @@ 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, | ||||
|        [DVB_DEVICE_CI]         = 9, | ||||
|        [DVB_DEVICE_MOD]        = 10, | ||||
|        [DVB_DEVICE_NS]         = 11, | ||||
|        [DVB_DEVICE_NSD]        = 12, | ||||
| }; | ||||
|  | ||||
| #define nums2minor(num, type, id) \ | ||||
|        (((num) << 6) | ((id) << 4) | minor_type[type]) | ||||
|  | ||||
| #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64) | ||||
| #endif | ||||
|  | ||||
| @@ -221,6 +252,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev) | ||||
|  | ||||
| 	if (dvbdev->adapter->conn) { | ||||
| 		media_device_unregister_entity(dvbdev->adapter->conn); | ||||
| 		kfree(dvbdev->adapter->conn); | ||||
| 		dvbdev->adapter->conn = NULL; | ||||
| 		kfree(dvbdev->adapter->conn_pads); | ||||
| 		dvbdev->adapter->conn_pads = NULL; | ||||
| @@ -319,8 +351,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 +454,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 +465,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 +490,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 +506,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); | ||||
| @@ -482,6 +517,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 			break; | ||||
|  | ||||
| 	if (minor == MAX_DVB_MINORS) { | ||||
| 		list_del (&dvbdev->list_head); | ||||
| 		kfree(dvbdevfops); | ||||
| 		kfree(dvbdev); | ||||
| 		up_write(&minor_rwsem); | ||||
| @@ -502,9 +538,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 		      __func__); | ||||
|  | ||||
| 		dvb_media_device_free(dvbdev); | ||||
| 		list_del (&dvbdev->list_head); | ||||
| 		kfree(dvbdevfops); | ||||
| 		kfree(dvbdev); | ||||
| 		up_write(&minor_rwsem); | ||||
| 		mutex_unlock(&dvbdev_register_lock); | ||||
| 		return ret; | ||||
| 	} | ||||
| @@ -517,6 +553,10 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||||
| 	if (IS_ERR(clsdev)) { | ||||
| 		pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", | ||||
| 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); | ||||
| 		dvb_media_device_free(dvbdev); | ||||
| 		list_del (&dvbdev->list_head); | ||||
| 		kfree(dvbdevfops); | ||||
| 		kfree(dvbdev); | ||||
| 		return PTR_ERR(clsdev); | ||||
| 	} | ||||
| 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", | ||||
| @@ -579,7 +619,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,7 +639,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 	unsigned demux_pad = 0; | ||||
| 	unsigned dvr_pad = 0; | ||||
| 	unsigned ntuner = 0, ndemod = 0; | ||||
| 	int ret; | ||||
| 	int ret, pad_source, pad_sink; | ||||
| 	static const char *connector_name = "Television"; | ||||
|  | ||||
| 	if (!mdev) | ||||
| @@ -658,7 +699,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
|  | ||||
| 		if (!ntuner) | ||||
| 		if (!ntuner) { | ||||
| 			ret = media_create_pad_links(mdev, | ||||
| 						     MEDIA_ENT_F_CONN_RF, | ||||
| 						     conn, 0, | ||||
| @@ -666,22 +707,41 @@ int dvb_create_media_graph(struct dvb_adapter *adap, | ||||
| 						     demod, 0, | ||||
| 						     MEDIA_LNK_FL_ENABLED, | ||||
| 						     false); | ||||
| 		else | ||||
| 		} 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, TUNER_PAD_RF_INPUT, | ||||
| 						     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)) | ||||
| 		/* 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 | ||||
| 		pad_source = TUNER_PAD_OUTPUT; | ||||
| #endif | ||||
| 		 | ||||
| 		ret = media_create_pad_links(mdev, | ||||
| 					     MEDIA_ENT_F_TUNER, | ||||
| 					     tuner, TUNER_PAD_OUTPUT, | ||||
| 					     tuner, pad_source, | ||||
| 					     MEDIA_ENT_F_DTV_DEMOD, | ||||
| 					     demod, 0, MEDIA_LNK_FL_ENABLED, | ||||
| 					     false); | ||||
| @@ -734,14 +794,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; | ||||
| 		} | ||||
| @@ -753,7 +815,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; | ||||
| 		} | ||||
| @@ -839,6 +902,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); | ||||
| @@ -859,7 +926,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, | ||||
| @@ -923,6 +990,57 @@ out: | ||||
| } | ||||
| EXPORT_SYMBOL(dvb_usercopy); | ||||
|  | ||||
| #if IS_ENABLED(CONFIG_I2C) | ||||
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,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$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core | ||||
|  | ||||
| drxk-objs := drxk_hard.o  | ||||
| obj-$(CONFIG_DVB_DRXK) += drxk.o | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| ccflags-y += -I$(srctree)/drivers/media/dvb-core/ | ||||
| ccflags-y += -I$(srctree)/drivers/media/tuners/ | ||||
| ccflags-y += --include=dd_compat.h | ||||
|  | ||||
| # FIXME: RTL2832 SDR driver uses power management directly from USB IF driver | ||||
| ifdef CONFIG_DVB_RTL2832_SDR | ||||
|   | ||||
| @@ -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)) | ||||
| @@ -54,6 +54,7 @@ struct cxd_state { | ||||
| 	struct dvb_frontend   frontend; | ||||
| 	struct i2c_adapter   *i2c; | ||||
| 	struct mutex          mutex; | ||||
| 	int repi2cerr; | ||||
|  | ||||
| 	u8  adrt; | ||||
| 	u8  curbankt; | ||||
| @@ -91,12 +92,13 @@ struct cxd_state { | ||||
| 	u8    is24MHz; | ||||
| }; | ||||
|  | ||||
| static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) | ||||
| static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len, int flag) | ||||
| { | ||||
| 	struct i2c_msg msg = { | ||||
| 		.addr = adr, .flags = 0, .buf = data, .len = len};  | ||||
| 	if (i2c_transfer(adap, &msg, 1) != 1) { | ||||
| 		pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); | ||||
| 		if (flag) | ||||
| 			pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| @@ -105,18 +107,22 @@ 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); | ||||
| 	return i2c_write(state->i2c, adr, data, len + 1, state->repi2cerr);  | ||||
| } | ||||
|  | ||||
| static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) | ||||
| { | ||||
| 	u8 mm[2] = {reg, dat}; | ||||
|  | ||||
| 	return i2c_write(state->i2c, adr, mm, 2); | ||||
| 	return i2c_write(state->i2c, adr, mm, 2, state->repi2cerr);  | ||||
| } | ||||
|  | ||||
| static int i2c_read(struct i2c_adapter *adap, | ||||
| @@ -126,17 +132,19 @@ static int i2c_read(struct i2c_adapter *adap, | ||||
| 				     .buf = msg, .len = len}, | ||||
| 				   { .addr = adr, .flags = I2C_M_RD, | ||||
| 				     .buf = answ, .len = alen } }; | ||||
| 	if (i2c_transfer(adap, msgs, 2) != 2) { | ||||
| 		pr_err("cxd2843: i2c_read error\n"); | ||||
| 	if (i2c_transfer(adap, msgs, 2) != 2) | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int readregs(struct cxd_state *state, u8 adr, u8 reg, | ||||
| 		    u8 *val, int count) | ||||
| { | ||||
| 	return i2c_read(state->i2c, adr, ®, 1, val, count); | ||||
| 	int ret = i2c_read(state->i2c, adr, ®, 1, val, count); | ||||
|  | ||||
| 	if (ret && state->repi2cerr) | ||||
| 		pr_err("cxd2843: i2c_read error\n"); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int readregst_unlocked(struct cxd_state *cxd, u8 bank, | ||||
| @@ -355,6 +363,7 @@ static int read_tps(struct cxd_state *state, u8 *tps) | ||||
| /*  OFDMInfo[3] [3:0]  OFDM_NDSYM[11:8] */ | ||||
| /*  OFDMInfo[4] [7:0]  OFDM_NDSYM[7:0]  */ | ||||
|  | ||||
| #if 0 | ||||
| static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm) | ||||
| { | ||||
| 	if (state->last_status != 0x1f) | ||||
| @@ -365,6 +374,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm) | ||||
| 	unfreeze_regst(state); | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Read DVBT2 QAM,  | ||||
|    Data PLP | ||||
| @@ -390,6 +400,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm) | ||||
|  19-37 same for common PLP | ||||
| */ | ||||
|  | ||||
| #if 0 | ||||
| static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp) | ||||
| { | ||||
| 	if (state->last_status != 0x1f) | ||||
| @@ -400,6 +411,7 @@ static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp) | ||||
| 	unfreeze_regst(state); | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void Active_to_Sleep(struct cxd_state *state) | ||||
| { | ||||
| @@ -1636,7 +1648,7 @@ static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) | ||||
| 	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ | ||||
| 	state->IF_FS = 0x50; | ||||
| 	state->is24MHz = (cfg->osc == 24000000) ? 1 : 0; | ||||
| 	printk("is24Mhz = %u\n", state->is24MHz); | ||||
| 	printk("is24Mhz = %u, adr = %02x\n", state->is24MHz, cfg->adr); | ||||
| } | ||||
|  | ||||
| static int get_tune_settings(struct dvb_frontend *fe, | ||||
| @@ -2236,14 +2248,14 @@ 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; | ||||
| } | ||||
|  | ||||
| static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p) | ||||
| { | ||||
| 	struct dvb_frontend *fe = &state->frontend; | ||||
| 	//struct dvb_frontend *fe = &state->frontend; | ||||
| 	u8 ofdm[5], modcod[2]; | ||||
| 	 | ||||
| 	freeze_regst(state); | ||||
| @@ -2343,7 +2355,7 @@ static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p) | ||||
|  | ||||
| static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p) | ||||
| { | ||||
| 	struct dvb_frontend *fe = &state->frontend; | ||||
| 	//struct dvb_frontend *fe = &state->frontend; | ||||
| 	u8 tps[7]; | ||||
|  | ||||
| 	read_tps(state, tps); | ||||
| @@ -2444,7 +2456,7 @@ static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p) | ||||
|  | ||||
| static int get_fe_c(struct cxd_state *state,  struct dtv_frontend_properties *p) | ||||
| { | ||||
| 	struct dvb_frontend *fe = &state->frontend; | ||||
| 	//struct dvb_frontend *fe = &state->frontend; | ||||
| 	u8 qam; | ||||
|  | ||||
| 	freeze_regst(state); | ||||
| @@ -2485,9 +2497,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 | | ||||
| @@ -2498,7 +2510,8 @@ static struct dvb_frontend_ops common_ops_2854 = { | ||||
| 			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_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | | ||||
| 		        FE_CAN_MULTISTREAM | ||||
| 	}, | ||||
| 	.release = release, | ||||
| 	.sleep = sleep, | ||||
| @@ -2518,9 +2531,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 | | ||||
| @@ -2531,7 +2544,8 @@ static struct dvb_frontend_ops common_ops_2843 = { | ||||
| 			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_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | | ||||
| 		        FE_CAN_MULTISTREAM | ||||
| 	}, | ||||
| 	.release = release, | ||||
| 	.sleep = sleep, | ||||
| @@ -2556,9 +2570,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 | | ||||
| @@ -2569,7 +2583,8 @@ static struct dvb_frontend_ops common_ops_2837 = { | ||||
| 			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_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | | ||||
| 		        FE_CAN_MULTISTREAM | ||||
| 	}, | ||||
| 	.release = release, | ||||
| 	.sleep = sleep, | ||||
| @@ -2594,9 +2609,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 | | ||||
| @@ -2636,7 +2651,8 @@ static int probe(struct cxd_state *state) | ||||
| 	if (status) | ||||
| 		return status; | ||||
| 	 | ||||
| 	printk("ChipID  = %02X\n", ChipID); | ||||
| 	state->repi2cerr = 1; | ||||
| 	//pr_info("cxd2843: ChipID  = %02X\n", ChipID); | ||||
| 	switch (ChipID) { | ||||
| 	case 0xa4: | ||||
| 		state->type = CXD2843; | ||||
| @@ -2671,7 +2687,6 @@ struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, | ||||
| { | ||||
| 	struct cxd_state *state = NULL; | ||||
|  | ||||
| 	pr_info("attach\n"); | ||||
| 	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); | ||||
| 	if (!state) | ||||
| 		return NULL; | ||||
|   | ||||
| @@ -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" | ||||
|  | ||||
| @@ -1566,7 +1566,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode) | ||||
| 			case OM_QAM_ITU_B: | ||||
| 				status = -1; | ||||
| 				break; | ||||
| 			case OM_QAM_ITU_A: /* fallthrough */ | ||||
| 			case OM_QAM_ITU_A:  | ||||
| 			case OM_QAM_ITU_C: | ||||
| 				CHK_ERROR(MPEGTSStop(state)); | ||||
| 				CHK_ERROR(PowerDownQAM(state)); | ||||
| @@ -1589,7 +1589,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode) | ||||
| 			case OM_QAM_ITU_B: | ||||
| 				status = -1; | ||||
| 				break; | ||||
| 			case OM_QAM_ITU_A:        /* fallthrough */ | ||||
| 			case OM_QAM_ITU_A: | ||||
| 			case OM_QAM_ITU_C: | ||||
| 				state->m_OperationMode = oMode; | ||||
| 				CHK_ERROR(SetQAMStandard(state,oMode)); | ||||
| @@ -1765,7 +1765,7 @@ static int MPEGTSDtoSetup(struct drxk_state *state, enum OperationMode oMode) | ||||
| 			fecOcRcnCtlRate = 0xC00000; | ||||
| 			staticCLK = state->m_DVBTStaticCLK; | ||||
| 			break; | ||||
| 		case OM_QAM_ITU_A: /* fallthrough */ | ||||
| 		case OM_QAM_ITU_A: | ||||
| 		case OM_QAM_ITU_C: | ||||
| 			fecOcTmdMode = 0x0004; | ||||
| 			fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ | ||||
| @@ -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 */ | ||||
| 		fallthrough; | ||||
| 	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 */ | ||||
| 		fallthrough; | ||||
| 	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 */ | ||||
| 			fallthrough; | ||||
| 		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 */ | ||||
| 			fallthrough; | ||||
| 		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; | ||||
| 			fallthrough; | ||||
| 		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 */ | ||||
| 			fallthrough; | ||||
| 		case QAM_64: | ||||
| 			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; | ||||
| 			break; | ||||
| @@ -3305,8 +3311,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF | ||||
| 	     transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; | ||||
| 	     WR16(devAddr, OFDM_EC_SB_PRIOR__A,   OFDM_EC_SB_PRIOR_HI)); | ||||
| 	     break; | ||||
| 	  case DRX_PRIORITY_UNKNOWN : /* fall through */ | ||||
| 	  default: | ||||
| 	  case DRX_PRIORITY_UNKNOWN: | ||||
| 		default: | ||||
| 	     return (DRX_STS_INVALID_ARG); | ||||
| 	     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 */ | ||||
| 			fallthrough; | ||||
| 		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 { | ||||
| @@ -106,6 +106,7 @@ static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int lnbh25_set_tone(struct dvb_frontend *fe, | ||||
| 			   enum fe_sec_tone_mode tone) | ||||
| { | ||||
| @@ -113,6 +114,7 @@ static int lnbh25_set_tone(struct dvb_frontend *fe, | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int lnbh25_init(struct lnbh25 *lnbh) | ||||
| { | ||||
|   | ||||
| @@ -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" | ||||
| @@ -98,26 +98,6 @@ struct mxl { | ||||
| 	unsigned long        tune_time; | ||||
| }; | ||||
|  | ||||
| static void le32_to_cpusn(u32 *data, u32 size) | ||||
| { | ||||
| 	u32 i; | ||||
|  | ||||
| 	for (i = 0; i < size; data++, i += 4) | ||||
| 		le32_to_cpus(data); | ||||
| } | ||||
|  | ||||
| static void flip_data_in_dword(u32 size, u8 *d) | ||||
| { | ||||
| 	u32 i; | ||||
| 	u8 t; | ||||
|  | ||||
| 	for (i = 0; i < size; i += 4) { | ||||
| 		t = d[i + 3]; d[i + 3] = d[i]; d[i] = t; | ||||
| 		t = d[i + 2]; d[i + 2] = d[i + 1]; d[i + 1] = t; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| static void convert_endian(u8 flag, u32 size, u8 *d) | ||||
| { | ||||
| 	u32 i; | ||||
| @@ -249,6 +229,7 @@ static int write_register(struct mxl *state, u32 reg, u32 val) | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int write_register_block(struct mxl *state, u32 reg, | ||||
| 				u32 size, u8 *data) | ||||
| { | ||||
| @@ -272,6 +253,7 @@ static int write_register_block(struct mxl *state, u32 reg, | ||||
| 	mutex_unlock(&state->base->i2c_lock); | ||||
| 	return stat; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int write_firmware_block(struct mxl *state, | ||||
| 				u32 reg, u32 size, u8 *regDataPtr) | ||||
| @@ -375,17 +357,6 @@ static int update_by_mnemonic(struct mxl *state, | ||||
| 	return stat; | ||||
| } | ||||
|  | ||||
| static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width, | ||||
| 				  u32 *toAddr, u8 *toLsbPos, u8 *toWidth) | ||||
| { | ||||
| 	if (toAddr) | ||||
| 		*toAddr = regAddr; | ||||
| 	if (toLsbPos) | ||||
| 		*toLsbPos = lsbPos; | ||||
| 	if (toWidth) | ||||
| 		*toWidth = width; | ||||
| } | ||||
|  | ||||
| static int firmware_is_alive(struct mxl *state) | ||||
| { | ||||
| 	u32 hb0, hb1; | ||||
| @@ -395,8 +366,10 @@ static int firmware_is_alive(struct mxl *state) | ||||
| 	msleep(20); | ||||
| 	if (read_register(state, HYDRA_HEAR_BEAT, &hb1)) | ||||
| 		return 0; | ||||
| 	if (hb1 == hb0) | ||||
| 	if (hb1 == hb0) { | ||||
| 		pr_warn("mxl5xx: Hydra FW not running!\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @@ -419,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; | ||||
| } | ||||
| @@ -470,9 +443,9 @@ static int CfgDemodAbortTune(struct mxl *state) | ||||
| 			    &cmdBuff[0]); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int reset_fec_counter(struct mxl *state) | ||||
| { | ||||
| 	MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd; | ||||
| 	u32 demodIndex = (u32) state->demod; | ||||
| 	u8 cmdSize = sizeof(u32); | ||||
| 	u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; | ||||
| @@ -482,6 +455,7 @@ static int reset_fec_counter(struct mxl *state) | ||||
| 	return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, | ||||
| 			    &cmdBuff[0]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int send_master_cmd(struct dvb_frontend *fe, | ||||
| 			   struct dvb_diseqc_master_cmd *cmd) | ||||
| @@ -686,9 +660,15 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber) | ||||
| 		p->pre_bit_error.stat[0].uvalue = reg[5]; | ||||
| 		p->pre_bit_count.len = 1; | ||||
| 		p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 		p->pre_bit_count.stat[0].uvalue = 8 * 188 * (u64)reg[6]; | ||||
| 		p->pre_bit_count.stat[0].uvalue = 8 * 188 * (u64) reg[6]; | ||||
| 		break; | ||||
| 	case SYS_DVBS2: | ||||
| 		p->block_error.len = 1; | ||||
| 		p->block_error.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 		p->block_error.stat[0].uvalue = reg[1]; | ||||
| 		p->block_count.len = 1; | ||||
| 		p->block_count.stat[0].scale = FE_SCALE_COUNTER; | ||||
| 		p->block_count.stat[0].uvalue = reg[2]; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| @@ -806,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]) { | ||||
| @@ -844,19 +825,21 @@ static int set_input(struct dvb_frontend *fe, int input) | ||||
| 	struct mxl *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
|  | ||||
| 	state->tuner = p->input = input; | ||||
| 	state->tuner = input; | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	p->input = input; | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct dvb_frontend_ops mxl_ops = { | ||||
| 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, | ||||
| 	.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 | | ||||
| @@ -875,7 +858,10 @@ static struct dvb_frontend_ops mxl_ops = { | ||||
| 	.read_signal_strength		= read_signal_strength, | ||||
| 	.read_ucblocks			= read_ucblocks, | ||||
| 	.get_frontend                   = get_frontend, | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	.set_input                      = set_input, | ||||
| 	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */ | ||||
| #endif | ||||
| 	.diseqc_send_master_cmd		= send_master_cmd, | ||||
| }; | ||||
|  | ||||
| @@ -1118,8 +1104,6 @@ static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len) | ||||
| 	if (!firmware_is_alive(state)) | ||||
| 		return -1; | ||||
|  | ||||
| 	pr_info("mxl5xx: Hydra FW alive. Hail!\n"); | ||||
|  | ||||
| 	/* sometimes register values are wrong shortly | ||||
| 	   after first heart beats */ | ||||
| 	msleep(50); | ||||
| @@ -1437,6 +1421,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, | ||||
| 		{XPT_NCO_COUNT_MIN4}, {XPT_NCO_COUNT_MIN5}, | ||||
| 		{XPT_NCO_COUNT_MIN6}, {XPT_NCO_COUNT_MIN7} }; | ||||
| 	 | ||||
| #if 0 | ||||
| 	MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = { | ||||
| 		{PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL}, | ||||
| 		{PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL}, | ||||
| @@ -1445,6 +1430,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, | ||||
| 		{PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL}, | ||||
| 		{PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL}, | ||||
| 		{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}}; | ||||
| #endif | ||||
|  | ||||
| 	demodId = state->base->ts_map[demodId]; | ||||
| 	 | ||||
| @@ -1609,6 +1595,7 @@ static int config_mux(struct mxl *state) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int config_dis(struct mxl *state, u32 id) | ||||
| { | ||||
| 	MXL_HYDRA_DISEQC_ID_E diseqcId = id; | ||||
| @@ -1630,6 +1617,7 @@ static int config_dis(struct mxl *state, u32 id) | ||||
| 	return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, | ||||
| 			    &cmdBuff[0]); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg) | ||||
| { | ||||
| @@ -1890,7 +1878,8 @@ static int probe(struct mxl *state, struct mxl5xx_cfg *cfg) | ||||
|  | ||||
| struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, | ||||
| 				   struct mxl5xx_cfg *cfg, | ||||
| 				   u32 demod, u32 tuner) | ||||
| 				   u32 demod, u32 tuner, | ||||
| 				   int (**fn_set_input)(struct dvb_frontend *, int)) | ||||
| { | ||||
| 	struct mxl *state; | ||||
| 	struct mxl_base *base; | ||||
| @@ -1930,9 +1919,12 @@ struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, | ||||
| 		list_add(&base->mxllist, &mxllist); | ||||
| 	} | ||||
| 	state->fe.ops               = mxl_ops; | ||||
| #ifndef KERNEL_DVB_CORE | ||||
| 	state->fe.ops.xbar[1]       = demod; | ||||
| 	state->fe.demodulator_priv  = state; | ||||
| 	state->fe.dtv_property_cache.input = tuner; | ||||
| #endif | ||||
| 	state->fe.demodulator_priv  = state; | ||||
| 	*fn_set_input = set_input; | ||||
| 	list_add(&state->mxl, &base->mxls); | ||||
| 	return &state->fe; | ||||
|  | ||||
|   | ||||
| @@ -23,12 +23,15 @@ struct mxl5xx_cfg { | ||||
|  | ||||
| extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, | ||||
| 					  struct mxl5xx_cfg *cfg, | ||||
| 					  u32 demod, u32 tuner); | ||||
| 					  u32 demod, u32 tuner, | ||||
| 					  int (**fn_set_input)(struct dvb_frontend *, int)); | ||||
|  | ||||
| #else | ||||
|  | ||||
| static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, | ||||
| 						 struct mxl5xx_cfg *cfg, | ||||
| 						 u32 demod, u32 tuner) | ||||
| 						 u32 demod, u32 tuner, | ||||
| 						 int (**fn_set_input)(struct dvb_frontend *, int)) | ||||
| { | ||||
| 	pr_warn("%s: driver disabled by Kconfig\n", __func__); | ||||
| 	return NULL; | ||||
|   | ||||
| @@ -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 */ | ||||
|  | ||||
| @@ -3644,7 +3644,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) | ||||
|  | ||||
| 	{ | ||||
| 		u16 val; | ||||
| 		u32 ber; | ||||
| 		 | ||||
| 		stv090x_read_cnr(fe, &val); | ||||
| 		stv090x_read_signal_strength(fe, &val); | ||||
| @@ -3657,7 +3656,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) | ||||
| static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber) | ||||
| { | ||||
|         struct stv090x_state *state = fe->demodulator_priv; | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	//struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
|         u32 reg, h, m, l; | ||||
|         enum fe_status status; | ||||
|  | ||||
| @@ -3836,7 +3835,7 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) | ||||
| 	u32 reg_0, reg_1, reg, i; | ||||
| 	s32 val_0, val_1, val = 0; | ||||
| 	u8 lock_f; | ||||
| 	s32 cnr_db; | ||||
| 	s32 cnr_db = 0; | ||||
| 	s32 div; | ||||
| 	u32 last; | ||||
|  | ||||
| @@ -5075,7 +5074,7 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, | ||||
| static int stv090x_get_frontend(struct dvb_frontend *fe,  struct dtv_frontend_properties *p) | ||||
| { | ||||
| 	struct stv090x_state *state = fe->demodulator_priv; | ||||
| 	u8 tmp; | ||||
| 	//u8 tmp; | ||||
| 	u32 reg = 0; | ||||
| 	 | ||||
| 	if (state->rec_mode == 2) { | ||||
| @@ -5143,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" | ||||
|  | ||||
| @@ -43,7 +43,7 @@ | ||||
| static LIST_HEAD(stvlist); | ||||
|  | ||||
| enum receive_mode { RCVMODE_NONE, RCVMODE_DVBS, RCVMODE_DVBS2, RCVMODE_AUTO }; | ||||
|  | ||||
| enum ScanMode { ColdStart, BlindScan }; | ||||
| enum dvbs2_fec_type { DVBS2_64K, DVBS2_16K }; | ||||
|  | ||||
| enum dvbs2_modcod { | ||||
| @@ -114,6 +114,7 @@ struct stv { | ||||
| 	u32                  first_time_lock; | ||||
| 	u8                   demod; | ||||
| 	u32                  symbol_rate; | ||||
| 	enum ScanMode        TuneMode; | ||||
|  | ||||
| 	enum fe_code_rate        puncture_rate; | ||||
| 	enum fe_stv0910_modcod   modcod; | ||||
| @@ -149,10 +150,12 @@ static int write_reg(struct stv *state, u16 reg, u8 val) | ||||
| 	return (i2c_transfer(state->base->i2c, &msg, 1) == 1) ? 0 : -1; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int write_reg_off(struct stv *state, u16 reg, u8 val) | ||||
| { | ||||
| 	return write_reg(state, reg + state->regoff, val); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, | ||||
| 				  u16 reg, u8 *val, int len) | ||||
| @@ -205,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val) | ||||
| 	return write_reg(state, field >> 16, new); | ||||
| } | ||||
|  | ||||
| static int read_field(struct stv *state, u32 field, u8 *val) | ||||
| { | ||||
| 	int status; | ||||
| 	u8 shift, mask; | ||||
|  | ||||
| 	status = read_reg(state, field >> 16, val); | ||||
| 	if (status) | ||||
| 		return status; | ||||
| 	mask = field & 0xff; | ||||
| 	shift = (field >> 12) & 0xf; | ||||
| 	*val = (*val & mask) >> shift; | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| #define set_field(_reg, _val)					\ | ||||
| 	write_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | ||||
| 		    FSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| #define get_field(_reg, _val)					\ | ||||
| 	read_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | ||||
| 		   FSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| #define set_reg(_reg, _val)					\ | ||||
| 	write_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||
| 		  RSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| #define get_reg(_reg, _val)					\ | ||||
| 	read_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||
| 		 RTV0910_P1_##_reg, _val) | ||||
| 		 RSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| static const struct slookup s1_sn_lookup[] = { | ||||
| 	{   0,    9242  }, /* C/N=  0dB */ | ||||
| @@ -1093,8 +1114,10 @@ static int start(struct stv *state, struct dtv_frontend_properties *p) | ||||
| 	write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); | ||||
|  | ||||
| 	write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); | ||||
|  | ||||
| 	/* Trigger acq */ | ||||
| 	write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); | ||||
| 	write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, | ||||
| 			state->TuneMode == BlindScan ? 0x00 : 0x15); | ||||
|  | ||||
| 	state->demod_lock_time += TUNING_DELAY; | ||||
| 	state->started = 1; | ||||
| @@ -1107,8 +1130,9 @@ static int init_diseqc(struct stv *state) | ||||
| 	u16 offs = state->nr ? 0x40 : 0;  /* Address offset */ | ||||
| 	u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); | ||||
|  | ||||
| 	/* Disable receiver */ | ||||
| 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); | ||||
| 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05); | ||||
| 	//write_reg(state, RSTV0910_P1_DISRXF220 + offs, 0x69); 2b? | ||||
|  | ||||
| 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ | ||||
| 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ | ||||
| 	write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); | ||||
| @@ -1245,11 +1269,17 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
|  | ||||
| 	stop(state); | ||||
| 	if (fe->ops.tuner_ops.set_params) | ||||
| 		fe->ops.tuner_ops.set_params(fe); | ||||
| 	if (fe->ops.tuner_ops.get_if_frequency) | ||||
| 		fe->ops.tuner_ops.get_if_frequency(fe, &IF); | ||||
| 	state->TuneMode = p->symbol_rate & 1 ? BlindScan : ColdStart; | ||||
| 	p->symbol_rate &= ~(0x1); | ||||
| 	state->symbol_rate = p->symbol_rate; | ||||
| 	if (state->TuneMode == BlindScan) | ||||
| 		p->symbol_rate = max((u32)(p->symbol_rate + p->symbol_rate/4), | ||||
| 				(u32)70000000); | ||||
|  | ||||
| 	if (fe->ops.tuner_ops.set_params) | ||||
| 		fe->ops.tuner_ops.set_params(fe); | ||||
| 	stat = start(state, p); | ||||
| 	return stat; | ||||
| } | ||||
| @@ -1570,7 +1600,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; | ||||
| } | ||||
| @@ -1606,12 +1636,28 @@ static int wait_dis(struct stv *state, u8 flag, u8 val) | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int clear_slave(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct stv *state = fe->demodulator_priv; | ||||
| 	u8 n, d, done; | ||||
|  | ||||
| 	get_field(RXEND, &done); | ||||
| 	get_reg(DISRXBYTES, &n); | ||||
| 	printk("clear: done = %u, %u fifo bytes\n", done, n); | ||||
| 	 | ||||
| 	for (get_reg(DISRXBYTES, &n); n; n--)  | ||||
| 		get_reg(DISRXFIFO, &d); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int send_master_cmd(struct dvb_frontend *fe, | ||||
| 			   struct dvb_diseqc_master_cmd *cmd) | ||||
| { | ||||
| 	struct stv *state = fe->demodulator_priv; | ||||
| 	int i; | ||||
|  | ||||
| 	clear_slave(fe); | ||||
| 	set_field(DISRX_ON, 0); | ||||
| 	set_reg(DISTXCFG, 0x3e); | ||||
| 	for (i = 0; i < cmd->msg_len; i++) { | ||||
| 		wait_dis(state, 0x40, 0x00); | ||||
| @@ -1619,17 +1665,65 @@ static int send_master_cmd(struct dvb_frontend *fe, | ||||
| 	} | ||||
| 	set_reg(DISTXCFG, 0x3a); | ||||
| 	wait_dis(state, 0x20, 0x20); | ||||
| 	set_field(DISRX_ON, 1); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int recv_slave_reply(struct dvb_frontend *fe, | ||||
| 			    struct dvb_diseqc_slave_reply *reply) | ||||
| { | ||||
| 	struct stv *state = fe->demodulator_priv; | ||||
| 	int i, to, flag = 0, max = sizeof(reply->msg); | ||||
| 	u8 done, val, n = 0; | ||||
|  | ||||
| 	 | ||||
| #if 0 | ||||
| 	get_reg(DISRXBYTES, &val); | ||||
| 	get_field(RXEND, &done); | ||||
| 	printk("slave: done = %u, %u fifo bytes\n", done, val); | ||||
| #endif | ||||
| 	to = reply->timeout; | ||||
| 	if (to < 0) { | ||||
| 		to = 100; | ||||
| 		flag = 1; | ||||
| 	} else if (to > 5000) | ||||
| 		to = 100; | ||||
| 	reply->msg_len = 0; | ||||
| 	for (i = 0; i < to; i += 10) { | ||||
| 		get_reg(DISRXBYTES, &val); | ||||
| 		if (flag && val) | ||||
| 			break; | ||||
| 		get_field(RXEND, &done); | ||||
| 		if (val >= max || done) | ||||
| 			break; | ||||
| 		msleep(10); | ||||
| 	} | ||||
| 	get_reg(DISRXBYTES, &val); | ||||
| 	printk("done = %u, %u fifo bytes, i=%u\n", done, val, i); | ||||
| 	if (i == to && !val) | ||||
| 		return -EIO; | ||||
| 	if (done && !val) | ||||
| 		return -EIO; | ||||
| 	for (i = 100; i; i--) { | ||||
| 		get_field(RXEND, &done); | ||||
| 		 | ||||
| 		for (get_reg(DISRXBYTES, &n); n; n--) { | ||||
| 			if (reply->msg_len == max) | ||||
| 				return 0; | ||||
| 			get_reg(DISRXFIFO, &reply->msg[reply->msg_len++]); | ||||
| 		} | ||||
| 		if (!n || done) | ||||
| 			break; | ||||
| 		msleep(10); | ||||
| 	} | ||||
| 	if (!i) | ||||
| 		return -EIO; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) | ||||
| { | ||||
| #if 0 | ||||
| 	struct stv *state = fe->demodulator_priv; | ||||
| 	u8 value; | ||||
|  | ||||
| @@ -1644,6 +1738,7 @@ static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) | ||||
| 	set_reg(DISTXFIFO, value); | ||||
| 	set_reg(DISTXCFG, 0x3a); | ||||
| 	wait_dis(state, 0x20, 0x20); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -1788,10 +1883,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 | | ||||
| @@ -1845,6 +1940,8 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, | ||||
| 	state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00; | ||||
| 	state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); | ||||
| 	state->tsspeed = cfg->parallel ? 0x10 : 0x28; | ||||
| 	if (cfg->tsspeed) | ||||
| 		state->tsspeed = cfg->tsspeed; | ||||
| 	state->nr = nr; | ||||
| 	state->regoff = state->nr ? 0 : 0x200; | ||||
| 	state->search_range = 16000000; | ||||
|   | ||||
| @@ -10,6 +10,7 @@ struct stv0910_cfg { | ||||
| 	u8  parallel; | ||||
| 	u8  rptlvl; | ||||
| 	u8  single; | ||||
| 	u8  tsspeed; | ||||
| }; | ||||
|  | ||||
| #if defined(CONFIG_DVB_STV0910) || \ | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
| @@ -100,12 +100,12 @@ static int read_reg(struct stv *state, u8 reg, u8 *val) | ||||
| 	return i2c_read(state->i2c, state->adr, ®, 1, val, 1); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int read_regs(struct stv *state, u8 reg, u8 *val, int len) | ||||
| { | ||||
| 	return i2c_read(state->i2c, state->adr, ®, 1, val, len); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static void dump_regs(struct stv *state) | ||||
| { | ||||
| 	u8 d[11], *c = &state->reg[0]; | ||||
| @@ -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 | ||||
| @@ -447,9 +447,6 @@ static int attach_init(struct tda_state *state) | ||||
| 	if (!state->m_isMaster) | ||||
| 		state->m_bLTEnable = false; | ||||
|  | ||||
| 	/*pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID, | ||||
| 	  state->m_isMaster ? "master" : "slave");*/ | ||||
|  | ||||
| 	if (state->m_ID != 18212) | ||||
| 		return -1; | ||||
|  | ||||
| @@ -457,8 +454,6 @@ static int attach_init(struct tda_state *state) | ||||
| 	if (stat < 0) | ||||
| 		return stat; | ||||
| 	 | ||||
| 	/*pr_info("tda18212dd: PowerState %02x\n", PowerState);*/ | ||||
|  | ||||
| 	if (state->m_isMaster) { | ||||
| 		if (PowerState & 0x02) { | ||||
| 			/* msleep for XTAL Calibration | ||||
| @@ -539,7 +534,6 @@ static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) | ||||
| 		if (*pPowerLevel > 110) | ||||
| 			*pPowerLevel = 110; | ||||
| 	} while (0); | ||||
| 	/* pr_info("PL %d\n", *pPowerLevel); */ | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| @@ -806,7 +800,6 @@ static int set_params(struct dvb_frontend *fe) | ||||
|  | ||||
| 	bw = (p->bandwidth_hz + 999999) / 1000000; | ||||
| 	state->m_Frequency = p->frequency; | ||||
| 	/*pr_info("tuner bw=%u  freq=%u\n", bw, state->m_Frequency);*/ | ||||
| 	if (p->delivery_system == SYS_DVBT || | ||||
| 	    p->delivery_system == SYS_DVBT2 || | ||||
| 	    p->delivery_system == SYS_ISDBT || | ||||
| @@ -889,9 +882,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, | ||||
|   | ||||
							
								
								
									
										39
									
								
								include/dd_compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								include/dd_compat.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #include <linux/version.h> | ||||
|  | ||||
| #if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE) | ||||
| #define __devexit | ||||
| #define __devinit | ||||
| #define __devinitconst | ||||
| #endif | ||||
|  | ||||
| #ifndef __has_attribute | ||||
| #define __has_attribute(x) 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef fallthrough | ||||
| #if __has_attribute(__fallthrough__) | ||||
| # define fallthrough                    __attribute__((__fallthrough__)) | ||||
| #else | ||||
| # define fallthrough                    do {} while (0)  /* fallthrough */ | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef KERNEL_DVB_CORE | ||||
| #define DVB_DEVICE_CI 0 | ||||
| #define DVB_DEVICE_MOD 6 | ||||
| #define DVB_DEVICE_NS 7 | ||||
| #define DVB_DEVICE_NSD 8 | ||||
|  | ||||
| #define SYS_DVBC2 19 | ||||
| #define ROLLOFF_15 4 | ||||
| #define ROLLOFF_10 5 | ||||
| #define ROLLOFF_5 6 | ||||
|  | ||||
| #define	FEC_1_4 13 | ||||
| #define	FEC_1_3 14 | ||||
|  | ||||
| #define APSK_64 14 | ||||
| #define APSK_128 15 | ||||
| #define APSK_256 16 | ||||
| #endif | ||||
| @@ -1,5 +1,8 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * audio.h | ||||
|  * audio.h - DEPRECATED MPEG-TS audio decoder API | ||||
|  * | ||||
|  * NOTE: should not be used on future drivers | ||||
|  * | ||||
|  * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de> | ||||
|  *                  & Marcus Metzler <marcus@convergence.de> | ||||
| @@ -51,7 +54,7 @@ typedef enum { | ||||
| typedef struct audio_mixer { | ||||
| 	unsigned int volume_left; | ||||
| 	unsigned int volume_right; | ||||
|   // what else do we need? bass, pass-through, ... | ||||
| /* what else do we need? bass, pass-through, ... */ | ||||
| } audio_mixer_t; | ||||
|  | ||||
|  | ||||
| @@ -66,27 +69,6 @@ typedef struct audio_status { | ||||
| } audio_status_t;                              /* separate decoder hardware */ | ||||
|  | ||||
|  | ||||
| typedef | ||||
| struct audio_karaoke {  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */ | ||||
| 	int vocal1;    /* into left and right t at 70% each */ | ||||
| 	int vocal2;    /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/ | ||||
| 	int melody;    /* mixed into the left channel and */ | ||||
| 		       /* Vocal2 into the right channel at 100% each. */ | ||||
| 		       /* if Melody is non-zero, the melody channel gets mixed*/ | ||||
| } audio_karaoke_t;     /* into left and right  */ | ||||
|  | ||||
|  | ||||
| typedef __u16 audio_attributes_t; | ||||
| /*   bits: descr. */ | ||||
| /*   15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */ | ||||
| /*   12    multichannel extension */ | ||||
| /*   11-10 audio type (0=not spec, 1=language included) */ | ||||
| /*    9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */ | ||||
| /*    7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit,  */ | ||||
| /*    5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */ | ||||
| /*    2- 0 number of audio channels (n+1 channels) */ | ||||
|  | ||||
|  | ||||
| /* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */ | ||||
| #define AUDIO_CAP_DTS    1 | ||||
| #define AUDIO_CAP_LPCM   2 | ||||
| @@ -114,22 +96,6 @@ typedef __u16 audio_attributes_t; | ||||
| #define AUDIO_SET_ID               _IO('o', 13) | ||||
| #define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t) | ||||
| #define AUDIO_SET_STREAMTYPE       _IO('o', 15) | ||||
| #define AUDIO_SET_EXT_ID           _IO('o', 16) | ||||
| #define AUDIO_SET_ATTRIBUTES       _IOW('o', 17, audio_attributes_t) | ||||
| #define AUDIO_SET_KARAOKE          _IOW('o', 18, audio_karaoke_t) | ||||
|  | ||||
| /** | ||||
|  * AUDIO_GET_PTS | ||||
|  * | ||||
|  * Read the 33 bit presentation time stamp as defined | ||||
|  * in ITU T-REC-H.222.0 / ISO/IEC 13818-1. | ||||
|  * | ||||
|  * The PTS should belong to the currently played | ||||
|  * frame if possible, but may also be a value close to it | ||||
|  * like the PTS of the last decoded frame or the last PTS | ||||
|  * extracted by the PES parser. | ||||
|  */ | ||||
| #define AUDIO_GET_PTS              _IOR('o', 19, __u64) | ||||
| #define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20) | ||||
|  | ||||
| #endif /* _DVBAUDIO_H_ */ | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * ca.h | ||||
|  * | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * dmx.h | ||||
|  * | ||||
| @@ -210,6 +211,96 @@ struct dmx_stc { | ||||
| 	__u64 stc; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * enum dmx_buffer_flags - DMX memory-mapped buffer flags | ||||
|  * | ||||
|  * @DMX_BUFFER_FLAG_HAD_CRC32_DISCARD: | ||||
|  *	Indicates that the Kernel discarded one or more frames due to wrong | ||||
|  *	CRC32 checksum. | ||||
|  * @DMX_BUFFER_FLAG_TEI: | ||||
|  *	Indicates that the Kernel has detected a Transport Error indicator | ||||
|  *	(TEI) on a filtered pid. | ||||
|  * @DMX_BUFFER_PKT_COUNTER_MISMATCH: | ||||
|  *	Indicates that the Kernel has detected a packet counter mismatch | ||||
|  *	on a filtered pid. | ||||
|  * @DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED: | ||||
|  *	Indicates that the Kernel has detected one or more frame discontinuity. | ||||
|  * @DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR: | ||||
|  *	Received at least one packet with a frame discontinuity indicator. | ||||
|  */ | ||||
|  | ||||
| enum dmx_buffer_flags { | ||||
| 	DMX_BUFFER_FLAG_HAD_CRC32_DISCARD		= 1 << 0, | ||||
| 	DMX_BUFFER_FLAG_TEI				= 1 << 1, | ||||
| 	DMX_BUFFER_PKT_COUNTER_MISMATCH			= 1 << 2, | ||||
| 	DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED		= 1 << 3, | ||||
| 	DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR		= 1 << 4, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmx_buffer - dmx buffer info | ||||
|  * | ||||
|  * @index:	id number of the buffer | ||||
|  * @bytesused:	number of bytes occupied by data in the buffer (payload); | ||||
|  * @offset:	for buffers with memory == DMX_MEMORY_MMAP; | ||||
|  *		offset from the start of the device memory for this plane, | ||||
|  *		(or a "cookie" that should be passed to mmap() as offset) | ||||
|  * @length:	size in bytes of the buffer | ||||
|  * @flags:	bit array of buffer flags as defined by &enum dmx_buffer_flags. | ||||
|  *		Filled only at &DMX_DQBUF. | ||||
|  * @count:	monotonic counter for filled buffers. Helps to identify | ||||
|  *		data stream loses. Filled only at &DMX_DQBUF. | ||||
|  * | ||||
|  * Contains data exchanged by application and driver using one of the streaming | ||||
|  * I/O methods. | ||||
|  * | ||||
|  * Please notice that, for &DMX_QBUF, only @index should be filled. | ||||
|  * On &DMX_DQBUF calls, all fields will be filled by the Kernel. | ||||
|  */ | ||||
| struct dmx_buffer { | ||||
| 	__u32			index; | ||||
| 	__u32			bytesused; | ||||
| 	__u32			offset; | ||||
| 	__u32			length; | ||||
| 	__u32			flags; | ||||
| 	__u32			count; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmx_requestbuffers - request dmx buffer information | ||||
|  * | ||||
|  * @count:	number of requested buffers, | ||||
|  * @size:	size in bytes of the requested buffer | ||||
|  * | ||||
|  * Contains data used for requesting a dmx buffer. | ||||
|  * All reserved fields must be set to zero. | ||||
|  */ | ||||
| struct dmx_requestbuffers { | ||||
| 	__u32			count; | ||||
| 	__u32			size; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct dmx_exportbuffer - export of dmx buffer as DMABUF file descriptor | ||||
|  * | ||||
|  * @index:	id number of the buffer | ||||
|  * @flags:	flags for newly created file, currently only O_CLOEXEC is | ||||
|  *		supported, refer to manual of open syscall for more details | ||||
|  * @fd:		file descriptor associated with DMABUF (set by driver) | ||||
|  * | ||||
|  * Contains data used for exporting a dmx buffer as DMABUF file descriptor. | ||||
|  * The buffer is identified by a 'cookie' returned by DMX_QUERYBUF | ||||
|  * (identical to the cookie used to mmap() the buffer to userspace). All | ||||
|  * reserved fields must be set to zero. The field reserved0 is expected to | ||||
|  * become a structure 'type' allowing an alternative layout of the structure | ||||
|  * content. Therefore this field should not be used for any other extensions. | ||||
|  */ | ||||
| struct dmx_exportbuffer { | ||||
| 	__u32		index; | ||||
| 	__u32		flags; | ||||
| 	__s32		fd; | ||||
| }; | ||||
|  | ||||
| #define DMX_START                _IO('o', 41) | ||||
| #define DMX_STOP                 _IO('o', 42) | ||||
| #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params) | ||||
| @@ -230,4 +321,10 @@ typedef struct dmx_filter dmx_filter_t; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif /* _UAPI_DVBDMX_H_ */ | ||||
| #define DMX_REQBUFS              _IOWR('o', 60, struct dmx_requestbuffers) | ||||
| #define DMX_QUERYBUF             _IOWR('o', 61, struct dmx_buffer) | ||||
| #define DMX_EXPBUF               _IOWR('o', 62, struct dmx_exportbuffer) | ||||
| #define DMX_QBUF                 _IOWR('o', 63, struct dmx_buffer) | ||||
| #define DMX_DQBUF                _IOWR('o', 64, struct dmx_buffer) | ||||
|  | ||||
| #endif /* _DVBDMX_H_ */ | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * frontend.h | ||||
|  * | ||||
| @@ -769,16 +770,15 @@ enum fecap_scale_params { | ||||
| /** | ||||
|  * struct dtv_stats - Used for reading a DTV status property | ||||
|  * | ||||
|  * @scale:	Filled with enum fecap_scale_params - the scale | ||||
|  *		in usage for that parameter | ||||
|  * @scale: | ||||
|  *    Filled with enum fecap_scale_params - the scale in usage | ||||
|  *    for that parameter | ||||
|  * | ||||
|  * The ``{unnamed_union}`` may have either one of the values below: | ||||
|  * | ||||
|  * %svalue | ||||
|  * @svalue: | ||||
|  *	integer value of the measure, for %FE_SCALE_DECIBEL, | ||||
|  *	used for dB measures. The unit is 0.001 dB. | ||||
|  * | ||||
|  * %uvalue | ||||
|  * @uvalue: | ||||
|  *	unsigned integer value of the measure, used when @scale is | ||||
|  *	either %FE_SCALE_RELATIVE or %FE_SCALE_COUNTER. | ||||
|  * | ||||
| @@ -844,16 +844,16 @@ struct dtv_fe_stats { | ||||
|  * @cmd:	Digital TV command. | ||||
|  * @reserved:	Not used. | ||||
|  * @u:		Union with the values for the command. | ||||
|  * @result:	Result of the command set (currently unused). | ||||
|  * @u.data:           A unsigned 32 bits integer with command value. | ||||
|  * @u.buffer:         Struct to store bigger properties. | ||||
|  *                    Currently unused. | ||||
|  * @u.buffer.data:    an unsigned 32-bits array. | ||||
|  * @u.buffer.len:     number of elements of the buffer. | ||||
|  * @u.buffer.reserved1:       Reserved. | ||||
|  * @u.buffer.reserved2:       Reserved. | ||||
|  * @u.st:             a &struct dtv_fe_stats array of statistics. | ||||
|  * @result:           Currently unused. | ||||
|  * | ||||
|  * The @u union may have either one of the values below: | ||||
|  * | ||||
|  * %data | ||||
|  *	an unsigned 32-bits number. | ||||
|  * %st | ||||
|  *	a &struct dtv_fe_stats array of statistics. | ||||
|  * %buffer | ||||
|  *	a buffer of up to 32 characters (currently unused). | ||||
|  */ | ||||
| struct dtv_property { | ||||
| 	__u32 cmd; | ||||
|   | ||||
| @@ -32,6 +32,23 @@ struct dvb_mod_channel_params { | ||||
| #define MODULATOR_GAIN           35 | ||||
| #define MODULATOR_RESET          36 | ||||
| #define MODULATOR_STATUS         37 | ||||
| #define MODULATOR_INFO           38 | ||||
| #define MODULATOR_OUTPUT_ARI     64 | ||||
| #define MODULATOR_OUTPUT_RATE    65 | ||||
|  | ||||
| enum mod_output_rate { | ||||
| 	SYS_DVBT_6 = 0, | ||||
| 	SYS_DVBT_7 = 1, | ||||
| 	SYS_DVBT_8 = 2, | ||||
| 	SYS_DVBC_6900 = 8, | ||||
| 	SYS_ISDBT_6 = 16, | ||||
| 	SYS_J83B_64_6 = 24, | ||||
| 	SYS_J83B_256_6 = 25, | ||||
| 	SYS_DVB_22 = 32, | ||||
| 	SYS_DVB_24 = 33, | ||||
| 	SYS_DVB_30 = 34, | ||||
| 	SYS_ISDBS_2886 = 48, | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif /*_UAPI_DVBMOD_H_*/ | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * net.h | ||||
|  * | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * osd.h | ||||
|  * osd.h - DEPRECATED On Screen Display API | ||||
|  * | ||||
|  * NOTE: should not be used on future drivers | ||||
|  * | ||||
|  * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de> | ||||
|  *                  & Marcus Metzler <marcus@convergence.de> | ||||
| @@ -26,79 +29,109 @@ | ||||
|  | ||||
| #include <linux/compiler.h> | ||||
|  | ||||
| #ifndef __user | ||||
| #define __user | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
|   // All functions return -2 on "not open" | ||||
|   OSD_Close=1,    // () | ||||
|   // Disables OSD and releases the buffers | ||||
|   // returns 0 on success | ||||
|   OSD_Open,       // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) | ||||
|   // Opens OSD with this size and bit depth | ||||
|   // returns 0 on success, -1 on DRAM allocation error, -2 on "already open" | ||||
|   OSD_Show,       // () | ||||
|   // enables OSD mode | ||||
|   // returns 0 on success | ||||
|   OSD_Hide,       // () | ||||
|   // disables OSD mode | ||||
|   // returns 0 on success | ||||
|   OSD_Clear,      // () | ||||
|   // Sets all pixel to color 0 | ||||
|   // returns 0 on success | ||||
|   OSD_Fill,       // (color) | ||||
|   // Sets all pixel to color <col> | ||||
|   // returns 0 on success | ||||
|   OSD_SetColor,   // (color,R{x0},G{y0},B{x1},opacity{y1}) | ||||
|   // set palette entry <num> to <r,g,b>, <mix> and <trans> apply | ||||
|   // R,G,B: 0..255 | ||||
|   // R=Red, G=Green, B=Blue | ||||
|   // opacity=0:      pixel opacity 0% (only video pixel shows) | ||||
|   // opacity=1..254: pixel opacity as specified in header | ||||
|   // opacity=255:    pixel opacity 100% (only OSD pixel shows) | ||||
|   // returns 0 on success, -1 on error | ||||
|   OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data) | ||||
|   // Set a number of entries in the palette | ||||
|   // sets the entries "firstcolor" through "lastcolor" from the array "data" | ||||
|   // data has 4 byte for each color: | ||||
|   // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel | ||||
|   OSD_SetTrans,   // (transparency{color}) | ||||
|   // Sets transparency of mixed pixel (0..15) | ||||
|   // returns 0 on success | ||||
|   OSD_SetPixel,   // (x0,y0,color) | ||||
|   // sets pixel <x>,<y> to color number <col> | ||||
|   // returns 0 on success, -1 on error | ||||
|   OSD_GetPixel,   // (x0,y0) | ||||
|   // returns color number of pixel <x>,<y>,  or -1 | ||||
|   OSD_SetRow,     // (x0,y0,x1,data) | ||||
|   // fills pixels x0,y through  x1,y with the content of data[] | ||||
|   // returns 0 on success, -1 on clipping all pixel (no pixel drawn) | ||||
|   OSD_SetBlock,   // (x0,y0,x1,y1,increment{color},data) | ||||
|   // fills pixels x0,y0 through  x1,y1 with the content of data[] | ||||
|   // inc contains the width of one line in the data block, | ||||
|   // inc<=0 uses blockwidth as linewidth | ||||
|   // returns 0 on success, -1 on clipping all pixel | ||||
|   OSD_FillRow,    // (x0,y0,x1,color) | ||||
|   // fills pixels x0,y through  x1,y with the color <col> | ||||
|   // returns 0 on success, -1 on clipping all pixel | ||||
|   OSD_FillBlock,  // (x0,y0,x1,y1,color) | ||||
|   // fills pixels x0,y0 through  x1,y1 with the color <col> | ||||
|   // returns 0 on success, -1 on clipping all pixel | ||||
|   OSD_Line,       // (x0,y0,x1,y1,color) | ||||
|   // draw a line from x0,y0 to x1,y1 with the color <col> | ||||
|   // returns 0 on success | ||||
|   OSD_Query,      // (x0,y0,x1,y1,xasp{color}}), yasp=11 | ||||
|   // fills parameters with the picture dimensions and the pixel aspect ratio | ||||
|   // returns 0 on success | ||||
|   OSD_Test,       // () | ||||
|   // draws a test picture. for debugging purposes only | ||||
|   // returns 0 on success | ||||
| // TODO: remove "test" in final version | ||||
|   OSD_Text,       // (x0,y0,size,color,text) | ||||
|   OSD_SetWindow, //  (x0) set window with number 0<x0<8 as current | ||||
|   OSD_MoveWindow, //  move current window to (x0, y0) | ||||
|   OSD_OpenRaw,	// Open other types of OSD windows | ||||
| 	/* All functions return -2 on "not open" */ | ||||
| 	OSD_Close = 1,	/* () */ | ||||
| 	/* | ||||
| 	 * Disables OSD and releases the buffers | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Open,	/* (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) */ | ||||
| 	/* | ||||
| 	 * Opens OSD with this size and bit depth | ||||
| 	 * returns 0 on success, -1 on DRAM allocation error, -2 on "already open" | ||||
| 	 */ | ||||
| 	OSD_Show,	/* () */ | ||||
| 	/* | ||||
| 	 * enables OSD mode | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Hide,	/* () */ | ||||
| 	/* | ||||
| 	 * disables OSD mode | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Clear,	/* () */ | ||||
| 	/* | ||||
| 	 * Sets all pixel to color 0 | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Fill,	/* (color) */ | ||||
| 	/* | ||||
| 	 * Sets all pixel to color <col> | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_SetColor,	/* (color,R{x0},G{y0},B{x1},opacity{y1}) */ | ||||
| 	/* | ||||
| 	 * set palette entry <num> to <r,g,b>, <mix> and <trans> apply | ||||
| 	 * R,G,B: 0..255 | ||||
| 	 * R=Red, G=Green, B=Blue | ||||
| 	 * opacity=0:      pixel opacity 0% (only video pixel shows) | ||||
| 	 * opacity=1..254: pixel opacity as specified in header | ||||
| 	 * opacity=255:    pixel opacity 100% (only OSD pixel shows) | ||||
| 	 * returns 0 on success, -1 on error | ||||
| 	 */ | ||||
| 	OSD_SetPalette,	/* (firstcolor{color},lastcolor{x0},data) */ | ||||
| 	/* | ||||
| 	 * Set a number of entries in the palette | ||||
| 	 * sets the entries "firstcolor" through "lastcolor" from the array "data" | ||||
| 	 * data has 4 byte for each color: | ||||
| 	 * R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel | ||||
| 	 */ | ||||
| 	OSD_SetTrans,	/* (transparency{color}) */ | ||||
| 	/* | ||||
| 	 * Sets transparency of mixed pixel (0..15) | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_SetPixel,	/* (x0,y0,color) */ | ||||
| 	/* | ||||
| 	 * sets pixel <x>,<y> to color number <col> | ||||
| 	 * returns 0 on success, -1 on error | ||||
| 	 */ | ||||
| 	OSD_GetPixel,	/* (x0,y0) */ | ||||
| 	/* returns color number of pixel <x>,<y>,  or -1 */ | ||||
| 	OSD_SetRow,	/* (x0,y0,x1,data) */ | ||||
| 	/* | ||||
| 	 * fills pixels x0,y through  x1,y with the content of data[] | ||||
| 	 * returns 0 on success, -1 on clipping all pixel (no pixel drawn) | ||||
| 	 */ | ||||
| 	OSD_SetBlock,	/* (x0,y0,x1,y1,increment{color},data) */ | ||||
| 	/* | ||||
| 	 * fills pixels x0,y0 through  x1,y1 with the content of data[] | ||||
| 	 * inc contains the width of one line in the data block, | ||||
| 	 * inc<=0 uses blockwidth as linewidth | ||||
| 	 * returns 0 on success, -1 on clipping all pixel | ||||
| 	 */ | ||||
| 	OSD_FillRow,	/* (x0,y0,x1,color) */ | ||||
| 	/* | ||||
| 	 * fills pixels x0,y through  x1,y with the color <col> | ||||
| 	 * returns 0 on success, -1 on clipping all pixel | ||||
| 	 */ | ||||
| 	OSD_FillBlock,	/* (x0,y0,x1,y1,color) */ | ||||
| 	/* | ||||
| 	 * fills pixels x0,y0 through  x1,y1 with the color <col> | ||||
| 	 * returns 0 on success, -1 on clipping all pixel | ||||
| 	 */ | ||||
| 	OSD_Line,	/* (x0,y0,x1,y1,color) */ | ||||
| 	/* | ||||
| 	 * draw a line from x0,y0 to x1,y1 with the color <col> | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Query,	/* (x0,y0,x1,y1,xasp{color}}), yasp=11 */ | ||||
| 	/* | ||||
| 	 * fills parameters with the picture dimensions and the pixel aspect ratio | ||||
| 	 * returns 0 on success | ||||
| 	 */ | ||||
| 	OSD_Test,       /* () */ | ||||
| 	/* | ||||
| 	 * draws a test picture. for debugging purposes only | ||||
| 	 * returns 0 on success | ||||
| 	 * TODO: remove "test" in final version | ||||
| 	 */ | ||||
| 	OSD_Text,	/* (x0,y0,size,color,text) */ | ||||
| 	OSD_SetWindow,	/* (x0) set window with number 0<x0<8 as current */ | ||||
| 	OSD_MoveWindow,	/* move current window to (x0, y0) */ | ||||
| 	OSD_OpenRaw,	/* Open other types of OSD windows */ | ||||
| } OSD_Command; | ||||
|  | ||||
| typedef struct osd_cmd_s { | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * version.h | ||||
|  * | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * video.h | ||||
|  * video.h - DEPRECATED MPEG-TS video decoder API | ||||
|  * | ||||
|  * NOTE: should not be used on future drivers | ||||
|  * | ||||
|  * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> | ||||
|  *                  & Ralph  Metzler <ralph@convergence.de> | ||||
| @@ -29,10 +32,6 @@ | ||||
| #include <time.h> | ||||
| #endif | ||||
|  | ||||
| #ifndef __user | ||||
| #define __user | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
| 	VIDEO_FORMAT_4_3,     /* Select 4:3 format */ | ||||
| 	VIDEO_FORMAT_16_9,    /* Select 16:9 format. */ | ||||
| @@ -40,18 +39,6 @@ typedef enum { | ||||
| } video_format_t; | ||||
|  | ||||
|  | ||||
| typedef enum { | ||||
| 	 VIDEO_SYSTEM_PAL, | ||||
| 	 VIDEO_SYSTEM_NTSC, | ||||
| 	 VIDEO_SYSTEM_PALN, | ||||
| 	 VIDEO_SYSTEM_PALNc, | ||||
| 	 VIDEO_SYSTEM_PALM, | ||||
| 	 VIDEO_SYSTEM_NTSC60, | ||||
| 	 VIDEO_SYSTEM_PAL60, | ||||
| 	 VIDEO_SYSTEM_PALM60 | ||||
| } video_system_t; | ||||
|  | ||||
|  | ||||
| typedef enum { | ||||
| 	VIDEO_PAN_SCAN,       /* use pan and scan format */ | ||||
| 	VIDEO_LETTER_BOX,     /* use letterbox format */ | ||||
| @@ -86,11 +73,11 @@ typedef enum { | ||||
| #define VIDEO_CMD_CONTINUE    (3) | ||||
|  | ||||
| /* Flags for VIDEO_CMD_FREEZE */ | ||||
| #define VIDEO_CMD_FREEZE_TO_BLACK     	(1 << 0) | ||||
| #define VIDEO_CMD_FREEZE_TO_BLACK	(1 << 0) | ||||
|  | ||||
| /* Flags for VIDEO_CMD_STOP */ | ||||
| #define VIDEO_CMD_STOP_TO_BLACK      	(1 << 0) | ||||
| #define VIDEO_CMD_STOP_IMMEDIATELY     	(1 << 1) | ||||
| #define VIDEO_CMD_STOP_TO_BLACK		(1 << 0) | ||||
| #define VIDEO_CMD_STOP_IMMEDIATELY	(1 << 1) | ||||
|  | ||||
| /* Play input formats: */ | ||||
| /* The decoder has no special format requirements */ | ||||
| @@ -127,8 +114,8 @@ struct video_command { | ||||
| /* FIELD_UNKNOWN can be used if the hardware does not know whether | ||||
|    the Vsync is for an odd, even or progressive (i.e. non-interlaced) | ||||
|    field. */ | ||||
| #define VIDEO_VSYNC_FIELD_UNKNOWN  	(0) | ||||
| #define VIDEO_VSYNC_FIELD_ODD 		(1) | ||||
| #define VIDEO_VSYNC_FIELD_UNKNOWN	(0) | ||||
| #define VIDEO_VSYNC_FIELD_ODD		(1) | ||||
| #define VIDEO_VSYNC_FIELD_EVEN		(2) | ||||
| #define VIDEO_VSYNC_FIELD_PROGRESSIVE	(3) | ||||
|  | ||||
| @@ -136,8 +123,8 @@ struct video_event { | ||||
| 	__s32 type; | ||||
| #define VIDEO_EVENT_SIZE_CHANGED	1 | ||||
| #define VIDEO_EVENT_FRAME_RATE_CHANGED	2 | ||||
| #define VIDEO_EVENT_DECODER_STOPPED 	3 | ||||
| #define VIDEO_EVENT_VSYNC 		4 | ||||
| #define VIDEO_EVENT_DECODER_STOPPED	3 | ||||
| #define VIDEO_EVENT_VSYNC		4 | ||||
| 	/* unused, make sure to use atomic time for y2038 if it ever gets used */ | ||||
| 	long timestamp; | ||||
| 	union { | ||||
| @@ -163,44 +150,6 @@ struct video_still_picture { | ||||
| }; | ||||
|  | ||||
|  | ||||
| typedef | ||||
| struct video_highlight { | ||||
| 	int     active;      /*    1=show highlight, 0=hide highlight */ | ||||
| 	__u8    contrast1;   /*    7- 4  Pattern pixel contrast */ | ||||
| 			     /*    3- 0  Background pixel contrast */ | ||||
| 	__u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */ | ||||
| 			     /*    3- 0  Emphasis pixel-1 contrast */ | ||||
| 	__u8    color1;      /*    7- 4  Pattern pixel color */ | ||||
| 			     /*    3- 0  Background pixel color */ | ||||
| 	__u8    color2;      /*    7- 4  Emphasis pixel-2 color */ | ||||
| 			     /*    3- 0  Emphasis pixel-1 color */ | ||||
| 	__u32    ypos;       /*   23-22  auto action mode */ | ||||
| 			     /*   21-12  start y */ | ||||
| 			     /*    9- 0  end y */ | ||||
| 	__u32    xpos;       /*   23-22  button color number */ | ||||
| 			     /*   21-12  start x */ | ||||
| 			     /*    9- 0  end x */ | ||||
| } video_highlight_t; | ||||
|  | ||||
|  | ||||
| typedef struct video_spu { | ||||
| 	int active; | ||||
| 	int stream_id; | ||||
| } video_spu_t; | ||||
|  | ||||
|  | ||||
| typedef struct video_spu_palette {      /* SPU Palette information */ | ||||
| 	int length; | ||||
| 	__u8 __user *palette; | ||||
| } video_spu_palette_t; | ||||
|  | ||||
|  | ||||
| typedef struct video_navi_pack { | ||||
| 	int length;          /* 0 ... 1024 */ | ||||
| 	__u8 data[1024]; | ||||
| } video_navi_pack_t; | ||||
|  | ||||
|  | ||||
| typedef __u16 video_attributes_t; | ||||
| /*   bits: descr. */ | ||||
| /*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ | ||||
| @@ -245,17 +194,9 @@ typedef __u16 video_attributes_t; | ||||
| #define VIDEO_SLOWMOTION           _IO('o', 32) | ||||
| #define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int) | ||||
| #define VIDEO_CLEAR_BUFFER         _IO('o',  34) | ||||
| #define VIDEO_SET_ID               _IO('o', 35) | ||||
| #define VIDEO_SET_STREAMTYPE       _IO('o', 36) | ||||
| #define VIDEO_SET_FORMAT           _IO('o', 37) | ||||
| #define VIDEO_SET_SYSTEM           _IO('o', 38) | ||||
| #define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t) | ||||
| #define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t) | ||||
| #define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t) | ||||
| #define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t) | ||||
| #define VIDEO_SET_ATTRIBUTES       _IO('o', 53) | ||||
| #define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t) | ||||
| #define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int) | ||||
|  | ||||
| /** | ||||
|  * VIDEO_GET_PTS | ||||
| @@ -271,9 +212,9 @@ typedef __u16 video_attributes_t; | ||||
| #define VIDEO_GET_PTS              _IOR('o', 57, __u64) | ||||
|  | ||||
| /* Read the number of displayed frames since the decoder was started */ | ||||
| #define VIDEO_GET_FRAME_COUNT  	   _IOR('o', 58, __u64) | ||||
| #define VIDEO_GET_FRAME_COUNT	   _IOR('o', 58, __u64) | ||||
|  | ||||
| #define VIDEO_COMMAND     	   _IOWR('o', 59, struct video_command) | ||||
| #define VIDEO_TRY_COMMAND 	   _IOWR('o', 60, struct video_command) | ||||
| #define VIDEO_COMMAND		   _IOWR('o', 59, struct video_command) | ||||
| #define VIDEO_TRY_COMMAND	   _IOWR('o', 60, struct video_command) | ||||
|  | ||||
| #endif /* _UAPI_DVBVIDEO_H_ */ | ||||
|   | ||||
| @@ -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,16 +46,21 @@ | ||||
| #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 | ||||
|  * should be smaller or equal to 32 | ||||
|  */ | ||||
| #define MAX_DELSYS	8 | ||||
| #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 | ||||
| 
 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user