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);
|
||||
@@ -1313,8 +1334,15 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
|
||||
uint8_t Id[8];
|
||||
uint32_t len, i, adr;
|
||||
|
||||
|
||||
|
||||
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];
|
||||
|
||||
fd = open("/dev/dvb/adapter0/mod0", O_RDONLY);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
get_property(fd, MODULATOR_STATUS, &data);
|
||||
printf("Modulator status = %u\n", data);
|
||||
set_property(fd, MODULATOR_STATUS, 2);
|
||||
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);
|
||||
|
||||
|
||||
//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);
|
||||
@@ -331,7 +329,7 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate)
|
||||
case DDB_CI_EXTERNAL_XO2_B:
|
||||
ci_xo2_attach(port);
|
||||
break;
|
||||
|
||||
|
||||
case DDB_CI_INTERNAL:
|
||||
ci_attach(port);
|
||||
break;
|
||||
|
||||
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,19 +902,22 @@ 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,
|
||||
u16 subvendor, u16 subdevice)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ddb_device_ids); i++) {
|
||||
const struct ddb_device_id *id = &ddb_device_ids[i];
|
||||
|
||||
|
||||
if (vendor == id->vendor &&
|
||||
device == id->device &&
|
||||
subvendor == id->subvendor &&
|
||||
(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;
|
||||
|
||||
if (!regmap || !regmap->mci)
|
||||
return -EINVAL;
|
||||
control = regmap->mci->base;
|
||||
vaddr = regmap->mci_buf->base + 0xf0;
|
||||
|
||||
ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL);
|
||||
ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */
|
||||
msleep(300);
|
||||
ddblwritel(link, 0, MCI_CONTROL);
|
||||
|
||||
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);
|
||||
|
||||
stat = wait_for_completion_timeout(&state->base->completion, HZ);
|
||||
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(&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;
|
||||
|
||||
return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32),
|
||||
res, sizeof(*result)/sizeof(u32));
|
||||
struct mci_result res;
|
||||
int stat;
|
||||
|
||||
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,15 +287,17 @@ 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,
|
||||
ROLLOFF_5, ROLLOFF_15, ROLLOFF_35, ROLLOFF_35
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
@@ -188,7 +368,7 @@ struct mci_command {
|
||||
u8 retry;
|
||||
u32 frequency;
|
||||
} dvbc_search;
|
||||
|
||||
|
||||
struct {
|
||||
u8 flags; /* Bit 0: LP Stream */
|
||||
u8 bandwidth;
|
||||
@@ -196,7 +376,7 @@ struct mci_command {
|
||||
u8 retry;
|
||||
u32 frequency;
|
||||
} dvbt_search;
|
||||
|
||||
|
||||
struct {
|
||||
u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */
|
||||
u8 bandwidth;
|
||||
@@ -207,7 +387,7 @@ struct mci_command {
|
||||
u8 plp;
|
||||
u8 rsvd2[3];
|
||||
} dvbt2_search;
|
||||
|
||||
|
||||
struct {
|
||||
u8 flags;
|
||||
u8 bandwidth;
|
||||
@@ -219,15 +399,39 @@ struct mci_command {
|
||||
u8 data_slice;
|
||||
u8 rsvd2[2];
|
||||
} dvbc2_search;
|
||||
|
||||
|
||||
struct {
|
||||
u8 flags;
|
||||
u8 flags;
|
||||
u8 bandwidth;
|
||||
u8 rsvd1;
|
||||
u8 retry;
|
||||
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;
|
||||
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 */
|
||||
@@ -288,12 +526,28 @@ struct mci_result {
|
||||
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;
|
||||
u32 ber_denominator;
|
||||
} 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,9 +589,10 @@ 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; //
|
||||
s16 channel_power; // channel power in dBm x 100
|
||||
@@ -344,12 +601,13 @@ struct mci_result {
|
||||
s16 rsvd2;
|
||||
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
|
||||
u32 ber_numerator; // Bit error rate: PreBCH
|
||||
u32 ber_denominator;
|
||||
u32 ber_denominator;
|
||||
} dvbc2_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
|
||||
@@ -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];
|
||||
@@ -385,9 +738,9 @@ struct mci_result {
|
||||
u8 L1P2ChangeCounter;
|
||||
u8 NumDataSlices;
|
||||
u8 NumNotches;
|
||||
struct {
|
||||
u8 Start[2];
|
||||
u8 Width[2];
|
||||
struct {
|
||||
u8 Start[2];
|
||||
u8 Width[2];
|
||||
u8 Reserved3;
|
||||
} NotchData[15];
|
||||
u8 ReservedTone;
|
||||
@@ -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)) {
|
||||
@@ -247,16 +327,15 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
|
||||
free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate;
|
||||
if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE)
|
||||
free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE;
|
||||
|
||||
|
||||
while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate)
|
||||
bits_per_symbol--;
|
||||
if (bits_per_symbol < 2) {
|
||||
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 |
|
||||
@@ -2635,8 +2650,9 @@ static int probe(struct cxd_state *state)
|
||||
status = readregsx(state, 0x00, 0xFD, &ChipID, 1);
|
||||
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,18 +447,13 @@ 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;
|
||||
|
||||
stat = read_reg(state, POWER_STATE_1 , &PowerState);
|
||||
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