mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
Compare commits
813 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da4938e3aa | |||
| 3439fd7725 | |||
| 818b9cb58d | |||
| 0bafbf534f | |||
| e5072debc0 | |||
| 2f49ece88c | |||
| 52b40198eb | |||
| 98f98fea0e | |||
| ccfdc2b984 | |||
| 9c920141ca | |||
| 6c2bbbe5b8 | |||
| 3eaae81e6a | |||
| aae6233b14 | |||
| c8f3c122af | |||
| 7258b32045 | |||
| c2a2a27500 | |||
| 847aa3c044 | |||
| 48d9945769 | |||
| 307ce85223 | |||
| 23b2e6d6a0 | |||
| 647e8d77c3 | |||
| 4943ea294a | |||
| 7118ecd9f5 | |||
| 02ded87d78 | |||
| 9698b87204 | |||
| 4d087a3b8c | |||
| a233c8a6f8 | |||
| e55ef2f0fb | |||
| a2f011f62d | |||
| 7250608d53 | |||
| 5e5ff60b21 | |||
| 060eac06b8 | |||
| dfde99c01e | |||
| 73f270d850 | |||
| 781177ea44 | |||
| 330f2c1821 | |||
| 3fc610f546 | |||
| c522f28d68 | |||
| 0fa14cca02 | |||
| ed14095a2f | |||
| 456886f4fb | |||
| abbb9e324a | |||
| e18b425f41 | |||
| 88e65b4db6 | |||
| f27b64b186 | |||
| 7478bcffb9 | |||
| 0d9b5ca619 | |||
| e9399971f8 | |||
| 626aa6d7be | |||
| 5bfa228d71 | |||
| 42df1e88d4 | |||
| 57101c22b7 | |||
| 37e423d19b | |||
| 17914cb451 | |||
| 25009b3afd | |||
| 58535dd4e3 | |||
| b51b7c0598 | |||
| e9ed73b929 | |||
| c0e174505a | |||
| 87478ec63a | |||
| 4f9cb2810e | |||
| 5988565066 | |||
|
|
6e4f8dc86b | ||
|
|
5d876b2615 | ||
|
|
2968f85c91 | ||
|
|
c008e44bf6 | ||
|
|
7e9650c841 | ||
|
|
a6565abde3 | ||
|
|
ee7c48e6ff | ||
|
|
6ce49ed990 | ||
|
|
0b36a69c44 | ||
|
|
e64ceb90fb | ||
|
|
efbf312d98 | ||
|
|
0c3c1f5753 | ||
|
|
4bf1f48926 | ||
|
|
7ce5232cd7 | ||
|
|
3f296bef62 | ||
|
|
ad01e9f508 | ||
|
|
e312df576c | ||
|
|
4b5cd433f9 | ||
|
|
6c068c0cc3 | ||
|
|
1488f326d0 | ||
|
|
c78905d4a2 | ||
|
|
7eb5c6e658 | ||
|
|
172c6c93ba | ||
|
|
0dd4f106ab | ||
|
|
60426304db | ||
|
|
177e71d62a | ||
|
|
cc03d96de2 | ||
|
|
6336bd3689 | ||
|
|
be79cec76e | ||
|
|
24801ab41a | ||
|
|
390f67c03b | ||
|
|
fa4e3331d8 | ||
|
|
29cc552a6b | ||
|
|
42a0b65235 | ||
|
|
b8abf46d06 | ||
|
|
ce06e50881 | ||
|
|
22ffb0ecac | ||
|
|
92f2132d79 | ||
|
|
727fba48be | ||
|
|
09e8a15d78 | ||
|
|
45c9f076bd | ||
|
|
5c2757d581 | ||
|
|
817a464f4a | ||
|
|
d627e6995f | ||
|
|
c8c1ee1835 | ||
|
|
002f39787a | ||
|
|
871821d6a0 | ||
|
|
2a88d220e4 | ||
|
|
457cb550bb | ||
|
|
ffe8764c01 | ||
|
|
0892a225d2 | ||
|
|
431dd4f5ee | ||
|
|
cdc5395996 | ||
|
|
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 | ||
|
|
8bda007f05 | ||
|
|
b606a7b2b2 | ||
|
|
3757c4671e | ||
|
|
719ac4d231 | ||
|
|
a3c6b5acc1 | ||
|
|
eeb013e0fa | ||
|
|
7f40a54b39 | ||
|
|
1518ba54a4 | ||
|
|
a97787c3b6 | ||
|
|
d676919e72 | ||
|
|
19eea5d42d | ||
|
|
b23187a049 | ||
|
|
0165538f13 | ||
|
|
0b9d3ffa6b | ||
|
|
61fd25836f | ||
|
|
d4aa1c634e | ||
|
|
5bb0a95b02 | ||
|
|
0a5fb7d6b9 | ||
|
|
fd21dbbd5e | ||
|
|
f7fcc1511d | ||
|
|
37ae102d57 | ||
|
|
66b1cf3623 | ||
|
|
7f002f1356 | ||
|
|
418bd83b40 | ||
|
|
442b1c3bf6 | ||
|
|
c23435e275 | ||
|
|
8f5af7742d | ||
|
|
309713674c | ||
|
|
2b0e5eb9d2 | ||
|
|
3ff4d900a5 | ||
|
|
e1e569975f | ||
|
|
b9998ee9e2 | ||
|
|
dfe6b385a9 | ||
|
|
6e926c1452 | ||
|
|
8039097426 | ||
|
|
f3d5adc777 | ||
|
|
e974925430 | ||
|
|
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 | ||
|
|
ce99c601f8 | ||
|
|
43ab548777 | ||
|
|
2808cf0d50 | ||
|
|
186ba6d414 | ||
|
|
f570b2e071 | ||
|
|
32f46389be | ||
|
|
4b68bcad91 | ||
|
|
1ad4dfacd1 | ||
|
|
f7772c7a88 | ||
|
|
6219e19ece | ||
|
|
192a4ad20d | ||
|
|
e13cec82e4 | ||
|
|
d13416157c | ||
|
|
755f502602 | ||
|
|
a05d1852a3 | ||
|
|
1e15f5474d | ||
|
|
9c1fc648dc | ||
|
|
2e5056c4a1 | ||
|
|
1b89edb4b1 | ||
|
|
875a768266 | ||
|
|
09c068c74c | ||
|
|
c471123f17 | ||
|
|
8dbd33fd82 | ||
|
|
a978e9455f | ||
|
|
9d8c7d4a63 | ||
|
|
81ed8fed9d | ||
|
|
f24a329f2f | ||
|
|
5d7f4fcbe8 | ||
|
|
6243397d99 | ||
|
|
5b86ac7627 | ||
|
|
c831ccfc9e | ||
|
|
cad161f939 | ||
|
|
67257ce132 | ||
|
|
bdea58c1b2 | ||
|
|
29eda9be8e | ||
|
|
2c3c9bdf08 | ||
|
|
2693c181bc | ||
|
|
53464162de | ||
|
|
8cbb835de0 | ||
|
|
d0f7b9be1f | ||
|
|
6b0feea253 | ||
|
|
bed4be534a | ||
|
|
1d7d8bc413 | ||
|
|
70778b818e | ||
|
|
e0fdedbef3 | ||
|
|
9acbf467ec | ||
|
|
3db30defab | ||
|
|
5bf9edba06 | ||
|
|
8f0365e36a | ||
|
|
08a161ba04 | ||
|
|
efbc108939 | ||
|
|
033432cf2f | ||
|
|
948c6c4fe7 | ||
|
|
dedb5bd387 | ||
|
|
991393950b | ||
|
|
ae9644d934 | ||
|
|
9cc6942c07 | ||
|
|
67e36cdef0 | ||
|
|
4f622ec27c | ||
|
|
e7d9457ef8 | ||
|
|
00a3e78f69 | ||
|
|
fc335de763 | ||
|
|
62e491c2cd | ||
|
|
402a822751 | ||
|
|
e19f29dbfa | ||
|
|
caa1dbecce | ||
|
|
642a010be6 | ||
|
|
94dfd16461 | ||
|
|
a6b6e3be29 | ||
|
|
4f136e5659 | ||
|
|
bda6c538ae | ||
|
|
2eb3b3e723 | ||
|
|
2e1c7b62a9 | ||
|
|
6001c5baf5 | ||
|
|
02b292987b | ||
|
|
4ebb3ca938 | ||
|
|
c5b45cdbac | ||
|
|
23826d9981 | ||
|
|
da3539c994 | ||
|
|
db463d0839 | ||
|
|
c07e4bebbd | ||
|
|
dfff0f5953 | ||
|
|
d87246de12 | ||
|
|
b54e6ed689 | ||
|
|
3b44e78bd0 | ||
|
|
f7fbeed21e | ||
|
|
a14cbc0eff | ||
|
|
2d41161cb4 | ||
|
|
c75a7892d9 | ||
|
|
d5bbd3a025 | ||
|
|
096bf9d5a9 | ||
|
|
3806b4d2da | ||
|
|
b42358eaa2 | ||
|
|
04fc90e4d6 | ||
|
|
50cf06cbb8 | ||
|
|
d398909c1d | ||
|
|
b814026565 | ||
|
|
611065f572 | ||
|
|
eabde4ab5a | ||
|
|
efd5070f76 | ||
|
|
ea09ce3b7b | ||
|
|
de27043d42 | ||
|
|
f7e8b25e02 | ||
|
|
c56e156176 | ||
|
|
6f164f38d8 | ||
|
|
ca3c26808f | ||
|
|
9e5576c562 | ||
|
|
021eae2eac | ||
|
|
b7c9038f51 | ||
|
|
a385bcb70c | ||
|
|
7bb6cf99e2 | ||
|
|
7e6f9d6e9d | ||
|
|
e239a6d772 | ||
|
|
3a2e87eefe | ||
|
|
0f05b1988a | ||
|
|
4a93f79093 | ||
|
|
8fa925317c | ||
|
|
0f4beb4e64 | ||
|
|
6ca3e2f2b3 | ||
|
|
249b1e0b40 | ||
|
|
4a137b3d1a | ||
|
|
20d4867869 | ||
|
|
8a1f27c3d2 | ||
|
|
3778a64de5 | ||
|
|
6bdfe43958 | ||
|
|
83000cd73a | ||
|
|
b5ae7ac76f | ||
|
|
872f99fbbe | ||
|
|
1c22a07eaa | ||
|
|
f84d196a1e | ||
|
|
41897e48c8 | ||
|
|
4765eac57a | ||
|
|
7756a09420 | ||
|
|
92b64711ec | ||
|
|
e817b91860 | ||
|
|
b814cf09e4 | ||
|
|
0dd0997133 | ||
|
|
983949f4dd | ||
|
|
fe5f6b737c | ||
|
|
3e67af1b5b | ||
|
|
e4acb524a7 | ||
|
|
aa2762747f | ||
|
|
117d9a065d | ||
|
|
17b3e1ed26 | ||
|
|
07f7720145 | ||
|
|
b2ca06e639 | ||
|
|
2b6babfdc0 | ||
|
|
5074e28e10 | ||
|
|
df4f23384b | ||
|
|
838eb620ba | ||
|
|
e55dcd2fd2 | ||
|
|
27601b4769 | ||
|
|
5751c3fb1a | ||
|
|
5c032058b9 | ||
|
|
a44dbc889b | ||
|
|
3d5fae7dd8 | ||
|
|
7602ecf3e5 | ||
|
|
bf0315bcc0 | ||
|
|
dcddb3437d | ||
|
|
665b5ef857 | ||
|
|
c063cffa63 | ||
|
|
640c15f4a7 | ||
|
|
d3ca949ec5 | ||
|
|
fd41904378 | ||
|
|
eb81f006e4 | ||
|
|
af554da865 | ||
|
|
d6f56c1807 | ||
|
|
31f22ef4de | ||
|
|
d4d0a9b84e | ||
|
|
24503d35ad | ||
|
|
3556d6464b | ||
|
|
862c7bfc60 | ||
|
|
fd21584ecc | ||
|
|
6814a8fa23 | ||
|
|
49d4bd0da8 | ||
|
|
6d1cfd4cd2 | ||
|
|
e68ce2ef62 | ||
|
|
023ae44411 | ||
|
|
7222bd58b3 | ||
|
|
f404b3fb6d | ||
|
|
de34e2ebbd | ||
|
|
774e92bd44 | ||
|
|
8c46d9a86a | ||
|
|
452771913e | ||
|
|
3285b6ade0 | ||
|
|
e6dd33deec | ||
|
|
93e42deeaa | ||
|
|
e415b6e203 | ||
|
|
1354b9021f | ||
|
|
4d17f2f5f0 | ||
|
|
5fa08eb288 | ||
|
|
933779aa24 | ||
|
|
01d35aad26 | ||
|
|
40c32767ec | ||
|
|
8704ceaf94 | ||
|
|
12b792ef3f | ||
|
|
3063b8e88b | ||
|
|
7d73553b61 | ||
|
|
5d4259f6f6 | ||
|
|
04294ab5ef | ||
|
|
4699a19bfb | ||
|
|
f44a9dfcbd | ||
|
|
b3b7a0ef2e | ||
|
|
8a98bd88cd | ||
|
|
bfd1f1979d | ||
|
|
8931ae4d9e | ||
|
|
4070713556 | ||
|
|
bba5fa5683 | ||
|
|
ae37a1e4e9 | ||
|
|
2aee51e447 | ||
|
|
264f08fbad | ||
|
|
6830f4df08 | ||
|
|
785d7c5126 | ||
|
|
52b81cfd8e | ||
|
|
263d593bcf | ||
|
|
f56ec446ae | ||
|
|
fa36763d43 | ||
|
|
08a6d78da7 | ||
|
|
b3806c61ce | ||
|
|
eb6652f18f | ||
|
|
21c69918d3 | ||
|
|
326e928f66 | ||
|
|
0e09153b1f | ||
|
|
adf4e40256 | ||
|
|
9dcd81fe42 | ||
|
|
a7ce2ef8da | ||
|
|
285d7aed49 | ||
|
|
9eb5458eeb | ||
|
|
d51a9db022 | ||
|
|
532afaa97c | ||
|
|
1984377f72 | ||
|
|
37de742aad | ||
|
|
4bfdb11762 | ||
|
|
1e99122d52 | ||
|
|
cd5de95023 | ||
|
|
c56f593a4c | ||
|
|
3a3a48654e | ||
|
|
1a80437b98 | ||
|
|
28a2aaa653 | ||
|
|
f6c7586815 | ||
|
|
d069dc051f | ||
|
|
9392ccec22 | ||
|
|
4c276fbc75 | ||
|
|
7cc9107597 | ||
|
|
1f77192d62 | ||
|
|
fc4a807b4e | ||
|
|
b6d5976e14 | ||
|
|
101289c77e | ||
|
|
26eedb3d26 | ||
|
|
d1387078f1 | ||
|
|
6bf258b54c | ||
|
|
4435efeab5 | ||
|
|
633797e05f | ||
|
|
4ee27ff317 | ||
|
|
7d7da35fb5 | ||
|
|
a3b517391a | ||
|
|
1171b345df | ||
|
|
7f746f0219 | ||
|
|
49a05e75af | ||
|
|
c546918e79 | ||
|
|
570a565f37 | ||
|
|
85b1447059 | ||
|
|
a4c275895d | ||
|
|
7a8d3f80c4 | ||
|
|
7db462ca68 | ||
|
|
cd229fabf5 | ||
|
|
5252c5318d | ||
|
|
95b9a644b6 | ||
|
|
4f452819df | ||
|
|
f20b16cd12 | ||
|
|
1f4ae2bd51 | ||
|
|
2ec7863b04 | ||
|
|
fb022009ee | ||
|
|
a98a7c95a8 | ||
|
|
bb191aa5d7 | ||
|
|
38f0e9611e | ||
|
|
4ed35e1de5 | ||
|
|
1567d804b1 | ||
|
|
8c82d0166c | ||
|
|
5c7b55490a | ||
|
|
e2db17b04e | ||
|
|
a1221c6e4e | ||
|
|
86d9ce8f11 | ||
|
|
f2091a50df | ||
|
|
131aaf361e | ||
|
|
c929aea04d | ||
|
|
16c0834b78 | ||
|
|
50fee67d49 | ||
|
|
9d0400d81a | ||
|
|
6f071763c3 | ||
|
|
98bdb95193 | ||
|
|
2c8fcc1df5 | ||
|
|
805a3ffeed | ||
|
|
ffdcd91a06 | ||
|
|
b36a6392cc | ||
|
|
0d27002a17 | ||
|
|
094e1f3e1f | ||
|
|
2d71c946d3 | ||
|
|
39ce49dbd8 | ||
|
|
8908df8098 | ||
|
|
421adf6872 | ||
|
|
154794ac51 | ||
|
|
6b73faeee5 | ||
|
|
80e0750c71 | ||
|
|
65f9f56cfe | ||
|
|
53c32d47e0 | ||
|
|
4db55036f3 | ||
|
|
eda007e71a | ||
|
|
6975dfdd5a | ||
|
|
0c6336292e | ||
|
|
a456f8d5d9 | ||
|
|
a8d5d5b50d | ||
|
|
d988c8562b | ||
|
|
aaf5707c45 | ||
|
|
1e9b7dc5cc | ||
|
|
40edadad3d | ||
|
|
535ffa6ca6 | ||
|
|
1b0df5fcfa | ||
|
|
5633c2f79d | ||
|
|
74f172a4fe | ||
|
|
cc6209af33 | ||
|
|
de16096894 | ||
|
|
a4062a1582 | ||
|
|
d180cb70e2 | ||
|
|
30ca8e9962 | ||
|
|
4591bab46b | ||
|
|
3c6028f485 | ||
|
|
6a49ab08ab | ||
|
|
8f30246ff1 | ||
|
|
92d8b37839 | ||
|
|
66c912d874 | ||
|
|
0b4d6d807a | ||
|
|
c4133d98c1 | ||
|
|
f111d6e097 | ||
|
|
7860d623e8 | ||
|
|
ab25eeefdf | ||
|
|
64f21d8f99 | ||
|
|
faee02e446 | ||
|
|
6d80791077 | ||
|
|
1d3bb91eb8 | ||
|
|
c18503fcad | ||
|
|
906efafd5e | ||
|
|
b479d9cdc2 | ||
|
|
6038e87250 | ||
|
|
1b0e822b07 | ||
|
|
cdaf838cb1 | ||
|
|
19fd6f1b26 | ||
|
|
472cacb0c4 | ||
|
|
fa66a70a35 | ||
|
|
b5a44d581d | ||
|
|
e8eaf4660c | ||
|
|
81966f8982 | ||
|
|
dd540699c3 | ||
|
|
a8ed36fef2 | ||
|
|
9ab1b7f533 | ||
|
|
197897731e | ||
|
|
781686c87d | ||
|
|
b354113d15 | ||
|
|
8d0bb02239 |
@@ -1,3 +1,10 @@
|
||||
0.9.29 compiles with most kernels up to 4.11.1
|
||||
|
||||
see git commit messages for newer changes
|
||||
|
||||
0.9.24 2016.08.03
|
||||
- suport new V2 modulator cards
|
||||
|
||||
0.9.19c 2015.07.20
|
||||
- MAX S8:
|
||||
do not turn on diseqc and tuners on init
|
||||
|
||||
339
COPYING.GPLv2
Normal file
339
COPYING.GPLv2
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
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
|
||||
33
Makefile
33
Makefile
@@ -1,19 +1,40 @@
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
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
|
||||
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 */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
|
||||
rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
|
||||
$(MAKE) -C apps clean
|
||||
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -1,10 +1,19 @@
|
||||
# DDBridge Driver
|
||||
|
||||
###Prepare for Building
|
||||
### Patches
|
||||
We can only accept patches which don't break compilation for older kernels (as far back as 2.6.37).
|
||||
|
||||
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
|
||||
|
||||
###Building
|
||||
### Building
|
||||
|
||||
TBD
|
||||
|
||||
|
||||
@@ -1,19 +1,34 @@
|
||||
all: cit citin flashprog modt ddtest setmod ddflash
|
||||
TARGETS = cit ddtest setmod1 setmod2 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
|
||||
gcc -o cit cit.c -lpthread
|
||||
$(CC) -o cit cit.c -lpthread
|
||||
|
||||
modt: modt.c
|
||||
gcc -o modt modt.c -lpthread
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@
|
||||
|
||||
setmod: setmod.c
|
||||
gcc -o setmod setmod.c -I../include/
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -I../ddbridge -o $@ $<
|
||||
|
||||
flashprog: flashprog.c
|
||||
gcc -o flashprog flashprog.c
|
||||
|
||||
ddtest: ddtest.c
|
||||
gcc -o ddtest ddtest.c
|
||||
|
||||
ddflash: ddflash.c
|
||||
gcc -o ddflash ddflash.c
|
||||
clean:
|
||||
rm test.ts -f
|
||||
for f in $(TARGETS) *.o *~ ; do \
|
||||
if [ -e "$$f" ]; then \
|
||||
rm "$$f" || exit 1; \
|
||||
fi \
|
||||
done
|
||||
|
||||
116
apps/cit.c
116
apps/cit.c
@@ -9,6 +9,9 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <pthread.h>
|
||||
#include <getopt.h>
|
||||
|
||||
uint32_t adapter = 0, device = 0, snum = 256, rnum = 256;
|
||||
|
||||
uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
@@ -24,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,
|
||||
@@ -37,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)
|
||||
{
|
||||
@@ -68,24 +87,39 @@ void proc_buf(uint8_t *buf, uint32_t *d)
|
||||
} else {
|
||||
if (memcmp(ts+8, buf+8, 180))
|
||||
printf("error\n");
|
||||
if (!(c&0xffff))
|
||||
printf("R %08x\n", c);
|
||||
if (!(c&0xffff)) {
|
||||
printf("R %08x\r", c);
|
||||
fflush(0);
|
||||
}
|
||||
}
|
||||
(*d)++;
|
||||
}
|
||||
|
||||
void *get_ts(void *a)
|
||||
{
|
||||
uint8_t buf[188*1024];
|
||||
uint8_t *buf;
|
||||
int len, off;
|
||||
|
||||
int fdi=open("/dev/dvb/adapter2/ci0", O_RDONLY);
|
||||
int fdi;
|
||||
char fname[80];
|
||||
uint32_t d=0;
|
||||
|
||||
buf = malloc(188*rnum);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
sprintf(fname, "/dev/dvb/adapter%u/ci%u", adapter, device);
|
||||
printf("using %s for reading\n", fname);
|
||||
fdi = open(fname, O_RDONLY);
|
||||
if (fdi == -1) {
|
||||
printf("Failed to open %s for read: %m\n", fname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
len=read(fdi, buf, 188*1024);
|
||||
memset(buf, 0, 188*rnum);
|
||||
len=read(fdi, buf, 188*rnum);
|
||||
if (len<0)
|
||||
continue;
|
||||
//printf("read %u\n", len);
|
||||
if (buf[0]!=0x47) {
|
||||
read(fdi, buf, 1);
|
||||
continue;
|
||||
@@ -96,20 +130,28 @@ void *get_ts(void *a)
|
||||
}
|
||||
}
|
||||
|
||||
#define SNUM 233
|
||||
//671
|
||||
void send(void)
|
||||
|
||||
int send(void)
|
||||
{
|
||||
uint8_t buf[188*SNUM], *cts;
|
||||
uint8_t *buf, *cts;
|
||||
int i;
|
||||
uint32_t c=0;
|
||||
int fdo;
|
||||
|
||||
fdo=open("/dev/dvb/adapter2/ci0", O_WRONLY);
|
||||
|
||||
char fname[80];
|
||||
|
||||
buf = malloc(188*snum);
|
||||
if (!buf)
|
||||
return -1;
|
||||
sprintf(fname, "/dev/dvb/adapter%u/ci%u", adapter, device);
|
||||
printf("using %s for writing\n", fname);
|
||||
fdo=open(fname, O_WRONLY);
|
||||
if (fdo == -1) {
|
||||
printf("Failed to open %s to write: %m\n", fname);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
for (i=0; i<SNUM; i++) {
|
||||
for (i=0; i<snum; i++) {
|
||||
cts=buf+i*188;
|
||||
memcpy(cts, ts, 188);
|
||||
cts[4]=(c>>24);
|
||||
@@ -122,15 +164,57 @@ void send(void)
|
||||
//usleep(100000+0xffff&rand());
|
||||
//usleep(1000);
|
||||
}
|
||||
write(fdo, buf, 188*SNUM);
|
||||
write(fdo, buf, 188*snum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"adapter", required_argument, 0, 'a'},
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"snum", required_argument, 0, 's'},
|
||||
{"rnum", required_argument, 0, 'r'},
|
||||
{"help", no_argument , 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv,
|
||||
"a:d:h",
|
||||
long_options, &option_index);
|
||||
if (c==-1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
device = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'a':
|
||||
adapter = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 's':
|
||||
snum = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'r':
|
||||
rnum = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'h':
|
||||
printf("cit -a<adapter> -d<device>\n");
|
||||
exit(-1);
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
printf("Warning: unused arguments\n");
|
||||
}
|
||||
printf("adapter %d, device: %d\n", adapter, device);
|
||||
memset(ts+8, 180, 0x5a);
|
||||
pthread_create(&th, NULL, get_ts, NULL);
|
||||
usleep(10000);
|
||||
|
||||
61
apps/citin.c
61
apps/citin.c
@@ -1,61 +0,0 @@
|
||||
#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>
|
||||
|
||||
void proc_ts(int i, uint8_t *buf)
|
||||
{
|
||||
uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
|
||||
|
||||
if (buf[3]&0xc0) /* only descrambled packets */
|
||||
return;
|
||||
/* only ORF */
|
||||
if (pid==160 || pid==161 || pid==1001||pid==13001 || pid==0)
|
||||
write(1, buf, 188);
|
||||
}
|
||||
|
||||
#define TSBUFSIZE (100*188)
|
||||
|
||||
void citest()
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint8_t id;
|
||||
int i, nts;
|
||||
int len;
|
||||
int ts=open("/dev/dvb/adapter4/ci0", 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()
|
||||
{
|
||||
citest();
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#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>
|
||||
|
||||
#define TSBUFSIZE (100*188)
|
||||
|
||||
void citest()
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint8_t id;
|
||||
int i, nts;
|
||||
int len;
|
||||
int ts0=open("/dev/dvb/adapter0/dvr0", O_RDONLY);
|
||||
int ts1=open("/dev/dvb/adapter4/sec0", O_WRONLY);
|
||||
int demux0=open("/dev/dvb/adapter0/demux0", O_RDWR);
|
||||
|
||||
struct dmx_pes_filter_params pesFilterParams;
|
||||
|
||||
pesFilterParams.input = DMX_IN_FRONTEND;
|
||||
pesFilterParams.output = DMX_OUT_TS_TAP;
|
||||
pesFilterParams.pes_type = DMX_PES_OTHER;
|
||||
pesFilterParams.flags = DMX_IMMEDIATE_START;
|
||||
|
||||
pesFilterParams.pid = 8192;
|
||||
if (ioctl(demux0, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
|
||||
printf("Could not set PES filter\n");
|
||||
return;
|
||||
}
|
||||
buf=(uint8_t *)malloc(TSBUFSIZE);
|
||||
|
||||
while(1) {
|
||||
len=read(ts0, buf, TSBUFSIZE);
|
||||
if (len<=0)
|
||||
break;
|
||||
if (buf[0]!=0x47)
|
||||
printf("oops\n");
|
||||
write(ts1, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
citest();
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
octonet/ddflash.c
|
||||
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 MX_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 MX_MODE_DVBT:
|
||||
printf("Locked DVB-T\n");
|
||||
break;
|
||||
case MX_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 */
|
||||
}
|
||||
}
|
||||
1
apps/flash.c
Symbolic link
1
apps/flash.c
Symbolic link
@@ -0,0 +1 @@
|
||||
./octonet/flash.c
|
||||
722
apps/flashprog.c
722
apps/flashprog.c
@@ -1,722 +0,0 @@
|
||||
/*
|
||||
/* flashprog - Programmer for flash on Digital Devices Octopus
|
||||
*
|
||||
* Copyright (C) 2010-2011 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
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DDB_MAGIC 'd'
|
||||
|
||||
static uint32_t linknr = 0;
|
||||
|
||||
struct ddb_id {
|
||||
__u16 vendor;
|
||||
__u16 device;
|
||||
__u16 subvendor;
|
||||
__u16 subdevice;
|
||||
__u32 hw;
|
||||
__u32 regmap;
|
||||
};
|
||||
|
||||
struct ddb_flashio {
|
||||
__u8 *write_buf;
|
||||
__u32 write_len;
|
||||
__u8 *read_buf;
|
||||
__u32 read_len;
|
||||
__u32 link;
|
||||
};
|
||||
|
||||
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
|
||||
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
|
||||
|
||||
|
||||
int flashio(int ddb, uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen)
|
||||
{
|
||||
struct ddb_flashio fio = {
|
||||
.write_buf=wbuf,
|
||||
.write_len=wlen,
|
||||
.read_buf=rbuf,
|
||||
.read_len=rlen,
|
||||
.link=linknr,
|
||||
};
|
||||
|
||||
return ioctl(ddb, IOCTL_DDB_FLASHIO, &fio);
|
||||
}
|
||||
|
||||
enum {
|
||||
UNKNOWN_FLASH = 0,
|
||||
ATMEL_AT45DB642D = 1,
|
||||
SSTI_SST25VF016B = 2,
|
||||
SSTI_SST25VF032B = 3,
|
||||
SSTI_SST25VF064C = 4,
|
||||
SPANSION_S25FL116K = 5,
|
||||
};
|
||||
|
||||
|
||||
int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
|
||||
{
|
||||
uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff,
|
||||
(addr >> 8) & 0xff, addr & 0xff};
|
||||
|
||||
return flashio(ddb, cmd, 4, buf, len);
|
||||
}
|
||||
|
||||
int flashdump(int ddb, uint32_t addr, uint32_t len)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t buf[32];
|
||||
int bl = sizeof(buf);
|
||||
|
||||
for (j=0; j<len; j+=bl, addr+=bl) {
|
||||
flashread(ddb, buf, addr, bl);
|
||||
for (i=0; i<bl; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FlashDetect(int dev)
|
||||
{
|
||||
uint8_t Cmd = 0x9F;
|
||||
uint8_t Id[3];
|
||||
|
||||
int r = flashio(dev, &Cmd,1,Id,3);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x41 )
|
||||
r = SSTI_SST25VF016B;
|
||||
else if( Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x4A )
|
||||
r = SSTI_SST25VF032B;
|
||||
else if( Id[0] == 0x1F && Id[1] == 0x28 )
|
||||
r = ATMEL_AT45DB642D;
|
||||
else if( Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x4B )
|
||||
r = SSTI_SST25VF064C;
|
||||
else if( Id[0] == 0x01 && Id[1] == 0x40 && Id[2] == 0x15 )
|
||||
r = SPANSION_S25FL116K;
|
||||
else
|
||||
r = UNKNOWN_FLASH;
|
||||
|
||||
switch(r) {
|
||||
case UNKNOWN_FLASH:
|
||||
printf("Unknown Flash Flash ID = %02x %02x %02x\n",Id[0],Id[1],Id[2]);
|
||||
break;
|
||||
case ATMEL_AT45DB642D:
|
||||
printf("Flash: Atmel AT45DB642D 64 MBit\n");
|
||||
break;
|
||||
case SSTI_SST25VF016B:
|
||||
printf("Flash: SSTI SST25VF016B 16 MBit\n");
|
||||
break;
|
||||
case SSTI_SST25VF032B:
|
||||
printf("Flash: SSTI SST25VF032B 32 MBit\n"); break;
|
||||
case SSTI_SST25VF064C:
|
||||
printf("Flash: SSTI SST25VF064C 64 MBit\n"); break;
|
||||
case SPANSION_S25FL116K:
|
||||
printf("Flash: SPANSION S25FL116K 16 MBit\n"); break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int FlashWriteAtmel(int dev,uint32_t FlashOffset, uint8_t *Buffer,int BufferSize)
|
||||
{
|
||||
int err = 0;
|
||||
int BlockErase = BufferSize >= 8192;
|
||||
int i;
|
||||
|
||||
if (BlockErase) {
|
||||
for(i = 0; i < BufferSize; i += 8192 ) {
|
||||
uint8_t Cmd[4];
|
||||
if( (i & 0xFFFF) == 0 )
|
||||
printf(" Erase %08x\n",FlashOffset + i);
|
||||
Cmd[0] = 0x50; // Block Erase
|
||||
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
|
||||
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
|
||||
Cmd[3] = 0x00;
|
||||
err = flashio(dev,Cmd,4,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
Cmd[0] = 0xD7; // Read Status register
|
||||
err = flashio(dev,Cmd,1,&Cmd[0],1);
|
||||
if( err < 0 ) break;
|
||||
if( (Cmd[0] & 0x80) == 0x80 ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < BufferSize; i += 1024 )
|
||||
{
|
||||
uint8_t Cmd[4 + 1024];
|
||||
if( (i & 0xFFFF) == 0 )
|
||||
{
|
||||
printf(" Program %08x\n",FlashOffset + i);
|
||||
}
|
||||
Cmd[0] = 0x84; // Buffer 1
|
||||
Cmd[1] = 0x00;
|
||||
Cmd[2] = 0x00;
|
||||
Cmd[3] = 0x00;
|
||||
memcpy(&Cmd[4],&Buffer[i],1024);
|
||||
|
||||
err = flashio(dev,Cmd,4 + 1024,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
Cmd[0] = BlockErase ? 0x88 : 0x83; // Buffer to Main Memory (with Erase)
|
||||
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
|
||||
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
|
||||
Cmd[3] = 0x00;
|
||||
|
||||
err = flashio(dev,Cmd,4,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
Cmd[0] = 0xD7; // Read Status register
|
||||
err = flashio(dev,Cmd,1,&Cmd[0],1);
|
||||
if( err < 0 ) break;
|
||||
if( (Cmd[0] & 0x80) == 0x80 ) break;
|
||||
}
|
||||
if( err < 0 ) break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int FlashWritePageMode(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize, uint8_t LockBits)
|
||||
{
|
||||
int err = 0, i, j;
|
||||
uint8_t Cmd[260];
|
||||
|
||||
if( (BufferSize % 4096) != 0 )
|
||||
return -1; // Must be multiple of sector size
|
||||
|
||||
do {
|
||||
Cmd[0] = 0x50; // EWSR
|
||||
err = flashio(dev, 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);
|
||||
if( err < 0 ) break;
|
||||
|
||||
for(i = 0; i < BufferSize; i += 4096 ) {
|
||||
if( (i & 0xFFFF) == 0 ) {
|
||||
printf(" Erase %08x\n",FlashOffset + i);
|
||||
}
|
||||
|
||||
Cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev, 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(dev, Cmd,4,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
while(1)
|
||||
{
|
||||
Cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev, 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 = BufferSize - 256; j >= 0; j -= 256 )
|
||||
{
|
||||
if( (j & 0xFFFF) == 0 )
|
||||
{
|
||||
printf(" Programm %08x\n",FlashOffset + j);
|
||||
}
|
||||
|
||||
Cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev, 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],&Buffer[j],256);
|
||||
err = flashio(dev, Cmd,260,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
while(1)
|
||||
{
|
||||
Cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev, 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(dev, Cmd,1,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
Cmd[0] = 0x01; // WRSR
|
||||
Cmd[1] = LockBits; // BPx = 0, Lock all blocks
|
||||
err = flashio(dev, Cmd,2,NULL,0);
|
||||
|
||||
} while(0);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int FlashWriteSSTI_B(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize)
|
||||
{
|
||||
int err = 0;
|
||||
uint8_t Cmd[6];
|
||||
int i, j;
|
||||
|
||||
// Must be multiple of sector size
|
||||
if( (BufferSize % 4096) != 0 )
|
||||
return -1;
|
||||
|
||||
do {
|
||||
Cmd[0] = 0x50; // EWSR
|
||||
err = flashio(dev,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);
|
||||
if( err < 0 )
|
||||
break;
|
||||
|
||||
for(i = 0; i < BufferSize; i += 4096 ) {
|
||||
if( (i & 0xFFFF) == 0 )
|
||||
printf(" Erase %08x\n",FlashOffset + i);
|
||||
Cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev,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(dev,Cmd,4,NULL,0);
|
||||
if( err < 0 )
|
||||
break;
|
||||
|
||||
while(1) {
|
||||
Cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev,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 = BufferSize - 4096; j >= 0; j -= 4096 ) {
|
||||
if( (j & 0xFFFF) == 0 )
|
||||
printf(" Program %08x\n",FlashOffset + j);
|
||||
|
||||
for(i = 0; i < 4096; i += 2 ) {
|
||||
if( i == 0 ) {
|
||||
Cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev,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] = Buffer[j+i];
|
||||
Cmd[5] = Buffer[j+i+1];
|
||||
err = flashio(dev,Cmd,6,NULL,0);
|
||||
} else {
|
||||
Cmd[0] = 0xAD; // AAI
|
||||
Cmd[1] = Buffer[j+i];
|
||||
Cmd[2] = Buffer[j+i+1];
|
||||
err = flashio(dev,Cmd,3,NULL,0);
|
||||
}
|
||||
if( err < 0 )
|
||||
break;
|
||||
|
||||
while(1) {
|
||||
Cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev,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(dev,Cmd,1,NULL,0);
|
||||
if( err < 0 ) break;
|
||||
|
||||
}
|
||||
if( err < 0 ) break;
|
||||
|
||||
Cmd[0] = 0x50; // EWSR
|
||||
err = flashio(dev,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);
|
||||
} while(0);
|
||||
return err;
|
||||
}
|
||||
|
||||
void get_id(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);
|
||||
printf("%02x %02x %02x %02x\n",
|
||||
id[0], id[1], id[2], id[3]);
|
||||
ddbid->subvendor=(id[0] << 8) | id[1];
|
||||
ddbid->subdevice=(id[2] << 8) | id[3];
|
||||
}
|
||||
|
||||
int sure()
|
||||
{
|
||||
char c;
|
||||
|
||||
printf("\n\nWARNING! Flashing a new FPGA image might make your card unusable!\n");
|
||||
printf("\n\nWARNUNG! Das Flashen eines neuen FPGA-Images kann Ihre Karte unbrauchbar machen.\n");
|
||||
printf("\n\nAre you sure? y/n?");
|
||||
printf("\n\nSind Sie sicher? y/n?");
|
||||
fflush(0);
|
||||
c = getchar();
|
||||
if (c!='y') {
|
||||
printf("\nFlashing aborted.\n\n");
|
||||
return -1;
|
||||
}
|
||||
printf("\nStarting to flash\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char ddbname[80];
|
||||
int type = 0;
|
||||
struct ddb_id ddbid;
|
||||
uint8_t *buffer;
|
||||
int BufferSize = 0;
|
||||
int BlockErase = 0;
|
||||
uint32_t FlashOffset = 0x10000;
|
||||
int ddb;
|
||||
int i, err;
|
||||
int SectorSize=0;
|
||||
int FlashSize=0;
|
||||
int Flash;
|
||||
|
||||
uint32_t svid=0, jump=0, dump=0;
|
||||
int bin;
|
||||
|
||||
int ddbnum = 0;
|
||||
int force = 0;
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"svid", required_argument, NULL, 's'},
|
||||
{"help", no_argument , NULL, 'h'},
|
||||
{"force", no_argument , NULL, 'f'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv,
|
||||
"d:n:s:o:l:dfhj",
|
||||
long_options, &option_index);
|
||||
if (c==-1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
dump = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 's':
|
||||
svid = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'o':
|
||||
FlashOffset = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'n':
|
||||
ddbnum = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'l':
|
||||
linknr = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'f':
|
||||
force = 1;
|
||||
break;
|
||||
case 'j':
|
||||
jump = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (optind<argc) {
|
||||
printf("Warning: unused arguments\n");
|
||||
}
|
||||
|
||||
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
|
||||
ddb=open(ddbname, O_RDWR);
|
||||
if (ddb < 0) {
|
||||
printf("Could not open device\n");
|
||||
return -1;
|
||||
}
|
||||
Flash=FlashDetect(ddb);
|
||||
|
||||
switch(Flash) {
|
||||
case ATMEL_AT45DB642D:
|
||||
SectorSize = 1024;
|
||||
FlashSize = 0x800000;
|
||||
break;
|
||||
case SSTI_SST25VF016B:
|
||||
SectorSize = 4096;
|
||||
FlashSize = 0x200000;
|
||||
break;
|
||||
case SSTI_SST25VF032B:
|
||||
SectorSize = 4096;
|
||||
FlashSize = 0x400000;
|
||||
break;
|
||||
case SSTI_SST25VF064C:
|
||||
SectorSize = 4096;
|
||||
FlashSize = 0x800000;
|
||||
break;
|
||||
case SPANSION_S25FL116K:
|
||||
SectorSize = 4096;
|
||||
FlashSize = 0x200000;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_id(ddb, &ddbid);
|
||||
#if 1
|
||||
printf("%04x %04x %04x %04x %08x %08x\n",
|
||||
ddbid.vendor, ddbid.device,
|
||||
ddbid.subvendor, ddbid.subdevice,
|
||||
ddbid.hw, ddbid.regmap);
|
||||
#endif
|
||||
|
||||
if (dump) {
|
||||
flashdump(ddb, dump, 128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ddbid.device == 0x0011)
|
||||
type = 1;
|
||||
if (ddbid.device == 0x0201)
|
||||
type = 2;
|
||||
if (ddbid.device == 0x02)
|
||||
type = 3;
|
||||
if (ddbid.device == 0x03)
|
||||
type = 0;
|
||||
if (ddbid.device == 0x07)
|
||||
type = 4;
|
||||
if (ddbid.device == 0x320)
|
||||
type = 5;
|
||||
if (ddbid.device == 0x13)
|
||||
type = 6;
|
||||
if (ddbid.device == 0x12)
|
||||
type = 7;
|
||||
|
||||
if (!SectorSize)
|
||||
return 0;
|
||||
|
||||
if (jump) {
|
||||
uint32_t Jump = 0x200000;
|
||||
|
||||
BufferSize = SectorSize;
|
||||
FlashOffset = FlashSize - SectorSize;
|
||||
buffer = malloc(BufferSize);
|
||||
if (!buffer) {
|
||||
printf("out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
memset(buffer, 0xFF, BufferSize);
|
||||
memset(&buffer[BufferSize - 256 + 0x10], 0x00, 16);
|
||||
|
||||
buffer[BufferSize - 256 + 0x10] = 0xbd;
|
||||
buffer[BufferSize - 256 + 0x11] = 0xb3;
|
||||
buffer[BufferSize - 256 + 0x12] = 0xc4;
|
||||
buffer[BufferSize - 256 + 0x1a] = 0xfe;
|
||||
buffer[BufferSize - 256 + 0x1e] = 0x03;
|
||||
buffer[BufferSize - 256 + 0x1f] = ( ( Jump >> 16 ) & 0xFF );
|
||||
buffer[BufferSize - 256 + 0x20] = ( ( Jump >> 8 ) & 0xFF );
|
||||
buffer[BufferSize - 256 + 0x21] = ( ( Jump ) & 0xFF );
|
||||
} else if (svid) {
|
||||
BufferSize = SectorSize;
|
||||
FlashOffset = 0;
|
||||
|
||||
buffer = malloc(BufferSize);
|
||||
if (!buffer) {
|
||||
printf("out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
memset(buffer,0xFF,BufferSize);
|
||||
|
||||
buffer[0] = ((svid >> 24 ) & 0xFF);
|
||||
buffer[1] = ((svid >> 16 ) & 0xFF);
|
||||
buffer[2] = ((svid >> 8 ) & 0xFF);
|
||||
buffer[3] = ((svid ) & 0xFF);
|
||||
} else {
|
||||
int fh, i;
|
||||
int fsize;
|
||||
char *fname;
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
fname="DVBBridgeV1B_DVBBridgeV1B.bit";
|
||||
printf("Octopus\n");
|
||||
break;
|
||||
case 1:
|
||||
fname="CIBridgeV1B_CIBridgeV1B.bit";
|
||||
printf("Octopus CI\n");
|
||||
break;
|
||||
case 2:
|
||||
fname="DVBModulatorV1B_DVBModulatorV1B.bit";
|
||||
printf("Modulator\n");
|
||||
break;
|
||||
case 3:
|
||||
fname="DVBBridgeV1A_DVBBridgeV1A.bit";
|
||||
printf("Octopus 35\n");
|
||||
break;
|
||||
case 4:
|
||||
fname="DVBBridgeV2A_DD01_0007_MXL.bit";
|
||||
printf("Octopus 4/8\n");
|
||||
break;
|
||||
case 6:
|
||||
fname="DVBBridgeV2B_DD01_0013_PRO.fpga";
|
||||
printf("Octopus PRO\n");
|
||||
break;
|
||||
case 7:
|
||||
fname="DVBBridgeV2B_DD01_0012_STD.fpga";
|
||||
printf("Octopus CI\n");
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN\n");
|
||||
break;
|
||||
}
|
||||
fh = open(fname, O_RDONLY);
|
||||
if (fh < 0 ) {
|
||||
printf("File not found \n");
|
||||
return 0;
|
||||
}
|
||||
printf("Using bitstream %s\n", fname);
|
||||
|
||||
fsize = lseek(fh,0,SEEK_END);
|
||||
if( fsize > 4000000 || fsize < SectorSize )
|
||||
{
|
||||
close(fh);
|
||||
printf("Invalid File Size \n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( Flash == ATMEL_AT45DB642D ) {
|
||||
BlockErase = fsize >= 8192;
|
||||
if( BlockErase )
|
||||
BufferSize = (fsize + 8191) & ~8191;
|
||||
else
|
||||
BufferSize = (fsize + 1023) & ~1023;
|
||||
} else {
|
||||
BufferSize = (fsize + SectorSize - 1 ) & ~(SectorSize - 1);
|
||||
}
|
||||
printf(" Size %08x, target %08x\n", BufferSize, FlashOffset);
|
||||
|
||||
buffer = malloc(BufferSize);
|
||||
|
||||
if( buffer == NULL ) {
|
||||
close(fh);
|
||||
printf("out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(buffer, 0xFF, BufferSize);
|
||||
lseek(fh, 0, SEEK_SET);
|
||||
read(fh, buffer, fsize);
|
||||
close(fh);
|
||||
|
||||
if (BufferSize >= 0x10000) {
|
||||
for(i = 0; i < 0x200; i += 1 ) {
|
||||
if ( *(uint16_t *) (&buffer[i]) == 0xFFFF )
|
||||
break;
|
||||
buffer[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!force && sure()<0)
|
||||
return 0;
|
||||
switch(Flash) {
|
||||
case ATMEL_AT45DB642D:
|
||||
err = FlashWriteAtmel(ddb,FlashOffset,buffer,BufferSize);
|
||||
break;
|
||||
case SSTI_SST25VF016B:
|
||||
case SSTI_SST25VF032B:
|
||||
err = FlashWriteSSTI_B(ddb,FlashOffset,buffer,BufferSize);
|
||||
break;
|
||||
case SSTI_SST25VF064C:
|
||||
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x3C);
|
||||
break;
|
||||
case SPANSION_S25FL116K:
|
||||
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
printf("Programming Error\n");
|
||||
else
|
||||
printf("Programming Done\n");
|
||||
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
}
|
||||
535
apps/modconfig.c
Normal file
535
apps/modconfig.c
Normal file
@@ -0,0 +1,535 @@
|
||||
#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 = 0,
|
||||
.mod_stream = 0,
|
||||
.mod_setup_stream = {
|
||||
.standard = MOD_STANDARD_DVBC_8,
|
||||
},
|
||||
};
|
||||
|
||||
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);
|
||||
printf("channels = %u\n", mc->channels.mod_setup_channels[0].num_channels);
|
||||
} 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);
|
||||
printf("%u %u %u %u %u %u %u %u\n",
|
||||
mc->stream.mod_command,
|
||||
mc->stream.mod_channel,
|
||||
mc->stream.mod_stream,
|
||||
mc->stream.mod_setup_stream.standard,
|
||||
mc->stream.mod_setup_stream.symbol_rate,
|
||||
mc->stream.mod_setup_stream.stream_format,
|
||||
mc->stream.mod_setup_stream.qam.modulation,
|
||||
mc->stream.mod_setup_stream.qam.rolloff);
|
||||
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);
|
||||
}
|
||||
}
|
||||
36
apps/modt.c
36
apps/modt.c
@@ -1,36 +0,0 @@
|
||||
#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 <pthread.h>
|
||||
|
||||
|
||||
#define SNUM 1000
|
||||
//671
|
||||
void send(void)
|
||||
{
|
||||
uint8_t buf[188*SNUM], *cts;
|
||||
int i;
|
||||
uint32_t c=0;
|
||||
int fdo;
|
||||
|
||||
fdo=open("/dev/dvb/adapter0/mod0", O_WRONLY);
|
||||
|
||||
|
||||
while (1) {
|
||||
read(0, buf, sizeof(buf));
|
||||
write(fdo, buf, 188*SNUM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
send();
|
||||
}
|
||||
1316
apps/modtest.c
Normal file
1316
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,19 +1,24 @@
|
||||
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
|
||||
|
||||
octokey: octokey.c
|
||||
$(CC) -o octokey octokey.c
|
||||
|
||||
|
||||
@@ -36,780 +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 type;
|
||||
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 flashio(int ddb, uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen)
|
||||
{
|
||||
struct ddb_flashio fio = {
|
||||
.write_buf=wbuf,
|
||||
.write_len=wlen,
|
||||
.read_buf=rbuf,
|
||||
.read_len=rlen,
|
||||
.link=0,
|
||||
};
|
||||
|
||||
return ioctl(ddb, IOCTL_DDB_FLASHIO, &fio);
|
||||
}
|
||||
|
||||
enum {
|
||||
UNKNOWN_FLASH = 0,
|
||||
ATMEL_AT45DB642D = 1,
|
||||
SSTI_SST25VF016B = 2,
|
||||
SSTI_SST25VF032B = 3,
|
||||
SSTI_SST25VF064C = 4,
|
||||
SPANSION_S25FL116K = 5,
|
||||
};
|
||||
|
||||
static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
|
||||
{
|
||||
uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff,
|
||||
(addr >> 8) & 0xff, addr & 0xff};
|
||||
|
||||
return flashio(ddb, cmd, 4, buf, len);
|
||||
}
|
||||
|
||||
static int flashdump(struct ddflash *ddf, uint32_t addr, uint32_t len)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t buf[32];
|
||||
int bl = sizeof(buf);
|
||||
|
||||
for (j = 0; j < len; j += bl, addr += bl) {
|
||||
flashread(ddf->fd, buf, addr, bl);
|
||||
for (i = 0; i < bl; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
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 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:
|
||||
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] == 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;
|
||||
}
|
||||
|
||||
|
||||
int FlashWriteAtmel(int dev,uint32_t FlashOffset, uint8_t *Buffer,int BufferSize)
|
||||
{
|
||||
int err = 0;
|
||||
int BlockErase = BufferSize >= 8192;
|
||||
int i;
|
||||
|
||||
if (BlockErase) {
|
||||
for (i = 0; i < BufferSize; i += 8192 ) {
|
||||
uint8_t cmd[4];
|
||||
if ((i & 0xFFFF) == 0 )
|
||||
printf(" Erase %08x\n",FlashOffset + i);
|
||||
cmd[0] = 0x50; // Block Erase
|
||||
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
|
||||
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
|
||||
cmd[3] = 0x00;
|
||||
err = flashio(dev,cmd,4,NULL,0);
|
||||
if (err < 0 ) break;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
cmd[0] = 0xD7; // Read Status register
|
||||
err = flashio(dev,cmd,1,&cmd[0],1);
|
||||
if (err < 0 ) break;
|
||||
if ((cmd[0] & 0x80) == 0x80 ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < BufferSize; i += 1024) {
|
||||
uint8_t cmd[4 + 1024];
|
||||
if ((i & 0xFFFF) == 0 )
|
||||
{
|
||||
printf(" Program %08x\n",FlashOffset + i);
|
||||
}
|
||||
cmd[0] = 0x84; // Buffer 1
|
||||
cmd[1] = 0x00;
|
||||
cmd[2] = 0x00;
|
||||
cmd[3] = 0x00;
|
||||
memcpy(&cmd[4],&Buffer[i],1024);
|
||||
|
||||
err = flashio(dev,cmd,4 + 1024,NULL,0);
|
||||
if (err < 0 ) break;
|
||||
|
||||
cmd[0] = BlockErase ? 0x88 : 0x83; // Buffer to Main Memory (with Erase)
|
||||
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
|
||||
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
|
||||
cmd[3] = 0x00;
|
||||
|
||||
err = flashio(dev,cmd,4,NULL,0);
|
||||
if (err < 0 ) break;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
cmd[0] = 0xD7; // Read Status register
|
||||
err = flashio(dev,cmd,1,&cmd[0],1);
|
||||
if (err < 0 ) break;
|
||||
if ((cmd[0] & 0x80) == 0x80 ) break;
|
||||
}
|
||||
if (err < 0 ) break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int FlashWriteSSTI(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize)
|
||||
{
|
||||
int err = 0;
|
||||
uint8_t cmd[6];
|
||||
int i, j;
|
||||
|
||||
// Must be multiple of sector size
|
||||
if ((BufferSize % 4096) != 0 )
|
||||
return -1;
|
||||
|
||||
do {
|
||||
cmd[0] = 0x50; // EWSR
|
||||
err = flashio(dev,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);
|
||||
if (err < 0 )
|
||||
break;
|
||||
|
||||
for (i = 0; i < BufferSize; i += 4096 ) {
|
||||
if ((i & 0xFFFF) == 0 )
|
||||
printf(" Erase %08x\n",FlashOffset + i);
|
||||
cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev,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(dev,cmd,4,NULL,0);
|
||||
if (err < 0 )
|
||||
break;
|
||||
|
||||
while(1) {
|
||||
cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev,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 = BufferSize - 4096; j >= 0; j -= 4096 ) {
|
||||
if ((j & 0xFFFF) == 0 )
|
||||
printf(" Program %08x\n",FlashOffset + j);
|
||||
|
||||
for (i = 0; i < 4096; i += 2 ) {
|
||||
if (i == 0 ) {
|
||||
cmd[0] = 0x06; // WREN
|
||||
err = flashio(dev,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] = Buffer[j+i];
|
||||
cmd[5] = Buffer[j+i+1];
|
||||
err = flashio(dev,cmd,6,NULL,0);
|
||||
} else {
|
||||
cmd[0] = 0xAD; // AAI
|
||||
cmd[1] = Buffer[j+i];
|
||||
cmd[2] = Buffer[j+i+1];
|
||||
err = flashio(dev,cmd,3,NULL,0);
|
||||
}
|
||||
if (err < 0 )
|
||||
break;
|
||||
|
||||
while(1) {
|
||||
cmd[0] = 0x05; // RDRS
|
||||
err = flashio(dev,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(dev,cmd,1,NULL,0);
|
||||
if (err < 0 ) break;
|
||||
|
||||
}
|
||||
if (err < 0 ) break;
|
||||
|
||||
cmd[0] = 0x50; // EWSR
|
||||
err = flashio(dev,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);
|
||||
} while(0);
|
||||
return err;
|
||||
}
|
||||
|
||||
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
|
||||
if (ddf->id.device == 0x0011)
|
||||
ddf->type = 1;
|
||||
if (ddf->id.device == 0x0201)
|
||||
ddf->type = 2;
|
||||
if (ddf->id.device == 0x02)
|
||||
ddf->type = 3;
|
||||
if (ddf->id.device == 0x03)
|
||||
ddf->type = 0;
|
||||
if (ddf->id.device == 0x0300)
|
||||
ddf->type = 4;
|
||||
if (ddf->id.device == 0x0320)
|
||||
ddf->type = 5;
|
||||
|
||||
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")) {
|
||||
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 = 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)
|
||||
{
|
||||
@@ -838,18 +65,40 @@ static int update_flash(struct ddflash *ddf)
|
||||
if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 0)) == 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 (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)
|
||||
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";
|
||||
@@ -858,6 +107,13 @@ static int update_flash(struct ddflash *ddf)
|
||||
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:
|
||||
return 0;
|
||||
}
|
||||
@@ -922,6 +178,7 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ddf.link = 0;
|
||||
flash = flash_detect(&ddf);
|
||||
if (flash < 0)
|
||||
return -1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
295
apps/octonet/ddupdate.c
Normal file
295
apps/octonet/ddupdate.c
Normal file
@@ -0,0 +1,295 @@
|
||||
#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;
|
||||
uint32_t imgadr = 0x10000;
|
||||
|
||||
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:
|
||||
{
|
||||
uint32_t val;
|
||||
if (!readreg(ddf->fd, (ddf->link << 28) | 0x10, &val)) {
|
||||
//printf("reg0x10=%08x\n", val);
|
||||
if ((val >> 24) == 5)
|
||||
imgadr = 0;
|
||||
}
|
||||
}
|
||||
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);
|
||||
printf("Address: %08x\n", imgadr);
|
||||
if ((res = update_image(ddf, fname, imgadr, 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;
|
||||
}
|
||||
1211
apps/octonet/flash.c
Normal file
1211
apps/octonet/flash.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -61,3 +61,47 @@ struct ddb_i2c_msg {
|
||||
#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)
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
165
apps/setmod2.c
Normal file
165
apps/setmod2.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <errno.h>
|
||||
#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 <pthread.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <linux/dvb/mod.h>
|
||||
|
||||
static int set_property(int fd, uint32_t cmd, uint32_t data)
|
||||
{
|
||||
struct dtv_property p;
|
||||
struct dtv_properties c;
|
||||
int ret;
|
||||
|
||||
p.cmd = cmd;
|
||||
c.num = 1;
|
||||
c.props = &p;
|
||||
p.u.data = data;
|
||||
ret = ioctl(fd, FE_SET_PROPERTY, &c);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_property(int fd, uint32_t cmd, uint32_t *data)
|
||||
{
|
||||
struct dtv_property p;
|
||||
struct dtv_properties c;
|
||||
int ret;
|
||||
|
||||
p.cmd = cmd;
|
||||
c.num = 1;
|
||||
c.props = &p;
|
||||
ret = ioctl(fd, FE_GET_PROPERTY, &c);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "FE_GET_PROPERTY returned %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
*data = p.u.data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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, att=-1, mod=-1;
|
||||
int32_t base = -1, freq = -1, rate = -1, srate = -1;
|
||||
char mod_name[128];
|
||||
|
||||
while (1) {
|
||||
int cur_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"adapter", required_argument, 0, 'a'},
|
||||
{"channel", required_argument, 0, 'c'},
|
||||
{"att", required_argument, 0, 't'},
|
||||
{"gain", required_argument, 0, 'g'},
|
||||
{"base", required_argument, 0, 'b'},
|
||||
{"frequency", required_argument, 0, 'f'},
|
||||
{"rate", required_argument, 0, 'r'},
|
||||
{"modulation", required_argument, 0, 'm'},
|
||||
{"symbolrate", required_argument, 0, 's'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv,
|
||||
"a:c:g:b:f:r:t:m:s:",
|
||||
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 't':
|
||||
att = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'b':
|
||||
base = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'f':
|
||||
freq = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'm':
|
||||
mod = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 's':
|
||||
srate = 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_ATTENUATOR, &data);
|
||||
//printf("Modulator attenuator = %u\n", data);
|
||||
|
||||
if (att >= 0)
|
||||
set_property(fd, MODULATOR_ATTENUATOR, att);
|
||||
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);
|
||||
if (mod >= 0)
|
||||
set_property(fd, MODULATOR_MODULATION, mod);
|
||||
if (srate > 0)
|
||||
set_property(fd, MODULATOR_SYMBOL_RATE, srate);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
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
|
||||
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
|
||||
|
||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
||||
obj-$(CONFIG_DVB_OCTONET) += octonet.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
|
||||
|
||||
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
|
||||
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
|
||||
|
||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
||||
|
||||
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$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core
|
||||
46
ddbridge/Kconfig
Normal file
46
ddbridge/Kconfig
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
config DVB_DDBRIDGE
|
||||
tristate "Digital Devices bridge support"
|
||||
depends on MEDIA_PCI_SUPPORT && DVB_CORE && PCI && I2C
|
||||
select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_MXL5XX if MEDIA_SUBDRV_AUTOSELECT
|
||||
---help---
|
||||
Support for cards with the Digital Devices PCI express bridge:
|
||||
- Octopus PCIe Bridge
|
||||
- Octopus mini PCIe Bridge
|
||||
- Octopus LE
|
||||
- DuoFlex S2 Octopus
|
||||
- DuoFlex CT Octopus
|
||||
- cineS2(v6)
|
||||
|
||||
Say Y if you own such a card and want to use it.
|
||||
|
||||
|
||||
config DVB_OCTONET
|
||||
tristate "Digital Devices octonet support"
|
||||
depends on MEDIA_DIGITAL_TV_SUPPORT && DVB_CORE && I2C
|
||||
select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0910 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV6111 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_MXL5XX if MEDIA_SUBDRV_AUTOSELECT
|
||||
---help---
|
||||
Support for OctopusNet
|
||||
|
||||
Say Y if you own such a card and want to use it.
|
||||
@@ -1,19 +1,13 @@
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
#
|
||||
# Makefile for the ddbridge device driver
|
||||
#
|
||||
|
||||
MODDEFS := CONFIG_DVB_DDBRIDGE=m
|
||||
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
|
||||
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules
|
||||
$(MAKE) -C apps
|
||||
|
||||
dep:
|
||||
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
|
||||
|
||||
install: all
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
|
||||
|
||||
clean:
|
||||
rm -rf */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
|
||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
||||
obj-$(CONFIG_DVB_OCTONET) += octonet.o
|
||||
|
||||
ccflags-y += -Idrivers/media/dvb-frontends/
|
||||
ccflags-y += -Idrivers/media/tuners/
|
||||
|
||||
|
||||
15
ddbridge/Makefile.kernel
Normal file
15
ddbridge/Makefile.kernel
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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 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
|
||||
|
||||
ccflags-y += -Idrivers/media/dvb-core/
|
||||
ccflags-y += -Idrivers/media/dvb-frontends/
|
||||
ccflags-y += -Idrivers/media/tuners/
|
||||
ccflags-y += --include=dd_compat.h
|
||||
|
||||
346
ddbridge/ddbridge-ci.c
Normal file
346
ddbridge/ddbridge-ci.c
Normal file
@@ -0,0 +1,346 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-ci.c: Digital Devices bridge and DuoFlex CI driver
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
#include "ddbridge-i2c.h"
|
||||
|
||||
/* Octopus CI internal CI interface */
|
||||
|
||||
static int wait_ci_ready(struct ddb_ci *ci)
|
||||
{
|
||||
u32 count = 10;
|
||||
|
||||
ndelay(500);
|
||||
do {
|
||||
if (ddbreadl(ci->port->dev,
|
||||
CI_CONTROL(ci)) & CI_READY)
|
||||
break;
|
||||
usleep_range(1, 2);
|
||||
if ((--count) == 0)
|
||||
return -1;
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_attribute_mem(struct dvb_ca_en50221 *ca,
|
||||
int slot, int address)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1);
|
||||
|
||||
if (address > CI_BUFFER_SIZE)
|
||||
return -1;
|
||||
ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
|
||||
CI_DO_READ_ATTRIBUTES(ci));
|
||||
wait_ci_ready(ci);
|
||||
val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
|
||||
return val;
|
||||
}
|
||||
|
||||
static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
|
||||
int address, u8 value)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
||||
CI_DO_ATTRIBUTE_RW(ci));
|
||||
wait_ci_ready(ci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_cam_control(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 address)
|
||||
{
|
||||
u32 count = 100;
|
||||
struct ddb_ci *ci = ca->data;
|
||||
u32 res;
|
||||
|
||||
ddbwritel(ci->port->dev, CI_READ_CMD | address,
|
||||
CI_DO_IO_RW(ci));
|
||||
ndelay(500);
|
||||
do {
|
||||
res = ddbreadl(ci->port->dev, CI_READDATA(ci));
|
||||
if (res & CI_READY)
|
||||
break;
|
||||
usleep_range(1, 2);
|
||||
if ((--count) == 0)
|
||||
return -1;
|
||||
} while (1);
|
||||
return 0xff & res;
|
||||
}
|
||||
|
||||
static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
|
||||
u8 address, u8 value)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
||||
CI_DO_IO_RW(ci));
|
||||
wait_ci_ready(ci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
ddbwritel(ci->port->dev, CI_POWER_ON,
|
||||
CI_CONTROL(ci));
|
||||
msleep(300);
|
||||
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
|
||||
CI_CONTROL(ci));
|
||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
|
||||
CI_CONTROL(ci));
|
||||
usleep_range(20, 25);
|
||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
|
||||
CI_CONTROL(ci));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
ddbwritel(ci->port->dev, 0, CI_CONTROL(ci));
|
||||
msleep(300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
|
||||
|
||||
ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
|
||||
CI_CONTROL(ci));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
|
||||
int stat = 0;
|
||||
|
||||
if (val & CI_CAM_DETECT)
|
||||
stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
|
||||
if (val & CI_CAM_READY)
|
||||
stat |= DVB_CA_EN50221_POLL_CAM_READY;
|
||||
return stat;
|
||||
}
|
||||
|
||||
static struct dvb_ca_en50221 en_templ = {
|
||||
.read_attribute_mem = read_attribute_mem,
|
||||
.write_attribute_mem = write_attribute_mem,
|
||||
.read_cam_control = read_cam_control,
|
||||
.write_cam_control = write_cam_control,
|
||||
.slot_reset = slot_reset,
|
||||
.slot_shutdown = slot_shutdown,
|
||||
.slot_ts_enable = slot_ts_enable,
|
||||
.poll_slot_status = poll_slot_status,
|
||||
};
|
||||
|
||||
static void ci_attach(struct ddb_port *port)
|
||||
{
|
||||
struct ddb_ci *ci;
|
||||
const struct ddb_info *info = port->dev->link[port->lnr].info;
|
||||
u32 off = info->ci_base ? info->ci_base : 0x400;
|
||||
|
||||
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
|
||||
if (!ci)
|
||||
return;
|
||||
memcpy(&ci->en, &en_templ, sizeof(en_templ));
|
||||
ci->en.data = ci;
|
||||
port->en = &ci->en;
|
||||
ci->port = port;
|
||||
ci->nr = port->nr - 2;
|
||||
ci->regs = DDB_LINK_TAG(port->lnr) | (off + 32 * ci->nr);
|
||||
}
|
||||
|
||||
/* DuoFlex Dual CI support */
|
||||
|
||||
static int write_creg(struct ddb_ci *ci, u8 data, u8 mask)
|
||||
{
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
|
||||
ci->port->creg = (ci->port->creg & ~mask) | data;
|
||||
return i2c_write_reg(i2c, adr, 0x02, ci->port->creg);
|
||||
}
|
||||
|
||||
static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca,
|
||||
int slot, int address)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
int res;
|
||||
u8 val;
|
||||
|
||||
res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val);
|
||||
return res ? res : val;
|
||||
}
|
||||
|
||||
static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot,
|
||||
int address, u8 value)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
|
||||
return i2c_write_reg16(i2c, adr, 0x8000 | address, value);
|
||||
}
|
||||
|
||||
static int read_cam_control_xo2(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 address)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
u8 val;
|
||||
int res;
|
||||
|
||||
res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val);
|
||||
return res ? res : val;
|
||||
}
|
||||
|
||||
static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot,
|
||||
u8 address, u8 value)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
|
||||
return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value);
|
||||
}
|
||||
|
||||
static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
write_creg(ci, 0x01, 0x01);
|
||||
write_creg(ci, 0x04, 0x04);
|
||||
msleep(300);
|
||||
write_creg(ci, 0x02, 0x02);
|
||||
write_creg(ci, 0x00, 0x04);
|
||||
write_creg(ci, 0x18, 0x18);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
/*i2c_write_reg(i2c, adr, 0x03, 0x60);*/
|
||||
/*i2c_write_reg(i2c, adr, 0x00, 0xc0);*/
|
||||
write_creg(ci, 0x10, 0xff);
|
||||
write_creg(ci, 0x08, 0x08);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
write_creg(ci, 0x00, 0x10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
struct i2c_adapter *i2c = &ci->port->i2c->adap;
|
||||
u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
|
||||
u8 val = 0;
|
||||
int stat = 0;
|
||||
|
||||
i2c_read_reg(i2c, adr, 0x01, &val);
|
||||
|
||||
if (val & 2)
|
||||
stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
|
||||
if (val & 1)
|
||||
stat |= DVB_CA_EN50221_POLL_CAM_READY;
|
||||
return stat;
|
||||
}
|
||||
|
||||
static struct dvb_ca_en50221 en_xo2_templ = {
|
||||
.read_attribute_mem = read_attribute_mem_xo2,
|
||||
.write_attribute_mem = write_attribute_mem_xo2,
|
||||
.read_cam_control = read_cam_control_xo2,
|
||||
.write_cam_control = write_cam_control_xo2,
|
||||
.slot_reset = slot_reset_xo2,
|
||||
.slot_shutdown = slot_shutdown_xo2,
|
||||
.slot_ts_enable = slot_ts_enable_xo2,
|
||||
.poll_slot_status = poll_slot_status_xo2,
|
||||
};
|
||||
|
||||
static void ci_xo2_attach(struct ddb_port *port)
|
||||
{
|
||||
struct ddb_ci *ci;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
|
||||
if (!ci)
|
||||
return;
|
||||
memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ));
|
||||
ci->en.data = ci;
|
||||
port->en = &ci->en;
|
||||
ci->port = port;
|
||||
ci->nr = port->nr - 2;
|
||||
ci->port->creg = 0;
|
||||
i2c = &ci->port->i2c->adap;
|
||||
write_creg(ci, 0x10, 0xff);
|
||||
write_creg(ci, 0x08, 0x08);
|
||||
}
|
||||
|
||||
static struct cxd2099_cfg cxd_cfg = {
|
||||
.bitrate = 72000,
|
||||
.adr = 0x40,
|
||||
.polarity = 1,
|
||||
.clock_mode = 1,
|
||||
.max_i2c = 512,
|
||||
};
|
||||
|
||||
int ddb_ci_attach(struct ddb_port *port, u32 bitrate)
|
||||
{
|
||||
switch (port->type) {
|
||||
case DDB_CI_EXTERNAL_SONY:
|
||||
cxd_cfg.bitrate = bitrate;
|
||||
port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
|
||||
break;
|
||||
|
||||
case DDB_CI_EXTERNAL_XO2:
|
||||
case DDB_CI_EXTERNAL_XO2_B:
|
||||
ci_xo2_attach(port);
|
||||
break;
|
||||
|
||||
case DDB_CI_INTERNAL:
|
||||
ci_attach(port);
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!port->en)
|
||||
return -ENODEV;
|
||||
dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
948
ddbridge/ddbridge-hw.c
Normal file
948
ddbridge/ddbridge-hw.c
Normal file
@@ -0,0 +1,948 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-hw.c: Digital Devices device information tables
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_regset octopus_mod_odma = {
|
||||
.base = 0x300,
|
||||
.num = 0x0a,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_mod_odma_buf = {
|
||||
.base = 0x2000,
|
||||
.num = 0x0a,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_mod_channel = {
|
||||
.base = 0x400,
|
||||
.num = 0x0a,
|
||||
.size = 0x40,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_regset octopus_mod_2_odma = {
|
||||
.base = 0x400,
|
||||
.num = 0x18,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_mod_2_odma_buf = {
|
||||
.base = 0x8000,
|
||||
.num = 0x18,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_mod_2_channel = {
|
||||
.base = 0x800,
|
||||
.num = 0x18,
|
||||
.size = 0x40,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_sdr_output = {
|
||||
.base = 0x240,
|
||||
.num = 0x14,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_regset octopus_input = {
|
||||
.base = 0x200,
|
||||
.num = 0x08,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_output = {
|
||||
.base = 0x280,
|
||||
.num = 0x08,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_idma = {
|
||||
.base = 0x300,
|
||||
.num = 0x08,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_idma_buf = {
|
||||
.base = 0x2000,
|
||||
.num = 0x08,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_odma = {
|
||||
.base = 0x380,
|
||||
.num = 0x04,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_odma_buf = {
|
||||
.base = 0x2800,
|
||||
.num = 0x04,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_i2c = {
|
||||
.base = 0x80,
|
||||
.num = 0x04,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_i2c_buf = {
|
||||
.base = 0x1000,
|
||||
.num = 0x04,
|
||||
.size = 0x200,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
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,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_output = {
|
||||
.base = 0x600,
|
||||
.num = 0x0a,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_idma = {
|
||||
.base = 0x800,
|
||||
.num = 0x40,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_idma_buf = {
|
||||
.base = 0x4000,
|
||||
.num = 0x40,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_odma = {
|
||||
.base = 0xc00,
|
||||
.num = 0x20,
|
||||
.size = 0x10,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_odma_buf = {
|
||||
.base = 0x8000,
|
||||
.num = 0x20,
|
||||
.size = 0x100,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_i2c = {
|
||||
.base = 0x200,
|
||||
.num = 0x0a,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_i2c_buf = {
|
||||
.base = 0x2000,
|
||||
.num = 0x0a,
|
||||
.size = 0x200,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopro_gtl = {
|
||||
.base = 0xe00,
|
||||
.num = 0x03,
|
||||
.size = 0x40,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
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,
|
||||
.irq_base_idma = 8,
|
||||
.irq_base_odma = 16,
|
||||
.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,
|
||||
};
|
||||
|
||||
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,
|
||||
.irq_base_idma = 64,
|
||||
.irq_base_odma = 128,
|
||||
.irq_base_gtl = 8,
|
||||
.i2c = &octopro_i2c,
|
||||
.i2c_buf = &octopro_i2c_buf,
|
||||
.idma = &octopro_idma,
|
||||
.idma_buf = &octopro_idma_buf,
|
||||
.odma = &octopro_odma,
|
||||
.odma_buf = &octopro_odma_buf,
|
||||
.input = &octopro_input,
|
||||
.output = &octopro_output,
|
||||
.gtl = &octopro_gtl,
|
||||
};
|
||||
|
||||
static const struct ddb_regmap octopro_hdin_map = {
|
||||
.irq_version = 2,
|
||||
.irq_base_i2c = 32,
|
||||
.irq_base_idma = 64,
|
||||
.irq_base_odma = 128,
|
||||
.i2c = &octopro_i2c,
|
||||
.i2c_buf = &octopro_i2c_buf,
|
||||
.idma = &octopro_idma,
|
||||
.idma_buf = &octopro_idma_buf,
|
||||
.odma = &octopro_odma,
|
||||
.odma_buf = &octopro_odma_buf,
|
||||
.input = &octopro_input,
|
||||
.output = &octopro_output,
|
||||
};
|
||||
|
||||
static const struct ddb_regmap octopus_mod_map = {
|
||||
.irq_version = 1,
|
||||
.irq_base_odma = 8,
|
||||
.irq_base_rate = 18,
|
||||
.output = &octopus_output,
|
||||
.odma = &octopus_mod_odma,
|
||||
.odma_buf = &octopus_mod_odma_buf,
|
||||
.channel = &octopus_mod_channel,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_info ddb_none = {
|
||||
.type = DDB_NONE,
|
||||
.name = "unknown Digital Devices device, install newer driver",
|
||||
.regmap = &octopus_map,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octopus = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octopusv3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus V3 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octopus_le = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus LE DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 2,
|
||||
.i2c_mask = 0x03,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octopus_oem = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus OEM",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.led_num = 1,
|
||||
.fan_num = 1,
|
||||
.temp_num = 1,
|
||||
.temp_bus = 0,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octopus_mini = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus Mini",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_v6 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_v6_5 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6.5 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_v7a = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V7 Advanced DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
.ts_quirks = TS_QUIRK_REVERSED,
|
||||
.hw_min = 0x010007,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_v7 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V7 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
.ts_quirks = TS_QUIRK_REVERSED,
|
||||
.hw_min = 0x010007,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ctv7 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine CT V7 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 3,
|
||||
.board_control_2 = 4,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_satixs2v3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Mystique SaTiX-S2 V3 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ci = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus CI",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x03,
|
||||
.ci_mask = 0x0c,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_cis = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus CI single",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x03,
|
||||
.ci_mask = 0x04,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ci_s2_pro = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus CI S2 Pro",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x01,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
.hw_min = 0x010007,
|
||||
.ci_mask = 0x0c,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ci_s2_pro_a = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus CI S2 Pro Advanced",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x01,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
.hw_min = 0x010007,
|
||||
.ci_mask = 0x0c,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_dvbct = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices DVBCT V6.1 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_info ddb_mod = {
|
||||
.type = DDB_MOD,
|
||||
.name = "Digital Devices DVB-C modulator",
|
||||
.regmap = &octopus_mod_map,
|
||||
.port_num = 10,
|
||||
.temp_num = 1,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_4 = {
|
||||
.type = DDB_MOD,
|
||||
.name = "Digital Devices DVB-C modulator",
|
||||
.regmap = &octopus_mod_map,
|
||||
.port_num = 4,
|
||||
.temp_num = 1,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_fsm_24 = {
|
||||
.type = DDB_MOD,
|
||||
.version = 2,
|
||||
.name = "Digital Devices DVB-C modulator FSM-24",
|
||||
.regmap = &octopus_mod_2_map,
|
||||
.port_num = 24,
|
||||
.temp_num = 1,
|
||||
.tempmon_irq = 8,
|
||||
.lostlock_irq = 9,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_fsm_16 = {
|
||||
.type = DDB_MOD,
|
||||
.version = 2,
|
||||
.name = "Digital Devices DVB-C modulator FSM-16",
|
||||
.regmap = &octopus_mod_2_map,
|
||||
.port_num = 16,
|
||||
.temp_num = 1,
|
||||
.tempmon_irq = 8,
|
||||
.lostlock_irq = 9,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_fsm_8 = {
|
||||
.type = DDB_MOD,
|
||||
.name = "Digital Devices DVB-C modulator FSM-8",
|
||||
.version = 2,
|
||||
.regmap = &octopus_mod_2_map,
|
||||
.port_num = 8,
|
||||
.temp_num = 1,
|
||||
.tempmon_irq = 8,
|
||||
.lostlock_irq = 9,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_fsm_4 = {
|
||||
.type = DDB_MOD,
|
||||
.name = "Digital Devices DVB-C modulator FSM-4",
|
||||
.version = 2,
|
||||
.regmap = &octopus_mod_2_map,
|
||||
.port_num = 4,
|
||||
.temp_num = 1,
|
||||
.tempmon_irq = 8,
|
||||
.lostlock_irq = 9,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_mod_fsm = {
|
||||
.type = DDB_MOD,
|
||||
.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 = 14,
|
||||
.temp_num = 1,
|
||||
.tempmon_irq = 8,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_s2_48 = {
|
||||
.type = DDB_OCTOPUS_MAX,
|
||||
.name = "Digital Devices MAX S8 4/8",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x01,
|
||||
.board_control = 1,
|
||||
.tempmon_irq = 24,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ct2_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX A8 CT2",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL,
|
||||
.tempmon_irq = 24,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_c2t2_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX A8 C2T2",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL,
|
||||
.tempmon_irq = 24,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_isdbt_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX A8 ISDBT",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL,
|
||||
.tempmon_irq = 24,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_c2t2i_v0_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX A8 C2T2I V0",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL | TS_QUIRK_ALT_OSC,
|
||||
.tempmon_irq = 24,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_c2t2i_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX A8 C2T2I",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL,
|
||||
.tempmon_irq = 24,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_info ddb_s2x_48 = {
|
||||
.type = DDB_OCTOPUS_MCI,
|
||||
.name = "Digital Devices MAX SX8",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x00,
|
||||
.tempmon_irq = 24,
|
||||
.mci_ports = 4,
|
||||
.mci_type = DDB_TUNER_MCI_SX8,
|
||||
.temp_num = 1,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
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,
|
||||
.mci_ports = 4,
|
||||
.mci_type = DDB_TUNER_MCI_SX8,
|
||||
.temp_num = 1,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_m4 = {
|
||||
.type = DDB_OCTOPUS_MCI,
|
||||
.name = "Digital Devices MAX M4",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 2,
|
||||
.i2c_mask = 0x00,
|
||||
.tempmon_irq = 24,
|
||||
.mci_ports = 2,
|
||||
.mci_type = DDB_TUNER_MCI_M4,
|
||||
.temp_num = 1,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_m8 = {
|
||||
.type = DDB_OCTOPUS_MCI,
|
||||
.name = "Digital Devices MAX M8",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x00,
|
||||
.tempmon_irq = 24,
|
||||
.mci_ports = 4,
|
||||
.mci_type = DDB_TUNER_MCI_M8,
|
||||
.temp_num = 1,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_m8a = {
|
||||
.type = DDB_OCTOPUS_MCI,
|
||||
.name = "Digital Devices MAX M8A",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 4,
|
||||
.tempmon_irq = 24,
|
||||
.mci_ports = 4,
|
||||
.mci_type = DDB_TUNER_MCI_M8A,
|
||||
.temp_num = 1,
|
||||
.lnb_base = 0x400,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_ci_m2 = {
|
||||
.type = DDB_OCTOPUS_MCI,
|
||||
.name = "Digital Devices Octopus CI M2",
|
||||
.regmap = &octopus_mci_map,
|
||||
.port_num = 4,
|
||||
.tempmon_irq = 24,
|
||||
.mci_ports = 1,
|
||||
.mci_type = DDB_TUNER_MCI_M2,
|
||||
.temp_num = 1,
|
||||
.ci_mask = 0x0c,
|
||||
.ci_base = 0x400,
|
||||
.lnb_base = 0x480,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static const struct ddb_regmap octopus_net_map = {
|
||||
.irq_version = 1,
|
||||
.irq_base_i2c = 0,
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
.input = &octopus_input,
|
||||
.output = &octopus_output,
|
||||
};
|
||||
|
||||
static const struct ddb_regset octopus_gtl = {
|
||||
.base = 0x180,
|
||||
.num = 0x01,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static const struct ddb_regmap octopus_net_gtl = {
|
||||
.irq_version = 1,
|
||||
.irq_base_i2c = 0,
|
||||
.irq_base_gtl = 10,
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
.input = &octopus_input,
|
||||
.output = &octopus_output,
|
||||
.gtl = &octopus_gtl,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octonet = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet network DVB adapter",
|
||||
.regmap = &octopus_net_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.ns_num = 12,
|
||||
.mdio_base = 0x20,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octonet_jse = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet network DVB adapter JSE",
|
||||
.regmap = &octopus_net_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.ns_num = 15,
|
||||
.mdio_base = 0x20,
|
||||
};
|
||||
|
||||
static const struct ddb_info ddb_octonet_gtl = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet GTL",
|
||||
.regmap = &octopus_net_gtl,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x05,
|
||||
.ns_num = 12,
|
||||
.mdio_base = 0x20,
|
||||
.con_clock = 1,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
struct ddb_device_id {
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
u16 subvendor;
|
||||
u16 subdevice;
|
||||
const struct ddb_info *info;
|
||||
};
|
||||
|
||||
#define DDB_DEVID(_device, _subdevice, _info) { \
|
||||
.vendor = 0xdd01, \
|
||||
.device = _device, \
|
||||
.subvendor = 0xdd01, \
|
||||
.subdevice = _subdevice, \
|
||||
.info = &(_info) }
|
||||
|
||||
static const struct ddb_device_id ddb_device_ids[] = {
|
||||
/* OctopusNet */
|
||||
DDB_DEVID(0x0300, 0xffff, ddb_octonet),
|
||||
DDB_DEVID(0x0301, 0xffff, ddb_octonet_jse),
|
||||
DDB_DEVID(0x0307, 0xffff, ddb_octonet_gtl),
|
||||
|
||||
/* PCIe devices */
|
||||
|
||||
/* DVB tuners and demodulators */
|
||||
DDB_DEVID(0x0002, 0x0001, ddb_octopus),
|
||||
DDB_DEVID(0x0003, 0x0001, ddb_octopus),
|
||||
DDB_DEVID(0x0005, 0x0004, ddb_octopusv3),
|
||||
DDB_DEVID(0x0003, 0x0002, ddb_octopus_le),
|
||||
DDB_DEVID(0x0003, 0x0003, ddb_octopus_oem),
|
||||
DDB_DEVID(0x0003, 0x0010, ddb_octopus_mini),
|
||||
DDB_DEVID(0x0005, 0x0011, ddb_octopus_mini),
|
||||
DDB_DEVID(0x0003, 0x0020, ddb_v6),
|
||||
DDB_DEVID(0x0003, 0x0021, ddb_v6_5),
|
||||
DDB_DEVID(0x0006, 0x0022, ddb_v7),
|
||||
DDB_DEVID(0x0006, 0x0024, ddb_v7a),
|
||||
DDB_DEVID(0x0003, 0x0030, ddb_dvbct),
|
||||
DDB_DEVID(0x0003, 0xdb03, ddb_satixs2v3),
|
||||
DDB_DEVID(0x0006, 0x0031, ddb_ctv7),
|
||||
DDB_DEVID(0x0006, 0x0032, ddb_ctv7),
|
||||
DDB_DEVID(0x0006, 0x0033, ddb_ctv7),
|
||||
DDB_DEVID(0x0007, 0x0023, ddb_s2_48),
|
||||
DDB_DEVID(0x0008, 0x0034, ddb_ct2_8),
|
||||
DDB_DEVID(0x0008, 0x0035, ddb_c2t2_8),
|
||||
DDB_DEVID(0x0008, 0x0036, ddb_isdbt_8),
|
||||
DDB_DEVID(0x0008, 0x0037, ddb_c2t2i_v0_8),
|
||||
DDB_DEVID(0x0008, 0x0038, ddb_c2t2i_8),
|
||||
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(0x0014, 0x0045, ddb_ci_m2),
|
||||
DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini),
|
||||
DDB_DEVID(0x0022, 0x0052, ddb_m8),
|
||||
DDB_DEVID(0x0024, 0x0053, ddb_m8a),
|
||||
|
||||
/* 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_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_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 ||
|
||||
id->subvendor == 0xffff) &&
|
||||
(subdevice == id->subdevice ||
|
||||
id->subdevice == 0xffff))
|
||||
return id->info;
|
||||
}
|
||||
return &ddb_none;
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-i2c.c: Digital Devices bridge i2c driver
|
||||
*
|
||||
* Copyright (C) 2010-2015 Digital Devices GmbH
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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,93 +19,11 @@
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static int i2c_io(struct i2c_adapter *adapter, u8 adr,
|
||||
u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
|
||||
{
|
||||
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
|
||||
.buf = wbuf, .len = wlen },
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = rbuf, .len = rlen } };
|
||||
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
||||
{
|
||||
struct i2c_msg msg = {.addr = adr, .flags = 0,
|
||||
.buf = data, .len = len};
|
||||
|
||||
return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
|
||||
{
|
||||
struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = val, .len = 1 } };
|
||||
return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_read_regs(struct i2c_adapter *adapter,
|
||||
u8 adr, u8 reg, u8 *val, u8 len)
|
||||
{
|
||||
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
|
||||
.buf = ®, .len = 1 },
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = val, .len = len } };
|
||||
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_read_regs16(struct i2c_adapter *adapter,
|
||||
u8 adr, u16 reg, u8 *val, u8 len)
|
||||
{
|
||||
u8 reg16[2] = { reg >> 8, reg };
|
||||
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
|
||||
.buf = reg16, .len = 2 },
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = val, .len = len } };
|
||||
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
|
||||
{
|
||||
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
|
||||
.buf = ®, .len = 1},
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = val, .len = 1 } };
|
||||
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
|
||||
u16 reg, u8 *val)
|
||||
{
|
||||
u8 msg[2] = {reg >> 8, reg & 0xff};
|
||||
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
|
||||
.buf = msg, .len = 2},
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = val, .len = 1 } };
|
||||
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
|
||||
u16 reg, u8 val)
|
||||
{
|
||||
u8 msg[3] = {reg >> 8, reg & 0xff, val};
|
||||
|
||||
return i2c_write(adap, adr, msg, 3);
|
||||
}
|
||||
|
||||
static int i2c_write_reg(struct i2c_adapter *adap, u8 adr,
|
||||
u8 reg, u8 val)
|
||||
{
|
||||
u8 msg[2] = {reg, val};
|
||||
|
||||
return i2c_write(adap, adr, msg, 2);
|
||||
}
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
|
||||
static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
|
||||
{
|
||||
@@ -115,31 +35,36 @@ 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) {
|
||||
pr_err("DDBridge 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);
|
||||
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);
|
||||
u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
|
||||
|
||||
dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n",
|
||||
val, mon);
|
||||
}
|
||||
dev_err(dev->dev, "I2C timeout, card %d, port %d, link %u\n",
|
||||
dev->nr, i2c->nr, i2c->link);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
return -EIO;
|
||||
}
|
||||
if (val & 0x70000)
|
||||
val &= 0x70000;
|
||||
if (val == 0x20000)
|
||||
dev_err(dev->dev, "I2C bus error\n");
|
||||
if (val)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
@@ -147,42 +72,47 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
|
||||
static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
|
||||
struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
|
||||
struct ddb *dev = i2c->dev;
|
||||
u8 addr = 0;
|
||||
|
||||
if (num != 1 && num != 2)
|
||||
return -EIO;
|
||||
|
||||
addr = msg[0].addr;
|
||||
if (msg[0].len > i2c->bsize)
|
||||
return -EIO;
|
||||
if (num == 2 && msg[1].flags & I2C_M_RD &&
|
||||
!(msg[0].flags & I2C_M_RD)) {
|
||||
if (msg[1].len > i2c->bsize)
|
||||
return -EIO;
|
||||
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
|
||||
ddbwritel(dev, msg[0].len | (msg[1].len << 16),
|
||||
i2c->regs + I2C_TASKLENGTH);
|
||||
if (!ddb_i2c_cmd(i2c, addr, 1)) {
|
||||
ddbcpyfrom(dev, msg[1].buf,
|
||||
i2c->rbuf,
|
||||
msg[1].len);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
|
||||
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
|
||||
ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
|
||||
if (!ddb_i2c_cmd(i2c, addr, 2))
|
||||
return num;
|
||||
}
|
||||
if (num == 1 && (msg[0].flags & I2C_M_RD)) {
|
||||
ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
|
||||
if (!ddb_i2c_cmd(i2c, addr, 3)) {
|
||||
switch (num) {
|
||||
case 1:
|
||||
if (msg[0].flags & I2C_M_RD) {
|
||||
ddbwritel(dev, msg[0].len << 16,
|
||||
i2c->regs + I2C_TASKLENGTH);
|
||||
if (ddb_i2c_cmd(i2c, addr, 3))
|
||||
break;
|
||||
ddbcpyfrom(dev, msg[0].buf,
|
||||
i2c->rbuf, msg[0].len);
|
||||
return num;
|
||||
}
|
||||
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
|
||||
ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
|
||||
if (ddb_i2c_cmd(i2c, addr, 2))
|
||||
break;
|
||||
return num;
|
||||
case 2:
|
||||
if ((msg[0].flags & I2C_M_RD) == I2C_M_RD)
|
||||
break;
|
||||
if ((msg[1].flags & I2C_M_RD) != I2C_M_RD)
|
||||
break;
|
||||
if (msg[1].len > i2c->bsize)
|
||||
break;
|
||||
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
|
||||
ddbwritel(dev, msg[0].len | (msg[1].len << 16),
|
||||
i2c->regs + I2C_TASKLENGTH);
|
||||
if (ddb_i2c_cmd(i2c, addr, 1))
|
||||
break;
|
||||
ddbcpyfrom(dev, msg[1].buf,
|
||||
i2c->rbuf,
|
||||
msg[1].len);
|
||||
return num;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
@@ -197,7 +127,7 @@ struct i2c_algorithm ddb_i2c_algo = {
|
||||
.functionality = ddb_i2c_functionality,
|
||||
};
|
||||
|
||||
static void ddb_i2c_release(struct ddb *dev)
|
||||
void ddb_i2c_release(struct ddb *dev)
|
||||
{
|
||||
int i;
|
||||
struct ddb_i2c *i2c;
|
||||
@@ -208,66 +138,69 @@ static void ddb_i2c_release(struct ddb *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_handler(unsigned long priv)
|
||||
static void i2c_handler(void *priv)
|
||||
{
|
||||
struct ddb_i2c *i2c = (struct ddb_i2c *) priv;
|
||||
struct ddb_i2c *i2c = (struct ddb_i2c *)priv;
|
||||
|
||||
complete(&i2c->completion);
|
||||
}
|
||||
|
||||
static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
|
||||
struct ddb_regmap *regmap, int link, int i, int num)
|
||||
const struct ddb_regmap *regmap,
|
||||
int link, int i, int num)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
|
||||
|
||||
i2c->nr = i;
|
||||
i2c->dev = dev;
|
||||
i2c->link = link;
|
||||
i2c->bsize = regmap->i2c_buf->size;
|
||||
i2c->wbuf = DDB_LINK_TAG(link) | (regmap->i2c_buf->base + i2c->bsize * i);
|
||||
i2c->rbuf = i2c->wbuf;// + i2c->bsize / 2;
|
||||
i2c->regs = DDB_LINK_TAG(link) | (regmap->i2c->base + regmap->i2c->size * i);
|
||||
i2c->wbuf = DDB_LINK_TAG(link) |
|
||||
(regmap->i2c_buf->base + i2c->bsize * i);
|
||||
i2c->rbuf = i2c->wbuf;/* + i2c->bsize / 2; */
|
||||
i2c->regs = DDB_LINK_TAG(link) |
|
||||
(regmap->i2c->base + regmap->i2c->size * i);
|
||||
ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
|
||||
ddbwritel(dev, ((i2c->rbuf & 0xffff) << 16) | (i2c->wbuf & 0xffff),
|
||||
i2c->regs + I2C_TASKADDRESS);
|
||||
init_completion(&i2c->completion);
|
||||
|
||||
adap = &i2c->adap;
|
||||
i2c_set_adapdata(adap, i2c);
|
||||
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
|
||||
adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
|
||||
adap->class = I2C_ADAP_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG;
|
||||
#else
|
||||
#ifdef I2C_CLASS_TV_ANALOG
|
||||
adap->class = I2C_CLASS_TV_ANALOG;
|
||||
#endif
|
||||
#endif
|
||||
strcpy(adap->name, "ddbridge");
|
||||
snprintf(adap->name, I2C_NAME_SIZE, "ddbridge_%02x.%x.%x",
|
||||
dev->nr, i2c->link, i);
|
||||
adap->algo = &ddb_i2c_algo;
|
||||
adap->algo_data = (void *)i2c;
|
||||
adap->dev.parent = dev->dev;
|
||||
return i2c_add_adapter(adap);
|
||||
}
|
||||
|
||||
static int ddb_i2c_init(struct ddb *dev)
|
||||
int ddb_i2c_init(struct ddb *dev)
|
||||
{
|
||||
int stat = 0;
|
||||
u32 i, j, num = 0, l;
|
||||
u32 i, j, num = 0, l, base;
|
||||
struct ddb_i2c *i2c;
|
||||
struct i2c_adapter *adap;
|
||||
struct ddb_regmap *regmap;
|
||||
|
||||
const struct ddb_regmap *regmap;
|
||||
|
||||
for (l = 0; l < DDB_MAX_LINK; l++) {
|
||||
if (!dev->link[l].info)
|
||||
continue;
|
||||
regmap = dev->link[l].info->regmap;
|
||||
if (!regmap || !regmap->i2c)
|
||||
continue;
|
||||
base = regmap->irq_base_i2c;
|
||||
for (i = 0; i < regmap->i2c->num; i++) {
|
||||
if (!(dev->link[l].info->i2c_mask & (1 << i)))
|
||||
continue;
|
||||
i2c = &dev->i2c[num];
|
||||
dev->handler_data[i + l * 32] = (unsigned long) i2c;
|
||||
dev->handler[i + l * 32] = i2c_handler;
|
||||
ddb_irq_set(dev, l, i + base, i2c_handler, i2c);
|
||||
stat = ddb_i2c_add(dev, i2c, regmap, l, i, num);
|
||||
if (stat)
|
||||
break;
|
||||
@@ -280,8 +213,9 @@ static int ddb_i2c_init(struct ddb *dev)
|
||||
adap = &i2c->adap;
|
||||
i2c_del_adapter(adap);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
dev->i2c_num = num;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ddbridge-i2c.h: Digital Devices bridge i2c driver
|
||||
*
|
||||
* Copyright (C) 2010-2015 Digital Devices GmbH
|
||||
* Marcus Metzler <mocm@metzlerbros.de>
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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,10 +19,7 @@
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, 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_
|
||||
|
||||
188
ddbridge/ddbridge-io.c
Normal file
188
ddbridge/ddbridge-io.c
Normal file
@@ -0,0 +1,188 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-io.c: Digital Devices bridge I/O functions
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
|
||||
u32 ddblreadl(struct ddb_link *link, u32 adr)
|
||||
{
|
||||
if (unlikely(link->nr)) {
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddblwritel0(link, adr & 0xfffc, link->regs + 0x14);
|
||||
ddblwritel0(link, 3, link->regs + 0x10);
|
||||
gtlw(link);
|
||||
val = ddblreadl0(link, link->regs + 0x1c);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return val;
|
||||
}
|
||||
return readl(link->dev->regs + adr);
|
||||
}
|
||||
|
||||
void ddblwritel(struct ddb_link *link, u32 val, u32 adr)
|
||||
{
|
||||
if (unlikely(link->nr)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddblwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
|
||||
ddblwritel0(link, val, link->regs + 0x18);
|
||||
ddblwritel0(link, 1, link->regs + 0x10);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return;
|
||||
}
|
||||
writel(val, link->dev->regs + adr);
|
||||
}
|
||||
|
||||
u32 ddbreadl(struct ddb *dev, u32 adr)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000)) {
|
||||
unsigned long flags;
|
||||
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);
|
||||
ddblwritel0(link, 3, link->regs + 0x10);
|
||||
gtlw(link);
|
||||
val = ddblreadl0(link, link->regs + 0x1c);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return val;
|
||||
}
|
||||
return readl(dev->regs + adr);
|
||||
}
|
||||
|
||||
void ddbwritel(struct ddb *dev, u32 val, u32 adr)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000)) {
|
||||
unsigned long flags;
|
||||
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);
|
||||
ddblwritel0(link, val, link->regs + 0x18);
|
||||
ddblwritel0(link, 1, link->regs + 0x10);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return;
|
||||
}
|
||||
writel(val, dev->regs + adr);
|
||||
}
|
||||
|
||||
void gtlcpyto(struct ddb *dev, u32 adr, const u8 *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
u32 val = 0, p = adr;
|
||||
u32 aa = p & 3;
|
||||
|
||||
if (aa) {
|
||||
while (p & 3 && count) {
|
||||
val >>= 8;
|
||||
val |= *buf << 24;
|
||||
p++;
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
ddbwritel(dev, val, adr);
|
||||
}
|
||||
while (count >= 4) {
|
||||
val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
ddbwritel(dev, val, p);
|
||||
p += 4;
|
||||
buf += 4;
|
||||
count -= 4;
|
||||
}
|
||||
if (count) {
|
||||
val = buf[0];
|
||||
if (count > 1)
|
||||
val |= buf[1] << 8;
|
||||
if (count > 2)
|
||||
val |= buf[2] << 16;
|
||||
ddbwritel(dev, val, p);
|
||||
}
|
||||
}
|
||||
|
||||
void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count)
|
||||
{
|
||||
u32 val = 0, p = adr;
|
||||
u32 a = p & 3;
|
||||
|
||||
if (a) {
|
||||
val = ddbreadl(dev, p & ~3) >> (8 * a);
|
||||
while ((p & 3) && count) {
|
||||
*buf = val & 0xff;
|
||||
val >>= 8;
|
||||
p++;
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
while (count >= 4) {
|
||||
val = ddbreadl(dev, p);
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
buf[3] = (val >> 24) & 0xff;
|
||||
p += 4;
|
||||
buf += 4;
|
||||
count -= 4;
|
||||
}
|
||||
if (count) {
|
||||
val = ddbreadl(dev, p);
|
||||
buf[0] = val & 0xff;
|
||||
if (count > 1)
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
if (count > 2)
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000))
|
||||
return gtlcpyto(dev, adr, src, count);
|
||||
return memcpy_toio(dev->regs + adr, src, 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);
|
||||
*/
|
||||
|
||||
}
|
||||
98
ddbridge/ddbridge-io.h
Normal file
98
ddbridge/ddbridge-io.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ddbridge-io.h: Digital Devices bridge I/O functions
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _DDBRIDGE_IO_H_
|
||||
#define _DDBRIDGE_IO_H_
|
||||
|
||||
u32 ddblreadl(struct ddb_link *link, u32 adr);
|
||||
void ddblwritel(struct ddb_link *link, u32 val, u32 adr);
|
||||
u32 ddbreadl(struct ddb *dev, u32 adr);
|
||||
void ddbwritel(struct ddb *dev, u32 val, u32 adr);
|
||||
void gtlcpyto(struct ddb *dev, u32 adr, const u8 *buf,
|
||||
unsigned int count);
|
||||
void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count);
|
||||
void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count);
|
||||
void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count);
|
||||
|
||||
static inline void ddbwriteb0(struct ddb *dev, u32 val, u32 adr)
|
||||
{
|
||||
writeb(val, dev->regs + adr);
|
||||
}
|
||||
|
||||
static inline u32 ddbreadb0(struct ddb *dev, u32 adr)
|
||||
{
|
||||
return readb(dev->regs + adr);
|
||||
}
|
||||
|
||||
static inline void ddbwritel0(struct ddb *dev, u32 val, u32 adr)
|
||||
{
|
||||
writel(val, dev->regs + adr);
|
||||
}
|
||||
|
||||
static inline u32 ddbreadl0(struct ddb *dev, u32 adr)
|
||||
{
|
||||
return readl(dev->regs + adr);
|
||||
}
|
||||
|
||||
static inline void ddblwritel0(struct ddb_link *link, u32 val, u32 adr)
|
||||
{
|
||||
writel(val, link->dev->regs + adr);
|
||||
}
|
||||
|
||||
static inline u32 ddblreadl0(struct ddb_link *link, u32 adr)
|
||||
{
|
||||
return readl(link->dev->regs + adr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_GTLW
|
||||
static inline void gtlw(struct ddb_link *link)
|
||||
{
|
||||
u32 count = 0;
|
||||
static u32 max;
|
||||
|
||||
while (1 & ddblreadl0(link, link->regs + 0x10)) {
|
||||
if (++count == 1024) {
|
||||
pr_info("LTO\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count > max) {
|
||||
max = count;
|
||||
pr_info("TO=%u\n", max);
|
||||
}
|
||||
if (ddblreadl0(link, link->regs + 0x10) & 0x8000)
|
||||
pr_err("link error\n");
|
||||
}
|
||||
#else
|
||||
static inline void gtlw(struct ddb_link *link)
|
||||
{
|
||||
while (1 & ddblreadl0(link, link->regs + 0x10))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ddbmemset(_dev, _adr, _val, _count) \
|
||||
memset_io(((_dev)->regs + (_adr)), (_val), (_count))
|
||||
|
||||
#endif
|
||||
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
|
||||
662
ddbridge/ddbridge-m4.c
Normal file
662
ddbridge/ddbridge-m4.c
Normal file
@@ -0,0 +1,662 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-m4.c: Digital Devices MAX M4 driver
|
||||
*
|
||||
* Copyright (C) 2018 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
#include "ddbridge-mci.h"
|
||||
|
||||
struct m4_base {
|
||||
struct mci_base mci_base;
|
||||
|
||||
};
|
||||
|
||||
struct m4 {
|
||||
struct mci mci;
|
||||
|
||||
int started;
|
||||
int t2_signalling_valid;
|
||||
int iq_constellation_point;
|
||||
int iq_constellation_point_max;
|
||||
int iq_constellation_tap;
|
||||
int first_time_lock;
|
||||
};
|
||||
|
||||
static int stop(struct dvb_frontend *fe)
|
||||
{
|
||||
struct m4 *state = fe->demodulator_priv;
|
||||
struct mci_command cmd;
|
||||
|
||||
if (!state->started)
|
||||
return -1;
|
||||
state->started = 0;
|
||||
state->t2_signalling_valid = 0;
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.command = MCI_CMD_STOP;
|
||||
cmd.demod = state->mci.demod;
|
||||
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search_s2(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_DVBS;
|
||||
cmd.dvbs2_search.flags = 3;
|
||||
cmd.dvbs2_search.s2_modulation_mask = 3;
|
||||
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 =
|
||||
p->scrambling_sequence_index;
|
||||
if (p->stream_id != NO_STREAM_ID_FILTER)
|
||||
cmd.dvbs2_search.input_stream_id = p->stream_id;
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int search_c(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_DVBC;
|
||||
if (p->bandwidth_hz <= 6000000)
|
||||
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_6MHZ;
|
||||
else if (p->bandwidth_hz <= 7000000)
|
||||
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_7MHZ;
|
||||
else
|
||||
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_8MHZ;
|
||||
cmd.dvbc_search.retry = 0;
|
||||
cmd.dvbc_search.frequency = p->frequency;
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int search_t(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_DVBT;
|
||||
switch (p->bandwidth_hz) {
|
||||
case 5000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_5MHZ;
|
||||
break;
|
||||
case 6000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_6MHZ;
|
||||
break;
|
||||
case 7000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_7MHZ;
|
||||
break;
|
||||
default:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ;
|
||||
break;
|
||||
}
|
||||
cmd.dvbt_search.retry = 0;
|
||||
cmd.dvbt_search.frequency = p->frequency;
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
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 dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
struct mci_command cmd;
|
||||
int stat;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.command = MCI_CMD_SEARCH_DVBT2;
|
||||
switch (p->bandwidth_hz) {
|
||||
case 1700000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_1_7MHZ;
|
||||
break;
|
||||
case 5000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_5MHZ;
|
||||
break;
|
||||
case 6000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_6MHZ;
|
||||
break;
|
||||
case 7000000:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_7MHZ;
|
||||
break;
|
||||
default:
|
||||
cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
cmd.dvbt2_search.flags |= 0x80;
|
||||
cmd.dvbt2_search.flags |= (p->stream_id >> 8) & 1;
|
||||
}
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int search_c2(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_DVBC2;
|
||||
switch (p->bandwidth_hz) {
|
||||
case 6000000:
|
||||
cmd.dvbc2_search.bandwidth = MCI_BANDWIDTH_6MHZ;
|
||||
break;
|
||||
default:
|
||||
cmd.dvbc2_search.bandwidth = MCI_BANDWIDTH_8MHZ;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
cmd.dvbc2_search.data_slice = (p->stream_id >> 8) & 0xff;
|
||||
}
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int search_isdbt(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_ISDBT;
|
||||
switch (p->bandwidth_hz) {
|
||||
case 8000000:
|
||||
cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_8MHZ;
|
||||
break;
|
||||
case 7000000:
|
||||
cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_7MHZ;
|
||||
break;
|
||||
default:
|
||||
cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_6MHZ;
|
||||
break;
|
||||
}
|
||||
cmd.isdbt_search.retry = 0;
|
||||
cmd.isdbt_search.frequency = p->frequency;
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
|
||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
if (stat)
|
||||
stop(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
state->t2_signalling_valid = 0;
|
||||
state->iq_constellation_point = 0;
|
||||
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:
|
||||
res = search_s2(fe);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
res = search_t2(fe);
|
||||
break;
|
||||
case SYS_DVBC2:
|
||||
res = search_c2(fe);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
if (!res) {
|
||||
state->started = 1;
|
||||
state->first_time_lock = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
int stat;
|
||||
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;
|
||||
stat = ddb_mci_get_info(&state->mci);
|
||||
if (stat)
|
||||
return stat;
|
||||
ddb_mci_get_strength(fe);
|
||||
if (res.status == MCI_DEMOD_WAIT_SIGNAL)
|
||||
*status = 0x01;
|
||||
else if (res.status == MX_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);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (re_tune) {
|
||||
r = set_parameters(fe);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r = read_status(fe, status);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (*status & FE_HAS_LOCK)
|
||||
return 0;
|
||||
*delay = HZ / 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct m4 *state = fe->demodulator_priv;
|
||||
|
||||
if (state->started)
|
||||
stop(fe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct m4 *state = fe->demodulator_priv;
|
||||
struct mci_base *mci_base = state->mci.base;
|
||||
|
||||
mci_base->count--;
|
||||
if (mci_base->count == 0) {
|
||||
list_del(&mci_base->mci_list);
|
||||
kfree(mci_base);
|
||||
}
|
||||
kfree(state);
|
||||
#ifdef CONFIG_MEDIA_ATTACH
|
||||
__module_get(THIS_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return DVBFE_ALGO_HW;
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct m4 *state = fe->demodulator_priv;
|
||||
|
||||
ddb_mci_proc_info(&state->mci, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops m4_ops = {
|
||||
.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_hz = 47125000, /* DVB-T: 47125000 */
|
||||
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||
.symbol_rate_min = 100000,
|
||||
.symbol_rate_max = 100000000,
|
||||
.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
|
||||
},
|
||||
.release = release,
|
||||
.get_frontend_algo = get_algo,
|
||||
.get_frontend = get_frontend,
|
||||
.read_status = read_status,
|
||||
.tune = tune,
|
||||
.sleep = sleep,
|
||||
};
|
||||
|
||||
static int init(struct mci *mci)
|
||||
{
|
||||
//struct m4 *state = (struct m4 *) mci;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int base_init(struct mci_base *mci_base)
|
||||
{
|
||||
//struct m4_base *base = (struct m4_base *) mci_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mci_cfg ddb_max_m4_cfg = {
|
||||
.type = 0,
|
||||
.fe_ops = &m4_ops,
|
||||
.base_size = sizeof(struct m4_base),
|
||||
.state_size = sizeof(struct m4),
|
||||
.init = init,
|
||||
.base_init = base_init,
|
||||
};
|
||||
|
||||
static struct dvb_frontend_ops m_ops = {
|
||||
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
|
||||
SYS_ISDBC,
|
||||
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
|
||||
SYS_DVBS, SYS_DVBS2, SYS_ISDBS, },
|
||||
.info = {
|
||||
.name = "M_AS",
|
||||
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||
.symbol_rate_min = 100000,
|
||||
.symbol_rate_max = 100000000,
|
||||
.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
|
||||
},
|
||||
.release = release,
|
||||
.get_frontend_algo = get_algo,
|
||||
.get_frontend = get_frontend,
|
||||
.read_status = read_status,
|
||||
.tune = tune,
|
||||
.sleep = sleep,
|
||||
};
|
||||
|
||||
static struct mci_cfg ddb_max_m_cfg = {
|
||||
.type = 0,
|
||||
.fe_ops = &m_ops,
|
||||
.base_size = sizeof(struct m4_base),
|
||||
.state_size = sizeof(struct m4),
|
||||
.init = init,
|
||||
.base_init = base_init,
|
||||
};
|
||||
|
||||
static struct dvb_frontend_ops m_s_ops = {
|
||||
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_ISDBS },
|
||||
.info = {
|
||||
.name = "M_S",
|
||||
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||
.symbol_rate_min = 100000,
|
||||
.symbol_rate_max = 100000000,
|
||||
.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
|
||||
},
|
||||
.release = release,
|
||||
.get_frontend_algo = get_algo,
|
||||
.get_frontend = get_frontend,
|
||||
.read_status = read_status,
|
||||
.tune = tune,
|
||||
.sleep = sleep,
|
||||
};
|
||||
|
||||
static struct mci_cfg ddb_max_m_s_cfg = {
|
||||
.type = 0,
|
||||
.fe_ops = &m_s_ops,
|
||||
.base_size = sizeof(struct m4_base),
|
||||
.state_size = sizeof(struct m4),
|
||||
.init = init,
|
||||
.base_init = base_init,
|
||||
};
|
||||
|
||||
static struct dvb_frontend_ops m_a_ops = {
|
||||
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
|
||||
SYS_ISDBC,
|
||||
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
|
||||
},
|
||||
.info = {
|
||||
.name = "M_A",
|
||||
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||
.symbol_rate_min = 100000,
|
||||
.symbol_rate_max = 100000000,
|
||||
.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
|
||||
},
|
||||
.release = release,
|
||||
.get_frontend_algo = get_algo,
|
||||
.get_frontend = get_frontend,
|
||||
.read_status = read_status,
|
||||
.tune = tune,
|
||||
.sleep = sleep,
|
||||
};
|
||||
|
||||
static struct mci_cfg ddb_max_m_a_cfg = {
|
||||
.type = 0,
|
||||
.fe_ops = &m_a_ops,
|
||||
.base_size = sizeof(struct m4_base),
|
||||
.state_size = sizeof(struct m4),
|
||||
.init = init,
|
||||
.base_init = base_init,
|
||||
};
|
||||
|
||||
static struct mci_cfg *ddb_max_cfgs [] = {
|
||||
&ddb_max_m4_cfg,
|
||||
&ddb_max_m_a_cfg,
|
||||
&ddb_max_m_s_cfg,
|
||||
&ddb_max_m_cfg,
|
||||
};
|
||||
|
||||
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type)
|
||||
{
|
||||
return ddb_mci_attach(input, ddb_max_cfgs[type], nr, tuner);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ddb_mx_attach);
|
||||
|
||||
510
ddbridge/ddbridge-main.c
Normal file
510
ddbridge/ddbridge-main.c
Normal file
@@ -0,0 +1,510 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge.c: Digital Devices PCIe bridge driver
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
static int msi = 1;
|
||||
module_param(msi, int, 0444);
|
||||
MODULE_PARM_DESC(msi,
|
||||
" Control MSI interrupts: 0-disable, 1-enable (default)");
|
||||
#endif
|
||||
|
||||
#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
|
||||
#if (KERNEL_VERSION(3, 19, 0) > LINUX_VERSION_CODE)
|
||||
#define msi_desc_to_dev(desc) (&(desc)->dev.dev)
|
||||
#define dev_to_msi_list(dev) (&to_pci_dev((dev))->msi_list)
|
||||
#define first_msi_entry(dev) \
|
||||
list_first_entry(dev_to_msi_list((dev)), struct msi_desc, list)
|
||||
#define for_each_msi_entry(desc, dev) \
|
||||
list_for_each_entry((desc), dev_to_msi_list((dev)), list)
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
#define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev)
|
||||
#define for_each_pci_msi_entry(desc, pdev) \
|
||||
for_each_msi_entry((desc), &(pdev)->dev)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <linux/msi.h>
|
||||
|
||||
int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
|
||||
{
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (dev->msix_enabled) {
|
||||
struct msi_desc *entry;
|
||||
int i = 0;
|
||||
|
||||
for_each_pci_msi_entry(entry, dev) {
|
||||
if (i == nr)
|
||||
return entry->irq;
|
||||
i++;
|
||||
}
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* This does not work < 3.19 because nvec_used is used differently. */
|
||||
#if (KERNEL_VERSION(3, 19, 0) <= LINUX_VERSION_CODE)
|
||||
if (dev->msi_enabled) {
|
||||
struct msi_desc *entry = first_pci_msi_entry(dev);
|
||||
|
||||
if (WARN_ON_ONCE(nr >= entry->nvec_used))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (WARN_ON_ONCE(nr > 0))
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return dev->irq + nr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static void ddb_irq_disable(struct ddb *dev)
|
||||
{
|
||||
if (dev->link[0].info->regmap->irq_version == 2) {
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_3);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_4);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_5);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_6);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_7);
|
||||
} else {
|
||||
ddbwritel(dev, 0, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0, MSI1_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void __devexit ddb_msi_exit(struct ddb *dev)
|
||||
{
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (dev->msi) {
|
||||
#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
|
||||
pci_free_irq_vectors(dev->pdev);
|
||||
#else
|
||||
pci_disable_msi(dev->pdev);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ddb_irq_exit(struct ddb *dev)
|
||||
{
|
||||
ddb_irq_disable(dev);
|
||||
if (dev->msi == 2)
|
||||
free_irq(pci_irq_vector(dev->pdev, 1), dev);
|
||||
free_irq(pci_irq_vector(dev->pdev, 0), dev);
|
||||
}
|
||||
|
||||
static void __devexit ddb_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ddb *dev = (struct ddb *)pci_get_drvdata(pdev);
|
||||
|
||||
ddb_device_destroy(dev);
|
||||
ddb_nsd_detach(dev);
|
||||
ddb_ports_detach(dev);
|
||||
ddb_i2c_release(dev);
|
||||
|
||||
if (dev->link[0].info->ns_num)
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
ddb_irq_exit(dev);
|
||||
ddb_msi_exit(dev);
|
||||
ddb_ports_release(dev);
|
||||
ddb_buffers_free(dev);
|
||||
|
||||
ddb_unmap(dev);
|
||||
pci_clear_master(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
|
||||
#define __devinit
|
||||
#define __devinitdata
|
||||
#endif
|
||||
|
||||
static int __devinit ddb_irq_msi(struct ddb *dev, int nr)
|
||||
{
|
||||
int stat = 0;
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (msi && pci_msi_enabled()) {
|
||||
#if (KERNEL_VERSION(3, 15, 0) <= LINUX_VERSION_CODE)
|
||||
#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
|
||||
stat = pci_alloc_irq_vectors(dev->pdev, 1, nr,
|
||||
PCI_IRQ_MSI | PCI_IRQ_MSIX);
|
||||
#else
|
||||
stat = pci_enable_msi_range(dev->pdev, 1, nr);
|
||||
#endif
|
||||
if (stat >= 1) {
|
||||
dev->msi = stat;
|
||||
dev_info(dev->dev, "using %d MSI interrupt(s)\n",
|
||||
dev->msi);
|
||||
} else {
|
||||
dev_info(dev->dev, "MSI not available.\n");
|
||||
}
|
||||
#else
|
||||
stat = pci_enable_msi_block(dev->pdev, nr);
|
||||
if (stat == 0) {
|
||||
dev->msi = nr;
|
||||
dev_info(dev->dev, "using %d MSI interrupts\n", nr);
|
||||
} else if (stat == 1) {
|
||||
stat = pci_enable_msi(dev->pdev);
|
||||
dev->msi = 1;
|
||||
}
|
||||
if (stat < 0)
|
||||
dev_info(dev->dev, "MSI not available.\n");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int __devinit ddb_irq_init2(struct ddb *dev)
|
||||
{
|
||||
int stat;
|
||||
int irq_flag = IRQF_SHARED;
|
||||
|
||||
dev_info(dev->dev, "init type 2 IRQ hardware block\n");
|
||||
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_3);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_4);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_5);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_6);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_7);
|
||||
|
||||
ddb_irq_msi(dev, 1);
|
||||
if (dev->msi)
|
||||
irq_flag = 0;
|
||||
|
||||
stat = request_irq(pci_irq_vector(dev->pdev, 0), ddb_irq_handler_v2,
|
||||
irq_flag, "ddbridge", (void *)dev);
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
|
||||
ddbwritel(dev, 0x0000ff7f, INTERRUPT_V2_CONTROL);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_1);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_2);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_3);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_4);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_5);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_6);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_7);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int __devinit ddb_irq_init(struct ddb *dev)
|
||||
{
|
||||
int stat;
|
||||
int irq_flag = IRQF_SHARED;
|
||||
|
||||
if (dev->link[0].info->regmap->irq_version == 2)
|
||||
return ddb_irq_init2(dev);
|
||||
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI2_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI3_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI4_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI5_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI6_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI7_ENABLE);
|
||||
|
||||
ddb_irq_msi(dev, 2);
|
||||
|
||||
if (dev->msi)
|
||||
irq_flag = 0;
|
||||
if (dev->msi == 2) {
|
||||
stat = request_irq(pci_irq_vector(dev->pdev, 0), ddb_irq_handler0,
|
||||
irq_flag, "ddbridge", (void *)dev);
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
stat = request_irq(pci_irq_vector(dev->pdev, 1), ddb_irq_handler1,
|
||||
irq_flag, "ddbridge", (void *)dev);
|
||||
if (stat < 0) {
|
||||
free_irq(pci_irq_vector(dev->pdev, 0), dev);
|
||||
return stat;
|
||||
}
|
||||
} else {
|
||||
stat = request_irq(pci_irq_vector(dev->pdev, 0),
|
||||
ddb_irq_handler,
|
||||
irq_flag, "ddbridge", (void *)dev);
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
}
|
||||
/*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/
|
||||
if (dev->msi == 2) {
|
||||
ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
|
||||
} else {
|
||||
ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int __devinit ddb_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct ddb *dev;
|
||||
int stat = 0;
|
||||
|
||||
if (pci_enable_device(pdev) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
#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)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&dev->mutex);
|
||||
dev->has_dma = 1;
|
||||
dev->pdev = pdev;
|
||||
dev->dev = &pdev->dev;
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
dev->link[0].ids.vendor = id->vendor;
|
||||
dev->link[0].ids.device = id->device;
|
||||
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->regs_len = pci_resource_len(dev->pdev, 0);
|
||||
dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0));
|
||||
|
||||
if (!dev->regs) {
|
||||
dev_err(dev->dev, "not enough memory for register map\n");
|
||||
stat = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (ddbreadl(dev, 0) == 0xffffffff) {
|
||||
dev_err(dev->dev, "cannot read registers\n");
|
||||
stat = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->link[0].ids.hwid = ddbreadl(dev, 0);
|
||||
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (dev->link[0].info->ns_num) {
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
ddb_reset_ios(dev);
|
||||
}
|
||||
ddbwritel(dev, 0, DMA_BASE_READ);
|
||||
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 (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) {
|
||||
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;
|
||||
|
||||
if (ddb_init(dev) == 0)
|
||||
return 0;
|
||||
|
||||
ddb_irq_exit(dev);
|
||||
fail0:
|
||||
dev_err(dev->dev, "fail0\n");
|
||||
ddb_msi_exit(dev);
|
||||
fail:
|
||||
dev_err(dev->dev, "fail\n");
|
||||
|
||||
ddb_unmap(dev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_disable_device(pdev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
#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) }
|
||||
|
||||
static const struct pci_device_id ddb_id_table[] __devinitconst = {
|
||||
DDB_DEVICE_ANY(0x0002),
|
||||
DDB_DEVICE_ANY(0x0003),
|
||||
DDB_DEVICE_ANY(0x0005),
|
||||
DDB_DEVICE_ANY(0x0006),
|
||||
DDB_DEVICE_ANY(0x0007),
|
||||
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(0x0014),
|
||||
DDB_DEVICE_ANY(0x0020),
|
||||
DDB_DEVICE_ANY(0x0022),
|
||||
DDB_DEVICE_ANY(0x0024),
|
||||
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),
|
||||
{0}
|
||||
};
|
||||
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)
|
||||
{
|
||||
int stat;
|
||||
|
||||
pr_info("Digital Devices PCIE bridge driver "
|
||||
DDBRIDGE_VERSION
|
||||
", Copyright (C) 2010-19 Digital Devices GmbH\n");
|
||||
stat = ddb_init_ddbridge();
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
stat = pci_register_driver(&ddb_pci_driver);
|
||||
if (stat < 0)
|
||||
ddb_exit_ddbridge(0, stat);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static __exit void module_exit_ddbridge(void)
|
||||
{
|
||||
pci_unregister_driver(&ddb_pci_driver);
|
||||
ddb_exit_ddbridge(0, 0);
|
||||
}
|
||||
|
||||
module_init(module_init_ddbridge);
|
||||
module_exit(module_exit_ddbridge);
|
||||
|
||||
MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
|
||||
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION(DDBRIDGE_VERSION);
|
||||
597
ddbridge/ddbridge-max.c
Normal file
597
ddbridge/ddbridge-max.c
Normal file
@@ -0,0 +1,597 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-max.c: Digital Devices MAX card line support functions
|
||||
*
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
#include "ddbridge-i2c.h"
|
||||
|
||||
/* MAX LNB interface related module parameters */
|
||||
|
||||
static int delmode;
|
||||
module_param(delmode, int, 0444);
|
||||
MODULE_PARM_DESC(delmode, "frontend delivery system mode");
|
||||
|
||||
static int fmode;
|
||||
module_param(fmode, int, 0444);
|
||||
MODULE_PARM_DESC(fmode, "frontend emulation mode");
|
||||
|
||||
static int fmode_sat = -1;
|
||||
module_param(fmode_sat, int, 0444);
|
||||
MODULE_PARM_DESC(fmode_sat, "set frontend emulation mode sat");
|
||||
|
||||
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)
|
||||
{
|
||||
u32 c, v = 0, tag = DDB_LINK_TAG(link);
|
||||
u32 base = dev->link[link].info->lnb_base;
|
||||
|
||||
v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb));
|
||||
ddbwritel(dev, cmd | v, tag | base | LNB_CONTROL(lnb));
|
||||
for (c = 0; c < 10; c++) {
|
||||
v = ddbreadl(dev, tag | base | LNB_CONTROL(lnb));
|
||||
if ((v & LNB_BUSY) == 0)
|
||||
break;
|
||||
msleep(20);
|
||||
}
|
||||
if (c == 10)
|
||||
dev_info(dev->dev,
|
||||
"%s lnb = %08x cmd = %08x\n",
|
||||
__func__, lnb, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
if ((cmd[0] != 0xe0) || (cmd[1] != 0x10) || (cmd[2] != 0x39))
|
||||
return -1;
|
||||
|
||||
input = cmd[3] & 3;
|
||||
max_set_input(fe, input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max_send_master_cmd(struct dvb_frontend *fe,
|
||||
struct dvb_diseqc_master_cmd *cmd)
|
||||
{
|
||||
struct ddb_input *input = fe->sec_priv;
|
||||
struct ddb_port *port = input->port;
|
||||
struct ddb *dev = port->dev;
|
||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||
u32 tag = DDB_LINK_TAG(port->lnr);
|
||||
u32 base = dev->link[port->lnr].info->lnb_base;
|
||||
int i;
|
||||
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
||||
|
||||
if (fmode == 2 || fmode == 1)
|
||||
return 0;
|
||||
|
||||
if (fmode == 4)
|
||||
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);
|
||||
|
||||
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
||||
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(dvb->input));
|
||||
for (i = 0; i < cmd->msg_len; i++)
|
||||
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(dvb->input));
|
||||
lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
|
||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input,
|
||||
struct dvb_diseqc_master_cmd *cmd)
|
||||
{
|
||||
u32 tag = DDB_LINK_TAG(link);
|
||||
u32 base = dev->link[link].info->lnb_base;
|
||||
int i;
|
||||
|
||||
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(input));
|
||||
for (i = 0; i < cmd->msg_len; i++)
|
||||
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(input));
|
||||
lnb_command(dev, link, input, LNB_CMD_DISEQC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lnb_set_sat(struct ddb *dev, u32 link,
|
||||
u32 input, u32 sat, u32 band, u32 hor)
|
||||
{
|
||||
struct dvb_diseqc_master_cmd cmd = {
|
||||
.msg = {0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00},
|
||||
.msg_len = 4
|
||||
};
|
||||
cmd.msg[3] = 0xf0 | (((sat << 2) & 0x0c) |
|
||||
(band ? 1 : 0) | (hor ? 2 : 0));
|
||||
return lnb_send_diseqc(dev, link, input, &cmd);
|
||||
}
|
||||
|
||||
static int lnb_set_tone(struct ddb *dev, u32 link, u32 input,
|
||||
enum fe_sec_tone_mode tone)
|
||||
{
|
||||
int s = 0;
|
||||
u32 mask = (1ULL << input);
|
||||
|
||||
switch (tone) {
|
||||
case SEC_TONE_OFF:
|
||||
if (!(dev->link[link].lnb.tone & mask))
|
||||
return 0;
|
||||
dev->link[link].lnb.tone &= ~(1ULL << input);
|
||||
break;
|
||||
case SEC_TONE_ON:
|
||||
if (dev->link[link].lnb.tone & mask)
|
||||
return 0;
|
||||
dev->link[link].lnb.tone |= (1ULL << input);
|
||||
break;
|
||||
default:
|
||||
s = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!s)
|
||||
s = lnb_command(dev, link, input, LNB_CMD_NOP);
|
||||
return s;
|
||||
}
|
||||
|
||||
static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input,
|
||||
enum fe_sec_voltage voltage)
|
||||
{
|
||||
int s = 0;
|
||||
|
||||
if (no_voltage)
|
||||
voltage = SEC_VOLTAGE_OFF;
|
||||
if (dev->link[link].lnb.oldvoltage[input] == voltage)
|
||||
return 0;
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
if (dev->link[link].lnb.voltage[input])
|
||||
return 0;
|
||||
lnb_command(dev, link, input, LNB_CMD_OFF);
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
lnb_command(dev, link, input, LNB_CMD_LOW);
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
lnb_command(dev, link, input, LNB_CMD_HIGH);
|
||||
break;
|
||||
default:
|
||||
s = -EINVAL;
|
||||
break;
|
||||
}
|
||||
dev->link[link].lnb.oldvoltage[input] = voltage;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int max_set_input_unlocked(struct dvb_frontend *fe, int in)
|
||||
{
|
||||
struct ddb_input *input = fe->sec_priv;
|
||||
struct ddb_port *port = input->port;
|
||||
struct ddb *dev = port->dev;
|
||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||
int res = 0;
|
||||
|
||||
if (in > 3)
|
||||
return -EINVAL;
|
||||
if (dvb->input != in) {
|
||||
u32 bit = (1ULL << input->nr);
|
||||
u32 obit = dev->link[port->lnr].lnb.voltage[dvb->input] & bit;
|
||||
|
||||
dev->link[port->lnr].lnb.voltage[dvb->input] &= ~bit;
|
||||
dvb->input = in;
|
||||
dev->link[port->lnr].lnb.voltage[dvb->input] |= obit;
|
||||
}
|
||||
if (dvb->set_input)
|
||||
res = dvb->set_input(fe, in);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int max_set_input(struct dvb_frontend *fe, int in)
|
||||
{
|
||||
struct ddb_input *input = fe->sec_priv;
|
||||
struct ddb_port *port = input->port;
|
||||
struct ddb *dev = input->port->dev;
|
||||
int res;
|
||||
|
||||
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
||||
res = max_set_input_unlocked(fe, in);
|
||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int max_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
|
||||
{
|
||||
struct ddb_input *input = fe->sec_priv;
|
||||
struct ddb_port *port = input->port;
|
||||
struct ddb *dev = port->dev;
|
||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||
int tuner = 0;
|
||||
int res = 0;
|
||||
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
||||
|
||||
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
||||
dvb->tone = tone;
|
||||
switch (fmode) {
|
||||
default:
|
||||
case 0:
|
||||
case 3:
|
||||
res = lnb_set_tone(dev, port->lnr, dvb->input, tone);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
if (old_quattro) {
|
||||
if (dvb->tone == SEC_TONE_ON)
|
||||
tuner |= 2;
|
||||
if (dvb->voltage == SEC_VOLTAGE_18)
|
||||
tuner |= 1;
|
||||
} else {
|
||||
if (dvb->tone == SEC_TONE_ON)
|
||||
tuner |= 1;
|
||||
if (dvb->voltage == SEC_VOLTAGE_18)
|
||||
tuner |= 2;
|
||||
}
|
||||
res = max_set_input_unlocked(fe, tuner);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
|
||||
{
|
||||
struct ddb_input *input = fe->sec_priv;
|
||||
struct ddb_port *port = input->port;
|
||||
struct ddb *dev = port->dev;
|
||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||
int tuner = 0;
|
||||
u32 nv, ov = dev->link[port->lnr].lnb.voltages;
|
||||
int res = 0;
|
||||
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
||||
|
||||
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
||||
dvb->voltage = voltage;
|
||||
|
||||
switch (fmode) {
|
||||
case 3:
|
||||
default:
|
||||
case 0:
|
||||
if (fmode == 3)
|
||||
max_set_input_unlocked(fe, 0);
|
||||
if (voltage == SEC_VOLTAGE_OFF)
|
||||
dev->link[port->lnr].lnb.voltage[dvb->input] &=
|
||||
~(1ULL << input->nr);
|
||||
else
|
||||
dev->link[port->lnr].lnb.voltage[dvb->input] |=
|
||||
(1ULL << input->nr);
|
||||
|
||||
res = lnb_set_voltage(dev, port->lnr, dvb->input, voltage);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
if (voltage == SEC_VOLTAGE_OFF)
|
||||
dev->link[port->lnr].lnb.voltages &=
|
||||
~(1ULL << input->nr);
|
||||
else
|
||||
dev->link[port->lnr].lnb.voltages |=
|
||||
(1ULL << input->nr);
|
||||
nv = dev->link[port->lnr].lnb.voltages;
|
||||
|
||||
if (old_quattro) {
|
||||
if (dvb->tone == SEC_TONE_ON)
|
||||
tuner |= 2;
|
||||
if (dvb->voltage == SEC_VOLTAGE_18)
|
||||
tuner |= 1;
|
||||
} else {
|
||||
if (dvb->tone == SEC_TONE_ON)
|
||||
tuner |= 1;
|
||||
if (dvb->voltage == SEC_VOLTAGE_18)
|
||||
tuner |= 2;
|
||||
}
|
||||
res = max_set_input_unlocked(fe, tuner);
|
||||
|
||||
if (nv != ov) {
|
||||
if (nv) {
|
||||
lnb_set_voltage(dev, port->lnr, 0,
|
||||
SEC_VOLTAGE_13);
|
||||
if (fmode == 1) {
|
||||
lnb_set_voltage(dev, port->lnr, 0,
|
||||
SEC_VOLTAGE_13);
|
||||
if (old_quattro) {
|
||||
lnb_set_voltage(dev,
|
||||
port->lnr, 1,
|
||||
SEC_VOLTAGE_18);
|
||||
lnb_set_voltage(dev, port->lnr,
|
||||
2,
|
||||
SEC_VOLTAGE_13);
|
||||
} else {
|
||||
lnb_set_voltage(dev, port->lnr,
|
||||
1,
|
||||
SEC_VOLTAGE_13);
|
||||
lnb_set_voltage(dev, port->lnr,
|
||||
2,
|
||||
SEC_VOLTAGE_18);
|
||||
}
|
||||
lnb_set_voltage(dev, port->lnr, 3,
|
||||
SEC_VOLTAGE_18);
|
||||
}
|
||||
} else {
|
||||
lnb_set_voltage(dev, port->lnr,
|
||||
0, SEC_VOLTAGE_OFF);
|
||||
if (fmode == 1) {
|
||||
lnb_set_voltage(dev, port->lnr, 1,
|
||||
SEC_VOLTAGE_OFF);
|
||||
lnb_set_voltage(dev, port->lnr, 2,
|
||||
SEC_VOLTAGE_OFF);
|
||||
lnb_set_voltage(dev, port->lnr, 3,
|
||||
SEC_VOLTAGE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
u32 base = dev->link[port->lnr].info->lnb_base;
|
||||
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 | base | LNB_CONTROL(dvb->input));
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(0));
|
||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(1));
|
||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(2));
|
||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(3));
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxl_fw_read(void *priv, u8 *buf, u32 len)
|
||||
{
|
||||
struct ddb_link *link = priv;
|
||||
struct ddb *dev = link->dev;
|
||||
|
||||
dev_info(dev->dev,
|
||||
"Read mxl_fw from link %u\n", link->nr);
|
||||
|
||||
return ddbridge_flashread(dev, link->nr, buf, 0xc0000, len);
|
||||
}
|
||||
|
||||
int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm)
|
||||
{
|
||||
u32 l = link->nr;
|
||||
|
||||
if (link->lnb.fmode == fm)
|
||||
return 0;
|
||||
dev_info(dev->dev, "Set fmode link %u = %u\n", l, fm);
|
||||
mutex_lock(&link->lnb.lock);
|
||||
if (fm == 2 || fm == 1) {
|
||||
if (fmode_sat >= 0) {
|
||||
lnb_set_sat(dev, l, 0, fmode_sat, 0, 0);
|
||||
if (old_quattro) {
|
||||
lnb_set_sat(dev, l, 1, fmode_sat, 0, 1);
|
||||
lnb_set_sat(dev, l, 2, fmode_sat, 1, 0);
|
||||
} else {
|
||||
lnb_set_sat(dev, l, 1, fmode_sat, 1, 0);
|
||||
lnb_set_sat(dev, l, 2, fmode_sat, 0, 1);
|
||||
}
|
||||
lnb_set_sat(dev, l, 3, fmode_sat, 1, 1);
|
||||
}
|
||||
lnb_set_tone(dev, l, 0, SEC_TONE_OFF);
|
||||
if (old_quattro) {
|
||||
lnb_set_tone(dev, l, 1, SEC_TONE_OFF);
|
||||
lnb_set_tone(dev, l, 2, SEC_TONE_ON);
|
||||
} else {
|
||||
lnb_set_tone(dev, l, 1, SEC_TONE_ON);
|
||||
lnb_set_tone(dev, l, 2, SEC_TONE_OFF);
|
||||
}
|
||||
lnb_set_tone(dev, l, 3, SEC_TONE_ON);
|
||||
}
|
||||
link->lnb.fmode = fm;
|
||||
mutex_unlock(&link->lnb.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MAXS8 related functions */
|
||||
|
||||
static struct mxl5xx_cfg mxl5xx = {
|
||||
.adr = 0x60,
|
||||
.type = 0x01,
|
||||
.clk = 27000000,
|
||||
.ts_clk = 139,
|
||||
.cap = 12,
|
||||
.fw_read = mxl_fw_read,
|
||||
};
|
||||
|
||||
int ddb_fe_attach_mxl5xx(struct ddb_input *input)
|
||||
{
|
||||
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];
|
||||
struct mxl5xx_cfg cfg;
|
||||
int demod, tuner;
|
||||
|
||||
cfg = mxl5xx;
|
||||
cfg.fw_priv = link;
|
||||
if (dev->link[0].info->type == DDB_OCTONET)
|
||||
;/*cfg.ts_clk = 69;*/
|
||||
|
||||
demod = input->nr;
|
||||
tuner = demod & 3;
|
||||
if (fmode >= 3)
|
||||
tuner = 0;
|
||||
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;
|
||||
}
|
||||
if (input->nr < 4) {
|
||||
lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
|
||||
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
|
||||
}
|
||||
ddb_lnb_init_fmode(dev, link, fmode);
|
||||
|
||||
dvb->fe->ops.set_voltage = max_set_voltage;
|
||||
dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage;
|
||||
dvb->fe->ops.set_tone = max_set_tone;
|
||||
dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd;
|
||||
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;
|
||||
#ifndef KERNEL_DVB_CORE
|
||||
dvb->fe->ops.set_input = max_set_input;
|
||||
#endif
|
||||
dvb->input = tuner;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MAX MCI related functions */
|
||||
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_mx_attach(struct ddb_input *input, int nr, int tuner, int type);
|
||||
|
||||
|
||||
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
||||
{
|
||||
struct ddb *dev = input->port->dev;
|
||||
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;
|
||||
int fm = fmode;
|
||||
|
||||
demod = input->nr;
|
||||
tuner = demod & 3;
|
||||
switch (type) {
|
||||
case DDB_TUNER_MCI_SX8:
|
||||
if (fm >= 3)
|
||||
tuner = 0;
|
||||
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
|
||||
dvb->input = tuner;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M4:
|
||||
fm = 0;
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 0);
|
||||
dvb->input = tuner;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M8:
|
||||
fm = 3;
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 1);
|
||||
dvb->input = 0;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M8A:
|
||||
fm = 3;
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 2);
|
||||
dvb->input = 0;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M2:
|
||||
{
|
||||
u32 mode, mmode;
|
||||
|
||||
// delmode: 0 - sat,sat 1-cable,cable/sat
|
||||
switch (delmode & 1) {
|
||||
case 0:
|
||||
mode = 2;
|
||||
mmode = 2;
|
||||
break;
|
||||
case 1:
|
||||
mode = 1;
|
||||
mmode = demod ? 3 : 1;
|
||||
break;
|
||||
}
|
||||
if (!demod)
|
||||
ddb_mci_cmd_link_simple(link, MCI_CMD_SET_INPUT_CONFIG,
|
||||
0xff, mode | (delmode & 0x10));
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, mmode);
|
||||
dvb->input = tuner;
|
||||
fm = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!dvb->fe) {
|
||||
dev_err(dev->dev, "No MCI card found!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!input->nr || (input->nr < 4 && type != DDB_TUNER_MCI_M8)) {
|
||||
lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
|
||||
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
|
||||
}
|
||||
ddb_lnb_init_fmode(dev, link, fm);
|
||||
|
||||
dvb->fe->ops.set_voltage = max_set_voltage;
|
||||
dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage;
|
||||
dvb->fe->ops.set_tone = max_set_tone;
|
||||
dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd;
|
||||
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;
|
||||
if (type == DDB_TUNER_MCI_SX8) {
|
||||
#ifndef KERNEL_DVB_CORE
|
||||
dvb->fe->ops.set_input = max_set_input;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
467
ddbridge/ddbridge-mci.c
Normal file
467
ddbridge/ddbridge-mci.c
Normal file
@@ -0,0 +1,467 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ddbridge-mci.c: Digital Devices microcode interface
|
||||
*
|
||||
* Copyright (C) 2017-2018 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
#include "ddbridge-mci.h"
|
||||
|
||||
static LIST_HEAD(mci_list);
|
||||
|
||||
static int mci_reset(struct ddb_link *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;
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link,
|
||||
u32 *cmd, u32 cmd_len,
|
||||
u32 *res, u32 res_len)
|
||||
{
|
||||
const struct ddb_regmap *regmap = link->info->regmap;
|
||||
u32 control, command, result;
|
||||
u32 i, val;
|
||||
unsigned long stat;
|
||||
|
||||
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], 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) {
|
||||
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, result + i * 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ddb_mci_cmd_link(struct ddb_link *link,
|
||||
struct mci_command *command,
|
||||
struct mci_result *result)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int ddb_mci_cmd_link_simple(struct ddb_link *link, u8 command, u8 demod, u8 value)
|
||||
{
|
||||
struct mci_command cmd;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.command = command;
|
||||
cmd.demod = demod;
|
||||
cmd.params8[0] = value;
|
||||
return ddb_mci_cmd_link(link, &cmd, 0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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(&link->mci_lock);
|
||||
stat = ddb_mci_cmd_raw_unlocked(link,
|
||||
(u32 *)command, command_len,
|
||||
(u32 *)result, result_len);
|
||||
mutex_unlock(&link->mci_lock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
|
||||
{
|
||||
struct mci_command cmd;
|
||||
|
||||
cmd.command = MCI_CMD_GETSTATUS;
|
||||
cmd.demod = mci->demod;
|
||||
return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1);
|
||||
}
|
||||
|
||||
int ddb_mci_get_snr(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mci *mci = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ddb_mci_get_strength(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mci *mci = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
s32 str;
|
||||
|
||||
str = mci->signal_info.dvbs2_signal_info.channel_power * 10;
|
||||
p->strength.len = 1;
|
||||
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
p->strength.stat[0].svalue = str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ddb_mci_get_info(struct mci *mci)
|
||||
{
|
||||
int stat;
|
||||
struct mci_command cmd;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.command = MCI_CMD_GETSIGNALINFO;
|
||||
cmd.demod = mci->demod;
|
||||
stat = ddb_mci_cmd(mci, &cmd, &mci->signal_info);
|
||||
return stat;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
|
||||
{
|
||||
const enum fe_modulation modcod2mod[0x20] = {
|
||||
QPSK, QPSK, QPSK, QPSK,
|
||||
QPSK, QPSK, QPSK, QPSK,
|
||||
QPSK, QPSK, QPSK, QPSK,
|
||||
PSK_8, PSK_8, PSK_8, PSK_8,
|
||||
PSK_8, PSK_8, APSK_16, APSK_16,
|
||||
APSK_16, APSK_16, APSK_16, APSK_16,
|
||||
APSK_32, APSK_32, APSK_32, APSK_32,
|
||||
APSK_32,
|
||||
};
|
||||
const enum fe_code_rate modcod2fec[0x20] = {
|
||||
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
|
||||
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
|
||||
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
|
||||
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
|
||||
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
|
||||
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
|
||||
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
|
||||
FEC_9_10, FEC_NONE, FEC_NONE, FEC_NONE,
|
||||
};
|
||||
const enum fe_code_rate dvbs_fec_lut[8] = {
|
||||
FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6,
|
||||
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:
|
||||
case SYS_DVBS2:
|
||||
{
|
||||
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;
|
||||
|
||||
p->delivery_system = SYS_DVBS2;
|
||||
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;
|
||||
p->pilot = PILOT_OFF;
|
||||
p->fec_inner = dvbs_fec_lut[pls_code & 7];
|
||||
p->modulation = QPSK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
p->modulation =
|
||||
mci->signal_info.dvbc_signal_info.constellation + 1;
|
||||
break;
|
||||
case SYS_DVBT:
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
break;
|
||||
case SYS_DVBC2:
|
||||
break;
|
||||
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 =
|
||||
mci->signal_info.dvbs2_signal_info.ber_numerator;
|
||||
|
||||
p->pre_bit_count.len = 1;
|
||||
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
|
||||
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 =
|
||||
mci->signal_info.dvbs2_signal_info.packet_errors;
|
||||
p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
|
||||
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->strength.len = 1;
|
||||
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
p->strength.stat[0].svalue = (s64)
|
||||
mci->signal_info.dvbs2_signal_info.channel_power * 10;
|
||||
}
|
||||
|
||||
static struct mci_base *match_base(void *key)
|
||||
{
|
||||
struct mci_base *p;
|
||||
|
||||
list_for_each_entry(p, &mci_list, mci_list)
|
||||
if (p->key == key)
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
struct ddb_link *link = &dev->link[port->lnr];
|
||||
struct mci_base *base;
|
||||
struct mci *state;
|
||||
void *key = cfg->type ? (void *) port : (void *) link;
|
||||
|
||||
state = kzalloc(cfg->state_size, GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
base = match_base(key);
|
||||
if (base) {
|
||||
base->count++;
|
||||
state->base = base;
|
||||
} else {
|
||||
base = kzalloc(cfg->base_size, GFP_KERNEL);
|
||||
if (!base)
|
||||
goto fail;
|
||||
base->key = key;
|
||||
base->count = 1;
|
||||
base->link = link;
|
||||
link->mci_base = base;
|
||||
mutex_init(&base->tuner_lock);
|
||||
state->base = base;
|
||||
|
||||
if (!link->mci_ok) {
|
||||
kfree(base);
|
||||
goto fail;
|
||||
}
|
||||
list_add(&base->mci_list, &mci_list);
|
||||
if (cfg->base_init)
|
||||
cfg->base_init(base);
|
||||
}
|
||||
memcpy(&state->fe.ops, cfg->fe_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->fe.demodulator_priv = state;
|
||||
state->nr = nr;
|
||||
state->demod = nr;
|
||||
state->tuner = tuner;
|
||||
state->input = input;
|
||||
if (cfg->init)
|
||||
cfg->init(state);
|
||||
return &state->fe;
|
||||
fail:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
1007
ddbridge/ddbridge-mci.h
Normal file
1007
ddbridge/ddbridge-mci.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2206
ddbridge/ddbridge-modulator.c
Normal file
2206
ddbridge/ddbridge-modulator.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming
|
||||
*
|
||||
* Copyright (C) 2010-2015 Marcus 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
|
||||
@@ -17,14 +17,12 @@
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
* along with this program; if not, point your browser to
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
static int ddb_dvb_ns_input_start(struct ddb_input *input);
|
||||
static int ddb_dvb_ns_input_stop(struct ddb_input *input);
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.h"
|
||||
|
||||
static u16 calc_pcs(struct dvb_ns_params *p)
|
||||
{
|
||||
@@ -46,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];
|
||||
}
|
||||
@@ -62,7 +60,7 @@ static u16 calc_pcs16(struct dvb_ns_params *p, int ipv)
|
||||
|
||||
static void ns_free(struct dvbnss *nss)
|
||||
{
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
@@ -87,7 +85,6 @@ static int ns_alloc(struct dvbnss *nss)
|
||||
dev->ns[i].fe = input;
|
||||
nss->priv = &dev->ns[i];
|
||||
ret = 0;
|
||||
/*pr_info("%s i=%d fe=%d\n", __func__, i, input->nr); */
|
||||
break;
|
||||
}
|
||||
ddbwritel(dev, 0x03, RTP_MASTER_CONTROL);
|
||||
@@ -100,7 +97,7 @@ static int ns_set_pids(struct dvbnss *nss)
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
|
||||
if (dev->link[0].ids.devid == 0x0301dd01) {
|
||||
u32 sys = 0;
|
||||
@@ -118,8 +115,9 @@ static int ns_set_pids(struct dvbnss *nss)
|
||||
/* disable unused pids */
|
||||
for (; j < 5; j++)
|
||||
ddbwritel(dev, 0, PID_FILTER_PID(dns->nr, j));
|
||||
} else
|
||||
} else {
|
||||
ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -128,7 +126,7 @@ static int ns_set_pid(struct dvbnss *nss, u16 pid)
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
u16 byte = (pid & 0x1fff) >> 3;
|
||||
u8 bit = 1 << (pid & 7);
|
||||
u32 off = STREAM_PIDS(dns->nr);
|
||||
@@ -154,12 +152,12 @@ static int ns_set_pid(struct dvbnss *nss, u16 pid)
|
||||
else
|
||||
ddbmemset(dev, off, 0x00, 0x400);
|
||||
} else {
|
||||
u8 val = ddbreadb(dev, off + byte);
|
||||
u8 val = ddbreadb0(dev, off + byte);
|
||||
|
||||
if (pid & 0x8000)
|
||||
ddbwriteb(dev, val | bit, off + byte);
|
||||
ddbwriteb0(dev, val | bit, off + byte);
|
||||
else
|
||||
ddbwriteb(dev, val & ~bit, off + byte);
|
||||
ddbwriteb0(dev, val & ~bit, off + byte);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -187,7 +185,7 @@ static int ns_set_ci(struct dvbnss *nss, u8 ci)
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
int ciport;
|
||||
|
||||
if (ci == 255) {
|
||||
@@ -197,11 +195,14 @@ static int ns_set_ci(struct dvbnss *nss, u8 ci)
|
||||
ciport = citoport(dev, ci);
|
||||
if (ciport < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("input %d.%d to ci %d at port %d\n", input->port->lnr, input->nr, ci, ciport);
|
||||
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c, TS_OUTPUT_CONTROL(ciport));
|
||||
|
||||
dev_info(dev->dev, "DDBridge: input %d.%d to ci %d at port %d\n",
|
||||
input->port->lnr, input->nr, ci, ciport);
|
||||
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c,
|
||||
TS_CONTROL(dev->port[ciport].output));
|
||||
usleep_range(1, 5);
|
||||
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d, TS_OUTPUT_CONTROL(ciport));
|
||||
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d,
|
||||
TS_CONTROL(dev->port[ciport].output));
|
||||
dns->fe = dev->port[ciport].input[0];
|
||||
return 0;
|
||||
}
|
||||
@@ -244,7 +245,7 @@ static int ns_set_rtcp_msg(struct dvbnss *nss, u8 *msg, u32 len)
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
u32 off = STREAM_PACKET_ADR(dns->nr);
|
||||
u32 coff = 96;
|
||||
u16 wlen;
|
||||
@@ -368,7 +369,7 @@ static u32 set_nsbuf(struct dvb_ns_params *p, u8 *buf,
|
||||
|
||||
static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len)
|
||||
{
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
@@ -385,7 +386,7 @@ static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len)
|
||||
|
||||
static int ns_insert_ts_packets(struct dvbnss *nss, u8 count)
|
||||
{
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
@@ -407,7 +408,7 @@ static int ns_set_net(struct dvbnss *nss)
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
struct dvb_ns_params *p = &nss->params;
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
u32 off = STREAM_PACKET_ADR(dns->nr);
|
||||
u32 coff = 96;
|
||||
|
||||
@@ -426,7 +427,7 @@ static int ns_set_net(struct dvbnss *nss)
|
||||
|
||||
static int ns_start(struct dvbnss *nss)
|
||||
{
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
@@ -440,18 +441,17 @@ 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);
|
||||
printk("ns start ns %u, fe %u link %u\n", dns->nr, dns->fe->nr, dns->fe->port->lnr);
|
||||
ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16),
|
||||
STREAM_CONTROL(dns->nr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ns_stop(struct dvbnss *nss)
|
||||
{
|
||||
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
|
||||
struct ddb_ns *dns = (struct ddb_ns *)nss->priv;
|
||||
struct dvb_netstream *ns = nss->ns;
|
||||
struct ddb_input *input = ns->priv;
|
||||
struct ddb *dev = input->port->dev;
|
||||
@@ -463,7 +463,7 @@ static int ns_stop(struct dvbnss *nss)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netstream_init(struct ddb_input *input)
|
||||
int netstream_init(struct ddb_input *input)
|
||||
{
|
||||
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
|
||||
struct dvb_adapter *adap = dvb->adap;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ddbridge-regs.h: Digital Devices PCIe bridge driver
|
||||
*
|
||||
* Copyright (C) 2010-2015 Digital Devices GmbH
|
||||
* Copyright (C) 2010-2017 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
|
||||
@@ -15,20 +15,22 @@
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
* along with this program; if not, point your browser to
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/* Register Definitions */
|
||||
|
||||
#define CUR_REGISTERMAP_VERSION 0x10003
|
||||
#define CUR_REGISTERMAP_VERSION_CI 0x10000
|
||||
#define CUR_REGISTERMAP_VERSION_MOD 0x10000
|
||||
#define CUR_REGISTERMAP_VERSION 0x10004
|
||||
#define CUR_REGISTERMAP_VERSION_0007 0x10002
|
||||
#define CUR_REGISTERMAP_VERSION_0008 0x10002
|
||||
#define CUR_REGISTERMAP_VERSION_CI 0x10000
|
||||
#define CUR_REGISTERMAP_VERSION_CI_PRO 0x10000
|
||||
|
||||
#define HARDWARE_VERSION 0x00
|
||||
#define REGISTERMAP_VERSION 0x04
|
||||
#define HARDWARE_VERSION 0x0000
|
||||
#define REGISTERMAP_VERSION 0x0004
|
||||
#define DEVICE_ID 0x0008
|
||||
#define BOARD_ID 0x000C
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* SPI Controller */
|
||||
@@ -46,10 +48,10 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* MDIO */
|
||||
|
||||
#define MDIO_CTRL 0x20
|
||||
#define MDIO_ADR 0x24
|
||||
#define MDIO_REG 0x28
|
||||
#define MDIO_VAL 0x2C
|
||||
#define MDIO_CTRL_OFF 0x00
|
||||
#define MDIO_ADR_OFF 0x04
|
||||
#define MDIO_REG_OFF 0x08
|
||||
#define MDIO_VAL_OFF 0x0C
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -58,9 +60,9 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Interrupt controller
|
||||
How many MSI's are available depends on HW (Min 2 max 8)
|
||||
How many are usable also depends on Host platform
|
||||
*/
|
||||
* How many MSI's are available depends on HW (Min 2 max 8)
|
||||
* How many are usable also depends on Host platform
|
||||
*/
|
||||
|
||||
#define INTERRUPT_BASE (0x40)
|
||||
|
||||
@@ -76,6 +78,8 @@
|
||||
|
||||
#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
|
||||
#define INTERRUPT_ACK (INTERRUPT_BASE + 0x20)
|
||||
#define INTERRUPT_ACK1 (INTERRUPT_BASE + 0x24)
|
||||
#define INTERRUPT_ACK2 (INTERRUPT_BASE + 0x28)
|
||||
|
||||
#define INTMASK_CLOCKGEN (0x00000001)
|
||||
#define INTMASK_TEMPMON (0x00000002)
|
||||
@@ -104,7 +108,23 @@
|
||||
#define INTMASK_TSOUTPUT3 (0x00040000)
|
||||
#define INTMASK_TSOUTPUT4 (0x00080000)
|
||||
|
||||
#define INTERRUPT_V2_CONTROL (INTERRUPT_BASE + 0x00)
|
||||
#define INTERRUPT_V2_ENABLE_1 (INTERRUPT_BASE + 0x04)
|
||||
#define INTERRUPT_V2_ENABLE_2 (INTERRUPT_BASE + 0x08)
|
||||
#define INTERRUPT_V2_ENABLE_3 (INTERRUPT_BASE + 0x0c)
|
||||
#define INTERRUPT_V2_ENABLE_4 (INTERRUPT_BASE + 0x10)
|
||||
#define INTERRUPT_V2_ENABLE_5 (INTERRUPT_BASE + 0x14)
|
||||
#define INTERRUPT_V2_ENABLE_6 (INTERRUPT_BASE + 0x18)
|
||||
#define INTERRUPT_V2_ENABLE_7 (INTERRUPT_BASE + 0x1c)
|
||||
|
||||
#define INTERRUPT_V2_STATUS (INTERRUPT_BASE + 0x20)
|
||||
#define INTERRUPT_V2_STATUS_1 (INTERRUPT_BASE + 0x24)
|
||||
#define INTERRUPT_V2_STATUS_2 (INTERRUPT_BASE + 0x28)
|
||||
#define INTERRUPT_V2_STATUS_3 (INTERRUPT_BASE + 0x2c)
|
||||
#define INTERRUPT_V2_STATUS_4 (INTERRUPT_BASE + 0x30)
|
||||
#define INTERRUPT_V2_STATUS_5 (INTERRUPT_BASE + 0x34)
|
||||
#define INTERRUPT_V2_STATUS_6 (INTERRUPT_BASE + 0x38)
|
||||
#define INTERRUPT_V2_STATUS_7 (INTERRUPT_BASE + 0x3c)
|
||||
|
||||
/* Modulator registers */
|
||||
|
||||
@@ -118,33 +138,71 @@
|
||||
/* DAC ( AD9781/AD9783 SPI ) */
|
||||
#define DAC_BASE (0x090)
|
||||
#define DAC_CONTROL (DAC_BASE)
|
||||
#define DAC_WRITE_DATA (DAC_BASE+4)
|
||||
#define DAC_READ_DATA (DAC_BASE+8)
|
||||
#define DAC_WRITE_DATA (DAC_BASE + 4)
|
||||
#define DAC_READ_DATA (DAC_BASE + 8)
|
||||
|
||||
#define DAC_CONTROL_INSTRUCTION_REG (0xFF)
|
||||
#define DAC_CONTROL_STARTIO (0x100)
|
||||
#define DAC_CONTROL_RESET (0x200)
|
||||
|
||||
/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */
|
||||
#define TEMPMON_BASE (0xA0)
|
||||
#define TEMPMON_BASE (0x1c0)
|
||||
#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00)
|
||||
/* SHORT Temperature in <20>C x 256 */
|
||||
|
||||
#define TEMPMON_CONTROL_SCAN (0x00000001)
|
||||
#define TEMPMON_CONTROL_AUTOSCAN (0x00000002)
|
||||
#define TEMPMON_CONTROL_INTENABLE (0x00000004)
|
||||
#define TEMPMON_CONTROL_CLEAR (0x00000008)
|
||||
#define TEMPMON_CONTROL_OVERTEMP (0x00008000)
|
||||
#define TEMPMON_STATUS_SHUTDOWN (0x00008000)
|
||||
|
||||
/* Temperature in C x 256 */
|
||||
#define TEMPMON_CORE (TEMPMON_BASE + 0x04)
|
||||
#define TEMPMON_SENSOR0 (TEMPMON_BASE + 0x04)
|
||||
#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08)
|
||||
#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C)
|
||||
|
||||
#define TEMPMON_FANCONTROL (TEMPMON_BASE + 0x10)
|
||||
#define TEMPMON_FANPWM (0x00000F00) /* PWM speed in 10% steps */
|
||||
#define TEMPMON_FANTACHO (0x000000FF) /* Rotations in 100/min steps */
|
||||
|
||||
#define TEMPMON_INTERRUPT_V1 (24)
|
||||
#define TEMPMON_INTERRUPT_V1_MASK (1<<24)
|
||||
|
||||
/* V1 Temperature Monitor
|
||||
* Temperature Monitor TEMPMON_CONTROL & 0x8000 == 0 : ( 2x LM75A @ 0x90,0x92 )
|
||||
* Temperature Monitor TEMPMON_CONTROL & 0x8000 == 1 :
|
||||
* ( 1x LM75A @ 0x90, 1x ADM1032 @ 0x9A )
|
||||
*/
|
||||
|
||||
/* Temperature in C x 256 (ADM1032 ext) */
|
||||
#define TEMPMON1_CORE (TEMPMON_SENSOR0)
|
||||
/* Temperature in C x 256 (LM75A 0x90) */
|
||||
#define TEMPMON1_SENSOR1 (TEMPMON_BASE + 0x08)
|
||||
/* Temperature in C x 256 (LM75A 0x92 or ADM1032 Int) */
|
||||
#define TEMPMON1_SENSOR2 (TEMPMON_BASE + 0x0C)
|
||||
|
||||
/* V2 Temperature Monitor 2 ADM1032 */
|
||||
|
||||
/* Temperature in C x 256 (ADM1032 int) */
|
||||
#define TEMPMON2_BOARD (TEMPMON_SENSOR0)
|
||||
/* Temperature in C x 256 (ADM1032 ext) */
|
||||
#define TEMPMON2_FPGACORE (TEMPMON_SENSOR1)
|
||||
/* Temperature in C x 256 (ADM1032 ext) */
|
||||
#define TEMPMON2_QAMCORE (TEMPMON_SENSOR2)
|
||||
/* SHORT Temperature in C x 256 (ADM1032 ext) */
|
||||
#define TEMPMON2_DACCORE (TEMPMON_SENSOR2)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* I2C Master Controller */
|
||||
|
||||
#define I2C_BASE (0x80) /* Byte offset */
|
||||
|
||||
#define I2C_COMMAND (0x00)
|
||||
#define I2C_TIMING (0x04)
|
||||
#define I2C_TASKLENGTH (0x08) /* High read, low write */
|
||||
#define I2C_TASKADDRESS (0x0C) /* High read, low write */
|
||||
#define I2C_MONITOR (0x1C)
|
||||
|
||||
|
||||
#define I2C_SPEED_666 (0x02010202)
|
||||
#define I2C_SPEED_400 (0x04030404)
|
||||
#define I2C_SPEED_200 (0x09080909)
|
||||
@@ -153,7 +211,6 @@
|
||||
#define I2C_SPEED_77 (0x19181919)
|
||||
#define I2C_SPEED_50 (0x27262727)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* DMA Controller */
|
||||
|
||||
@@ -173,32 +230,25 @@
|
||||
#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38)
|
||||
#define DMA_DIAG_WAITCOUNTER (0x3C)
|
||||
|
||||
#define TS_INPUT_BASE (0x200)
|
||||
#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00)
|
||||
#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04)
|
||||
#define TS_CONTROL(_io) ((_io)->regs + 0x00)
|
||||
#define TS_CONTROL2(_io) ((_io)->regs + 0x04)
|
||||
#define TS_STAT(_io) ((_io)->regs + 0x08)
|
||||
|
||||
#define TS_OUTPUT_BASE (0x280)
|
||||
#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00)
|
||||
#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04)
|
||||
#define TS_INPUT_CONTROL_ENABLE (0x00000001)
|
||||
#define TS_INPUT_CONTROL_RESET (0x00000002)
|
||||
#define TS_INPUT_CONTROL_SKIPERROR (0x00000008)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* DMA Buffer */
|
||||
|
||||
#define DMA_BUFFER_BASE (0x300)
|
||||
|
||||
#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00)
|
||||
#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04)
|
||||
#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
|
||||
#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
|
||||
|
||||
#define DMA_BASE_ADDRESS_TABLE (0x2000)
|
||||
#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
|
||||
|
||||
#define DMA_BUFFER_CONTROL(_dma) ((_dma)->regs + 0x00)
|
||||
#define DMA_BUFFER_ACK(_dma) ((_dma)->regs + 0x04)
|
||||
#define DMA_BUFFER_CURRENT(_dma) ((_dma)->regs + 0x08)
|
||||
#define DMA_BUFFER_SIZE(_dma) ((_dma)->regs + 0x0c)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define LNB_BASE (0x400)
|
||||
#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00)
|
||||
#define LNB_CONTROL(i) ((i) * 0x20 + 0x00)
|
||||
#define LNB_CMD (7ULL << 0)
|
||||
#define LNB_CMD_NOP 0
|
||||
#define LNB_CMD_INIT 1
|
||||
@@ -207,27 +257,33 @@
|
||||
#define LNB_CMD_HIGH 4
|
||||
#define LNB_CMD_OFF 5
|
||||
#define LNB_CMD_DISEQC 6
|
||||
#define LNB_CMD_UNI 7
|
||||
#define LNB_CMD_SCIF 7
|
||||
|
||||
#define LNB_BUSY (1ULL << 4)
|
||||
#define LNB_BUSY (1ULL << 4)
|
||||
#define LNB_TONE (1ULL << 15)
|
||||
|
||||
#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04)
|
||||
#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08)
|
||||
#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c)
|
||||
#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
|
||||
#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14)
|
||||
#define LNB_INTERRUPT_BASE 4
|
||||
|
||||
#define LNB_STATUS(i) ((i) * 0x20 + 0x04)
|
||||
#define LNB_VOLTAGE(i) ((i) * 0x20 + 0x08)
|
||||
#define LNB_CONFIG(i) ((i) * 0x20 + 0x0c)
|
||||
#define LNB_BUF_LEVEL(i) ((i) * 0x20 + 0x10)
|
||||
#define LNB_BUF_WRITE(i) ((i) * 0x20 + 0x14)
|
||||
|
||||
#define LNB_SETTING(i) ((i) * 0x20 + 0x0c)
|
||||
#define LNB_FIFO_LEVEL(i) ((i) * 0x20 + 0x10)
|
||||
#define LNB_RESET_FIFO(i) ((i) * 0x20 + 0x10)
|
||||
#define LNB_WRITE_FIFO(i) ((i) * 0x20 + 0x14)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* CI Interface (only CI-Bridge) */
|
||||
|
||||
#define CI_BASE (0x400)
|
||||
#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00)
|
||||
#define CI_CONTROL(_ci) ((_ci)->regs + 0x00)
|
||||
|
||||
#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04)
|
||||
#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08)
|
||||
#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c)
|
||||
#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10)
|
||||
#define CI_DO_ATTRIBUTE_RW(_ci) ((_ci)->regs + 0x04)
|
||||
#define CI_DO_IO_RW(_ci) ((_ci)->regs + 0x08)
|
||||
#define CI_READDATA(_ci) ((_ci)->regs + 0x0c)
|
||||
#define CI_DO_READ_ATTRIBUTES(_ci) ((_ci)->regs + 0x10)
|
||||
|
||||
#define CI_RESET_CAM (0x00000001)
|
||||
#define CI_POWER_ON (0x00000002)
|
||||
@@ -247,8 +303,8 @@
|
||||
#define CI_READ_CMD (0x40000000)
|
||||
#define CI_WRITE_CMD (0x80000000)
|
||||
|
||||
#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14)
|
||||
#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18)
|
||||
#define CI_BLOCKIO_SEND(_ci) ((_ci)->regs + 0x14)
|
||||
#define CI_BLOCKIO_RECEIVE(_ci) ((_ci)->regs + 0x18)
|
||||
|
||||
#define CI_BLOCKIO_SEND_COMMAND (0x80000000)
|
||||
#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000)
|
||||
@@ -256,13 +312,15 @@
|
||||
|
||||
#define CI_BUFFER_BASE (0x3000)
|
||||
#define CI_BUFFER_SIZE (0x0800)
|
||||
#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2)
|
||||
#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE / 2)
|
||||
|
||||
#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
|
||||
#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
|
||||
#define CI_BLOCKIO_SEND_BUFFER(i) \
|
||||
(CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE)
|
||||
|
||||
/* V1 */
|
||||
|
||||
#define VCO1_BASE (0xC0)
|
||||
#define VCO1_CONTROL (VCO1_BASE + 0x00)
|
||||
#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */
|
||||
@@ -293,12 +351,80 @@
|
||||
/* Muxout from VCO (usually = Lock) */
|
||||
#define VCO3_CONTROL_MUXOUT (0x00000004)
|
||||
|
||||
/* V2 */
|
||||
|
||||
#define MAX2871_BASE (0xC0)
|
||||
#define MAX2871_CONTROL (MAX2871_BASE + 0x00)
|
||||
#define MAX2871_OUTDATA (MAX2871_BASE + 0x04)
|
||||
#define MAX2871_INDATA (MAX2871_BASE + 0x08)
|
||||
/* 1 = Trigger write, resets when done */
|
||||
#define MAX2871_CONTROL_WRITE (0x00000001)
|
||||
/* 0 = Put VCO into power down */
|
||||
#define MAX2871_CONTROL_CE (0x00000002)
|
||||
/* Muxout from VCO */
|
||||
#define MAX2871_CONTROL_MUXOUT (0x00000004)
|
||||
/* Lock from VCO */
|
||||
#define MAX2871_CONTROL_LOCK (0x00000008)
|
||||
/* Signal the loss of lock event (currently only an interrupt) */
|
||||
#define MAX2871_CONTROL_ENABLE_LOSTLOCK_EVENT (0x00000010)
|
||||
/* Loss of Lock, needs to be cleared by writing a 1
|
||||
* during initial setup this bit can be set.
|
||||
*/
|
||||
#define MAX2871_CONTROL_LOSTLOCK (0x00008000)
|
||||
|
||||
|
||||
#define FSM_BASE (0x200)
|
||||
#define FSM_CONTROL (FSM_BASE + 0x00)
|
||||
|
||||
#define FSM_CONTROL_ENABLE (0x00000100)
|
||||
|
||||
#define FSM_CMD_MASK (0x00000087)
|
||||
#define FSM_CMD_STATUS (0x00000080)
|
||||
#define FSM_CMD_RESET (0x00000080)
|
||||
#define FSM_CMD_POWERDOWN (0x00000081)
|
||||
#define FSM_CMD_SETUP (0x00000082)
|
||||
|
||||
#define FSM_STATUS (FSM_BASE + 0x00)
|
||||
#define FSM_STATUS_READY (0x00010000)
|
||||
#define FSM_STATUS_QAMREADY (0x00020000)
|
||||
|
||||
#define FSM_CAPACITY (FSM_BASE + 0x04)
|
||||
#define FSM_CAPACITY_MAX (0x3F000000)
|
||||
#define FSM_CAPACITY_CUR (0x003F0000)
|
||||
#define FSM_CAPACITY_INUSE (0x0000003F)
|
||||
|
||||
#define FSM_GAIN (FSM_BASE + 0x10)
|
||||
#define FSM_GAINMASK (0x000000FF)
|
||||
|
||||
#define FSM_GAIN_N1 (0x000000FE)
|
||||
#define FSM_GAIN_N2 (0x000000A1)
|
||||
#define FSM_GAIN_N4 (0x00000066)
|
||||
#define FSM_GAIN_N8 (0x00000048)
|
||||
#define FSM_GAIN_N16 (0x0000002D)
|
||||
#define FSM_GAIN_N24 (0x00000029)
|
||||
#define FSM_GAIN_N96 (0x00000011)
|
||||
|
||||
/* Attenuator/VGA */
|
||||
|
||||
#define RF_ATTENUATOR (0xD8)
|
||||
/* 0x00 = 0 dB
|
||||
0x01 = 1 dB
|
||||
...
|
||||
0x1F = 31 dB
|
||||
*/
|
||||
* 0x01 = 1 dB
|
||||
* ...
|
||||
* 0x1F = 31 dB
|
||||
*/
|
||||
|
||||
#define RF_VGA (0xDC)
|
||||
/* Only V2 */
|
||||
/* 8 bit range 0 - 31.75 dB Gain */
|
||||
|
||||
/* VGA Gain for same output level as V1 Modulator */
|
||||
#define RF_VGA_GAIN_N8 (85)
|
||||
#define RF_VGA_GAIN_N16 (117)
|
||||
#define RF_VGA_GAIN_N24 (122)
|
||||
|
||||
#define RF_VGA_GAIN_MAX (200)
|
||||
|
||||
/* V1 only */
|
||||
|
||||
#define RF_POWER (0xE0)
|
||||
#define RF_POWER_BASE (0xE0)
|
||||
@@ -310,10 +436,9 @@
|
||||
#define RF_POWER_CONTROL_VALIDMASK (0x00000700)
|
||||
#define RF_POWER_CONTROL_VALID (0x00000500)
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Output control
|
||||
*/
|
||||
/*
|
||||
* Output control
|
||||
*/
|
||||
|
||||
#define IQOUTPUT_BASE (0x240)
|
||||
#define IQOUTPUT_CONTROL (IQOUTPUT_BASE + 0x00)
|
||||
@@ -342,14 +467,13 @@
|
||||
#define IQOUTPUT_CONTROL_ENABLE_PEAK (0x00000008)
|
||||
#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010)
|
||||
|
||||
|
||||
/* Modulator Base */
|
||||
/* Modulator Base V1 */
|
||||
|
||||
#define MODULATOR_BASE (0x200)
|
||||
#define MODULATOR_CONTROL (MODULATOR_BASE)
|
||||
#define MODULATOR_IQTABLE_END (MODULATOR_BASE+4)
|
||||
#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE+8)
|
||||
#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE+12)
|
||||
#define MODULATOR_IQTABLE_END (MODULATOR_BASE + 4)
|
||||
#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE + 8)
|
||||
#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE + 12)
|
||||
|
||||
#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK (0x000F0000)
|
||||
#define MODULATOR_IQTABLE_INDEX_IQ_MASK (0x00008000)
|
||||
@@ -358,12 +482,13 @@
|
||||
#define MODULATOR_IQTABLE_INDEX_SEL_Q (MODULATOR_IQTABLE_INDEX_IQ_MASK)
|
||||
#define MODULATOR_IQTABLE_SIZE (2048)
|
||||
|
||||
|
||||
/* Modulator Channels */
|
||||
|
||||
#define CHANNEL_BASE (0x400)
|
||||
#define CHANNEL_BASE dev->link[0].info->regmap->channel->base
|
||||
|
||||
#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00)
|
||||
#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04)
|
||||
#define CHANNEL_SETTINGS2(i) (CHANNEL_BASE + (i) * 64 + 0x08)
|
||||
#define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C)
|
||||
#define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10)
|
||||
#define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14)
|
||||
@@ -373,6 +498,8 @@
|
||||
#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24)
|
||||
#define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28)
|
||||
#define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C)
|
||||
#define CHANNEL_KF(i) (CHANNEL_BASE + (i) * 64 + 0x30)
|
||||
#define CHANNEL_LF(i) (CHANNEL_BASE + (i) * 64 + 0x34)
|
||||
|
||||
#define CHANNEL_CONTROL_RESET (0x00000001)
|
||||
#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002)
|
||||
@@ -381,8 +508,17 @@
|
||||
#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010)
|
||||
#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100)
|
||||
|
||||
#define CHANNEL_CONTROL_CMD_MASK (0x0000F000)
|
||||
#define CHANNEL_CONTROL_CMD_STATUS (0x00008000)
|
||||
#define CHANNEL_CONTROL_CMD_FREE (0x00008000)
|
||||
#define CHANNEL_CONTROL_CMD_SETUP (0x00009000)
|
||||
#define CHANNEL_CONTROL_CMD_MUTE (0x0000A000)
|
||||
#define CHANNEL_CONTROL_CMD_UNMUTE (0x0000B000)
|
||||
|
||||
#define CHANNEL_CONTROL_RESET_ERROR (0x00010000)
|
||||
#define CHANNEL_CONTROL_BUSY (0x01000000)
|
||||
#define CHANNEL_CONTROL_ACTIVE (0x00400000)
|
||||
#define CHANNEL_CONTROL_BUSY (0x00800000)
|
||||
#define CHANNEL_CONTROL_ERROR_CMD (0x10000000)
|
||||
#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000)
|
||||
#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000)
|
||||
#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000)
|
||||
@@ -394,6 +530,13 @@
|
||||
#define CHANNEL_SETTINGS_QAM128 (0x00000003)
|
||||
#define CHANNEL_SETTINGS_QAM256 (0x00000004)
|
||||
|
||||
#define CHANNEL_SETTINGS2_OUTPUT_MASK (0x0000007F)
|
||||
|
||||
#define KFLF_MAX (0x07FFFFFFUL)
|
||||
#define KF_INIT(_symbol_rate) (_symbol_rate)
|
||||
#define LF_INIT(_symbol_rate) (9000000UL)
|
||||
#define MIN_SYMBOLRATE (1000000)
|
||||
#define MAX_SYMBOLRATE (7100000)
|
||||
|
||||
/* OCTONET */
|
||||
|
||||
@@ -431,5 +574,77 @@
|
||||
#define PID_FILTER_SYSTEM_PIDS(i) (PID_FILTER_BASE + (i) * 0x20)
|
||||
#define PID_FILTER_PID(i, j) (PID_FILTER_BASE + (i) * 0x20 + (j) * 4)
|
||||
|
||||
/* V2 */
|
||||
|
||||
/* MAX2871 same as DVB Modulator V2 */
|
||||
|
||||
#define RFDAC_BASE (0x200)
|
||||
#define RFDAC_CONTROL (RFDAC_BASE + 0x00)
|
||||
|
||||
#define RFDAC_CMD_MASK (0x00000087)
|
||||
#define RFDAC_CMD_STATUS (0x00000080)
|
||||
#define RFDAC_CMD_RESET (0x00000080)
|
||||
#define RFDAC_CMD_POWERDOWN (0x00000081)
|
||||
#define RFDAC_CMD_SETUP (0x00000082)
|
||||
|
||||
#define RFDAC_STATUS (RFDAC_BASE + 0x00)
|
||||
#define RFDAC_STATUS_READY (0x00010000)
|
||||
#define RFDAC_STATUS_DACREADY (0x00020000)
|
||||
|
||||
#define RFDAC_FCW (RFDAC_BASE + 0x10)
|
||||
|
||||
#define JESD204B_BASE (0x280)
|
||||
|
||||
/* Additional Status Bits */
|
||||
|
||||
#define DMA_PCIE_LANES_MASK (0x00070000)
|
||||
|
||||
/* Modulator Channels, partially compatible to DVB Modulator V1 */
|
||||
|
||||
#define SDR_CHANNEL_BASE (0x800)
|
||||
|
||||
#define SDR_CHANNEL_CONTROL(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x00)
|
||||
#define SDR_CHANNEL_CONFIG(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x04)
|
||||
#define SDR_CHANNEL_CFCW(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x08)
|
||||
#define SDR_CHANNEL_ARICW(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x0C)
|
||||
#define SDR_CHANNEL_RGAIN(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x10)
|
||||
#define SDR_CHANNEL_SETFIR(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x14)
|
||||
|
||||
#define SDR_CHANNEL_FMDCW(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x20)
|
||||
#define SDR_CHANNEL_FM1FCW(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x24)
|
||||
#define SDR_CHANNEL_FM2FCW(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x28)
|
||||
#define SDR_CHANNEL_FM1GAIN(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x2C)
|
||||
#define SDR_CHANNEL_FM2GAIN(i) ((SDR_CHANNEL_BASE) + (i) * 64 + 0x30)
|
||||
|
||||
/* Control and status bits */
|
||||
#define SDR_CONTROL_ENABLE_CHANNEL (0x00000004)
|
||||
#define SDR_CONTROL_ENABLE_DMA (0x00000008)
|
||||
#define SDR_STATUS_DMA_UNDERRUN (0x00010000)
|
||||
|
||||
/* Config */
|
||||
#define SDR_CONFIG_ENABLE_FM1 (0x00000002)
|
||||
#define SDR_CONFIG_ENABLE_FM2 (0x00000004)
|
||||
#define SDR_CONFIG_DISABLE_ARI (0x00000010)
|
||||
#define SDR_CONFIG_DISABLE_VSB (0x00000020)
|
||||
|
||||
/* SET FIR */
|
||||
#define SDR_FIR_COEFF_MASK (0x00000FFF)
|
||||
#define SDR_FIR_TAP_MASK (0x001F0000)
|
||||
#define SDR_FIR_SELECT_MASK (0x00C00000)
|
||||
#define SDR_VSB_LENGTH_MASK (0x01000000)
|
||||
|
||||
#define SDR_SET_FIR(select, tap, coeff, vsblen) \
|
||||
((((select) << 22) & SDR_FIR_SELECT_MASK) | \
|
||||
(((tap) << 16) & SDR_FIR_TAP_MASK) | \
|
||||
((coeff) & SDR_FIR_COEFF_MASK) | \
|
||||
(((vsblen) << 24) & SDR_VSB_LENGTH_MASK) | \
|
||||
0 \
|
||||
)
|
||||
|
||||
/* SDR_CONTROL */
|
||||
|
||||
#define SDR_CONTROL (0xd0)
|
||||
#define SDR_GAIN_SMA (0xd4)
|
||||
#define SDR_ATTENUATER (0xd8)
|
||||
#define SDR_GAIN_F (0xdc)
|
||||
|
||||
|
||||
654
ddbridge/ddbridge-sx8.c
Normal file
654
ddbridge/ddbridge-sx8.c
Normal file
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* ddbridge-sx8.c: Digital Devices MAX SX8 driver
|
||||
*
|
||||
* Copyright (C) 2018 Digital Devices GmbH
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-io.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);
|
||||
|
||||
/* 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
|
||||
#define SX8_DEMOD_NUM 8
|
||||
#define SX8_DEMOD_NONE 0xff
|
||||
|
||||
struct sx8_base {
|
||||
struct mci_base mci_base;
|
||||
|
||||
u8 tuner_use_count[SX8_TUNER_NUM];
|
||||
|
||||
u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
|
||||
u8 demod_in_use[SX8_DEMOD_NUM];
|
||||
u32 iq_mode;
|
||||
};
|
||||
|
||||
struct sx8 {
|
||||
struct mci mci;
|
||||
struct mutex lock;
|
||||
|
||||
int first_time_lock;
|
||||
int started;
|
||||
int iq_started;
|
||||
};
|
||||
|
||||
static const u8 dvbs2_bits_per_symbol[] = {
|
||||
0, 0, 0, 0,
|
||||
/* S2 QPSK */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* S2 8PSK */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
/* S2 16APSK */
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
/* S2 32APSK */
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
3, 0, 4, 0,
|
||||
2, 2, 2, 2, 2, 2, // S2X QPSK
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // S2X 8PSK
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // S2X 16APSK
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // S2X 32APSK
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // S2X 64APSK
|
||||
7, 7, 7, 7, // S2X 128APSK
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // S2X 256APSK
|
||||
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // S2X QPSK
|
||||
3, 3, 3, 3, 3, 3, 3, 3, // S2X 8PSK
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // S2X 16APSK
|
||||
5, 5, 5, 5, // S2X 32APSK
|
||||
|
||||
3, 4, 5, 6, 8, 10,
|
||||
};
|
||||
|
||||
|
||||
static void release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct sx8 *state = fe->demodulator_priv;
|
||||
struct mci_base *mci_base = state->mci.base;
|
||||
|
||||
mci_base->count--;
|
||||
if (mci_base->count == 0) {
|
||||
list_del(&mci_base->mci_list);
|
||||
kfree(mci_base);
|
||||
}
|
||||
kfree(state);
|
||||
#ifdef CONFIG_MEDIA_ATTACH
|
||||
__module_get(THIS_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 = 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)
|
||||
goto unlock;
|
||||
ddb_mci_get_info(&state->mci);
|
||||
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,
|
||||
u8 flags, u8 gain)
|
||||
{
|
||||
struct sx8 *state = fe->demodulator_priv;
|
||||
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 = 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;
|
||||
|
||||
input = state->mci.tuner;
|
||||
if (!state->started)
|
||||
return -1;
|
||||
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);
|
||||
if (sx8_base->iq_mode) {
|
||||
cmd.command = SX8_CMD_DISABLE_IQOUTPUT;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = 0;
|
||||
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;
|
||||
sx8_base->iq_mode = 0;
|
||||
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;
|
||||
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;
|
||||
static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6);
|
||||
u32 used_ldpc_bitrate = 0, free_ldpc_bitrate;
|
||||
u32 used_demods = 0;
|
||||
struct mci_command cmd;
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & 2) {
|
||||
u32 tmp = modmask;
|
||||
|
||||
bits_per_symbol = 1;
|
||||
while (tmp & 1) {
|
||||
tmp >>= 1;
|
||||
bits_per_symbol++;
|
||||
}
|
||||
}
|
||||
mutex_lock(&mci_base->tuner_lock);
|
||||
if (sx8_base->iq_mode) {
|
||||
stat = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (direct_mode) {
|
||||
if (p->symbol_rate >= MCLK / 2) {
|
||||
if (state->mci.nr < 4)
|
||||
i = state->mci.nr;
|
||||
} else {
|
||||
i = state->mci.nr;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < SX8_DEMOD_NUM; i++) {
|
||||
used_ldpc_bitrate += sx8_base->used_ldpc_bitrate[i];
|
||||
if (sx8_base->demod_in_use[i])
|
||||
used_demods++;
|
||||
}
|
||||
if ((used_ldpc_bitrate >= MAX_LDPC_BITRATE) ||
|
||||
((ts_config & SX8_TSCONFIG_MODE_MASK) >
|
||||
SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) {
|
||||
stat = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
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)) {
|
||||
stat = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
i = (p->symbol_rate > MCLK / 2) ? 3 : 7;
|
||||
while (i >= 0 && sx8_base->demod_in_use[i])
|
||||
i--;
|
||||
}
|
||||
if (i < 0) {
|
||||
stat = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
sx8_base->demod_in_use[i] = 1;
|
||||
sx8_base->used_ldpc_bitrate[state->mci.nr] = p->symbol_rate * bits_per_symbol;
|
||||
state->mci.demod = i;
|
||||
|
||||
if (!sx8_base->tuner_use_count[input])
|
||||
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:
|
||||
mutex_unlock(&mci_base->tuner_lock);
|
||||
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 = p->stream_id & 0x0f;
|
||||
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||
ddb_mci_tsconfig(&state->mci, ts_config);
|
||||
}
|
||||
if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000))
|
||||
flags |= 0x80;
|
||||
//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;
|
||||
cmd.dvbs2_search.scrambling_sequence_index =
|
||||
p->scrambling_sequence_index | 0x80000000;
|
||||
cmd.dvbs2_search.input_stream_id = p->stream_id;
|
||||
cmd.tuner = state->mci.tuner;
|
||||
cmd.demod = state->mci.demod;
|
||||
cmd.output = state->mci.nr;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int start_iq(struct dvb_frontend *fe, u32 flags,
|
||||
u32 ts_config)
|
||||
{
|
||||
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;
|
||||
u32 used_demods = 0;
|
||||
struct mci_command cmd;
|
||||
u32 input = state->mci.tuner;
|
||||
int i, stat = 0;
|
||||
|
||||
mutex_lock(&mci_base->tuner_lock);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 >> 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_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, ts_mode = 0;
|
||||
|
||||
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:
|
||||
case APSK_256_L:
|
||||
mask = 0x7f;
|
||||
break;
|
||||
case APSK_128:
|
||||
mask = 0x3f;
|
||||
break;
|
||||
case APSK_64:
|
||||
case APSK_64_L:
|
||||
mask = 0x1f;
|
||||
break;
|
||||
case APSK_32:
|
||||
mask = 0x0f;
|
||||
break;
|
||||
case APSK_16:
|
||||
case APSK_16_L:
|
||||
mask = 0x07;
|
||||
break;
|
||||
default:
|
||||
mask = default_mod;
|
||||
break;
|
||||
}
|
||||
stat = start(fe, 3, mask, ts_config);
|
||||
} else {
|
||||
stat = start_iq(fe, isi & 0xffffff, ts_config);
|
||||
}
|
||||
mutex_unlock(&state->lock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (re_tune) {
|
||||
r = set_parameters(fe);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r = read_status(fe, status);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (*status & FE_HAS_LOCK)
|
||||
return 0;
|
||||
*delay = HZ / 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return DVBFE_ALGO_HW;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct sx8 *state = fe->demodulator_priv;
|
||||
|
||||
ddb_mci_proc_info(&state->mci, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops sx8_ops = {
|
||||
.delsys = { SYS_DVBS, SYS_DVBS2 },
|
||||
.info = {
|
||||
.name = "DVB-S/S2X",
|
||||
.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 |
|
||||
FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK |
|
||||
FE_CAN_2G_MODULATION |
|
||||
FE_CAN_MULTISTREAM,
|
||||
},
|
||||
.get_frontend_algo = get_algo,
|
||||
.get_frontend = get_frontend,
|
||||
.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,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int base_init(struct mci_base *mci_base)
|
||||
{
|
||||
//struct sx8_base *base = (struct sx8_base *) mci_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mci_cfg ddb_max_sx8_cfg = {
|
||||
.type = 0,
|
||||
.fe_ops = &sx8_ops,
|
||||
.base_size = sizeof(struct sx8_base),
|
||||
.state_size = sizeof(struct sx8),
|
||||
.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,550 +0,0 @@
|
||||
/*
|
||||
* ddbridge.c: Digital Devices PCIe bridge driver
|
||||
*
|
||||
* Copyright (C) 2010-2015 Digital Devices GmbH
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*#define DDB_ALT_DMA*/
|
||||
#define DDB_USE_WORK
|
||||
/*#define DDB_TEST_THREADED*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-regs.h"
|
||||
|
||||
static struct workqueue_struct *ddb_wq;
|
||||
|
||||
static int adapter_alloc;
|
||||
module_param(adapter_alloc, int, 0444);
|
||||
MODULE_PARM_DESC(adapter_alloc,
|
||||
"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
static int msi = 1;
|
||||
module_param(msi, int, 0444);
|
||||
MODULE_PARM_DESC(msi,
|
||||
" Control MSI interrupts: 0-disable, 1-enable (default)");
|
||||
#endif
|
||||
|
||||
#include "ddbridge-core.c"
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static void ddb_unmap(struct ddb *dev)
|
||||
{
|
||||
if (dev->regs)
|
||||
iounmap(dev->regs);
|
||||
vfree(dev);
|
||||
}
|
||||
|
||||
|
||||
static void __devexit ddb_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
|
||||
|
||||
ddb_device_destroy(dev);
|
||||
ddb_nsd_detach(dev);
|
||||
ddb_ports_detach(dev);
|
||||
ddb_i2c_release(dev);
|
||||
|
||||
if (dev->link[0].info->ns_num)
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
ddbwritel(dev, 0, INTERRUPT_ENABLE);
|
||||
|
||||
ddbwritel(dev, 0, MSI1_ENABLE);
|
||||
if (dev->msi == 2)
|
||||
free_irq(dev->pdev->irq + 1, dev);
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
#endif
|
||||
ddb_ports_release(dev);
|
||||
ddb_buffers_free(dev);
|
||||
|
||||
ddb_unmap(dev);
|
||||
pci_set_drvdata(pdev, 0);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
|
||||
#define __devinit
|
||||
#define __devinitdata
|
||||
#endif
|
||||
|
||||
static int __devinit ddb_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct ddb *dev;
|
||||
int stat = 0;
|
||||
int irq_flag = IRQF_SHARED;
|
||||
|
||||
if (pci_enable_device(pdev) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev = vzalloc(sizeof(struct ddb));
|
||||
if (dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&dev->mutex);
|
||||
dev->has_dma = 1;
|
||||
dev->pdev = pdev;
|
||||
dev->dev = &pdev->dev;
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
dev->link[0].ids.vendor = id->vendor;
|
||||
dev->link[0].ids.device = id->device;
|
||||
dev->link[0].ids.subvendor = id->subvendor;
|
||||
dev->link[0].ids.subdevice = id->subdevice;
|
||||
|
||||
dev->link[0].dev = dev;
|
||||
dev->link[0].info = (struct ddb_info *) id->driver_data;
|
||||
pr_info("DDBridge driver detected: %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),
|
||||
pci_resource_len(dev->pdev, 0));
|
||||
|
||||
if (!dev->regs) {
|
||||
pr_err("DDBridge: not enough memory for register map\n");
|
||||
stat = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (ddbreadl(dev, 0) == 0xffffffff) {
|
||||
pr_err("DDBridge: cannot read registers\n");
|
||||
stat = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->link[0].ids.hwid = ddbreadl(dev, 0);
|
||||
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
|
||||
|
||||
pr_info("DDBridge: HW %08x REGMAP %08x\n",
|
||||
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
|
||||
|
||||
if (dev->link[0].info->ns_num) {
|
||||
int i;
|
||||
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
for (i = 0; i < 16; i++)
|
||||
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
|
||||
usleep_range(5000, 6000);
|
||||
}
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI2_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI3_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI4_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI5_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI6_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI7_ENABLE);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (msi && pci_msi_enabled()) {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
|
||||
stat = pci_enable_msi_range(dev->pdev, 1, 2);
|
||||
if (stat >= 1) {
|
||||
dev->msi = stat;
|
||||
pr_info("DDBridge: using %d MSI interrupt(s)\n", dev->msi);
|
||||
irq_flag = 0;
|
||||
} else
|
||||
pr_info("DDBridge: MSI not available.\n");
|
||||
|
||||
#else
|
||||
stat = pci_enable_msi_block(dev->pdev, 2);
|
||||
if (stat == 0) {
|
||||
dev->msi = 1;
|
||||
pr_info("DDBridge: using 2 MSI interrupts\n");
|
||||
}
|
||||
if (stat == 1)
|
||||
stat = pci_enable_msi(dev->pdev);
|
||||
if (stat < 0) {
|
||||
pr_info("DDBridge: MSI not available.\n");
|
||||
} else {
|
||||
irq_flag = 0;
|
||||
dev->msi++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (dev->msi == 2) {
|
||||
stat = request_irq(dev->pdev->irq, irq_handler0,
|
||||
irq_flag, "ddbridge", (void *) dev);
|
||||
if (stat < 0)
|
||||
goto fail0;
|
||||
stat = request_irq(dev->pdev->irq + 1, irq_handler1,
|
||||
irq_flag, "ddbridge", (void *) dev);
|
||||
if (stat < 0) {
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
goto fail0;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef DDB_TEST_THREADED
|
||||
stat = request_threaded_irq(dev->pdev->irq, irq_handler,
|
||||
irq_thread,
|
||||
irq_flag,
|
||||
"ddbridge", (void *) dev);
|
||||
#else
|
||||
stat = request_irq(dev->pdev->irq, irq_handler,
|
||||
irq_flag, "ddbridge", (void *) dev);
|
||||
#endif
|
||||
if (stat < 0)
|
||||
goto fail0;
|
||||
}
|
||||
ddbwritel(dev, 0, DMA_BASE_READ);
|
||||
if (dev->link[0].info->type != DDB_MOD)
|
||||
ddbwritel(dev, 0, DMA_BASE_WRITE);
|
||||
|
||||
if (dev->link[0].info->type == DDB_MOD) {
|
||||
if (ddbreadl(dev, 0x1c) == 4)
|
||||
dev->link[0].info->port_num = 4;
|
||||
}
|
||||
|
||||
/*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/
|
||||
if (dev->msi == 2) {
|
||||
ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
|
||||
} else {
|
||||
ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
|
||||
}
|
||||
if (ddb_init(dev) == 0)
|
||||
return 0;
|
||||
|
||||
ddbwritel(dev, 0, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0, MSI1_ENABLE);
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
if (dev->msi == 2)
|
||||
free_irq(dev->pdev->irq + 1, dev);
|
||||
fail0:
|
||||
pr_err("fail0\n");
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
fail:
|
||||
pr_err("fail\n");
|
||||
|
||||
ddb_unmap(dev);
|
||||
pci_set_drvdata(pdev, 0);
|
||||
pci_disable_device(pdev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
static struct ddb_regset octopus_i2c = {
|
||||
.base = 0x80,
|
||||
.num = 0x04,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static struct ddb_regset octopus_i2c_buf = {
|
||||
.base = 0x1000,
|
||||
.num = 0x04,
|
||||
.size = 0x200,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
static struct ddb_regmap octopus_map = {
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
};
|
||||
|
||||
static struct ddb_regmap octopus_net_map = {
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
};
|
||||
|
||||
static struct ddb_regmap octopus_mod_map = {
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static struct ddb_info ddb_none = {
|
||||
.type = DDB_NONE,
|
||||
.name = "unknown Digital Devices PCIe card, install newer driver",
|
||||
.regmap = &octopus_map,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopusv3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus V3 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus_le = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus LE DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 2,
|
||||
.i2c_mask = 0x03,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus_oem = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus OEM",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.led_num = 1,
|
||||
.fan_num = 1,
|
||||
.temp_num = 1,
|
||||
.temp_bus = 0,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus_mini = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus Mini",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_v6 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_v6_5 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6.5 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_v7 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V7 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
.ts_quirks = TS_QUIRK_REVERSED,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_ctv7 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine CT V7 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 3,
|
||||
.board_control_2 = 4,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_satixS2v3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Mystique SaTiX-S2 V3 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_ci = {
|
||||
.type = DDB_OCTOPUS_CI,
|
||||
.name = "Digital Devices Octopus CI",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x03,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_cis = {
|
||||
.type = DDB_OCTOPUS_CI,
|
||||
.name = "Digital Devices Octopus CI single",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x03,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_ci_s2_pro = {
|
||||
.type = DDB_OCTOPUS_CI,
|
||||
.name = "Digital Devices Octopus CI S2 Pro",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x01,
|
||||
.board_control = 2,
|
||||
.board_control_2 = 4,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_dvbct = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices DVBCT V6.1 DVB adapter",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 3,
|
||||
.i2c_mask = 0x07,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static struct ddb_info ddb_s2_48 = {
|
||||
.type = DDB_OCTOPUS_MAX,
|
||||
.name = "Digital Devices MAX S8 4/8",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x01,
|
||||
.board_control = 1,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_ct_8 = {
|
||||
.type = DDB_OCTOPUS_MAX_CT,
|
||||
.name = "Digital Devices MAX CT8",
|
||||
.regmap = &octopus_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.board_control = 0x0ff,
|
||||
.board_control_2 = 0xf00,
|
||||
.ts_quirks = TS_QUIRK_SERIAL,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_mod = {
|
||||
.type = DDB_MOD,
|
||||
.name = "Digital Devices DVB-C modulator",
|
||||
.regmap = &octopus_mod_map,
|
||||
.port_num = 10,
|
||||
.temp_num = 1,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus_net = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet network DVB adapter",
|
||||
.regmap = &octopus_net_map,
|
||||
.port_num = 10,
|
||||
.i2c_mask = 0x3ff,
|
||||
.ns_num = 12,
|
||||
.mdio_num = 1,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
#define DDVID 0xdd01 /* Digital Devices Vendor ID */
|
||||
|
||||
#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
|
||||
.vendor = _vend, .device = _dev, \
|
||||
.subvendor = _subvend, .subdevice = _subdev, \
|
||||
.driver_data = (unsigned long)&_driverdata }
|
||||
|
||||
static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
|
||||
DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
|
||||
DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
|
||||
DDB_ID(DDVID, 0x0005, DDVID, 0x0011, ddb_octopus_mini),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
|
||||
DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
|
||||
DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7),
|
||||
DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7),
|
||||
DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7),
|
||||
DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48),
|
||||
DDB_ID(DDVID, 0x0008, DDVID, 0x0034, ddb_ct_8),
|
||||
DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
|
||||
DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
|
||||
DDB_ID(DDVID, 0x0012, DDVID, 0x0042, ddb_ci),
|
||||
DDB_ID(DDVID, 0x0013, DDVID, 0x0043, ddb_ci_s2_pro),
|
||||
DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
|
||||
DDB_ID(DDVID, 0x0201, DDVID, 0x0002, ddb_mod),
|
||||
DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_octopus_net),
|
||||
/* in case sub-ids got deleted in flash */
|
||||
DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0005, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0006, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0007, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0013, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
{0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
|
||||
|
||||
static struct pci_driver ddb_pci_driver = {
|
||||
.name = "ddbridge",
|
||||
.id_table = ddb_id_tbl,
|
||||
.probe = ddb_probe,
|
||||
.remove = ddb_remove,
|
||||
};
|
||||
|
||||
static __init int module_init_ddbridge(void)
|
||||
{
|
||||
int stat = -1;
|
||||
|
||||
pr_info("Digital Devices PCIE bridge driver "
|
||||
DDBRIDGE_VERSION
|
||||
", Copyright (C) 2010-15 Digital Devices GmbH\n");
|
||||
if (ddb_class_create() < 0)
|
||||
return -1;
|
||||
ddb_wq = create_workqueue("ddbridge");
|
||||
if (ddb_wq == NULL)
|
||||
goto exit1;
|
||||
stat = pci_register_driver(&ddb_pci_driver);
|
||||
if (stat < 0)
|
||||
goto exit2;
|
||||
return stat;
|
||||
exit2:
|
||||
destroy_workqueue(ddb_wq);
|
||||
exit1:
|
||||
ddb_class_destroy();
|
||||
return stat;
|
||||
}
|
||||
|
||||
static __exit void module_exit_ddbridge(void)
|
||||
{
|
||||
pci_unregister_driver(&ddb_pci_driver);
|
||||
destroy_workqueue(ddb_wq);
|
||||
ddb_class_destroy();
|
||||
}
|
||||
|
||||
module_init(module_init_ddbridge);
|
||||
module_exit(module_exit_ddbridge);
|
||||
|
||||
MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
|
||||
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DDBRIDGE_VERSION);
|
||||
@@ -1,8 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ddbridge.h: Digital Devices PCIe bridge driver
|
||||
*
|
||||
* Copyright (C) 2010-2015 Digital Devices GmbH
|
||||
* Ralph Metzler <rmetzler@digitaldevices.de>
|
||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
||||
* 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,12 +16,8 @@
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, 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_
|
||||
@@ -27,7 +25,7 @@
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
|
||||
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
|
||||
#define __devexit
|
||||
#define __devinit
|
||||
#define __devinitconst
|
||||
@@ -41,7 +39,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pci.h>
|
||||
//#include <linux/pci_ids.h>
|
||||
/*#include <linux/pci_ids.h>*/
|
||||
#include <linux/timer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/swab.h>
|
||||
@@ -55,27 +53,24 @@
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#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"
|
||||
@@ -91,14 +86,17 @@
|
||||
#include "lnbh25.h"
|
||||
#include "mxl5xx.h"
|
||||
|
||||
#define DDB_MAX_I2C 16
|
||||
#define DDB_MAX_PORT 16
|
||||
#define DDB_MAX_INPUT 44
|
||||
#define DDB_MAX_OUTPUT 10
|
||||
#include "ddbridge-regs.h"
|
||||
#include "ddbridge-mci.h"
|
||||
|
||||
#define DDB_MAX_I2C 32
|
||||
#define DDB_MAX_PORT 32
|
||||
#define DDB_MAX_INPUT 64
|
||||
#define DDB_MAX_OUTPUT 32
|
||||
#define DDB_MAX_LINK 4
|
||||
#define DDB_LINK_SHIFT 28
|
||||
|
||||
#define DDB_LINK_TAG(_x) (_x << DDB_LINK_SHIFT)
|
||||
#define DDB_LINK_TAG(_x) ((_x) << DDB_LINK_SHIFT)
|
||||
|
||||
struct ddb_regset {
|
||||
u32 base;
|
||||
@@ -106,25 +104,30 @@ struct ddb_regset {
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct ddb_ports {
|
||||
u32 base;
|
||||
u32 num;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct ddb_regmap {
|
||||
struct ddb_ports *bc;
|
||||
struct ddb_regset *i2c;
|
||||
struct ddb_regset *i2c_buf;
|
||||
struct ddb_regset *dma;
|
||||
struct ddb_regset *dma_buf;
|
||||
struct ddb_regset *input;
|
||||
struct ddb_regset *output;
|
||||
struct ddb_regset *channel;
|
||||
struct ddb_regset *ci;
|
||||
struct ddb_regset *pid_filter;
|
||||
struct ddb_regset *ns;
|
||||
struct ddb_regset *gtl;
|
||||
u32 irq_version;
|
||||
u32 irq_base_i2c;
|
||||
u32 irq_base_idma;
|
||||
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;
|
||||
const struct ddb_regset *idma;
|
||||
const struct ddb_regset *idma_buf;
|
||||
const struct ddb_regset *odma;
|
||||
const struct ddb_regset *odma_buf;
|
||||
|
||||
const struct ddb_regset *input;
|
||||
const struct ddb_regset *output;
|
||||
|
||||
const struct ddb_regset *channel;
|
||||
const struct ddb_regset *gtl;
|
||||
|
||||
const struct ddb_regset *mci;
|
||||
const struct ddb_regset *mci_buf;
|
||||
};
|
||||
|
||||
struct ddb_ids {
|
||||
@@ -132,80 +135,87 @@ struct ddb_ids {
|
||||
u16 device;
|
||||
u16 subvendor;
|
||||
u16 subdevice;
|
||||
|
||||
|
||||
u32 hwid;
|
||||
u32 regmapid;
|
||||
u32 devid;
|
||||
u32 mac;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
struct ddb_info {
|
||||
int type;
|
||||
#define DDB_NONE 0
|
||||
#define DDB_OCTOPUS 1
|
||||
#define DDB_OCTOPUS_CI 2
|
||||
#define DDB_MOD 3
|
||||
#define DDB_OCTONET 4
|
||||
#define DDB_OCTOPUS_MAX 5
|
||||
#define DDB_OCTOPUS_MAX_CT 6
|
||||
u32 type;
|
||||
#define DDB_NONE 0
|
||||
#define DDB_OCTOPUS 1
|
||||
#define DDB_MOD 3
|
||||
#define DDB_OCTONET 4
|
||||
#define DDB_OCTOPUS_MAX 5
|
||||
#define DDB_OCTOPUS_MAX_CT 6
|
||||
#define DDB_OCTOPUS_MCI 9
|
||||
u32 version;
|
||||
char *name;
|
||||
u32 i2c_mask;
|
||||
u32 board_control;
|
||||
u32 board_control_2;
|
||||
|
||||
u8 port_num;
|
||||
u8 led_num;
|
||||
u8 fan_num;
|
||||
u8 temp_num;
|
||||
u8 temp_bus;
|
||||
u32 board_control;
|
||||
u32 board_control_2;
|
||||
u8 ns_num;
|
||||
u8 mdio_num;
|
||||
u8 con_clock; /* use a continuous clock */
|
||||
u8 ts_quirks;
|
||||
#define TS_QUIRK_SERIAL 1
|
||||
#define TS_QUIRK_REVERSED 2
|
||||
struct ddb_regmap *regmap;
|
||||
#define TS_QUIRK_SERIAL 1
|
||||
#define TS_QUIRK_REVERSED 2
|
||||
#define TS_QUIRK_NO_OUTPUT 4
|
||||
#define TS_QUIRK_ALT_OSC 8
|
||||
u8 mci_ports;
|
||||
u8 mci_type;
|
||||
u8 ci_mask;
|
||||
|
||||
u32 tempmon_irq;
|
||||
u32 lostlock_irq;
|
||||
u32 mdio_base;
|
||||
u32 hw_min;
|
||||
u32 ci_base;
|
||||
u32 lnb_base;
|
||||
const struct ddb_regmap *regmap;
|
||||
};
|
||||
|
||||
/* DMA_SIZE MUST be smaller than 256k and
|
||||
MUST be divisible by 188 and 128 !!! */
|
||||
|
||||
#define DMA_MAX_BUFS 32 /* hardware table limit */
|
||||
|
||||
#define INPUT_DMA_BUFS 8
|
||||
#define INPUT_DMA_SIZE (128*47*21)
|
||||
#define INPUT_DMA_IRQ_DIV 1
|
||||
|
||||
#define OUTPUT_DMA_BUFS 8
|
||||
#define OUTPUT_DMA_SIZE (128*47*21)
|
||||
#define OUTPUT_DMA_IRQ_DIV 1
|
||||
#define OUTPUT_DMA_BUFS_SDR 32
|
||||
#define OUTPUT_DMA_SIZE_SDR (256 * 1024)
|
||||
|
||||
struct ddb;
|
||||
struct ddb_port;
|
||||
|
||||
struct ddb_dma {
|
||||
void *io;
|
||||
u32 nr;
|
||||
u32 regs;
|
||||
u32 bufregs;
|
||||
|
||||
dma_addr_t pbuf[DMA_MAX_BUFS];
|
||||
u8 *vbuf[DMA_MAX_BUFS];
|
||||
u32 num;
|
||||
u32 size;
|
||||
u32 div;
|
||||
u32 bufreg;
|
||||
|
||||
#ifdef DDB_USE_WORK
|
||||
struct work_struct work;
|
||||
#else
|
||||
u32 bufval;
|
||||
|
||||
struct tasklet_struct tasklet;
|
||||
#endif
|
||||
spinlock_t lock;
|
||||
spinlock_t lock; /* DMA lock */
|
||||
wait_queue_head_t wq;
|
||||
int running;
|
||||
u32 stat;
|
||||
u32 ctrl;
|
||||
u32 cbuf;
|
||||
u32 coff;
|
||||
|
||||
u32 stall_count;
|
||||
u32 packet_loss;
|
||||
u32 unaligned;
|
||||
};
|
||||
|
||||
|
||||
struct ddb_dvb {
|
||||
struct dvb_adapter *adap;
|
||||
int adap_registered;
|
||||
@@ -221,26 +231,30 @@ struct ddb_dvb {
|
||||
int users;
|
||||
u32 attached;
|
||||
u8 input;
|
||||
|
||||
fe_sec_tone_mode_t tone;
|
||||
fe_sec_voltage_t voltage;
|
||||
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend *, int);
|
||||
int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
|
||||
|
||||
enum fe_sec_tone_mode tone;
|
||||
enum fe_sec_voltage voltage;
|
||||
|
||||
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);
|
||||
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
|
||||
int (*diseqc_send_master_cmd)(struct dvb_frontend *fe,
|
||||
struct dvb_diseqc_master_cmd *cmd);
|
||||
};
|
||||
|
||||
struct ddb_ci {
|
||||
struct dvb_ca_en50221 en;
|
||||
struct ddb_port *port;
|
||||
u32 nr;
|
||||
struct mutex lock;
|
||||
u32 regs;
|
||||
};
|
||||
|
||||
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;
|
||||
@@ -268,7 +282,7 @@ struct ddb_port {
|
||||
u32 regs;
|
||||
u32 lnr;
|
||||
struct ddb_i2c *i2c;
|
||||
struct mutex i2c_gate_lock;
|
||||
struct mutex i2c_gate_lock; /* I2C access lock */
|
||||
u32 class;
|
||||
#define DDB_PORT_NONE 0
|
||||
#define DDB_PORT_CI 1
|
||||
@@ -278,6 +292,7 @@ struct ddb_port {
|
||||
char *name;
|
||||
char *type_name;
|
||||
u32 type;
|
||||
#define DDB_TUNER_DUMMY 0xffffffff
|
||||
#define DDB_TUNER_NONE 0
|
||||
#define DDB_TUNER_DVBS_ST 1
|
||||
#define DDB_TUNER_DVBS_ST_AA 2
|
||||
@@ -293,6 +308,7 @@ struct ddb_port {
|
||||
#define DDB_CI_EXTERNAL_XO2 12
|
||||
#define DDB_CI_EXTERNAL_XO2_B 13
|
||||
#define DDB_TUNER_DVBS_STV0910_PR 14
|
||||
#define DDB_TUNER_DVBC2T2I_SONY_P 15
|
||||
|
||||
#define DDB_TUNER_XO2 32
|
||||
#define DDB_TUNER_DVBS_STV0910 (DDB_TUNER_XO2 + 0)
|
||||
@@ -300,7 +316,14 @@ struct ddb_port {
|
||||
#define DDB_TUNER_ISDBT_SONY (DDB_TUNER_XO2 + 2)
|
||||
#define DDB_TUNER_DVBC2T2_SONY (DDB_TUNER_XO2 + 3)
|
||||
#define DDB_TUNER_ATSC_ST (DDB_TUNER_XO2 + 4)
|
||||
#define DDB_TUNER_DVBC2T2_ST (DDB_TUNER_XO2 + 5)
|
||||
#define DDB_TUNER_DVBC2T2I_SONY (DDB_TUNER_XO2 + 5)
|
||||
|
||||
#define DDB_TUNER_MCI 48
|
||||
#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0)
|
||||
#define DDB_TUNER_MCI_M4 (DDB_TUNER_MCI + 1)
|
||||
#define DDB_TUNER_MCI_M8 (DDB_TUNER_MCI + 2)
|
||||
#define DDB_TUNER_MCI_M8A (DDB_TUNER_MCI + 3)
|
||||
#define DDB_TUNER_MCI_M2 (DDB_TUNER_MCI + 4)
|
||||
|
||||
struct ddb_input *input[2];
|
||||
struct ddb_output *output;
|
||||
@@ -317,8 +340,13 @@ struct mod_base {
|
||||
u32 flat_end;
|
||||
};
|
||||
|
||||
struct mod_state {
|
||||
struct ddb_mod {
|
||||
struct ddb_port *port;
|
||||
|
||||
u32 frequency;
|
||||
u32 modulation;
|
||||
u32 symbolrate;
|
||||
|
||||
u64 obitrate;
|
||||
u64 ibitrate;
|
||||
u32 pcr_correction;
|
||||
@@ -372,36 +400,51 @@ struct ddb_ns {
|
||||
};
|
||||
|
||||
struct ddb_lnb {
|
||||
struct mutex lock;
|
||||
struct mutex lock; /* lock lnb access */
|
||||
u32 tone;
|
||||
fe_sec_voltage_t oldvoltage[4];
|
||||
enum fe_sec_voltage oldvoltage[4];
|
||||
u32 voltage[4];
|
||||
u32 voltages;
|
||||
u32 fmode;
|
||||
};
|
||||
|
||||
struct ddb_irq {
|
||||
void (*handler)(void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct ddb_link {
|
||||
struct ddb *dev;
|
||||
struct ddb_info *info;
|
||||
const struct ddb_info *info;
|
||||
u32 nr;
|
||||
u32 regs;
|
||||
spinlock_t lock;
|
||||
struct mutex flash_mutex;
|
||||
spinlock_t lock; /* lock link access */
|
||||
struct mutex flash_mutex; /* lock flash access */
|
||||
struct ddb_lnb lnb;
|
||||
struct tasklet_struct tasklet;
|
||||
struct ddb_ids ids;
|
||||
|
||||
spinlock_t temp_lock; /* lock temp chip access */
|
||||
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 {
|
||||
struct pci_dev *pdev;
|
||||
struct platform_device *pfdev;
|
||||
struct device *dev;
|
||||
|
||||
|
||||
int msi;
|
||||
struct workqueue_struct *wq;
|
||||
u32 has_dma;
|
||||
u32 has_ns;
|
||||
|
||||
|
||||
struct ddb_link link[DDB_MAX_LINK];
|
||||
unsigned char *regs;
|
||||
u32 regs_len;
|
||||
@@ -412,13 +455,11 @@ struct ddb {
|
||||
struct ddb_input input[DDB_MAX_INPUT];
|
||||
struct ddb_output output[DDB_MAX_OUTPUT];
|
||||
struct dvb_adapter adap[DDB_MAX_INPUT];
|
||||
struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT];
|
||||
|
||||
void (*handler[128])(unsigned long);
|
||||
unsigned long handler_data[128];
|
||||
struct ddb_dma idma[DDB_MAX_INPUT];
|
||||
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];
|
||||
|
||||
@@ -429,227 +470,16 @@ struct ddb {
|
||||
int ns_num;
|
||||
struct ddb_ns ns[DDB_NS_MAX];
|
||||
int vlan;
|
||||
struct mutex mutex;
|
||||
struct mutex mutex; /* lock accces to global ddb array */
|
||||
|
||||
struct dvb_device *nsd_dev;
|
||||
u8 tsbuf[TS_CAPTURE_LEN];
|
||||
|
||||
struct mod_base mod_base;
|
||||
struct mod_state mod[10];
|
||||
struct ddb_mod mod[24];
|
||||
struct mutex ioctl_mutex; /* lock extra ioctls */
|
||||
};
|
||||
|
||||
static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
|
||||
{
|
||||
writeb(val, (char *) (dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static inline u32 ddbreadb(struct ddb *dev, u32 adr)
|
||||
{
|
||||
return readb((char *) (dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static inline void ddbwritel0(struct ddb_link *link, u32 val, u32 adr)
|
||||
{
|
||||
writel(val, (char *) (link->dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static inline u32 ddbreadl0(struct ddb_link *link, u32 adr)
|
||||
{
|
||||
return readl((char *) (link->dev->regs + (adr)));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline void gtlw(struct ddb_link *link)
|
||||
{
|
||||
u32 count = 0;
|
||||
static u32 max = 0;
|
||||
|
||||
while (1 & ddbreadl0(link, link->regs + 0x10)) {
|
||||
if (++count == 1024) {
|
||||
printk("LTO\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count > max) {
|
||||
max = count;
|
||||
printk("TO=%u\n", max);
|
||||
}
|
||||
if (ddbreadl0(link, link->regs + 0x10) & 0x8000)
|
||||
printk("link error\n");
|
||||
}
|
||||
#else
|
||||
static inline void gtlw(struct ddb_link *link)
|
||||
{
|
||||
while (1 & ddbreadl0(link, link->regs + 0x10));
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 ddblreadl(struct ddb_link *link, u32 adr)
|
||||
{
|
||||
if (unlikely(link->nr)) {
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddbwritel0(link, adr & 0xfffc, link->regs + 0x14);
|
||||
ddbwritel0(link, 3, link->regs + 0x10);
|
||||
gtlw(link);
|
||||
val = ddbreadl0(link, link->regs + 0x1c);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return val;
|
||||
}
|
||||
return readl((char *) (link->dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static void ddblwritel(struct ddb_link *link, u32 val, u32 adr)
|
||||
{
|
||||
if (unlikely(link->nr)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddbwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
|
||||
ddbwritel0(link, val, link->regs + 0x18);
|
||||
ddbwritel0(link, 1, link->regs + 0x10);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return;
|
||||
}
|
||||
writel(val, (char *) (link->dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static u32 ddbreadl(struct ddb *dev, u32 adr)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000)) {
|
||||
unsigned long flags;
|
||||
u32 val, l = (adr >> DDB_LINK_SHIFT);
|
||||
struct ddb_link *link = &dev->link[l];
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddbwritel0(link, adr & 0xfffc, link->regs + 0x14);
|
||||
ddbwritel0(link, 3, link->regs + 0x10);
|
||||
gtlw(link);
|
||||
val = ddbreadl0(link, link->regs + 0x1c);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return val;
|
||||
}
|
||||
return readl((char *) (dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static void ddbwritel(struct ddb *dev, u32 val, u32 adr)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000)) {
|
||||
unsigned long flags;
|
||||
u32 l = (adr >> DDB_LINK_SHIFT);
|
||||
struct ddb_link *link = &dev->link[l];
|
||||
|
||||
spin_lock_irqsave(&link->lock, flags);
|
||||
gtlw(link);
|
||||
ddbwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
|
||||
ddbwritel0(link, val, link->regs + 0x18);
|
||||
ddbwritel0(link, 1, link->regs + 0x10);
|
||||
spin_unlock_irqrestore(&link->lock, flags);
|
||||
return;
|
||||
}
|
||||
writel(val, (char *) (dev->regs + (adr)));
|
||||
}
|
||||
|
||||
static void gtlcpyto(struct ddb *dev, u32 adr, const u8 *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
u32 val = 0, p = adr;
|
||||
u32 aa = p & 3;
|
||||
|
||||
if (aa) {
|
||||
while (p & 3 && count) {
|
||||
val >>= 8;
|
||||
val |= *buf << 24;
|
||||
p++;
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
ddbwritel(dev, val, adr);
|
||||
}
|
||||
while (count >= 4) {
|
||||
val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
ddbwritel(dev, val, p);
|
||||
p += 4;
|
||||
buf += 4;
|
||||
count -= 4;
|
||||
}
|
||||
if (count) {
|
||||
val = buf[0];
|
||||
if (count > 1)
|
||||
val |= buf[1] << 8;
|
||||
if (count > 2)
|
||||
val |= buf[2] << 16;
|
||||
ddbwritel(dev, val, p);
|
||||
}
|
||||
}
|
||||
|
||||
static void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count)
|
||||
{
|
||||
u32 val = 0, p = adr;
|
||||
u32 a = p & 3;
|
||||
|
||||
if (a) {
|
||||
val = ddbreadl(dev, p) >> (8 * a);
|
||||
while (p & 3 && count) {
|
||||
*buf = val & 0xff;
|
||||
val >>= 8;
|
||||
p++;
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
while (count >= 4) {
|
||||
val = ddbreadl(dev, p);
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
buf[3] = (val >> 24) & 0xff;
|
||||
p += 4;
|
||||
buf += 4;
|
||||
count -= 4;
|
||||
}
|
||||
if (count) {
|
||||
val = ddbreadl(dev, p);
|
||||
buf[0] = val & 0xff;
|
||||
if (count > 1)
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
if (count > 2)
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000))
|
||||
return gtlcpyto(dev, adr, src, count);
|
||||
return memcpy_toio((char *) (dev->regs + adr), src, count);
|
||||
}
|
||||
|
||||
static void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count)
|
||||
{
|
||||
if (unlikely(adr & 0xf0000000))
|
||||
return gtlcpyfrom(dev, dst, adr, count);
|
||||
return memcpy_fromio(dst, (char *) (dev->regs + adr), count);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#define ddbcpyto(_dev, _adr, _src, _count) \
|
||||
memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count))
|
||||
|
||||
#define ddbcpyfrom(_dev, _dst, _adr, _count) \
|
||||
memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count))
|
||||
#endif
|
||||
|
||||
#define ddbmemset(_dev, _adr, _val, _count) \
|
||||
memset_io((char *) (_dev->regs + (_adr)), (_val), (_count))
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
@@ -702,16 +532,51 @@ struct DDMOD_FLASH {
|
||||
|
||||
#define DDMOD_FLASH_MAGIC 0x5F564d5F
|
||||
|
||||
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
|
||||
|
||||
#define DDBRIDGE_VERSION "0.9.38"
|
||||
|
||||
/* linked function prototypes */
|
||||
|
||||
const struct ddb_info *get_ddb_info(u16 vendor, u16 device,
|
||||
u16 subvendor, u16 subdevice);
|
||||
int netstream_init(struct ddb_input *input);
|
||||
int ddb_dvb_ns_input_start(struct ddb_input *input);
|
||||
int ddb_dvb_ns_input_stop(struct ddb_input *input);
|
||||
|
||||
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);
|
||||
void ddbridge_mod_output_start(struct ddb_output *output);
|
||||
void ddbridge_mod_rate_handler(unsigned long data);
|
||||
int ddbridge_mod_output_start(struct ddb_output *output);
|
||||
void ddbridge_mod_rate_handler(void *data);
|
||||
|
||||
void ddb_device_destroy(struct ddb *dev);
|
||||
void ddb_nsd_detach(struct ddb *dev);
|
||||
void ddb_ports_detach(struct ddb *dev);
|
||||
void ddb_ports_release(struct ddb *dev);
|
||||
void ddb_buffers_free(struct ddb *dev);
|
||||
void ddb_unmap(struct ddb *dev);
|
||||
irqreturn_t ddb_irq_handler0(int irq, void *dev_id);
|
||||
irqreturn_t ddb_irq_handler1(int irq, void *dev_id);
|
||||
irqreturn_t ddb_irq_handler(int irq, void *dev_id);
|
||||
irqreturn_t ddb_irq_handler_v2(int irq, void *dev_id);
|
||||
void ddb_reset_ios(struct ddb *dev);
|
||||
int ddb_init(struct ddb *dev);
|
||||
int ddb_exit_ddbridge(int stage, int error);
|
||||
int ddb_init_ddbridge(void);
|
||||
|
||||
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
|
||||
int ddb_i2c_init(struct ddb *dev);
|
||||
void ddb_i2c_release(struct ddb *dev);
|
||||
|
||||
#define DDBRIDGE_VERSION "0.9.21"
|
||||
int ddb_ci_attach(struct ddb_port *port, u32 bitrate);
|
||||
|
||||
int ddb_fe_attach_mxl5xx(struct ddb_input *input);
|
||||
int ddb_fe_attach_mci(struct ddb_input *input, u32 type);
|
||||
int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm);
|
||||
|
||||
struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
|
||||
void (*handler)(void *), void *data);
|
||||
|
||||
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 = {
|
||||
@@ -241,11 +244,11 @@ int dvb_netstream_init(struct dvb_adapter *dvb_adapter,
|
||||
spin_lock_init(&ns->lock);
|
||||
ns->exit = 0;
|
||||
dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns,
|
||||
DVB_DEVICE_NS);
|
||||
DVB_DEVICE_NS, 0);
|
||||
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_*/
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* octonet.c: Digital Devices network tuner driver
|
||||
*
|
||||
* Copyright (C) 2012-15 Digital Devices GmbH
|
||||
* Copyright (C) 2012-17 Digital Devices GmbH
|
||||
* Marcus Metzler <mocm@metzlerbros.de>
|
||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||
*
|
||||
@@ -17,95 +17,12 @@
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
* along with this program; if not, point your browser to
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include "ddbridge.h"
|
||||
#include "ddbridge-regs.h"
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
|
||||
static int adapter_alloc = 3;
|
||||
module_param(adapter_alloc, int, 0444);
|
||||
MODULE_PARM_DESC(adapter_alloc,
|
||||
"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
|
||||
|
||||
#include "ddbridge-core.c"
|
||||
|
||||
static struct ddb_regset octopus_i2c = {
|
||||
.base = 0x80,
|
||||
.num = 0x04,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static struct ddb_regset octopus_i2c_buf = {
|
||||
.base = 0x1000,
|
||||
.num = 0x04,
|
||||
.size = 0x200,
|
||||
};
|
||||
|
||||
static struct ddb_regmap octopus_net_map = {
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
};
|
||||
|
||||
static struct ddb_regset octopus_gtl = {
|
||||
.base = 0x180,
|
||||
.num = 0x01,
|
||||
.size = 0x20,
|
||||
};
|
||||
|
||||
static struct ddb_regmap octopus_net_gtl = {
|
||||
.i2c = &octopus_i2c,
|
||||
.i2c_buf = &octopus_i2c_buf,
|
||||
.gtl = &octopus_gtl,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octonet = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet network DVB adapter",
|
||||
.regmap = &octopus_net_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.ns_num = 12,
|
||||
.mdio_num = 1,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octonet_jse = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet network DVB adapter JSE",
|
||||
.regmap = &octopus_net_map,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x0f,
|
||||
.ns_num = 15,
|
||||
.mdio_num = 1,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octonet_gtl = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet GTL",
|
||||
.regmap = &octopus_net_gtl,
|
||||
.port_num = 4,
|
||||
.i2c_mask = 0x05,
|
||||
.ns_num = 12,
|
||||
.mdio_num = 1,
|
||||
.con_clock = 1,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octonet_tbd = {
|
||||
.type = DDB_OCTONET,
|
||||
.name = "Digital Devices OctopusNet",
|
||||
.regmap = &octopus_net_map,
|
||||
};
|
||||
|
||||
static void octonet_unmap(struct ddb *dev)
|
||||
{
|
||||
if (dev->regs)
|
||||
iounmap(dev->regs);
|
||||
vfree(dev);
|
||||
}
|
||||
#include "ddbridge-io.h"
|
||||
|
||||
static int __exit octonet_remove(struct platform_device *pdev)
|
||||
{
|
||||
@@ -124,7 +41,7 @@ static int __exit octonet_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(platform_get_irq(dev->pfdev, 0), dev);
|
||||
ddb_ports_release(dev);
|
||||
octonet_unmap(dev);
|
||||
ddb_unmap(dev);
|
||||
platform_set_drvdata(pdev, 0);
|
||||
return 0;
|
||||
}
|
||||
@@ -134,9 +51,8 @@ static int __init octonet_probe(struct platform_device *pdev)
|
||||
struct ddb *dev;
|
||||
struct resource *regs;
|
||||
int irq;
|
||||
int i;
|
||||
|
||||
dev = vzalloc(sizeof(struct ddb));
|
||||
dev = vzalloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, dev);
|
||||
@@ -149,7 +65,7 @@ static int __init octonet_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
dev->regs_len = (regs->end - regs->start) + 1;
|
||||
dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n",
|
||||
(u32) regs->start, (u32) dev->regs_len);
|
||||
(u32)regs->start, (u32)dev->regs_len);
|
||||
dev->regs = ioremap(regs->start, dev->regs_len);
|
||||
|
||||
if (!dev->regs) {
|
||||
@@ -168,31 +84,25 @@ static int __init octonet_probe(struct platform_device *pdev)
|
||||
dev->link[0].ids.subdevice = dev->link[0].ids.devid >> 16;
|
||||
|
||||
dev->link[0].dev = dev;
|
||||
if (dev->link[0].ids.devid == 0x0300dd01)
|
||||
dev->link[0].info = &ddb_octonet;
|
||||
else if (dev->link[0].ids.devid == 0x0301dd01)
|
||||
dev->link[0].info = &ddb_octonet_jse;
|
||||
else if (dev->link[0].ids.devid == 0x0307dd01)
|
||||
dev->link[0].info = &ddb_octonet_gtl;
|
||||
else
|
||||
dev->link[0].info = &ddb_octonet_tbd;
|
||||
|
||||
pr_info("HW %08x REGMAP %08x\n", dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
|
||||
pr_info("MAC %08x DEVID %08x\n", dev->link[0].ids.mac, dev->link[0].ids.devid);
|
||||
dev->link[0].info = get_ddb_info(dev->link[0].ids.vendor,
|
||||
dev->link[0].ids.device,
|
||||
0xdd01, 0xffff);
|
||||
dev_info(dev->dev, "DDBridge: HW %08x REGMAP %08x\n",
|
||||
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
|
||||
dev_info(dev->dev, "DDBridge: MAC %08x DEVID %08x\n",
|
||||
dev->link[0].ids.mac, dev->link[0].ids.devid);
|
||||
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
|
||||
ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS);
|
||||
for (i = 0; i < 16; i++)
|
||||
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
|
||||
usleep_range(5000, 6000);
|
||||
ddb_reset_ios(dev);
|
||||
|
||||
irq = platform_get_irq(dev->pfdev, 0);
|
||||
if (irq < 0)
|
||||
goto fail;
|
||||
if (request_irq(irq, irq_handler,
|
||||
if (request_irq(irq, ddb_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
"octonet-dvb", (void *) dev) < 0)
|
||||
"octonet-dvb", (void *)dev) < 0)
|
||||
goto fail;
|
||||
ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
|
||||
|
||||
@@ -203,7 +113,7 @@ fail:
|
||||
dev_err(dev->dev, "fail\n");
|
||||
ddbwritel(dev, 0, ETHER_CONTROL);
|
||||
ddbwritel(dev, 0, INTERRUPT_ENABLE);
|
||||
octonet_unmap(dev);
|
||||
ddb_unmap(dev);
|
||||
platform_set_drvdata(pdev, 0);
|
||||
return -1;
|
||||
}
|
||||
@@ -217,7 +127,7 @@ static const struct of_device_id octonet_dt_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, octonet_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver octonet_driver = {
|
||||
static struct platform_driver octonet_driver __refdata = {
|
||||
.remove = __exit_p(octonet_remove),
|
||||
.probe = octonet_probe,
|
||||
.driver = {
|
||||
@@ -231,25 +141,23 @@ static struct platform_driver octonet_driver = {
|
||||
|
||||
static __init int init_octonet(void)
|
||||
{
|
||||
int res;
|
||||
int stat;
|
||||
|
||||
pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION
|
||||
", Copyright (C) 2010-15 Digital Devices GmbH\n");
|
||||
res = ddb_class_create();
|
||||
if (res)
|
||||
return res;
|
||||
res = platform_driver_probe(&octonet_driver, octonet_probe);
|
||||
if (res) {
|
||||
ddb_class_destroy();
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
pr_info("DDBridge: Digital Devices OctopusNet driver " DDBRIDGE_VERSION
|
||||
", Copyright (C) 2010-17 Digital Devices GmbH\n");
|
||||
stat = ddb_init_ddbridge();
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
stat = platform_driver_probe(&octonet_driver, octonet_probe);
|
||||
if (stat < 0)
|
||||
ddb_exit_ddbridge(0, stat);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static __exit void exit_octonet(void)
|
||||
{
|
||||
platform_driver_unregister(&octonet_driver);
|
||||
ddb_class_destroy();
|
||||
ddb_exit_ddbridge(0, 0);
|
||||
}
|
||||
|
||||
module_init(init_octonet);
|
||||
@@ -257,5 +165,5 @@ module_exit(exit_octonet);
|
||||
|
||||
MODULE_DESCRIPTION("GPL");
|
||||
MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung GbR");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.6");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION(DDBRIDGE_VERSION);
|
||||
104
docs/bbframes
Normal file
104
docs/bbframes
Normal file
@@ -0,0 +1,104 @@
|
||||
To allow the transport of DVB-S2 baseband frames (BBFrame) across existing hard- and software
|
||||
interfaces, we have added the ability to embed the BBFrame data into
|
||||
an MPEG2 transport stream.
|
||||
|
||||
This feature is available on supported cards as firmware update and
|
||||
is currently considered experimental.
|
||||
|
||||
Supported hardware:
|
||||
|
||||
cineS2 V7A (>=1.7 FW)
|
||||
OctopusCI S2 Pro Advanced (>=1.7 FW)
|
||||
Duoflex S2 v4 Advanced (TBA)
|
||||
MaxSX8 (NOT the MAXS8!)
|
||||
|
||||
The following cards are based on the broadcast version of the
|
||||
DVB-S2 demodulator. The BBFrame output is working but
|
||||
not documented. We therefore can not guarantee the
|
||||
feature will work under all conditions.
|
||||
|
||||
cineS2 V7 (>=1.7 FW)
|
||||
OctopusCI S2 Pro (>=1.7 FW)
|
||||
Duoflex S2 v4 (TBA)
|
||||
|
||||
|
||||
Current FPGA images (including FW 1.7 for the above mentioned cards)
|
||||
can be found here:
|
||||
|
||||
http://download.digital-devices.de/download/firmware/html/firmwareupdate.html
|
||||
|
||||
|
||||
|
||||
Packet format:
|
||||
|
||||
The BBFrames are packetized into MPEG2 private sections (0x80), one section per transport stream
|
||||
packet. The PID is fixed at 0x010E.
|
||||
|
||||
|
||||
Header packet of frame:
|
||||
|
||||
0x47 0x41 0x0E 0x1X 0x00 0x80 0x00 L 0xB8 BBHeader (169 * Data)
|
||||
|
||||
L: Section Length, always 180 (0xB4)
|
||||
BBHeader: 10 Bytes BBFrame header (see DVB-S2, EN-302307)
|
||||
Data: 169 Bytes of BBFrame payload
|
||||
|
||||
|
||||
Payload packets:
|
||||
|
||||
0x47 0x41 0x0E 0x1X 0x00 0x80 0x00 L N (179 * Data)
|
||||
|
||||
L: Section Length, always 180 (0xB4)
|
||||
N: Packet counter, starting with 0x01 after header packet
|
||||
Data: 179 Bytes of BBFrame payload
|
||||
|
||||
|
||||
Last packet:
|
||||
0x47 0x41 0x0E 0x1X 0x00 0x80 0x00 L N ((L-1) * Data) ((180 – L) * 0xFF)
|
||||
|
||||
L: Section Length, remaining Data – 1, (0x01 .. 0xB4)
|
||||
N: Packet counter
|
||||
Data: L-1 Bytes of BBFrame payload
|
||||
|
||||
|
||||
|
||||
Automatic detection of input format:
|
||||
|
||||
The bridge firmware allows automatic detection of the incoming data.
|
||||
To receive regular transport streams in this formats it is still required to setup
|
||||
the DVB-S2 demodulator to output BBFrames instead of regular TS Packets.
|
||||
When enabled the embedding mode is automatically turned on or off depending on incoming data
|
||||
from the DVB-S2/S2X frontend. The decision depends currently only on the first byte of a packet.
|
||||
If it is 0x47 it switches to transport stream mode else it switches to embedding mode.
|
||||
|
||||
Note that 0x47 can currently not occur in the first byte of a BBFrame header if all reserved
|
||||
values of DVB-S2 and -S2X are observed.
|
||||
|
||||
|
||||
|
||||
|
||||
API:
|
||||
|
||||
Currently DTV_STREAM_ID is misused.
|
||||
Set it to 0x80000000 to enable frame mode in the demod.
|
||||
|
||||
|
||||
|
||||
Because there were some questions why we use this data format,
|
||||
here are some examples for why using this format this makes handling BBFrames easier:
|
||||
|
||||
- The start of a frame is easily found because a new set of sections is
|
||||
started.
|
||||
|
||||
- Existing software layers like the Linux kernel DVB demuxer can be used unchanged.
|
||||
|
||||
- Existing hardware like the OctopusNet SAT>IP server which can only handle TS packets can
|
||||
stream BBFrames via SAT>IP with this method.
|
||||
|
||||
- There is at least one demodulator (e.g. on the MaxSX8) which supports this format in hardware.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
22
docs/ci
22
docs/ci
@@ -1,3 +1,5 @@
|
||||
- General Information
|
||||
|
||||
The caX device associated with a CI device behaves just like any other
|
||||
caX interface. You usually use it through a library like libdvben50221
|
||||
which is part of the dvb-apps package available at linuxtv.org.
|
||||
@@ -26,6 +28,24 @@ use the new interface.
|
||||
See docs/redirect for more info.
|
||||
|
||||
|
||||
- Clock Speed
|
||||
|
||||
The normal clock speed for the TS output is 72 MHz wich is the standard
|
||||
speed used for CI.
|
||||
|
||||
Packets are sent with an adjustable gap between the packets.
|
||||
The gap size is (gap value * 2) + 4 or 0 if the gap is disabled.
|
||||
So, the standard gap value of 4 leads to a gap of 12 bytes which means
|
||||
that the effective data rate is (72*188)/200 = 67.68 MBits/s.
|
||||
|
||||
Depending on the hardware, the clock speed can be changed with the
|
||||
ci_bitrate module parameter:
|
||||
|
||||
- Octopus CI, Octopus CI S2 Pro : supported
|
||||
|
||||
- old CI single flex modules: supported
|
||||
|
||||
- new dual CI flex module: not yet supported, use the standard 72000 kHz
|
||||
|
||||
|
||||
|
||||
Valid ranges for are from ... to 96000 KHz.
|
||||
|
||||
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
|
||||
103
docs/modulator
103
docs/modulator
@@ -26,4 +26,105 @@ talks to the CI to decrypt the desired services.
|
||||
For testing one can use a standard application that
|
||||
supports decryption. Additionally to seeing the
|
||||
decoded service on the PC it will then also be streamed
|
||||
into cable by the modulator.
|
||||
into cable by the modulator.
|
||||
|
||||
|
||||
|
||||
The modulator device can be controlled with the
|
||||
following properties:
|
||||
|
||||
MODULATOR_FREQUENCY:
|
||||
|
||||
Set the frequency on Version 2 (FSM) cards
|
||||
units - Hz
|
||||
range - 114000000-874000000
|
||||
allowed values - 114 + 8000000*X
|
||||
|
||||
For older cards you have to use the
|
||||
DVB_MOD_SET ioctl.
|
||||
|
||||
|
||||
|
||||
MODULATOR_SYMBOLRATE:
|
||||
|
||||
Set the symbol rate
|
||||
units - Hz
|
||||
range - Version 1 cards: only 6900000
|
||||
Version 2 cards(FSM): X-7100000
|
||||
|
||||
|
||||
MODULATOR_MODULATION:
|
||||
|
||||
Set the modulation type
|
||||
range: QAM_16 .. QAM_256
|
||||
|
||||
|
||||
|
||||
MODULATOR_ATTENUATION:
|
||||
|
||||
range - 0-31
|
||||
unit - 1 dB
|
||||
|
||||
|
||||
MODULATOR_GAIN:
|
||||
|
||||
range - 0-255
|
||||
unit - 0.125 dB
|
||||
|
||||
|
||||
The MODULATOR_ATTENUATOR is based on a switched resistor network,
|
||||
also it is backward compatible to our old modulator.
|
||||
the MODULATOR_GAIN is based on a variable gain amplifier, so it is less
|
||||
accurate then the attenuator.
|
||||
High gain values will drive the output amplifier into clipping. The
|
||||
limit depends on # of channels active.
|
||||
|
||||
|
||||
|
||||
|
||||
MODULATOR_INPUT_BITRATE:
|
||||
|
||||
The modulator will ALWAY insert null packets if it
|
||||
does not get enough data.
|
||||
If you specify the input bitrate it will insert additional
|
||||
null packets according to the difference between input
|
||||
and output bit rate.
|
||||
The latter is determined by symbol rte and modulation.
|
||||
So, this property should be set last.
|
||||
|
||||
unit - 2^-32 Hz
|
||||
|
||||
|
||||
|
||||
Debugging features:
|
||||
|
||||
MODULATOR_STATUS and MODULATOR_RESET have been added to debug
|
||||
possible problems with too high temperatures (overtemperature)
|
||||
or PLL lock loss on FSM type cards.
|
||||
|
||||
The MODULATOR_STATUS property returns a __u32 with the following status bits:
|
||||
|
||||
- bit 0 : Lock status 1=lock OK, 0 = lock lost
|
||||
|
||||
- bit 1 : Sticky lock lost indicator
|
||||
0 = no PLL lock loss since last status read
|
||||
1 = lock has been lost since last status read
|
||||
|
||||
- bit 2 : 0 = no overtemperature
|
||||
1 = overtemperature detected
|
||||
|
||||
- bit 4 : 0 = PCIe link OK
|
||||
1 = PCIe link lost
|
||||
|
||||
In case of overtemperratur or PCIe link loss you will have to reboot the PC.
|
||||
|
||||
|
||||
Putting a MODULATOR_STATUS property with value 2 will enable the lost lock
|
||||
interrupt. This will set the gain to 0 and the attenuation to 31 in case
|
||||
of a lost PLL lock.
|
||||
|
||||
|
||||
The MODULATOR_RESET property can be used to reset the modulator without
|
||||
needing to reload the driver or rebooting in case of PLL lock loss.
|
||||
All channels should be stopped before using it and restarted after using it.
|
||||
Otherwise, results are unpredictable.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
- NAND flash
|
||||
|
||||
0x00000000 - 0x0025ffff U-boot
|
||||
0x00260000 - 0x0027ffff ENV
|
||||
0x00300000 - 0x00ffffff Linux image
|
||||
|
||||
0x01000000 - 0x01ffffff Linux recovery
|
||||
0x02000000 - 0x1fffffff Linux UBI
|
||||
0x00000000 - 0x0007ffff spl 512K
|
||||
0x00080000 - 0x0047ffff uboot 4M
|
||||
0x00480000 - 0x004fffff env 512K
|
||||
0x00500000 - 0x00ffffff spare 11M
|
||||
0x01000000 - 0x01ffffff recovery 16M
|
||||
0x02000000 - 0x1fffffff ubi -
|
||||
|
||||
|
||||
@@ -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.
|
||||
80
dvb-core/Kconfig
Normal file
80
dvb-core/Kconfig
Normal file
@@ -0,0 +1,80 @@
|
||||
# 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
|
||||
default 16
|
||||
range 1 255
|
||||
help
|
||||
Maximum number of DVB/ATSC adapters. Increasing this number
|
||||
increases the memory consumption of the DVB subsystem even
|
||||
if a much lower number of DVB/ATSC adapters is present.
|
||||
Only values in the range 4-32 are tested.
|
||||
|
||||
If you are unsure about this, use the default value 16
|
||||
|
||||
config DVB_DYNAMIC_MINORS
|
||||
bool "Dynamic DVB minor allocation"
|
||||
depends on DVB_CORE
|
||||
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.
|
||||
This means that you can have more than 4 of a single type
|
||||
of device (like demuxes and frontends) per adapter, but udev
|
||||
will be required to manage the device nodes.
|
||||
|
||||
If you are unsure about this, say N here.
|
||||
|
||||
config DVB_DEMUX_SECTION_LOSS_LOG
|
||||
bool "Enable DVB demux section packet loss log"
|
||||
depends on DVB_CORE
|
||||
help
|
||||
Enable extra log messages meant to detect 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.
|
||||
|
||||
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
|
||||
|
||||
14
dvb-core/Makefile.kernel
Normal file
14
dvb-core/Makefile.kernel
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Makefile for the kernel DVB device drivers.
|
||||
#
|
||||
|
||||
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
|
||||
|
||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
|
||||
|
||||
ccflags-y += -Idrivers/media/dvb-core/
|
||||
ccflags-y += --include=dd_compat.h
|
||||
241
dvb-core/demux.h
241
dvb-core/demux.h
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* demux.h
|
||||
*
|
||||
* Copyright (c) 2002 Convergence GmbH
|
||||
*
|
||||
* based on code:
|
||||
* Copyright (c) 2000 Nokia Research Center
|
||||
* Tampere, FINLAND
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DEMUX_H
|
||||
#define __DEMUX_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Common definitions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
|
||||
*/
|
||||
|
||||
#ifndef DMX_MAX_FILTER_SIZE
|
||||
#define DMX_MAX_FILTER_SIZE 18
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
|
||||
*/
|
||||
|
||||
#ifndef DMX_MAX_SECTION_SIZE
|
||||
#define DMX_MAX_SECTION_SIZE 4096
|
||||
#endif
|
||||
#ifndef DMX_MAX_SECFEED_SIZE
|
||||
#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* enum dmx_success: Success codes for the Demux Callback API.
|
||||
*/
|
||||
|
||||
enum dmx_success {
|
||||
DMX_OK = 0, /* Received Ok */
|
||||
DMX_LENGTH_ERROR, /* Incorrect length */
|
||||
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
|
||||
DMX_CRC_ERROR, /* Incorrect CRC */
|
||||
DMX_FRAME_ERROR, /* Frame alignment error */
|
||||
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
|
||||
DMX_MISSED_ERROR /* Receiver missed packet */
|
||||
} ;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* TS packet reception */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* TS filter type for set() */
|
||||
|
||||
#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */
|
||||
#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS
|
||||
payload (<=184 bytes per packet) to callback */
|
||||
#define TS_DECODER 4 /* send stream to built-in decoder (if present) */
|
||||
#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
|
||||
the demux device, not to the dvr device */
|
||||
|
||||
struct dmx_ts_feed {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
struct dmx_demux *parent; /* Back-pointer */
|
||||
void *priv; /* Pointer to private data of the API client */
|
||||
int (*set) (struct dmx_ts_feed *feed,
|
||||
u16 pid,
|
||||
int type,
|
||||
enum dmx_ts_pes pes_type,
|
||||
size_t circular_buffer_size,
|
||||
struct timespec timeout);
|
||||
int (*start_filtering) (struct dmx_ts_feed* feed);
|
||||
int (*stop_filtering) (struct dmx_ts_feed* feed);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Section reception */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
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 {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
struct dmx_demux* parent; /* Back-pointer */
|
||||
void* priv; /* Pointer to private data of the API client */
|
||||
|
||||
int check_crc;
|
||||
u32 crc_val;
|
||||
|
||||
u8 *secbuf;
|
||||
u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
|
||||
u16 secbufp, seclen, tsfeedp;
|
||||
|
||||
int (*set) (struct dmx_section_feed* feed,
|
||||
u16 pid,
|
||||
size_t circular_buffer_size,
|
||||
int check_crc);
|
||||
int (*allocate_filter) (struct dmx_section_feed* feed,
|
||||
struct dmx_section_filter** filter);
|
||||
int (*release_filter) (struct dmx_section_feed* feed,
|
||||
struct dmx_section_filter* filter);
|
||||
int (*start_filtering) (struct dmx_section_feed* feed);
|
||||
int (*stop_filtering) (struct dmx_section_feed* feed);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Callback functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
typedef int (*dmx_ts_cb) ( const u8 * buffer1,
|
||||
size_t buffer1_length,
|
||||
const u8 * buffer2,
|
||||
size_t buffer2_length,
|
||||
struct dmx_ts_feed* source,
|
||||
enum dmx_success success);
|
||||
|
||||
typedef int (*dmx_section_cb) ( const u8 * buffer1,
|
||||
size_t buffer1_len,
|
||||
const u8 * buffer2,
|
||||
size_t buffer2_len,
|
||||
struct dmx_section_filter * source,
|
||||
enum dmx_success success);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DVB Front-End */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
enum dmx_frontend_source {
|
||||
DMX_MEMORY_FE,
|
||||
DMX_FRONTEND_0,
|
||||
DMX_FRONTEND_1,
|
||||
DMX_FRONTEND_2,
|
||||
DMX_FRONTEND_3,
|
||||
DMX_STREAM_0, /* external stream input, e.g. LVDS */
|
||||
DMX_STREAM_1,
|
||||
DMX_STREAM_2,
|
||||
DMX_STREAM_3
|
||||
};
|
||||
|
||||
struct dmx_frontend {
|
||||
struct list_head connectivity_list; /* List of front-ends that can
|
||||
be connected to a particular
|
||||
demux */
|
||||
enum dmx_frontend_source source;
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MPEG-2 TS Demux */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Flags OR'ed in the capabilities field of struct dmx_demux.
|
||||
*/
|
||||
|
||||
#define DMX_TS_FILTERING 1
|
||||
#define DMX_PES_FILTERING 2
|
||||
#define DMX_SECTION_FILTERING 4
|
||||
#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
|
||||
#define DMX_CRC_CHECKING 16
|
||||
#define DMX_TS_DESCRAMBLING 32
|
||||
|
||||
/*
|
||||
* Demux resource type identifier.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DMX_FE_ENTRY(): Casts elements in the list of registered
|
||||
* front-ends from the generic type struct list_head
|
||||
* to the type * struct dmx_frontend
|
||||
*.
|
||||
*/
|
||||
|
||||
#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
|
||||
|
||||
struct dmx_demux {
|
||||
u32 capabilities; /* Bitfield of capability flags */
|
||||
struct dmx_frontend* frontend; /* Front-end connected to the demux */
|
||||
void* priv; /* Pointer to private data of the API client */
|
||||
int (*open) (struct dmx_demux* demux);
|
||||
int (*close) (struct dmx_demux* demux);
|
||||
int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
|
||||
int (*allocate_ts_feed) (struct dmx_demux* demux,
|
||||
struct dmx_ts_feed** feed,
|
||||
dmx_ts_cb callback);
|
||||
int (*release_ts_feed) (struct dmx_demux* demux,
|
||||
struct dmx_ts_feed* feed);
|
||||
int (*allocate_section_feed) (struct dmx_demux* demux,
|
||||
struct dmx_section_feed** feed,
|
||||
dmx_section_cb callback);
|
||||
int (*release_section_feed) (struct dmx_demux* demux,
|
||||
struct dmx_section_feed* feed);
|
||||
int (*add_frontend) (struct dmx_demux* demux,
|
||||
struct dmx_frontend* frontend);
|
||||
int (*remove_frontend) (struct dmx_demux* demux,
|
||||
struct dmx_frontend* frontend);
|
||||
struct list_head* (*get_frontends) (struct dmx_demux* demux);
|
||||
int (*connect_frontend) (struct dmx_demux* demux,
|
||||
struct dmx_frontend* frontend);
|
||||
int (*disconnect_frontend) (struct dmx_demux* demux);
|
||||
|
||||
int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
|
||||
|
||||
int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
|
||||
|
||||
int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
|
||||
|
||||
int (*get_stc) (struct dmx_demux* demux, unsigned int num,
|
||||
u64 *stc, unsigned int *base);
|
||||
};
|
||||
|
||||
#endif /* #ifndef __DEMUX_H */
|
||||
@@ -1,25 +1,14 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* dmxdev.c - DVB demultiplexer device
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dmxdev: " fmt
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -28,15 +17,22 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "dmxdev.h"
|
||||
#include <linux/uaccess.h>
|
||||
#include <media/dmxdev.h>
|
||||
#ifdef CONFIG_DVB_MMAP
|
||||
#include <media/dvb_vb2.h>
|
||||
#endif
|
||||
|
||||
static int debug;
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define dprintk if (debug) printk
|
||||
#define dprintk(fmt, arg...) do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
|
||||
__func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
|
||||
const u8 *src, size_t len)
|
||||
@@ -50,7 +46,7 @@ static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
|
||||
|
||||
free = dvb_ringbuffer_free(buf);
|
||||
if (len > free) {
|
||||
dprintk("dmxdev: buffer overflow\n");
|
||||
dprintk("buffer overflow\n");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
@@ -125,8 +121,9 @@ 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("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
@@ -136,15 +133,35 @@ 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) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -EBUSY;
|
||||
@@ -155,6 +172,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--;
|
||||
}
|
||||
|
||||
@@ -192,10 +214,19 @@ 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;
|
||||
/*memory barrier*/
|
||||
mb();
|
||||
spin_lock_irq(&dmxdev->lock);
|
||||
dmxdev->dvr_buffer.data = NULL;
|
||||
@@ -206,8 +237,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
||||
/* TODO */
|
||||
dvbdev->users--;
|
||||
if (dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else
|
||||
@@ -260,7 +289,7 @@ static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
|
||||
void *newmem;
|
||||
void *oldmem;
|
||||
|
||||
dprintk("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (buf->size == size)
|
||||
return 0;
|
||||
@@ -327,10 +356,34 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
static void dvb_dmxdev_filter_timeout(struct timer_list *t)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
|
||||
|
||||
dmxdevfilter->buffer.error = -ETIMEDOUT;
|
||||
spin_lock_irq(&dmxdevfilter->dev->lock);
|
||||
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
|
||||
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
}
|
||||
|
||||
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
||||
{
|
||||
struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
|
||||
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
if (para->timeout) {
|
||||
dmxdevfilter->timer.expires =
|
||||
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
|
||||
add_timer(&dmxdevfilter->timer);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void dvb_dmxdev_filter_timeout(unsigned long data)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
|
||||
|
||||
|
||||
dmxdevfilter->buffer.error = -ETIMEDOUT;
|
||||
spin_lock_irq(&dmxdevfilter->dev->lock);
|
||||
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
|
||||
@@ -351,16 +404,22 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
||||
add_timer(&dmxdevfilter->timer);
|
||||
}
|
||||
}
|
||||
#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,
|
||||
enum dmx_success success)
|
||||
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;
|
||||
}
|
||||
@@ -370,13 +429,32 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
return 0;
|
||||
}
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
|
||||
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)
|
||||
@@ -389,10 +467,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,
|
||||
enum dmx_success success)
|
||||
u32 *buffer_flags)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||
struct dvb_ringbuffer *buffer;
|
||||
#ifdef CONFIG_DVB_MMAP
|
||||
struct dvb_vb2_ctx *ctx;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
@@ -401,19 +482,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);
|
||||
@@ -560,9 +662,9 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
||||
struct dmxdev_filter *filter,
|
||||
struct dmxdev_feed *feed)
|
||||
{
|
||||
struct timespec timeout = { 0 };
|
||||
ktime_t timeout = ktime_set(0, 0);
|
||||
struct dmx_pes_filter_params *para = &filter->params.pes;
|
||||
dmx_output_t otype;
|
||||
enum dmx_output otype;
|
||||
int ret;
|
||||
int ts_type;
|
||||
enum dmx_ts_pes ts_pes;
|
||||
@@ -593,7 +695,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
||||
tsfeed = feed->ts;
|
||||
tsfeed->priv = filter;
|
||||
|
||||
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
|
||||
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout);
|
||||
if (ret < 0) {
|
||||
dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
|
||||
return ret;
|
||||
@@ -658,16 +760,16 @@ 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) {
|
||||
printk("DVB (%s): could not alloc feed\n",
|
||||
if (!*secfeed) {
|
||||
pr_err("DVB (%s): could not alloc feed\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (*secfeed)->set(*secfeed, para->pid, 32768,
|
||||
ret = (*secfeed)->set(*secfeed, para->pid,
|
||||
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
|
||||
if (ret < 0) {
|
||||
printk("DVB (%s): could not set feed\n",
|
||||
pr_err("DVB (%s): could not set feed\n",
|
||||
__func__);
|
||||
dvb_dmxdev_feed_restart(filter);
|
||||
return ret;
|
||||
@@ -738,6 +840,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
|
||||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dmxdev->exit) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < dmxdev->filternum; i++)
|
||||
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
|
||||
break;
|
||||
@@ -751,10 +858,24 @@ 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))
|
||||
timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0);
|
||||
#else
|
||||
init_timer(&dmxdevfilter->timer);
|
||||
#endif
|
||||
|
||||
dvbdev->users++;
|
||||
|
||||
@@ -767,6 +888,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);
|
||||
@@ -787,7 +913,7 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void invert_mode(dmx_filter_t *filter)
|
||||
static inline void invert_mode(struct dmx_filter *filter)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -848,7 +974,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
|
||||
struct dmxdev_filter *dmxdevfilter,
|
||||
struct dmx_sct_filter_params *params)
|
||||
{
|
||||
dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
|
||||
dprintk("%s: PID=0x%04x, flags=%02x, timeout=%d\n",
|
||||
__func__, params->pid, params->flags, params->timeout);
|
||||
|
||||
dvb_dmxdev_filter_stop(dmxdevfilter);
|
||||
@@ -874,7 +1000,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
|
||||
dvb_dmxdev_filter_stop(dmxdevfilter);
|
||||
dvb_dmxdev_filter_reset(dmxdevfilter);
|
||||
|
||||
if ((unsigned)params->pes_type > DMX_PES_OTHER)
|
||||
if ((unsigned int)params->pes_type > DMX_PES_OTHER)
|
||||
return -EINVAL;
|
||||
|
||||
dmxdevfilter->type = DMXDEV_TYPE_PES;
|
||||
@@ -1025,22 +1151,6 @@ static int dvb_demux_do_ioctl(struct file *file,
|
||||
dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_GET_CAPS:
|
||||
if (!dmxdev->demux->get_caps) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_SET_SOURCE:
|
||||
if (!dmxdev->demux->set_source) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = dmxdev->demux->set_source(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_GET_STC:
|
||||
if (!dmxdev->demux->get_stc) {
|
||||
ret = -EINVAL;
|
||||
@@ -1070,8 +1180,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);
|
||||
@@ -1084,30 +1242,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)
|
||||
return -EINVAL;
|
||||
__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;
|
||||
@@ -1119,9 +1317,7 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
|
||||
|
||||
mutex_lock(&dmxdev->mutex);
|
||||
dmxdev->dvbdev->users--;
|
||||
if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
if (dmxdev->dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dmxdev->dvbdev->wait_queue);
|
||||
} else
|
||||
@@ -1134,16 +1330,23 @@ 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 struct dvb_device dvbdev_demux = {
|
||||
static const struct dvb_device dvbdev_demux = {
|
||||
.priv = NULL,
|
||||
.users = 1,
|
||||
.writers = 1,
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
.name = "dvb-demux",
|
||||
#endif
|
||||
.fops = &dvb_demux_fops
|
||||
};
|
||||
|
||||
@@ -1163,8 +1366,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);
|
||||
@@ -1177,28 +1403,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("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
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,
|
||||
@@ -1208,23 +1464,34 @@ 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 struct dvb_device dvbdev_dvr = {
|
||||
static const struct dvb_device dvbdev_dvr = {
|
||||
.priv = NULL,
|
||||
.readers = 1,
|
||||
.users = 1,
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
.name = "dvb-dvr",
|
||||
#endif
|
||||
.fops = &dvb_dvr_fops
|
||||
};
|
||||
|
||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
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;
|
||||
|
||||
@@ -1237,28 +1504,43 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||
DMXDEV_STATE_FREE);
|
||||
}
|
||||
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||
DVB_DEVICE_DEMUX);
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||
dmxdev, DVB_DEVICE_DVR);
|
||||
ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
||||
if (ret < 0)
|
||||
goto err_register_dvbdev;
|
||||
|
||||
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
||||
if (ret < 0)
|
||||
goto err_register_dvr_dvbdev;
|
||||
|
||||
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
||||
|
||||
return 0;
|
||||
|
||||
err_register_dvr_dvbdev:
|
||||
dvb_unregister_device(dmxdev->dvbdev);
|
||||
err_register_dvbdev:
|
||||
vfree(dmxdev->filter);
|
||||
dmxdev->filter = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmxdev_init);
|
||||
|
||||
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
||||
{
|
||||
dmxdev->exit=1;
|
||||
mutex_lock(&dmxdev->mutex);
|
||||
dmxdev->exit = 1;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
||||
if (dmxdev->dvbdev->users > 1) {
|
||||
wait_event(dmxdev->dvbdev->wait_queue,
|
||||
dmxdev->dvbdev->users==1);
|
||||
dmxdev->dvbdev->users == 1);
|
||||
}
|
||||
if (dmxdev->dvr_dvbdev->users > 1) {
|
||||
wait_event(dmxdev->dvr_dvbdev->wait_queue,
|
||||
dmxdev->dvr_dvbdev->users==1);
|
||||
dmxdev->dvr_dvbdev->users == 1);
|
||||
}
|
||||
|
||||
dvb_unregister_device(dmxdev->dvbdev);
|
||||
|
||||
@@ -1,119 +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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#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_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* dvb_ca.h: generic DVB functions for EN50221 CA interfaces
|
||||
*
|
||||
* Copyright (C) 2004 Andrew de Quincey
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_CA_EN50221_H_
|
||||
#define _DVB_CA_EN50221_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/dvb/ca.h>
|
||||
|
||||
#include "dvbdev.h"
|
||||
|
||||
#define DVB_CA_EN50221_POLL_CAM_PRESENT 1
|
||||
#define DVB_CA_EN50221_POLL_CAM_CHANGED 2
|
||||
#define DVB_CA_EN50221_POLL_CAM_READY 4
|
||||
|
||||
#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1
|
||||
#define DVB_CA_EN50221_FLAG_IRQ_FR 2
|
||||
#define DVB_CA_EN50221_FLAG_IRQ_DA 4
|
||||
|
||||
#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0
|
||||
#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1
|
||||
|
||||
|
||||
|
||||
/* Structure describing a CA interface */
|
||||
struct dvb_ca_en50221 {
|
||||
|
||||
/* the module owning this structure */
|
||||
struct module* owner;
|
||||
|
||||
/* NOTE: the read_*, write_* and poll_slot_status functions will be
|
||||
* called for different slots concurrently and need to use locks where
|
||||
* and if appropriate. There will be no concurrent access to one slot.
|
||||
*/
|
||||
|
||||
/* functions for accessing attribute memory on the CAM */
|
||||
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
|
||||
int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
|
||||
|
||||
/* functions for accessing the control interface on the CAM */
|
||||
int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
|
||||
int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
|
||||
|
||||
/* functions for readin/writing data */
|
||||
int (*read_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
|
||||
int (*write_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
|
||||
|
||||
/* Functions for controlling slots */
|
||||
int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
|
||||
int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
|
||||
int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
|
||||
|
||||
/*
|
||||
* Poll slot status.
|
||||
* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
|
||||
*/
|
||||
int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
|
||||
|
||||
/* private data, used by caller */
|
||||
void* data;
|
||||
|
||||
/* Opaque data used by the dvb_ca core. Do not modify! */
|
||||
void* private;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* ******************************************************************************** */
|
||||
/* Functions for reporting IRQ events */
|
||||
|
||||
/**
|
||||
* A CAMCHANGE IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
* @param change_type One of the DVB_CA_CAMCHANGE_* values
|
||||
*/
|
||||
void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
|
||||
|
||||
/**
|
||||
* A CAMREADY IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
*/
|
||||
void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
|
||||
|
||||
/**
|
||||
* An FR or a DA IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
*/
|
||||
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
|
||||
|
||||
|
||||
|
||||
/* ******************************************************************************** */
|
||||
/* Initialisation/shutdown functions */
|
||||
|
||||
/**
|
||||
* Initialise a new DVB CA device.
|
||||
*
|
||||
* @param dvb_adapter DVB adapter to attach the new CA device to.
|
||||
* @param ca The dvb_ca instance.
|
||||
* @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
|
||||
* @param slot_count Number of slots supported.
|
||||
*
|
||||
* @return 0 on success, nonzero on failure
|
||||
*/
|
||||
extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
|
||||
|
||||
/**
|
||||
* Release a DVB CA device.
|
||||
*
|
||||
* @param ca The associated dvb_ca instance.
|
||||
*/
|
||||
extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,27 +1,20 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* dvb_demux.c - DVB kernel demux API
|
||||
*
|
||||
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
|
||||
* & Marcus Metzler <marcus@convergence.de>
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dvb_demux: " fmt
|
||||
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
#include <linux/sched/signal.h>
|
||||
#else
|
||||
#include <linux/sched.h>
|
||||
#endif
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
@@ -29,16 +22,18 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_demux.h"
|
||||
#include <media/dvb_demux.h>
|
||||
|
||||
#define NOBUFS
|
||||
/*
|
||||
** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
|
||||
*/
|
||||
// #define DVB_DEMUX_SECTION_LOSS_LOG
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
|
||||
static inline s64 ktime_ms_delta(const ktime_t later, const ktime_t earlier)
|
||||
{
|
||||
return ktime_to_ms(ktime_sub(later, earlier));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dvb_demux_tscheck;
|
||||
module_param(dvb_demux_tscheck, int, 0644);
|
||||
@@ -55,9 +50,23 @@ module_param(dvb_demux_feed_err_pkts, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
|
||||
"when set to 0, drop packets with the TEI bit set (1 by default)");
|
||||
|
||||
#define dprintk_tscheck(x...) do { \
|
||||
if (dvb_demux_tscheck && printk_ratelimit()) \
|
||||
printk(x); \
|
||||
#define dprintk(fmt, arg...) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
|
||||
|
||||
#define dprintk_tscheck(x...) do { \
|
||||
if (dvb_demux_tscheck && printk_ratelimit()) \
|
||||
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)
|
||||
|
||||
/******************************************************************************
|
||||
@@ -109,28 +118,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
|
||||
{
|
||||
int count = payload(buf);
|
||||
int p;
|
||||
//int ccok;
|
||||
//u8 cc;
|
||||
int ccok;
|
||||
u8 cc;
|
||||
|
||||
if (count == 0)
|
||||
return -1;
|
||||
|
||||
p = 188 - count;
|
||||
|
||||
/*
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
if (!ccok)
|
||||
printk("missed packet!\n");
|
||||
*/
|
||||
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, DMX_OK);
|
||||
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,
|
||||
@@ -152,7 +163,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, DMX_OK);
|
||||
NULL, 0, &f->filter, &feed->buffer_flags);
|
||||
}
|
||||
|
||||
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
|
||||
@@ -171,8 +182,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 {
|
||||
@@ -189,9 +202,8 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
|
||||
{
|
||||
struct dmx_section_feed *sec = &feed->feed.sec;
|
||||
|
||||
#ifdef 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.
|
||||
@@ -199,15 +211,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) {
|
||||
printk("dvb_demux.c section ts padding loss: %d/%d\n",
|
||||
n, sec->tsfeedp);
|
||||
printk("dvb_demux.c pad data:");
|
||||
for (i = 0; i < n; i++)
|
||||
printk(" %02x", sec->secbuf[i]);
|
||||
printk("\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;
|
||||
@@ -226,27 +236,26 @@ 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)
|
||||
{
|
||||
struct dvb_demux *demux = feed->demux;
|
||||
struct dmx_section_feed *sec = &feed->feed.sec;
|
||||
u16 limit, seclen, n;
|
||||
u16 limit, seclen;
|
||||
|
||||
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
||||
return 0;
|
||||
|
||||
if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
printk("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;
|
||||
}
|
||||
|
||||
@@ -266,7 +275,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
|
||||
/* to be sure always set secbuf */
|
||||
sec->secbuf = sec->secbuf_base + sec->secbufp;
|
||||
|
||||
for (n = 0; sec->secbufp + 2 < limit; n++) {
|
||||
while (sec->secbufp + 2 < limit) {
|
||||
seclen = section_length(sec->secbuf);
|
||||
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|
||||
|| seclen + sec->secbufp > limit)
|
||||
@@ -274,12 +283,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 DVB_DEMUX_SECTION_LOSS_LOG
|
||||
else
|
||||
printk("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 */
|
||||
}
|
||||
@@ -312,19 +322,31 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
}
|
||||
|
||||
if (!ccok || dc_i) {
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
printk("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);
|
||||
}
|
||||
|
||||
@@ -338,16 +360,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 DVB_DEMUX_SECTION_LOSS_LOG
|
||||
else if (count > 0)
|
||||
printk("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);
|
||||
@@ -368,8 +390,9 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
|
||||
dvb_dmx_swfilter_payload(feed, buf);
|
||||
else
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
|
||||
DMX_OK);
|
||||
&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);
|
||||
@@ -399,31 +422,27 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
int dvr_done = 0;
|
||||
|
||||
if (dvb_demux_speedcheck) {
|
||||
struct timespec cur_time, delta_time;
|
||||
ktime_t cur_time;
|
||||
u64 speed_bytes, speed_timedelta;
|
||||
|
||||
demux->speed_pkts_cnt++;
|
||||
|
||||
/* show speed every SPEED_PKTS_INTERVAL packets */
|
||||
if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) {
|
||||
cur_time = current_kernel_time();
|
||||
cur_time = ktime_get();
|
||||
|
||||
if (demux->speed_last_time.tv_sec != 0 &&
|
||||
demux->speed_last_time.tv_nsec != 0) {
|
||||
delta_time = timespec_sub(cur_time,
|
||||
demux->speed_last_time);
|
||||
if (ktime_to_ns(demux->speed_last_time) != 0) {
|
||||
speed_bytes = (u64)demux->speed_pkts_cnt
|
||||
* 188 * 8;
|
||||
/* convert to 1024 basis */
|
||||
speed_bytes = 1000 * div64_u64(speed_bytes,
|
||||
1024);
|
||||
speed_timedelta =
|
||||
(u64)timespec_to_ns(&delta_time);
|
||||
speed_timedelta = div64_u64(speed_timedelta,
|
||||
1000000); /* nsec -> usec */
|
||||
printk(KERN_INFO "TS speed %llu Kbits/sec \n",
|
||||
speed_timedelta = ktime_ms_delta(cur_time,
|
||||
demux->speed_last_time);
|
||||
if (speed_timedelta)
|
||||
dprintk("TS speed %llu Kbits/sec \n",
|
||||
div64_u64(speed_bytes,
|
||||
speed_timedelta));
|
||||
speed_timedelta));
|
||||
}
|
||||
|
||||
demux->speed_last_time = cur_time;
|
||||
@@ -432,10 +451,14 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
}
|
||||
|
||||
if (buf[1] & 0x80) {
|
||||
dprintk_tscheck("TEI detected. "
|
||||
"PID=0x%x data1=0x%x\n",
|
||||
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 cant be trusted - drop it unless
|
||||
/* data in this packet can't be trusted - drop it unless
|
||||
* module option dvb_demux_feed_err_pkts is set */
|
||||
if (!dvb_demux_feed_err_pkts)
|
||||
return;
|
||||
@@ -448,9 +471,16 @@ 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);
|
||||
pid, demux->cnt_storage[pid],
|
||||
buf[3] & 0xf);
|
||||
demux->cnt_storage[pid] = buf[3] & 0xf;
|
||||
}
|
||||
}
|
||||
@@ -469,14 +499,17 @@ 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, DMX_OK);
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
|
||||
&feed->buffer_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
while (count--) {
|
||||
if (buf[0] == 0x47)
|
||||
@@ -484,7 +517,7 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
buf += 188;
|
||||
}
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
@@ -519,8 +552,9 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
{
|
||||
int p = 0, i, j;
|
||||
const u8 *q;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
|
||||
i = demux->tsbufp;
|
||||
@@ -564,7 +598,7 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
@@ -581,11 +615,22 @@ EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
||||
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
#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);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
|
||||
|
||||
@@ -636,7 +681,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
|
||||
{
|
||||
spin_lock_irq(&feed->demux->lock);
|
||||
if (dvb_demux_feed_find(feed)) {
|
||||
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
|
||||
pr_err("%s: feed already in list (type=%x state=%x pid=%x)\n",
|
||||
__func__, feed->type, feed->state, feed->pid);
|
||||
goto out;
|
||||
}
|
||||
@@ -650,7 +695,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
|
||||
{
|
||||
spin_lock_irq(&feed->demux->lock);
|
||||
if (!(dvb_demux_feed_find(feed))) {
|
||||
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
|
||||
pr_err("%s: feed not in list (type=%x state=%x pid=%x)\n",
|
||||
__func__, feed->type, feed->state, feed->pid);
|
||||
goto out;
|
||||
}
|
||||
@@ -661,8 +706,7 @@ out:
|
||||
}
|
||||
|
||||
static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
|
||||
enum dmx_ts_pes pes_type,
|
||||
size_t circular_buffer_size, struct timespec timeout)
|
||||
enum dmx_ts_pes pes_type, ktime_t timeout)
|
||||
{
|
||||
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
|
||||
struct dvb_demux *demux = feed->demux;
|
||||
@@ -692,23 +736,10 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
|
||||
dvb_demux_feed_add(feed);
|
||||
|
||||
feed->pid = pid;
|
||||
feed->buffer_size = circular_buffer_size;
|
||||
feed->timeout = timeout;
|
||||
feed->ts_type = ts_type;
|
||||
feed->pes_type = pes_type;
|
||||
|
||||
if (feed->buffer_size) {
|
||||
#ifdef NOBUFS
|
||||
feed->buffer = NULL;
|
||||
#else
|
||||
feed->buffer = vmalloc(feed->buffer_size);
|
||||
if (!feed->buffer) {
|
||||
mutex_unlock(&demux->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
feed->state = DMX_STATE_READY;
|
||||
mutex_unlock(&demux->mutex);
|
||||
|
||||
@@ -797,7 +828,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
|
||||
feed->demux = demux;
|
||||
feed->pid = 0xffff;
|
||||
feed->peslen = 0xfffa;
|
||||
feed->buffer = NULL;
|
||||
feed->buffer_flags = 0;
|
||||
|
||||
(*ts_feed) = &feed->feed.ts;
|
||||
(*ts_feed)->parent = dmx;
|
||||
@@ -834,10 +865,6 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
|
||||
mutex_unlock(&demux->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
#ifndef NOBUFS
|
||||
vfree(feed->buffer);
|
||||
feed->buffer = NULL;
|
||||
#endif
|
||||
|
||||
feed->state = DMX_STATE_FREE;
|
||||
feed->filter->state = DMX_STATE_FREE;
|
||||
@@ -889,8 +916,7 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
|
||||
}
|
||||
|
||||
static int dmx_section_feed_set(struct dmx_section_feed *feed,
|
||||
u16 pid, size_t circular_buffer_size,
|
||||
int check_crc)
|
||||
u16 pid, int check_crc)
|
||||
{
|
||||
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
|
||||
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
|
||||
@@ -904,19 +930,8 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed,
|
||||
dvb_demux_feed_add(dvbdmxfeed);
|
||||
|
||||
dvbdmxfeed->pid = pid;
|
||||
dvbdmxfeed->buffer_size = circular_buffer_size;
|
||||
dvbdmxfeed->feed.sec.check_crc = check_crc;
|
||||
|
||||
#ifdef NOBUFS
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
#else
|
||||
dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
|
||||
if (!dvbdmxfeed->buffer) {
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
dvbdmxfeed->state = DMX_STATE_READY;
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return 0;
|
||||
@@ -933,14 +948,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));
|
||||
}
|
||||
|
||||
@@ -967,6 +982,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);
|
||||
@@ -1027,8 +1043,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (feed->is_filtering)
|
||||
if (feed->is_filtering) {
|
||||
/* release dvbdmx->mutex as far as it is
|
||||
acquired by stop_filtering() itself */
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
feed->stop_filtering(feed);
|
||||
mutex_lock(&dvbdmx->mutex);
|
||||
}
|
||||
|
||||
spin_lock_irq(&dvbdmx->lock);
|
||||
f = dvbdmxfeed->filter;
|
||||
@@ -1066,11 +1087,11 @@ 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;
|
||||
dvbdmxfeed->filter = NULL;
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
|
||||
(*feed) = &dvbdmxfeed->feed.sec;
|
||||
(*feed)->is_filtering = 0;
|
||||
@@ -1099,10 +1120,6 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
#ifndef NOBUFS
|
||||
vfree(dvbdmxfeed->buffer);
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
#endif
|
||||
dvbdmxfeed->state = DMX_STATE_FREE;
|
||||
|
||||
dvb_demux_feed_del(dvbdmxfeed);
|
||||
@@ -1242,12 +1259,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;
|
||||
@@ -1264,7 +1294,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
|
||||
|
||||
dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
|
||||
if (!dvbdemux->cnt_storage)
|
||||
printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
|
||||
pr_warn("Couldn't allocate memory for TS/TEI check. Disabling it\n");
|
||||
|
||||
INIT_LIST_HEAD(&dvbdemux->frontend_list);
|
||||
|
||||
|
||||
@@ -1,151 +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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
u8 *buffer;
|
||||
int buffer_size;
|
||||
|
||||
struct timespec 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 */
|
||||
|
||||
struct timespec 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
@@ -1,441 +0,0 @@
|
||||
/*
|
||||
* dvb_frontend.h
|
||||
*
|
||||
* Copyright (C) 2001 convergence integrated media GmbH
|
||||
* Copyright (C) 2004 convergence GmbH
|
||||
*
|
||||
* Written by Ralph Metzler
|
||||
* Overhauled by Holger Waechtler
|
||||
* Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DVB_FRONTEND_H_
|
||||
#define _DVB_FRONTEND_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
#include "dvbdev.h"
|
||||
|
||||
/*
|
||||
* Maximum number of Delivery systems per frontend. It
|
||||
* should be smaller or equal to 32
|
||||
*/
|
||||
#define MAX_DELSYS 8
|
||||
|
||||
struct dvb_frontend_tune_settings {
|
||||
int min_delay_ms;
|
||||
int step_size;
|
||||
int max_drift;
|
||||
};
|
||||
|
||||
struct dvb_frontend;
|
||||
|
||||
struct dvb_tuner_info {
|
||||
char name[128];
|
||||
|
||||
u32 frequency_min;
|
||||
u32 frequency_max;
|
||||
u32 frequency_step;
|
||||
|
||||
u32 bandwidth_min;
|
||||
u32 bandwidth_max;
|
||||
u32 bandwidth_step;
|
||||
};
|
||||
|
||||
struct analog_parameters {
|
||||
unsigned int frequency;
|
||||
unsigned int mode;
|
||||
unsigned int audmode;
|
||||
u64 std;
|
||||
};
|
||||
|
||||
enum dvbfe_modcod {
|
||||
DVBFE_MODCOD_DUMMY_PLFRAME = 0,
|
||||
DVBFE_MODCOD_QPSK_1_4,
|
||||
DVBFE_MODCOD_QPSK_1_3,
|
||||
DVBFE_MODCOD_QPSK_2_5,
|
||||
DVBFE_MODCOD_QPSK_1_2,
|
||||
DVBFE_MODCOD_QPSK_3_5,
|
||||
DVBFE_MODCOD_QPSK_2_3,
|
||||
DVBFE_MODCOD_QPSK_3_4,
|
||||
DVBFE_MODCOD_QPSK_4_5,
|
||||
DVBFE_MODCOD_QPSK_5_6,
|
||||
DVBFE_MODCOD_QPSK_8_9,
|
||||
DVBFE_MODCOD_QPSK_9_10,
|
||||
DVBFE_MODCOD_8PSK_3_5,
|
||||
DVBFE_MODCOD_8PSK_2_3,
|
||||
DVBFE_MODCOD_8PSK_3_4,
|
||||
DVBFE_MODCOD_8PSK_5_6,
|
||||
DVBFE_MODCOD_8PSK_8_9,
|
||||
DVBFE_MODCOD_8PSK_9_10,
|
||||
DVBFE_MODCOD_16APSK_2_3,
|
||||
DVBFE_MODCOD_16APSK_3_4,
|
||||
DVBFE_MODCOD_16APSK_4_5,
|
||||
DVBFE_MODCOD_16APSK_5_6,
|
||||
DVBFE_MODCOD_16APSK_8_9,
|
||||
DVBFE_MODCOD_16APSK_9_10,
|
||||
DVBFE_MODCOD_32APSK_3_4,
|
||||
DVBFE_MODCOD_32APSK_4_5,
|
||||
DVBFE_MODCOD_32APSK_5_6,
|
||||
DVBFE_MODCOD_32APSK_8_9,
|
||||
DVBFE_MODCOD_32APSK_9_10,
|
||||
DVBFE_MODCOD_RESERVED_1,
|
||||
DVBFE_MODCOD_BPSK_1_3,
|
||||
DVBFE_MODCOD_BPSK_1_4,
|
||||
DVBFE_MODCOD_RESERVED_2
|
||||
};
|
||||
|
||||
enum tuner_param {
|
||||
DVBFE_TUNER_FREQUENCY = (1 << 0),
|
||||
DVBFE_TUNER_TUNERSTEP = (1 << 1),
|
||||
DVBFE_TUNER_IFFREQ = (1 << 2),
|
||||
DVBFE_TUNER_BANDWIDTH = (1 << 3),
|
||||
DVBFE_TUNER_REFCLOCK = (1 << 4),
|
||||
DVBFE_TUNER_IQSENSE = (1 << 5),
|
||||
DVBFE_TUNER_DUMMY = (1 << 31)
|
||||
};
|
||||
|
||||
/*
|
||||
* ALGO_HW: (Hardware Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* Devices that support this algorithm do everything in hardware
|
||||
* and no software support is needed to handle them.
|
||||
* Requesting these devices to LOCK is the only thing required,
|
||||
* device is supposed to do everything in the hardware.
|
||||
*
|
||||
* ALGO_SW: (Software Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* These are dumb devices, that require software to do everything
|
||||
*
|
||||
* ALGO_CUSTOM: (Customizable Agorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* Devices having this algorithm can be customized to have specific
|
||||
* algorithms in the frontend driver, rather than simply doing a
|
||||
* software zig-zag. In this case the zigzag maybe hardware assisted
|
||||
* or it maybe completely done in hardware. In all cases, usage of
|
||||
* this algorithm, in conjunction with the search and track
|
||||
* callbacks, utilizes the driver specific algorithm.
|
||||
*
|
||||
* ALGO_RECOVERY: (Recovery Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* 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)
|
||||
};
|
||||
|
||||
struct tuner_state {
|
||||
u32 frequency;
|
||||
u32 tunerstep;
|
||||
u32 ifreq;
|
||||
u32 bandwidth;
|
||||
u32 iqsense;
|
||||
u32 refclock;
|
||||
};
|
||||
|
||||
/*
|
||||
* search callback possible return status
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_SUCCESS
|
||||
* The frontend search algorithm completed and returned successfully
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_ASLEEP
|
||||
* The frontend search algorithm is sleeping
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_FAILED
|
||||
* The frontend search for a signal failed
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_INVALID
|
||||
* The frontend search algorith was probably supplied with invalid
|
||||
* parameters and the search is an invalid one
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_ERROR
|
||||
* The frontend search algorithm failed due to some error
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_AGAIN
|
||||
* 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),
|
||||
};
|
||||
|
||||
|
||||
struct dvb_tuner_ops {
|
||||
|
||||
struct dvb_tuner_info info;
|
||||
|
||||
int (*release)(struct dvb_frontend *fe);
|
||||
int (*init)(struct dvb_frontend *fe);
|
||||
int (*sleep)(struct dvb_frontend *fe);
|
||||
|
||||
/** This is for simple PLLs - set all parameters in one go. */
|
||||
int (*set_params)(struct dvb_frontend *fe);
|
||||
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
|
||||
|
||||
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
|
||||
int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
|
||||
|
||||
/** This is to allow setting tuner-specific configs */
|
||||
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
|
||||
|
||||
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
|
||||
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
|
||||
int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
|
||||
|
||||
#define TUNER_STATUS_LOCKED 1
|
||||
#define TUNER_STATUS_STEREO 2
|
||||
int (*get_status)(struct dvb_frontend *fe, u32 *status);
|
||||
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
|
||||
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
|
||||
|
||||
/** These are provided separately from set_params in order to facilitate silicon
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
|
||||
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
|
||||
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
|
||||
|
||||
/*
|
||||
* These are provided separately from set_params in order to facilitate silicon
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter separately.
|
||||
*/
|
||||
int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
|
||||
int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
|
||||
};
|
||||
|
||||
struct analog_demod_info {
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct analog_demod_ops {
|
||||
|
||||
struct analog_demod_info info;
|
||||
|
||||
void (*set_params)(struct dvb_frontend *fe,
|
||||
struct analog_parameters *params);
|
||||
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
|
||||
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
|
||||
void (*tuner_status)(struct dvb_frontend *fe);
|
||||
void (*standby)(struct dvb_frontend *fe);
|
||||
void (*release)(struct dvb_frontend *fe);
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
|
||||
|
||||
/** This is to allow setting tuner-specific configuration */
|
||||
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
|
||||
};
|
||||
|
||||
struct dtv_frontend_properties;
|
||||
|
||||
struct dvb_frontend_ops {
|
||||
|
||||
struct dvb_frontend_info info;
|
||||
|
||||
u8 delsys[MAX_DELSYS];
|
||||
|
||||
void (*release)(struct dvb_frontend* fe);
|
||||
void (*release_sec)(struct dvb_frontend* fe);
|
||||
|
||||
int (*init)(struct dvb_frontend* fe);
|
||||
int (*sleep)(struct dvb_frontend* fe);
|
||||
|
||||
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
|
||||
|
||||
/* if this is set, it overrides the default swzigzag */
|
||||
int (*tune)(struct dvb_frontend* fe,
|
||||
bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay,
|
||||
fe_status_t *status);
|
||||
/* get frontend tuning algorithm from the module */
|
||||
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
|
||||
|
||||
/* these two are only used for the swzigzag code */
|
||||
int (*set_frontend)(struct dvb_frontend *fe);
|
||||
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
|
||||
|
||||
int (*get_frontend)(struct dvb_frontend *fe);
|
||||
|
||||
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
|
||||
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
|
||||
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
|
||||
int (*read_snr)(struct dvb_frontend* fe, u16* snr);
|
||||
int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
|
||||
|
||||
int (*diseqc_reset_overload)(struct dvb_frontend* fe);
|
||||
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
|
||||
int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
|
||||
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
|
||||
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
|
||||
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
||||
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
|
||||
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
|
||||
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
|
||||
int (*set_lna)(struct dvb_frontend *);
|
||||
int (*set_input)(struct dvb_frontend *, int);
|
||||
|
||||
/* These callbacks are for devices that implement their own
|
||||
* tuning algorithms, rather than a simple swzigzag
|
||||
*/
|
||||
enum dvbfe_search (*search)(struct dvb_frontend *fe);
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
#ifdef __DVB_CORE__
|
||||
#define MAX_EVENT 8
|
||||
|
||||
struct dvb_fe_events {
|
||||
struct dvb_frontend_event events[MAX_EVENT];
|
||||
int eventw;
|
||||
int eventr;
|
||||
int overflow;
|
||||
wait_queue_head_t wait_queue;
|
||||
struct mutex mtx;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct dtv_frontend_properties {
|
||||
|
||||
/* Cache State */
|
||||
u32 state;
|
||||
|
||||
u32 frequency;
|
||||
fe_modulation_t modulation;
|
||||
|
||||
fe_sec_voltage_t voltage;
|
||||
fe_sec_tone_mode_t sectone;
|
||||
fe_spectral_inversion_t inversion;
|
||||
fe_code_rate_t fec_inner;
|
||||
fe_transmit_mode_t transmission_mode;
|
||||
u32 bandwidth_hz; /* 0 = AUTO */
|
||||
fe_guard_interval_t guard_interval;
|
||||
fe_hierarchy_t hierarchy;
|
||||
u32 symbol_rate;
|
||||
fe_code_rate_t code_rate_HP;
|
||||
fe_code_rate_t code_rate_LP;
|
||||
|
||||
fe_pilot_t pilot;
|
||||
fe_rolloff_t rolloff;
|
||||
|
||||
fe_delivery_system_t delivery_system;
|
||||
|
||||
enum fe_interleaving interleaving;
|
||||
|
||||
/* ISDB-T specifics */
|
||||
u8 isdbt_partial_reception;
|
||||
u8 isdbt_sb_mode;
|
||||
u8 isdbt_sb_subchannel;
|
||||
u32 isdbt_sb_segment_idx;
|
||||
u32 isdbt_sb_segment_count;
|
||||
u8 isdbt_layer_enabled;
|
||||
struct {
|
||||
u8 segment_count;
|
||||
fe_code_rate_t fec;
|
||||
fe_modulation_t modulation;
|
||||
u8 interleaving;
|
||||
} layer[3];
|
||||
|
||||
/* Multistream specifics */
|
||||
u32 stream_id;
|
||||
|
||||
/* ATSC-MH specifics */
|
||||
u8 atscmh_fic_ver;
|
||||
u8 atscmh_parade_id;
|
||||
u8 atscmh_nog;
|
||||
u8 atscmh_tnog;
|
||||
u8 atscmh_sgn;
|
||||
u8 atscmh_prc;
|
||||
|
||||
u8 atscmh_rs_frame_mode;
|
||||
u8 atscmh_rs_frame_ensemble;
|
||||
u8 atscmh_rs_code_mode_pri;
|
||||
u8 atscmh_rs_code_mode_sec;
|
||||
u8 atscmh_sccc_block_mode;
|
||||
u8 atscmh_sccc_code_mode_a;
|
||||
u8 atscmh_sccc_code_mode_b;
|
||||
u8 atscmh_sccc_code_mode_c;
|
||||
u8 atscmh_sccc_code_mode_d;
|
||||
|
||||
u32 lna;
|
||||
s32 input;
|
||||
|
||||
/* statistics data */
|
||||
struct dtv_fe_stats strength;
|
||||
struct dtv_fe_stats cnr;
|
||||
struct dtv_fe_stats pre_bit_error;
|
||||
struct dtv_fe_stats pre_bit_count;
|
||||
struct dtv_fe_stats post_bit_error;
|
||||
struct dtv_fe_stats post_bit_count;
|
||||
struct dtv_fe_stats block_error;
|
||||
struct dtv_fe_stats block_count;
|
||||
};
|
||||
|
||||
struct dvb_frontend {
|
||||
struct dvb_frontend_ops ops;
|
||||
struct dvb_adapter *dvb;
|
||||
void *demodulator_priv;
|
||||
void *tuner_priv;
|
||||
void *frontend_priv;
|
||||
void *sec_priv;
|
||||
void *analog_demod_priv;
|
||||
struct dtv_frontend_properties dtv_property_cache;
|
||||
#define DVB_FRONTEND_COMPONENT_TUNER 0
|
||||
#define DVB_FRONTEND_COMPONENT_DEMOD 1
|
||||
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
|
||||
int id;
|
||||
};
|
||||
|
||||
extern int dvb_register_frontend(struct dvb_adapter *dvb,
|
||||
struct dvb_frontend *fe);
|
||||
|
||||
extern int dvb_unregister_frontend(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_detach(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
|
||||
extern int dvb_frontend_suspend(struct dvb_frontend *fe);
|
||||
extern int dvb_frontend_resume(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
|
||||
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
|
||||
|
||||
#endif
|
||||
@@ -13,17 +13,13 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#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,
|
||||
|
||||
1176
dvb-core/dvb_net.c
1176
dvb-core/dvb_net.c
File diff suppressed because it is too large
Load Diff
@@ -18,10 +18,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
@@ -31,9 +27,14 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
|
||||
#include <asm/uaccess.h>
|
||||
#else
|
||||
#include <linux/uaccess.h>
|
||||
#endif
|
||||
|
||||
#include "dvb_ringbuffer.h"
|
||||
#include <media/dvb_ringbuffer.h>
|
||||
|
||||
#define PKT_READY 0
|
||||
#define PKT_DISPOSED 1
|
||||
@@ -55,7 +56,17 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
|
||||
|
||||
int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
return (rbuf->pread==rbuf->pwrite);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
return (rbuf->pread == rbuf->pwrite);
|
||||
#else
|
||||
/* smp_load_acquire() to load write pointer on reader side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
||||
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
||||
*
|
||||
* for memory barriers also see Documentation/core-api/circular-buffers.rst
|
||||
*/
|
||||
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +75,16 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
ssize_t free;
|
||||
|
||||
free = rbuf->pread - rbuf->pwrite;
|
||||
/* READ_ONCE() to load read pointer on writer side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_read(),
|
||||
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
|
||||
* or dvb_ringbuffer_reset()
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
free = READ_ONCE(rbuf->pread) - rbuf->pwrite;
|
||||
#else
|
||||
free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite;
|
||||
#endif
|
||||
if (free <= 0)
|
||||
free += rbuf->size;
|
||||
return free-1;
|
||||
@@ -76,7 +96,15 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
ssize_t avail;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
avail = rbuf->pwrite - rbuf->pread;
|
||||
#else
|
||||
/* smp_load_acquire() to load write pointer on reader side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
||||
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
||||
*/
|
||||
avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread;
|
||||
#endif
|
||||
if (avail < 0)
|
||||
avail += rbuf->size;
|
||||
return avail;
|
||||
@@ -86,14 +114,33 @@ 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;
|
||||
#else
|
||||
/* dvb_ringbuffer_flush() counts as read operation
|
||||
* smp_load_acquire() to load write pointer
|
||||
* smp_store_release() to update read pointer, this ensures that the
|
||||
* correct pointer is visible for subsequent dvb_ringbuffer_free()
|
||||
* calls on other cpu cores
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite));
|
||||
#endif
|
||||
rbuf->error = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_flush);
|
||||
|
||||
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pread = rbuf->pwrite = 0;
|
||||
#else
|
||||
/* dvb_ringbuffer_reset() counts as read and write operation
|
||||
* smp_store_release() to update read pointer
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
/* smp_store_release() to update write pointer */
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
#endif
|
||||
rbuf->error = 0;
|
||||
}
|
||||
|
||||
@@ -119,13 +166,25 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
|
||||
return -EFAULT;
|
||||
buf += split;
|
||||
todo -= split;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pread = 0;
|
||||
#else
|
||||
/* smp_store_release() for read pointer update to ensure
|
||||
* that buf is not overwritten until read is complete,
|
||||
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
#endif
|
||||
}
|
||||
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
|
||||
return -EFAULT;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
||||
|
||||
#else
|
||||
/* smp_store_release() to update read pointer, see above */
|
||||
smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -139,11 +198,24 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
|
||||
memcpy(buf, rbuf->data+rbuf->pread, split);
|
||||
buf += split;
|
||||
todo -= split;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pread = 0;
|
||||
#else
|
||||
/* smp_store_release() for read pointer update to ensure
|
||||
* that buf is not overwritten until read is complete,
|
||||
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
#endif
|
||||
}
|
||||
memcpy(buf, rbuf->data+rbuf->pread, todo);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
||||
#else
|
||||
/* smp_store_release() to update read pointer, see above */
|
||||
smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -158,10 +230,63 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
|
||||
memcpy(rbuf->data+rbuf->pwrite, buf, split);
|
||||
buf += split;
|
||||
todo -= split;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pwrite = 0;
|
||||
#else
|
||||
/* smp_store_release() for write pointer update to ensure that
|
||||
* written data is visible on other cpu cores before the pointer
|
||||
* update, this pairs with smp_load_acquire() in
|
||||
* dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
||||
*/
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
#endif
|
||||
}
|
||||
memcpy(rbuf->data+rbuf->pwrite, buf, todo);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
||||
#else
|
||||
/* smp_store_release() for write pointer update, see above */
|
||||
smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
||||
const u8 __user *buf, size_t len)
|
||||
{
|
||||
int status;
|
||||
size_t todo = len;
|
||||
size_t split;
|
||||
|
||||
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
|
||||
|
||||
if (split > 0) {
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split);
|
||||
if (status)
|
||||
return len - todo;
|
||||
buf += split;
|
||||
todo -= split;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pwrite = 0;
|
||||
#else
|
||||
/* smp_store_release() for write pointer update to ensure that
|
||||
* written data is visible on other cpu cores before the pointer
|
||||
* update, this pairs with smp_load_acquire() in
|
||||
* dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
||||
*/
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
#endif
|
||||
}
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
|
||||
if (status)
|
||||
return len - todo;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
||||
#else
|
||||
/* smp_store_release() for write pointer update, see above */
|
||||
smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -266,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) {
|
||||
|
||||
@@ -297,3 +424,4 @@ EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write_user);
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* dvb_ringbuffer.h: ring buffer implementation for the dvb driver
|
||||
*
|
||||
* Copyright (C) 2003 Oliver Endriss
|
||||
* Copyright (C) 2004 Andrew de Quincey
|
||||
*
|
||||
* based on code originally found in av7110.c & dvb_ci.c:
|
||||
* Copyright (C) 1999-2003 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_RINGBUFFER_H_
|
||||
#define _DVB_RINGBUFFER_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
struct dvb_ringbuffer {
|
||||
u8 *data;
|
||||
ssize_t size;
|
||||
ssize_t pread;
|
||||
ssize_t pwrite;
|
||||
int error;
|
||||
|
||||
wait_queue_head_t queue;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
#define DVB_RINGBUFFER_PKTHDRSIZE 3
|
||||
|
||||
|
||||
/*
|
||||
** Notes:
|
||||
** ------
|
||||
** (1) For performance reasons read and write routines don't check buffer sizes
|
||||
** and/or number of bytes free/available. This has to be done before these
|
||||
** routines are called. For example:
|
||||
**
|
||||
** *** write <buflen> bytes ***
|
||||
** free = dvb_ringbuffer_free(rbuf);
|
||||
** if (free >= buflen)
|
||||
** count = dvb_ringbuffer_write(rbuf, buffer, buflen);
|
||||
** else
|
||||
** ...
|
||||
**
|
||||
** *** read min. 1000, max. <bufsize> bytes ***
|
||||
** avail = dvb_ringbuffer_avail(rbuf);
|
||||
** if (avail >= 1000)
|
||||
** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
|
||||
** else
|
||||
** ...
|
||||
**
|
||||
** (2) If there is exactly one reader and one writer, there is no need
|
||||
** to lock read or write operations.
|
||||
** Two or more readers must be locked against each other.
|
||||
** Flushing the buffer counts as a read operation.
|
||||
** Resetting the buffer counts as a read and write operation.
|
||||
** Two or more writers must be locked against each other.
|
||||
*/
|
||||
|
||||
/* initialize ring buffer, lock and queue */
|
||||
extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len);
|
||||
|
||||
/* test whether buffer is empty */
|
||||
extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* return the number of free bytes in the buffer */
|
||||
extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* return the number of bytes waiting in the buffer */
|
||||
extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
|
||||
/*
|
||||
** Reset the read and write pointers to zero and flush the buffer
|
||||
** This counts as a read and write operation
|
||||
*/
|
||||
extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
|
||||
/* read routines & macros */
|
||||
/* ---------------------- */
|
||||
/* flush buffer */
|
||||
extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* flush buffer protected by spinlock and wake-up waiting task(s) */
|
||||
extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* peek at byte <offs> in the buffer */
|
||||
#define DVB_RINGBUFFER_PEEK(rbuf,offs) \
|
||||
(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
|
||||
|
||||
/* advance read ptr by <num> bytes */
|
||||
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
|
||||
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
|
||||
|
||||
/*
|
||||
** read <len> bytes from ring buffer into <buf>
|
||||
** <usermem> specifies whether <buf> resides in user space
|
||||
** returns number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
|
||||
u8 __user *buf, size_t len);
|
||||
extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
|
||||
u8 *buf, size_t len);
|
||||
|
||||
|
||||
/* write routines & macros */
|
||||
/* ----------------------- */
|
||||
/* write single byte to ring buffer */
|
||||
#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \
|
||||
{ (rbuf)->data[(rbuf)->pwrite]=(byte); \
|
||||
(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
|
||||
/*
|
||||
** write <len> bytes to ring buffer
|
||||
** <usermem> specifies whether <buf> resides in user space
|
||||
** returns number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
|
||||
/**
|
||||
* Write a packet into the ringbuffer.
|
||||
*
|
||||
* <rbuf> Ringbuffer to write to.
|
||||
* <buf> Buffer to write.
|
||||
* <len> Length of buffer (currently limited to 65535 bytes max).
|
||||
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
|
||||
* does NOT update the read pointer in the ringbuffer. You must use
|
||||
* dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required.
|
||||
*
|
||||
* <rbuf> Ringbuffer concerned.
|
||||
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
* <offset> Offset into packet to read from.
|
||||
* <buf> Destination buffer for data.
|
||||
* <len> Size of destination buffer.
|
||||
* <usermem> Set to 1 if <buf> is in userspace.
|
||||
* returns Number of bytes read, or -EFAULT.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
|
||||
int offset, u8 __user *buf, size_t len);
|
||||
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
|
||||
int offset, u8 *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Dispose of a packet in the ring buffer.
|
||||
*
|
||||
* <rbuf> Ring buffer concerned.
|
||||
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
*/
|
||||
extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
|
||||
|
||||
/**
|
||||
* Get the index of the next packet in a ringbuffer.
|
||||
*
|
||||
* <rbuf> Ringbuffer concerned.
|
||||
* <idx> Previous packet index, or -1 to return the first packet index.
|
||||
* <pktlen> On success, will be updated to contain the length of the packet in bytes.
|
||||
* returns Packet index (if >=0), or -1 if no packets available.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen);
|
||||
|
||||
|
||||
#endif /* _DVB_RINGBUFFER_H_ */
|
||||
449
dvb-core/dvb_vb2.c
Normal file
449
dvb-core/dvb_vb2.c
Normal file
@@ -0,0 +1,449 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* dvb-vb2.c - dvb-vb2
|
||||
*
|
||||
* Copyright (C) 2015 Samsung Electronics
|
||||
*
|
||||
* Author: jh1009.sung@samsung.com
|
||||
*/
|
||||
|
||||
#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)
|
||||
{
|
||||
struct vb2_queue *q = &ctx->vb_q;
|
||||
|
||||
if (b->index >= q->num_buffers) {
|
||||
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct vb2_queue *q = &ctx->vb_q;
|
||||
int ret;
|
||||
|
||||
if (b->index >= q->num_buffers) {
|
||||
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,20 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* dvbdev.c
|
||||
*
|
||||
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
|
||||
* & Marcus Metzler <marcus@convergence.de>
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dvbdev: " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#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>
|
||||
@@ -33,7 +22,12 @@
|
||||
#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 */
|
||||
#include <media/tuner.h>
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(dvbdev_mutex);
|
||||
static int dvbdev_debug;
|
||||
@@ -41,22 +35,56 @@ static int dvbdev_debug;
|
||||
module_param(dvbdev_debug, int, 0644);
|
||||
MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
|
||||
|
||||
#define dprintk if (dvbdev_debug) printk
|
||||
#define dprintk(fmt, arg...) do { \
|
||||
if (dvbdev_debug) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
|
||||
__func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
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
|
||||
#define MAX_DVB_MINORS 256
|
||||
#define MAX_DVB_MINORS 512
|
||||
#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
|
||||
|
||||
@@ -75,22 +103,15 @@ static int dvb_device_open(struct inode *inode, struct file *file)
|
||||
|
||||
if (dvbdev && dvbdev->fops) {
|
||||
int err = 0;
|
||||
const struct file_operations *old_fops;
|
||||
const struct file_operations *new_fops;
|
||||
|
||||
file->private_data = dvbdev;
|
||||
old_fops = file->f_op;
|
||||
file->f_op = fops_get(dvbdev->fops);
|
||||
if (file->f_op == NULL) {
|
||||
file->f_op = old_fops;
|
||||
new_fops = fops_get(dvbdev->fops);
|
||||
if (!new_fops)
|
||||
goto fail;
|
||||
}
|
||||
if(file->f_op->open)
|
||||
err = file->f_op->open(inode,file);
|
||||
if (err) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = fops_get(old_fops);
|
||||
}
|
||||
fops_put(old_fops);
|
||||
file->private_data = dvb_device_get(dvbdev);
|
||||
replace_fops(file, new_fops);
|
||||
if (file->f_op->open)
|
||||
err = file->f_op->open(inode, file);
|
||||
up_read(&minor_rwsem);
|
||||
mutex_unlock(&dvbdev_mutex);
|
||||
return err;
|
||||
@@ -151,6 +172,9 @@ int dvb_generic_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
dvbdev->users++;
|
||||
|
||||
dvb_device_put(dvbdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_generic_release);
|
||||
@@ -188,33 +212,280 @@ skip:
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
static void dvb_media_device_free(struct dvb_device *dvbdev)
|
||||
{
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
if (dvbdev->entity) {
|
||||
media_device_unregister_entity(dvbdev->entity);
|
||||
kfree(dvbdev->entity);
|
||||
kfree(dvbdev->pads);
|
||||
dvbdev->entity = NULL;
|
||||
dvbdev->pads = NULL;
|
||||
}
|
||||
|
||||
if (dvbdev->tsout_entity) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dvbdev->tsout_num_entities; i++) {
|
||||
media_device_unregister_entity(&dvbdev->tsout_entity[i]);
|
||||
kfree(dvbdev->tsout_entity[i].name);
|
||||
}
|
||||
kfree(dvbdev->tsout_entity);
|
||||
kfree(dvbdev->tsout_pads);
|
||||
dvbdev->tsout_entity = NULL;
|
||||
dvbdev->tsout_pads = NULL;
|
||||
|
||||
dvbdev->tsout_num_entities = 0;
|
||||
}
|
||||
|
||||
if (dvbdev->intf_devnode) {
|
||||
media_devnode_remove(dvbdev->intf_devnode);
|
||||
dvbdev->intf_devnode = NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
||||
const char *name, int npads)
|
||||
{
|
||||
int i;
|
||||
|
||||
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->tsout_pads)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->tsout_entity)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->tsout_num_entities = npads;
|
||||
|
||||
for (i = 0; i < npads; i++) {
|
||||
struct media_pad *pads = &dvbdev->tsout_pads[i];
|
||||
struct media_entity *entity = &dvbdev->tsout_entity[i];
|
||||
int ret;
|
||||
|
||||
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
|
||||
if (!entity->name)
|
||||
return -ENOMEM;
|
||||
|
||||
entity->function = MEDIA_ENT_F_IO_DTV;
|
||||
pads->flags = MEDIA_PAD_FL_SINK;
|
||||
|
||||
ret = media_entity_pads_init(entity, 1, pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = media_device_register_entity(dvbdev->adapter->mdev,
|
||||
entity);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEMUX_TSOUT "demux-tsout"
|
||||
#define DVR_TSOUT "dvr-tsout"
|
||||
|
||||
static int dvb_create_media_entity(struct dvb_device *dvbdev,
|
||||
int type, int demux_sink_pads)
|
||||
{
|
||||
int i, ret, npads;
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
npads = 2;
|
||||
break;
|
||||
case DVB_DEVICE_DVR:
|
||||
ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT,
|
||||
demux_sink_pads);
|
||||
return ret;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
npads = 1 + demux_sink_pads;
|
||||
ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT,
|
||||
demux_sink_pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
npads = 2;
|
||||
break;
|
||||
case DVB_DEVICE_NET:
|
||||
/*
|
||||
* We should be creating entities for the MPE/ULE
|
||||
* decapsulation hardware (or software implementation).
|
||||
*
|
||||
* However, the number of for the MPE/ULE decaps may not be
|
||||
* fixed. As we don't have yet dynamic support for PADs at
|
||||
* the Media Controller, let's not create the decap
|
||||
* entities yet.
|
||||
*/
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
|
||||
if (!dvbdev->entity)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->entity->name = dvbdev->name;
|
||||
|
||||
if (npads) {
|
||||
dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->pads) {
|
||||
kfree(dvbdev->entity);
|
||||
dvbdev->entity = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
for (i = 1; i < npads; i++)
|
||||
dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_DTV_CA;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
default:
|
||||
/* Should never happen, as the first switch prevents it */
|
||||
kfree(dvbdev->entity);
|
||||
kfree(dvbdev->pads);
|
||||
dvbdev->entity = NULL;
|
||||
dvbdev->pads = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (npads) {
|
||||
ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = media_device_register_entity(dvbdev->adapter->mdev,
|
||||
dvbdev->entity);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pr_info("%s: media entity '%s' registered.\n",
|
||||
__func__, dvbdev->entity->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dvb_register_media_device(struct dvb_device *dvbdev,
|
||||
int type, int minor,
|
||||
unsigned demux_sink_pads)
|
||||
{
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
struct media_link *link;
|
||||
u32 intf_type;
|
||||
int ret;
|
||||
|
||||
if (!dvbdev->adapter->mdev)
|
||||
return 0;
|
||||
|
||||
ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
intf_type = MEDIA_INTF_T_DVB_FE;
|
||||
break;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
intf_type = MEDIA_INTF_T_DVB_DEMUX;
|
||||
break;
|
||||
case DVB_DEVICE_DVR:
|
||||
intf_type = MEDIA_INTF_T_DVB_DVR;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
intf_type = MEDIA_INTF_T_DVB_CA;
|
||||
break;
|
||||
case DVB_DEVICE_NET:
|
||||
intf_type = MEDIA_INTF_T_DVB_NET;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
|
||||
intf_type, 0,
|
||||
DVB_MAJOR, minor);
|
||||
|
||||
if (!dvbdev->intf_devnode)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Create the "obvious" link, e. g. the ones that represent
|
||||
* a direct association between an interface and an entity.
|
||||
* Other links should be created elsewhere, like:
|
||||
* DVB FE intf -> tuner
|
||||
* DVB demux intf -> dvr
|
||||
*/
|
||||
|
||||
if (!dvbdev->entity)
|
||||
return 0;
|
||||
|
||||
link = media_create_intf_link(dvbdev->entity,
|
||||
&dvbdev->intf_devnode->intf,
|
||||
MEDIA_LNK_FL_ENABLED |
|
||||
MEDIA_LNK_FL_IMMUTABLE);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
const struct dvb_device *template, void *priv, int type)
|
||||
const struct dvb_device *template, void *priv,
|
||||
enum dvb_device_type type, int demux_sink_pads)
|
||||
{
|
||||
struct dvb_device *dvbdev;
|
||||
struct file_operations *dvbdevfops;
|
||||
struct device *clsdev;
|
||||
int minor;
|
||||
int id;
|
||||
int id, ret;
|
||||
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
|
||||
if ((id = dvbdev_get_free_id (adap, type)) < 0){
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
*pdvbdev = NULL;
|
||||
printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
|
||||
pr_err("%s: couldn't find free device id\n", __func__);
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
|
||||
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
|
||||
|
||||
if (!dvbdev){
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
|
||||
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
|
||||
|
||||
if (!dvbdevfops){
|
||||
kfree (dvbdev);
|
||||
@@ -223,6 +494,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
}
|
||||
|
||||
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
||||
kref_init(&dvbdev->ref);
|
||||
dvbdev->type = type;
|
||||
dvbdev->id = id;
|
||||
dvbdev->adapter = adap;
|
||||
@@ -230,7 +502,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);
|
||||
@@ -242,6 +513,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);
|
||||
@@ -253,21 +525,37 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
#endif
|
||||
|
||||
dvbdev->minor = minor;
|
||||
dvb_minors[minor] = dvbdev;
|
||||
dvb_minors[minor] = dvb_device_get(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
||||
if (ret) {
|
||||
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
|
||||
__func__);
|
||||
|
||||
dvb_media_device_free(dvbdev);
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
clsdev = device_create(dvb_class, adap->device,
|
||||
MKDEV(DVB_MAJOR, minor),
|
||||
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
if (IS_ERR(clsdev)) {
|
||||
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
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(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
adap->num, dnames[type], id, minor, minor);
|
||||
|
||||
return 0;
|
||||
@@ -275,23 +563,290 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
EXPORT_SYMBOL(dvb_register_device);
|
||||
|
||||
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
void dvb_remove_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (!dvbdev)
|
||||
return;
|
||||
|
||||
down_write(&minor_rwsem);
|
||||
dvb_minors[dvbdev->minor] = NULL;
|
||||
dvb_device_put(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
dvb_media_device_free(dvbdev);
|
||||
|
||||
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
|
||||
|
||||
list_del (&dvbdev->list_head);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_remove_device);
|
||||
|
||||
|
||||
static void dvb_free_device(struct kref *ref)
|
||||
{
|
||||
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
|
||||
|
||||
kfree (dvbdev->fops);
|
||||
kfree (dvbdev);
|
||||
}
|
||||
|
||||
|
||||
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
|
||||
{
|
||||
kref_get(&dvbdev->ref);
|
||||
return dvbdev;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_device_get);
|
||||
|
||||
|
||||
void dvb_device_put(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (dvbdev)
|
||||
kref_put(&dvbdev->ref, dvb_free_device);
|
||||
}
|
||||
|
||||
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
dvb_remove_device(dvbdev);
|
||||
dvb_device_put(dvbdev);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_device);
|
||||
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
|
||||
static int dvb_create_io_intf_links(struct dvb_adapter *adap,
|
||||
struct media_interface *intf,
|
||||
char *name)
|
||||
{
|
||||
struct media_device *mdev = adap->mdev;
|
||||
struct media_entity *entity;
|
||||
struct media_link *link;
|
||||
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
if (entity->function == MEDIA_ENT_F_IO_DTV) {
|
||||
if (strncmp(entity->name, name, strlen(name)))
|
||||
continue;
|
||||
link = media_create_intf_link(entity, intf,
|
||||
MEDIA_LNK_FL_ENABLED |
|
||||
MEDIA_LNK_FL_IMMUTABLE);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
bool create_rf_connector)
|
||||
{
|
||||
struct media_device *mdev = adap->mdev;
|
||||
struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn;
|
||||
struct media_entity *demux = NULL, *ca = NULL;
|
||||
struct media_link *link;
|
||||
struct media_interface *intf;
|
||||
unsigned demux_pad = 0;
|
||||
unsigned dvr_pad = 0;
|
||||
unsigned ntuner = 0, ndemod = 0;
|
||||
int ret, pad_source, pad_sink;
|
||||
static const char *connector_name = "Television";
|
||||
|
||||
if (!mdev)
|
||||
return 0;
|
||||
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
switch (entity->function) {
|
||||
case MEDIA_ENT_F_TUNER:
|
||||
tuner = entity;
|
||||
ntuner++;
|
||||
break;
|
||||
case MEDIA_ENT_F_DTV_DEMOD:
|
||||
demod = entity;
|
||||
ndemod++;
|
||||
break;
|
||||
case MEDIA_ENT_F_TS_DEMUX:
|
||||
demux = entity;
|
||||
break;
|
||||
case MEDIA_ENT_F_DTV_CA:
|
||||
ca = entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to signalize to media_create_pad_links() that multiple
|
||||
* entities of the same type exists and a 1:n or n:1 links need to be
|
||||
* created.
|
||||
* NOTE: if both tuner and demod have multiple instances, it is up
|
||||
* to the caller driver to create such links.
|
||||
*/
|
||||
if (ntuner > 1)
|
||||
tuner = NULL;
|
||||
if (ndemod > 1)
|
||||
demod = NULL;
|
||||
|
||||
if (create_rf_connector) {
|
||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||
if (!conn)
|
||||
return -ENOMEM;
|
||||
adap->conn = conn;
|
||||
|
||||
adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL);
|
||||
if (!adap->conn_pads)
|
||||
return -ENOMEM;
|
||||
|
||||
conn->flags = MEDIA_ENT_FL_CONNECTOR;
|
||||
conn->function = MEDIA_ENT_F_CONN_RF;
|
||||
conn->name = connector_name;
|
||||
adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
ret = media_entity_pads_init(conn, 1, adap->conn_pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = media_device_register_entity(mdev, conn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ntuner) {
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_CONN_RF,
|
||||
conn, 0,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 0,
|
||||
MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
} else {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
|
||||
pad_sink = media_get_pad_index(tuner, true,
|
||||
PAD_SIGNAL_ANALOG);
|
||||
if (pad_sink < 0)
|
||||
return -EINVAL;
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_CONN_RF,
|
||||
conn, 0,
|
||||
MEDIA_ENT_F_TUNER,
|
||||
tuner, 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, pad_source,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 0, MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ndemod && demux) {
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 1,
|
||||
MEDIA_ENT_F_TS_DEMUX,
|
||||
demux, 0, MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (demux && ca) {
|
||||
ret = media_create_pad_link(demux, 1, ca,
|
||||
0, MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create demux links for each ringbuffer/pad */
|
||||
if (demux) {
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
if (entity->function == MEDIA_ENT_F_IO_DTV) {
|
||||
if (!strncmp(entity->name, DVR_TSOUT,
|
||||
strlen(DVR_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++dvr_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!strncmp(entity->name, DEMUX_TSOUT,
|
||||
strlen(DEMUX_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++demux_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create interface links for FE->tuner, DVR->demux and CA->ca */
|
||||
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_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_IMMUTABLE);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* Indirect link - let's not create yet, as we don't know how
|
||||
* to handle indirect links, nor if this will
|
||||
* actually be needed.
|
||||
*/
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
|
||||
link = media_create_intf_link(demux, intf,
|
||||
MEDIA_LNK_FL_ENABLED |
|
||||
MEDIA_LNK_FL_IMMUTABLE);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DVR) {
|
||||
ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DEMUX) {
|
||||
ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dvb_create_media_graph);
|
||||
#endif
|
||||
|
||||
static int dvbdev_check_free_adapter_num(int num)
|
||||
{
|
||||
struct list_head *entry;
|
||||
@@ -347,7 +902,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
memset (adap, 0, sizeof(struct dvb_adapter));
|
||||
INIT_LIST_HEAD (&adap->device_list);
|
||||
|
||||
printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
|
||||
pr_info("DVB: registering new adapter (%s)\n", name);
|
||||
|
||||
adap->num = num;
|
||||
adap->name = name;
|
||||
@@ -357,6 +912,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);
|
||||
@@ -377,7 +936,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,
|
||||
@@ -406,7 +965,7 @@ int dvb_usercopy(struct file *file,
|
||||
parg = sbuf;
|
||||
} else {
|
||||
/* too big to allocate from stack */
|
||||
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
|
||||
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
|
||||
if (NULL == mbuf)
|
||||
return -ENOMEM;
|
||||
parg = mbuf;
|
||||
@@ -419,11 +978,8 @@ int dvb_usercopy(struct file *file,
|
||||
}
|
||||
|
||||
/* call driver */
|
||||
/* this lock is much too coarse */
|
||||
//mutex_lock(&dvbdev_mutex);
|
||||
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
|
||||
err = -ENOTTY;
|
||||
//mutex_unlock(&dvbdev_mutex);
|
||||
|
||||
if (err < 0)
|
||||
goto out;
|
||||
@@ -444,9 +1000,64 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usercopy);
|
||||
|
||||
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
#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 dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||
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
|
||||
|
||||
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
|
||||
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
#else
|
||||
static int dvb_uevent(const struct device *dev, struct kobj_uevent_env *env)
|
||||
#endif
|
||||
{
|
||||
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||
|
||||
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
|
||||
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
|
||||
@@ -454,13 +1065,13 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
|
||||
static char *dvb_devnode(struct device *dev, mode_t *mode)
|
||||
#else
|
||||
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
|
||||
static char *dvb_devnode(struct device *dev, umode_t *mode)
|
||||
#else
|
||||
static char *dvb_devnode(const struct device *dev, umode_t *mode)
|
||||
#endif
|
||||
{
|
||||
struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||
|
||||
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
|
||||
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
|
||||
@@ -473,17 +1084,21 @@ static int __init init_dvbdev(void)
|
||||
dev_t dev = MKDEV(DVB_MAJOR, 0);
|
||||
|
||||
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
|
||||
printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
|
||||
pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
|
||||
return retval;
|
||||
}
|
||||
|
||||
cdev_init(&dvb_device_cdev, &dvb_device_fops);
|
||||
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
|
||||
printk(KERN_ERR "dvb-core: unable register character device\n");
|
||||
pr_err("dvb-core: unable register character device\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0))
|
||||
dvb_class = class_create(THIS_MODULE, "dvb");
|
||||
#else
|
||||
dvb_class = class_create("dvb");
|
||||
#endif
|
||||
if (IS_ERR(dvb_class)) {
|
||||
retval = PTR_ERR(dvb_class);
|
||||
goto error;
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* dvbdev.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 General Lesser 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DVBDEV_H_
|
||||
#define _DVBDEV_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#define DVB_MAJOR 212
|
||||
|
||||
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
|
||||
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
|
||||
#else
|
||||
#define DVB_MAX_ADAPTERS 8
|
||||
#endif
|
||||
|
||||
#define DVB_UNSET (-1)
|
||||
|
||||
#define DVB_DEVICE_VIDEO 0
|
||||
#define DVB_DEVICE_AUDIO 1
|
||||
#define DVB_DEVICE_SEC 2
|
||||
#define DVB_DEVICE_FRONTEND 3
|
||||
#define DVB_DEVICE_DEMUX 4
|
||||
#define DVB_DEVICE_DVR 5
|
||||
#define DVB_DEVICE_CA 6
|
||||
#define DVB_DEVICE_NET 7
|
||||
#define DVB_DEVICE_OSD 8
|
||||
#define DVB_DEVICE_CI 9
|
||||
#define DVB_DEVICE_MOD 10
|
||||
#define DVB_DEVICE_NS 11
|
||||
#define DVB_DEVICE_NSD 12
|
||||
|
||||
#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
|
||||
static short adapter_nr[] = \
|
||||
{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
|
||||
module_param_array(adapter_nr, short, NULL, 0444); \
|
||||
MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
|
||||
|
||||
struct dvb_frontend;
|
||||
|
||||
struct dvb_adapter {
|
||||
int num;
|
||||
struct list_head list_head;
|
||||
struct list_head device_list;
|
||||
const char *name;
|
||||
u8 proposed_mac [6];
|
||||
void* priv;
|
||||
|
||||
struct device *device;
|
||||
|
||||
struct module *module;
|
||||
|
||||
int mfe_shared; /* indicates mutually exclusive frontends */
|
||||
struct dvb_device *mfe_dvbdev; /* frontend device in use */
|
||||
struct mutex mfe_lock; /* access lock for thread creation */
|
||||
};
|
||||
|
||||
|
||||
struct dvb_device {
|
||||
struct list_head list_head;
|
||||
const struct file_operations *fops;
|
||||
struct dvb_adapter *adapter;
|
||||
int type;
|
||||
int minor;
|
||||
u32 id;
|
||||
|
||||
/* in theory, 'users' can vanish now,
|
||||
but I don't want to change too much now... */
|
||||
int readers;
|
||||
int writers;
|
||||
int users;
|
||||
|
||||
wait_queue_head_t wait_queue;
|
||||
/* don't really need those !? -- FIXME: use video_usercopy */
|
||||
int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
||||
extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
struct module *module, struct device *device,
|
||||
short *adapter_nums);
|
||||
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
|
||||
|
||||
extern int dvb_register_device (struct dvb_adapter *adap,
|
||||
struct dvb_device **pdvbdev,
|
||||
const struct dvb_device *template,
|
||||
void *priv,
|
||||
int type);
|
||||
|
||||
extern void dvb_unregister_device (struct dvb_device *dvbdev);
|
||||
|
||||
extern int dvb_generic_open (struct inode *inode, struct file *file);
|
||||
extern int dvb_generic_release (struct inode *inode, struct file *file);
|
||||
extern long dvb_generic_ioctl (struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* we don't mess with video_usercopy() any more,
|
||||
we simply define out own dvb_usercopy(), which will hopefully become
|
||||
generic_usercopy() someday... */
|
||||
|
||||
extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
int (*func)(struct file *file, unsigned int cmd, void *arg));
|
||||
|
||||
/** generic DVB attach function. */
|
||||
#ifdef CONFIG_MEDIA_ATTACH
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
void *__r = NULL; \
|
||||
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
|
||||
if (__a) { \
|
||||
__r = (void *) __a(ARGS); \
|
||||
if (__r == NULL) \
|
||||
symbol_put(FUNCTION); \
|
||||
} else { \
|
||||
printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
|
||||
} \
|
||||
__r; \
|
||||
})
|
||||
|
||||
#else
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
FUNCTION(ARGS); \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _DVBDEV_H_ */
|
||||
838
frontends/Kconfig
Normal file
838
frontends/Kconfig
Normal file
@@ -0,0 +1,838 @@
|
||||
menu "Customise DVB Frontends"
|
||||
visible if !MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
comment "Multistandard (satellite) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_STB0899
|
||||
tristate "STB0899 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
|
||||
to support this demodulator based frontends
|
||||
|
||||
config DVB_STB6100
|
||||
tristate "STB6100 based tuners"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Silicon tuner from ST used in conjunction with the STB0899
|
||||
demodulator. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_STV090x
|
||||
tristate "STV0900/STV0903(A/B) based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
|
||||
Say Y when you want to support these frontends.
|
||||
|
||||
config DVB_STV6110x
|
||||
tristate "STV6110/(A) based tuners"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Silicon tuner that supports DVB-S and DVB-S2 modes
|
||||
|
||||
config DVB_STV0910
|
||||
tristate "STV0910 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
|
||||
Say Y when you want to support these frontends.
|
||||
|
||||
config DVB_MXL5XX
|
||||
tristate "MXL5XX based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
|
||||
Say Y when you want to support these frontends.
|
||||
|
||||
config DVB_STV6111
|
||||
tristate "STV6111 based tuners"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Silicon tuner that supports DVB-S and DVB-S2 modes
|
||||
|
||||
config DVB_M88DS3103
|
||||
tristate "Montage M88DS3103"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "Multistandard (cable + terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_DRXK
|
||||
tristate "Micronas DRXK based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Micronas DRX-K DVB-C/T demodulator.
|
||||
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
|
||||
config DVB_TDA18271C2DD
|
||||
tristate "NXP TDA18271C2 silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
NXP TDA18271 silicon tuner.
|
||||
|
||||
Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_SI2165
|
||||
tristate "Silicon Labs si2165 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C/T demodulator.
|
||||
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-S (satellite) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_CX24110
|
||||
tristate "Conexant CX24110 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX24123
|
||||
tristate "Conexant CX24123 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MT312
|
||||
tristate "Zarlink VP310/MT312/ZL10313 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_ZL10036
|
||||
tristate "Zarlink ZL10036 silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_ZL10039
|
||||
tristate "Zarlink ZL10039 silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_S5H1420
|
||||
tristate "Samsung S5H1420 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0288
|
||||
tristate "ST STV0288 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STB6000
|
||||
tristate "ST STB6000 silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_STV0299
|
||||
tristate "ST STV0299 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV6110
|
||||
tristate "ST STV6110 silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_STV0900
|
||||
tristate "ST STV0900 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/S2 demodulator. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA8083
|
||||
tristate "Philips TDA8083 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10086
|
||||
tristate "Philips TDA10086 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA8261
|
||||
tristate "Philips TDA8261 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_VES1X93
|
||||
tristate "VLSI VES1893 or VES1993 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TUNER_ITD1000
|
||||
tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TUNER_CX24113
|
||||
tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
|
||||
config DVB_TDA826X
|
||||
tristate "Philips TDA826X silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_TUA6100
|
||||
tristate "Infineon TUA6100 PLL"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S PLL chip.
|
||||
|
||||
config DVB_CX24116
|
||||
tristate "Conexant CX24116 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX24117
|
||||
tristate "Conexant CX24117 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Dual DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_SI21XX
|
||||
tristate "Silicon Labs SI21XX based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TS2020
|
||||
tristate "Montage Tehnology TS2020 based tuners"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_DS3000
|
||||
tristate "Montage Tehnology DS3000 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MB86A16
|
||||
tristate "Fujitsu MB86A16 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S/DSS Direct Conversion reveiver.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10071
|
||||
tristate "NXP TDA10071"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-T (terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_SP8870
|
||||
tristate "Spase sp8870 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the command
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
|
||||
download/extract it, and then copy it to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
|
||||
config DVB_SP887X
|
||||
tristate "Spase sp887x based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the command
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
|
||||
download/extract it, and then copy it to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
|
||||
config DVB_CX22700
|
||||
tristate "Conexant CX22700 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX22702
|
||||
tristate "Conexant cx22702 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_S5H1432
|
||||
tristate "Samsung s5h1432 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DRXD
|
||||
tristate "Micronas DRXD driver"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
Note: this driver was based on vendor driver reference code (released
|
||||
under the GPL) as opposed to the existing drx397xd driver, which
|
||||
was written via reverse engineering.
|
||||
|
||||
config DVB_L64781
|
||||
tristate "LSI L64781"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA1004X
|
||||
tristate "Philips TDA10045H/TDA10046H based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the commands
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
|
||||
download/extract them, and then copy them to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
|
||||
config DVB_NXT6000
|
||||
tristate "NxtWave Communications NXT6000 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MT352
|
||||
tristate "Zarlink MT352 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_ZL10353
|
||||
tristate "Zarlink ZL10353 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DIB3000MB
|
||||
tristate "DiBcom 3000M-B"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB3000MC
|
||||
tristate "DiBcom 3000P/M-C"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB7000M
|
||||
tristate "DiBcom 7000MA/MB/PA/PB/MC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB7000P
|
||||
tristate "DiBcom 7000PC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB9000
|
||||
tristate "DiBcom 9000"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_TDA10048
|
||||
tristate "Philips TDA10048HN based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA18212DD
|
||||
tristate "Philips TDA18212 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_AF9013
|
||||
tristate "Afatech AF9013 demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_EC100
|
||||
tristate "E3C EC100"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_HD29L2
|
||||
tristate "HDIC HD29L2"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0367
|
||||
tristate "ST STV0367 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T/C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0367DD
|
||||
tristate "ST STV0367dd based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T/C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CXD2843
|
||||
tristate "Sony CXD2843"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-T/T2/C/C2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CXD2820R
|
||||
tristate "Sony CXD2820R"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_RTL2830
|
||||
tristate "Realtek RTL2830 DVB-T"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_RTL2832
|
||||
tristate "Realtek RTL2832 DVB-T"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_RTL2832_SDR
|
||||
tristate "Realtek RTL2832 SDR"
|
||||
depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT && USB
|
||||
select DVB_RTL2832
|
||||
select VIDEOBUF2_VMALLOC
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this SDR module.
|
||||
|
||||
config DVB_SI2168
|
||||
tristate "Silicon Labs Si2168"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_VES1820
|
||||
tristate "VLSI VES1820 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10021
|
||||
tristate "Philips TDA10021 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10023
|
||||
tristate "Philips TDA10023 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0297
|
||||
tristate "ST STV0297 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_NXT200X
|
||||
tristate "NxtWave Communications NXT2002/NXT2004 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the commands
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
|
||||
download/extract them, and then copy them to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
|
||||
config DVB_OR51211
|
||||
tristate "Oren OR51211 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the command
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
|
||||
download it, and then copy it to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
|
||||
config DVB_OR51132
|
||||
tristate "Oren OR51132 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
This driver needs external firmware. Please use the commands
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
|
||||
download firmwares for 8VSB and QAM64/256, respectively. Copy them to
|
||||
/usr/lib/hotplug/firmware or /lib/firmware (depending on
|
||||
configuration of firmware hotplug).
|
||||
|
||||
config DVB_BCM3510
|
||||
tristate "Broadcom BCM3510"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
|
||||
support this frontend.
|
||||
|
||||
config DVB_LGDT330X
|
||||
tristate "LG Electronics LGDT3302/LGDT3303 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_LGDT3305
|
||||
tristate "LG Electronics LGDT3304 and LGDT3305 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_LG2160
|
||||
tristate "LG Electronics LG216x based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC/MH demodulator module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_S5H1409
|
||||
tristate "Samsung S5H1409 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_AU8522
|
||||
depends on I2C
|
||||
tristate
|
||||
|
||||
config DVB_AU8522_DTV
|
||||
tristate "Auvitek AU8522 based DTV demod"
|
||||
depends on DVB_CORE && I2C
|
||||
select DVB_AU8522
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
|
||||
you want to enable DTV demodulation support for this frontend.
|
||||
|
||||
config DVB_AU8522_V4L
|
||||
tristate "Auvitek AU8522 based ATV demod"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
select DVB_AU8522
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
|
||||
you want to enable ATV demodulation support for this frontend.
|
||||
|
||||
config DVB_S5H1411
|
||||
tristate "Samsung S5H1411 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
comment "ISDB-T (terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_S921
|
||||
tristate "Sharp S921 frontend"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DIB8000
|
||||
tristate "DiBcom 8000MB/MC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MB86A20S
|
||||
tristate "Fujitsu mb86a20s"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "Digital terrestrial only tuners/PLL"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_PLL
|
||||
tristate "Generic I2C PLL based tuners"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
This module drives a number of tuners based on PLL chips with a
|
||||
common I2C interface. Say Y when you want to support these tuners.
|
||||
|
||||
config DVB_TUNER_DIB0070
|
||||
tristate "DiBcom DiB0070 silicon base-band tuner"
|
||||
depends on I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A driver for the silicon baseband tuner DiB0070 from DiBcom.
|
||||
This device is only used inside a SiP called together with a
|
||||
demodulator for now.
|
||||
|
||||
config DVB_TUNER_DIB0090
|
||||
tristate "DiBcom DiB0090 silicon base-band tuner"
|
||||
depends on I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A driver for the silicon baseband tuner DiB0090 from DiBcom.
|
||||
This device is only used inside a SiP called together with a
|
||||
demodulator for now.
|
||||
|
||||
comment "SEC control devices for DVB-S"
|
||||
depends on DVB_CORE
|
||||
|
||||
source "drivers/media/dvb-frontends/drx39xyj/Kconfig"
|
||||
|
||||
config DVB_LNBP21
|
||||
tristate "LNBP21/LNBH24 SEC controllers"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An SEC control chips.
|
||||
|
||||
config DVB_LNBH25
|
||||
tristate "LNBH25 SEC controllers"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An SEC control chips.
|
||||
|
||||
config DVB_LNBP22
|
||||
tristate "LNBP22 SEC controllers"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
LNB power supply and control voltage
|
||||
regulator chip with step-up converter
|
||||
and I2C interface.
|
||||
Say Y when you want to support this chip.
|
||||
|
||||
config DVB_ISL6405
|
||||
tristate "ISL6405 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
config DVB_ISL6421
|
||||
tristate "ISL6421 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
config DVB_ISL6423
|
||||
tristate "ISL6423 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A SEC controller chip from Intersil
|
||||
|
||||
config DVB_A8293
|
||||
tristate "Allegro A8293"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
config DVB_LGS8GL5
|
||||
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DMB-TH tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_LGS8GXX
|
||||
tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
select FW_LOADER
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DMB-TH tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_ATBM8830
|
||||
tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DMB-TH tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA665x
|
||||
tristate "TDA665x tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Support for tuner modules based on Philips TDA6650/TDA6651 chips.
|
||||
Say Y when you want to support this chip.
|
||||
|
||||
Currently supported tuners:
|
||||
* Panasonic ENV57H12D5 (ET-50DT)
|
||||
|
||||
config DVB_IX2505V
|
||||
tristate "Sharp IX2505V silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_M88RS2000
|
||||
tristate "M88RS2000 DVB-S demodulator and tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-S tuner module.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_AF9033
|
||||
tristate "Afatech AF9033 DVB-T demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
config DVB_CXD2099
|
||||
tristate "cxd2099"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
comment "Tools to develop new frontends"
|
||||
|
||||
config DVB_DUMMY_FE
|
||||
tristate "Dummy frontend driver"
|
||||
default n
|
||||
endmenu
|
||||
@@ -14,8 +14,8 @@ EXTRA_CFLAGS += -DCONFIG_DVB_STV6111
|
||||
EXTRA_CFLAGS += -DCONFIG_DVB_STV0910
|
||||
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
|
||||
|
||||
124
frontends/Makefile.kernel
Normal file
124
frontends/Makefile.kernel
Normal file
@@ -0,0 +1,124 @@
|
||||
#
|
||||
# Makefile for the kernel DVB frontend device drivers.
|
||||
#
|
||||
|
||||
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
|
||||
ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
|
||||
endif
|
||||
|
||||
stb0899-objs := stb0899_drv.o stb0899_algo.o
|
||||
stv0900-objs := stv0900_core.o stv0900_sw.o
|
||||
drxd-objs := drxd_firm.o drxd_hard.o
|
||||
cxd2820r-objs := cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
|
||||
drxk-objs := drxk_hard.o
|
||||
|
||||
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
|
||||
obj-$(CONFIG_DVB_STV0299) += stv0299.o
|
||||
obj-$(CONFIG_DVB_STB0899) += stb0899.o
|
||||
obj-$(CONFIG_DVB_STB6100) += stb6100.o
|
||||
obj-$(CONFIG_DVB_SP8870) += sp8870.o
|
||||
obj-$(CONFIG_DVB_CX22700) += cx22700.o
|
||||
obj-$(CONFIG_DVB_S5H1432) += s5h1432.o
|
||||
obj-$(CONFIG_DVB_CX24110) += cx24110.o
|
||||
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
|
||||
obj-$(CONFIG_DVB_L64781) += l64781.o
|
||||
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
|
||||
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB9000) += dib9000.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_MT312) += mt312.o
|
||||
obj-$(CONFIG_DVB_VES1820) += ves1820.o
|
||||
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
|
||||
obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
|
||||
obj-$(CONFIG_DVB_SP887X) += sp887x.o
|
||||
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
|
||||
obj-$(CONFIG_DVB_MT352) += mt352.o
|
||||
obj-$(CONFIG_DVB_ZL10036) += zl10036.o
|
||||
obj-$(CONFIG_DVB_ZL10039) += zl10039.o
|
||||
obj-$(CONFIG_DVB_ZL10353) += zl10353.o
|
||||
obj-$(CONFIG_DVB_CX22702) += cx22702.o
|
||||
obj-$(CONFIG_DVB_DRXD) += drxd.o
|
||||
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
|
||||
obj-$(CONFIG_DVB_TDA10023) += tda10023.o
|
||||
obj-$(CONFIG_DVB_STV0297) += stv0297.o
|
||||
obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
|
||||
obj-$(CONFIG_DVB_OR51211) += or51211.o
|
||||
obj-$(CONFIG_DVB_OR51132) += or51132.o
|
||||
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
|
||||
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
|
||||
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
|
||||
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
|
||||
obj-$(CONFIG_DVB_LG2160) += lg2160.o
|
||||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
|
||||
obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
|
||||
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
|
||||
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
|
||||
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
|
||||
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
|
||||
obj-$(CONFIG_DVB_TDA8261) += tda8261.o
|
||||
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
|
||||
obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
|
||||
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
|
||||
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
|
||||
obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
|
||||
obj-$(CONFIG_DVB_AU8522) += au8522_common.o
|
||||
obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
|
||||
obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
|
||||
obj-$(CONFIG_DVB_TDA10048) += tda10048.o
|
||||
obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
|
||||
obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
|
||||
obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
|
||||
obj-$(CONFIG_DVB_TDA665x) += tda665x.o
|
||||
obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
|
||||
obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
|
||||
obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
|
||||
obj-$(CONFIG_DVB_AF9013) += af9013.o
|
||||
obj-$(CONFIG_DVB_CX24116) += cx24116.o
|
||||
obj-$(CONFIG_DVB_CX24117) += cx24117.o
|
||||
obj-$(CONFIG_DVB_SI21XX) += si21xx.o
|
||||
obj-$(CONFIG_DVB_SI2168) += si2168.o
|
||||
obj-$(CONFIG_DVB_STV0288) += stv0288.o
|
||||
obj-$(CONFIG_DVB_STB6000) += stb6000.o
|
||||
obj-$(CONFIG_DVB_S921) += s921.o
|
||||
obj-$(CONFIG_DVB_STV6110) += stv6110.o
|
||||
obj-$(CONFIG_DVB_STV0900) += stv0900.o
|
||||
obj-$(CONFIG_DVB_STV090x) += stv090x.o
|
||||
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
|
||||
obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o
|
||||
obj-$(CONFIG_DVB_ISL6423) += isl6423.o
|
||||
obj-$(CONFIG_DVB_EC100) += ec100.o
|
||||
obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
|
||||
obj-$(CONFIG_DVB_DS3000) += ds3000.o
|
||||
obj-$(CONFIG_DVB_TS2020) += ts2020.o
|
||||
obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
|
||||
obj-$(CONFIG_DVB_DRX39XYJ) += drx39xyj/
|
||||
obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
|
||||
obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
|
||||
obj-$(CONFIG_DVB_STV0367) += stv0367.o
|
||||
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
|
||||
obj-$(CONFIG_DVB_DRXK) += drxk.o
|
||||
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
|
||||
obj-$(CONFIG_DVB_SI2165) += si2165.o
|
||||
obj-$(CONFIG_DVB_A8293) += a8293.o
|
||||
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
|
||||
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
|
||||
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
|
||||
obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
|
||||
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
|
||||
obj-$(CONFIG_DVB_AF9033) += af9033.o
|
||||
obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
|
||||
obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
|
||||
obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
|
||||
obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
|
||||
obj-$(CONFIG_DVB_STV6111) += stv6111.o
|
||||
obj-$(CONFIG_DVB_STV0910) += stv0910.o
|
||||
obj-$(CONFIG_DVB_LNBH25) += lnbh25.o
|
||||
obj-$(CONFIG_DVB_MXL5XX) += mxl5xx.o
|
||||
@@ -22,12 +22,9 @@
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -36,7 +33,9 @@
|
||||
|
||||
#include "cxd2099.h"
|
||||
|
||||
//#define BUFFER_MODE 1
|
||||
static int buffermode;
|
||||
module_param(buffermode, int, 0444);
|
||||
MODULE_PARM_DESC(buffermode, "Enable use of the CXD2099AR buffer mode (default: disabled)");
|
||||
|
||||
static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);
|
||||
|
||||
@@ -73,8 +72,9 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
|
||||
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) != 1) {
|
||||
pr_err("Failed to write to I2C register %02x@%02x!\n",
|
||||
reg, adr);
|
||||
dev_err(&adapter->dev,
|
||||
"Failed to write to I2C register %02x@%02x!\n",
|
||||
reg, adr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -86,7 +86,7 @@ static int i2c_write(struct i2c_adapter *adapter, u8 adr,
|
||||
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) != 1) {
|
||||
pr_err("Failed to write to I2C!\n");
|
||||
dev_err(&adapter->dev, "Failed to write to I2C!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -101,7 +101,7 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
|
||||
.buf = val, .len = 1} };
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) != 2) {
|
||||
pr_err("error in i2c_read_reg\n");
|
||||
dev_err(&adapter->dev, "error in i2c_read_reg\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -114,9 +114,9 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr,
|
||||
.buf = ®, .len = 1},
|
||||
{.addr = adr, .flags = I2C_M_RD,
|
||||
.buf = data, .len = n} };
|
||||
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) != 2) {
|
||||
pr_err("error in i2c_read\n");
|
||||
dev_err(&adapter->dev, "error in i2c_read\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -133,9 +133,8 @@ static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
|
||||
|
||||
while (n) {
|
||||
int len = n;
|
||||
|
||||
if (ci->cfg.max_i2c &&
|
||||
len > ci->cfg.max_i2c)
|
||||
|
||||
if (ci->cfg.max_i2c && (len > ci->cfg.max_i2c))
|
||||
len = ci->cfg.max_i2c;
|
||||
status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len);
|
||||
if (status)
|
||||
@@ -152,7 +151,6 @@ static int read_reg(struct cxd *ci, u8 reg, u8 *val)
|
||||
return read_block(ci, reg, val, 1);
|
||||
}
|
||||
|
||||
|
||||
static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
|
||||
{
|
||||
int status;
|
||||
@@ -174,7 +172,7 @@ static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
|
||||
u8 buf[256] = {3};
|
||||
|
||||
memcpy(buf + 1, data, n);
|
||||
status = i2c_write(ci->i2c, ci->cfg.adr, buf, n+1);
|
||||
status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -253,7 +251,6 @@ static int write_reg(struct cxd *ci, u8 reg, u8 val)
|
||||
return write_regm(ci, reg, val, 0xff);
|
||||
}
|
||||
|
||||
#ifdef BUFFER_MODE
|
||||
static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
|
||||
{
|
||||
int status = 0;
|
||||
@@ -263,17 +260,14 @@ static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
|
||||
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
|
||||
if (status)
|
||||
return status;
|
||||
printk("write_block %d\n", n);
|
||||
|
||||
ci->lastaddress = adr;
|
||||
buf[0] = 1;
|
||||
while (n) {
|
||||
int len = n;
|
||||
|
||||
if (ci->cfg.max_i2c &&
|
||||
len + 1 > ci->cfg.max_i2c)
|
||||
|
||||
if (ci->cfg.max_i2c && (len + 1 > ci->cfg.max_i2c))
|
||||
len = ci->cfg.max_i2c - 1;
|
||||
printk("write %d\n", len);
|
||||
memcpy(buf + 1, data, len);
|
||||
status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1);
|
||||
if (status)
|
||||
@@ -283,7 +277,6 @@ static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_mode(struct cxd *ci, int mode)
|
||||
{
|
||||
@@ -318,7 +311,7 @@ static void cam_mode(struct cxd *ci, int mode)
|
||||
if (!ci->en.read_data)
|
||||
return;
|
||||
ci->write_busy = 0;
|
||||
pr_info("enable cam buffer mode\n");
|
||||
dev_info(&ci->i2c->dev, "enable cam buffer mode\n");
|
||||
write_reg(ci, 0x0d, 0x00);
|
||||
write_reg(ci, 0x0e, 0x01);
|
||||
write_regm(ci, 0x08, 0x40, 0x40);
|
||||
@@ -331,8 +324,6 @@ static void cam_mode(struct cxd *ci, int mode)
|
||||
ci->cammode = mode;
|
||||
}
|
||||
|
||||
#define CHK_ERROR(s) if ((status = s)) break
|
||||
|
||||
static int init(struct cxd *ci)
|
||||
{
|
||||
int status;
|
||||
@@ -340,67 +331,140 @@ static int init(struct cxd *ci)
|
||||
mutex_lock(&ci->lock);
|
||||
ci->mode = -1;
|
||||
do {
|
||||
CHK_ERROR(write_reg(ci, 0x00, 0x00));
|
||||
CHK_ERROR(write_reg(ci, 0x01, 0x00));
|
||||
CHK_ERROR(write_reg(ci, 0x02, 0x10));
|
||||
CHK_ERROR(write_reg(ci, 0x03, 0x00));
|
||||
CHK_ERROR(write_reg(ci, 0x05, 0xFF));
|
||||
CHK_ERROR(write_reg(ci, 0x06, 0x1F));
|
||||
CHK_ERROR(write_reg(ci, 0x07, 0x1F));
|
||||
CHK_ERROR(write_reg(ci, 0x08, 0x28));
|
||||
CHK_ERROR(write_reg(ci, 0x14, 0x20));
|
||||
status = write_reg(ci, 0x00, 0x00);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x01, 0x00);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x02, 0x10);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x03, 0x00);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x05, 0xFF);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x06, 0x1F);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x07, 0x1F);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x08, 0x28);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x14, 0x20);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
/* TOSTRT = 8, Mode B (gated clock), falling Edge,
|
||||
Serial, POL=HIGH, MSB */
|
||||
CHK_ERROR(write_reg(ci, 0x0A, 0xA7));
|
||||
* Serial, POL=HIGH, MSB
|
||||
*/
|
||||
status = write_reg(ci, 0x0A, 0xA7);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
CHK_ERROR(write_reg(ci, 0x0B, 0x33));
|
||||
CHK_ERROR(write_reg(ci, 0x0C, 0x33));
|
||||
status = write_reg(ci, 0x0B, 0x33);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x0C, 0x33);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
CHK_ERROR(write_regm(ci, 0x14, 0x00, 0x0F));
|
||||
CHK_ERROR(write_reg(ci, 0x15, ci->clk_reg_b));
|
||||
CHK_ERROR(write_regm(ci, 0x16, 0x00, 0x0F));
|
||||
CHK_ERROR(write_reg(ci, 0x17, ci->clk_reg_f));
|
||||
status = write_regm(ci, 0x14, 0x00, 0x0F);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x15, ci->clk_reg_b);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_regm(ci, 0x16, 0x00, 0x0F);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x17, ci->clk_reg_f);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
if (ci->cfg.clock_mode == 2) {
|
||||
/* bitrate*2^13/ 72000 */
|
||||
u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000;
|
||||
|
||||
|
||||
if (ci->cfg.polarity) {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x6f));
|
||||
status = write_reg(ci, 0x09, 0x6f);
|
||||
if (status < 0)
|
||||
break;
|
||||
} else {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x6d));
|
||||
status = write_reg(ci, 0x09, 0x6d);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
CHK_ERROR(write_reg(ci, 0x20, 0x08));
|
||||
CHK_ERROR(write_reg(ci, 0x21, (reg >> 8) & 0xff));
|
||||
CHK_ERROR(write_reg(ci, 0x22, reg & 0xff));
|
||||
status = write_reg(ci, 0x20, 0x08);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x21, (reg >> 8) & 0xff);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x22, reg & 0xff);
|
||||
if (status < 0)
|
||||
break;
|
||||
} else if (ci->cfg.clock_mode == 1) {
|
||||
if (ci->cfg.polarity) {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x6f)); /* D */
|
||||
status = write_reg(ci, 0x09, 0x6f); /* D */
|
||||
if (status < 0)
|
||||
break;
|
||||
} else {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x6d));
|
||||
status = write_reg(ci, 0x09, 0x6d);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
CHK_ERROR(write_reg(ci, 0x20, 0x68));
|
||||
CHK_ERROR(write_reg(ci, 0x21, 0x00));
|
||||
CHK_ERROR(write_reg(ci, 0x22, 0x02));
|
||||
status = write_reg(ci, 0x20, 0x68);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x21, 0x00);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x22, 0x02);
|
||||
if (status < 0)
|
||||
break;
|
||||
} else {
|
||||
if (ci->cfg.polarity) {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x4f)); /* C */
|
||||
status = write_reg(ci, 0x09, 0x4f); /* C */
|
||||
if (status < 0)
|
||||
break;
|
||||
} else {
|
||||
CHK_ERROR(write_reg(ci, 0x09, 0x4d));
|
||||
status = write_reg(ci, 0x09, 0x4d);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
CHK_ERROR(write_reg(ci, 0x20, 0x28));
|
||||
CHK_ERROR(write_reg(ci, 0x21, 0x00));
|
||||
CHK_ERROR(write_reg(ci, 0x22, 0x07));
|
||||
status = write_reg(ci, 0x20, 0x28);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x21, 0x00);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x22, 0x07);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
CHK_ERROR(write_regm(ci, 0x20, 0x80, 0x80));
|
||||
CHK_ERROR(write_regm(ci, 0x03, 0x02, 0x02));
|
||||
CHK_ERROR(write_reg(ci, 0x01, 0x04));
|
||||
CHK_ERROR(write_reg(ci, 0x00, 0x31));
|
||||
status = write_regm(ci, 0x20, 0x80, 0x80);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_regm(ci, 0x03, 0x02, 0x02);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x01, 0x04);
|
||||
if (status < 0)
|
||||
break;
|
||||
status = write_reg(ci, 0x00, 0x31);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
/* Put TS in bypass */
|
||||
CHK_ERROR(write_regm(ci, 0x09, 0x08, 0x08));
|
||||
status = write_regm(ci, 0x09, 0x08, 0x08);
|
||||
if (status < 0)
|
||||
break;
|
||||
ci->cammode = -1;
|
||||
cam_mode(ci, 0);
|
||||
} while (0);
|
||||
@@ -504,14 +568,16 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
ci->ready = 0;
|
||||
#endif
|
||||
#endif
|
||||
ci->ready = 0;
|
||||
ci->mode = -1;
|
||||
{
|
||||
int i;
|
||||
#if 0
|
||||
u8 val;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
msleep(20);
|
||||
usleep_range(10000, 11000);
|
||||
#if 0
|
||||
read_reg(ci, 0x06, &val);
|
||||
pr_info(KERN_INFO "%d:%02x\n", i, val);
|
||||
@@ -524,7 +590,10 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ci->lock);
|
||||
/* msleep(500); */
|
||||
|
||||
/* Ensure cam stability after reset */
|
||||
msleep(2000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,7 +601,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct cxd *ci = ca->data;
|
||||
|
||||
pr_info("slot_shutdown\n");
|
||||
dev_info(&ci->i2c->dev, "%s\n", __func__);
|
||||
if (ci->cammode)
|
||||
read_data(ca, slot, ci->rbuf, 0);
|
||||
mutex_lock(&ci->lock);
|
||||
@@ -562,7 +631,6 @@ static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int campoll(struct cxd *ci)
|
||||
{
|
||||
u8 istat;
|
||||
@@ -576,6 +644,7 @@ static int campoll(struct cxd *ci)
|
||||
ci->dr = 1;
|
||||
if (istat & 0x20)
|
||||
ci->write_busy = 0;
|
||||
|
||||
if (istat & 2) {
|
||||
u8 slotstat;
|
||||
|
||||
@@ -583,7 +652,7 @@ static int campoll(struct cxd *ci)
|
||||
if (!(2 & slotstat)) {
|
||||
if (!ci->slot_stat) {
|
||||
ci->slot_stat |=
|
||||
DVB_CA_EN50221_POLL_CAM_PRESENT;
|
||||
DVB_CA_EN50221_POLL_CAM_PRESENT;
|
||||
write_regm(ci, 0x03, 0x08, 0x08);
|
||||
}
|
||||
|
||||
@@ -591,7 +660,7 @@ static int campoll(struct cxd *ci)
|
||||
if (ci->slot_stat) {
|
||||
ci->slot_stat = 0;
|
||||
write_regm(ci, 0x03, 0x00, 0x08);
|
||||
pr_info("NO CAM\n");
|
||||
dev_info(&ci->i2c->dev, "NO CAM\n");
|
||||
ci->ready = 0;
|
||||
}
|
||||
}
|
||||
@@ -604,7 +673,6 @@ static int campoll(struct cxd *ci)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||
{
|
||||
struct cxd *ci = ca->data;
|
||||
@@ -634,7 +702,7 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
|
||||
mutex_lock(&ci->lock);
|
||||
read_reg(ci, 0x0f, &msb);
|
||||
read_reg(ci, 0x10, &lsb);
|
||||
len = ((u16) msb << 8) | lsb;
|
||||
len = ((u16)msb << 8) | lsb;
|
||||
if (len > ecount || len < 2) {
|
||||
/* read it anyway or cxd may hang */
|
||||
read_block(ci, 0x12, ci->rbuf, len);
|
||||
@@ -644,21 +712,9 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
|
||||
read_block(ci, 0x12, ebuf, len);
|
||||
ci->dr = 0;
|
||||
mutex_unlock(&ci->lock);
|
||||
#if 0
|
||||
pr_info("read_data %d\n", len);
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
pr_info("%02x ", ebuf[i]);
|
||||
pr_info("\n");
|
||||
}
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef BUFFER_MODE
|
||||
|
||||
static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
|
||||
{
|
||||
struct cxd *ci = ca->data;
|
||||
@@ -673,7 +729,6 @@ static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
|
||||
mutex_unlock(&ci->lock);
|
||||
return ecount;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct dvb_ca_en50221 en_templ = {
|
||||
.read_attribute_mem = read_attribute_mem,
|
||||
@@ -684,43 +739,49 @@ static struct dvb_ca_en50221 en_templ = {
|
||||
.slot_shutdown = slot_shutdown,
|
||||
.slot_ts_enable = slot_ts_enable,
|
||||
.poll_slot_status = poll_slot_status,
|
||||
#ifdef BUFFER_MODE
|
||||
.read_data = read_data,
|
||||
.write_data = write_data,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
|
||||
void *priv,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
struct cxd *ci = 0;
|
||||
struct cxd *ci;
|
||||
u8 val;
|
||||
|
||||
if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
|
||||
pr_info("No CXD2099 detected at %02x\n", cfg->adr);
|
||||
return 0;
|
||||
dev_info(&i2c->dev, "No CXD2099 detected at %02x\n", cfg->adr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ci = kzalloc(sizeof(struct cxd), GFP_KERNEL);
|
||||
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
|
||||
if (!ci)
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
mutex_init(&ci->lock);
|
||||
memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg));
|
||||
ci->cfg = *cfg;
|
||||
ci->i2c = i2c;
|
||||
ci->lastaddress = 0xff;
|
||||
ci->clk_reg_b = 0x4a;
|
||||
ci->clk_reg_f = 0x1b;
|
||||
|
||||
memcpy(&ci->en, &en_templ, sizeof(en_templ));
|
||||
ci->en = en_templ;
|
||||
ci->en.data = ci;
|
||||
init(ci);
|
||||
pr_info("Attached CXD2099AR at %02x\n", ci->cfg.adr);
|
||||
dev_info(&i2c->dev, "Attached CXD2099AR at %02x\n", ci->cfg.adr);
|
||||
|
||||
if (!buffermode) {
|
||||
ci->en.read_data = NULL;
|
||||
ci->en.write_data = NULL;
|
||||
} else {
|
||||
dev_info(&i2c->dev, "Using CXD2099AR buffer mode");
|
||||
}
|
||||
|
||||
return &ci->en;
|
||||
}
|
||||
EXPORT_SYMBOL(cxd2099_attach);
|
||||
|
||||
MODULE_DESCRIPTION("cxd2099");
|
||||
MODULE_AUTHOR("Ralph Metzler");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -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;
|
||||
@@ -36,8 +36,18 @@ struct cxd2099_cfg {
|
||||
u32 max_i2c;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CXD2099) || \
|
||||
(defined(CONFIG_DVB_CXD2099_MODULE) && defined(MODULE))
|
||||
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
|
||||
void *priv, struct i2c_adapter *i2c);
|
||||
#else
|
||||
|
||||
static inline struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
|
||||
void *priv, struct i2c_adapter *i2c)
|
||||
{
|
||||
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1078
frontends/cxd2843.c
1078
frontends/cxd2843.c
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ struct cxd2843_cfg {
|
||||
u8 adr;
|
||||
u32 ts_clock;
|
||||
u8 parallel;
|
||||
u32 osc;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CXD2843) || \
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef _DRXK_H_
|
||||
#define _DRXK_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
extern struct dvb_frontend *drxk_attach(struct i2c_adapter *i2c,
|
||||
u8 adr,
|
||||
struct dvb_frontend **fe_t);
|
||||
#endif
|
||||
#ifndef _DRXK_H_
|
||||
#define _DRXK_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
extern struct dvb_frontend *drxk_attach(struct i2c_adapter *i2c,
|
||||
u8 adr,
|
||||
struct dvb_frontend **fe_t);
|
||||
#endif
|
||||
|
||||
10197
frontends/drxk_hard.c
10197
frontends/drxk_hard.c
File diff suppressed because it is too large
Load Diff
@@ -1,343 +1,343 @@
|
||||
#include "drxk_map.h"
|
||||
|
||||
#define DRXK_VERSION_MAJOR 0
|
||||
#define DRXK_VERSION_MINOR 9
|
||||
#define DRXK_VERSION_PATCH 4300
|
||||
|
||||
#define HI_I2C_DELAY 42
|
||||
#define HI_I2C_BRIDGE_DELAY 350
|
||||
#define DRXK_MAX_RETRIES 100
|
||||
|
||||
#define DRIVER_4400 1
|
||||
|
||||
#define DRXX_JTAGID 0x039210D9
|
||||
#define DRXX_J_JTAGID 0x239310D9
|
||||
#define DRXX_K_JTAGID 0x039210D9
|
||||
|
||||
#define DRX_UNKNOWN 254
|
||||
#define DRX_AUTO 255
|
||||
|
||||
#define DRX_SCU_READY 0
|
||||
#define DRXK_MAX_WAITTIME (200)
|
||||
#define SCU_RESULT_OK 0
|
||||
#define SCU_RESULT_UNKSTD -2
|
||||
#define SCU_RESULT_UNKCMD -1
|
||||
|
||||
#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
|
||||
#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
|
||||
#endif
|
||||
|
||||
#define DRXK_8VSB_MPEG_BIT_RATE 19392658UL /*bps*/
|
||||
#define DRXK_DVBT_MPEG_BIT_RATE 32000000UL /*bps*/
|
||||
#define DRXK_QAM16_MPEG_BIT_RATE 27000000UL /*bps*/
|
||||
#define DRXK_QAM32_MPEG_BIT_RATE 33000000UL /*bps*/
|
||||
#define DRXK_QAM64_MPEG_BIT_RATE 40000000UL /*bps*/
|
||||
#define DRXK_QAM128_MPEG_BIT_RATE 46000000UL /*bps*/
|
||||
#define DRXK_QAM256_MPEG_BIT_RATE 52000000UL /*bps*/
|
||||
#define DRXK_MAX_MPEG_BIT_RATE 52000000UL /*bps*/
|
||||
|
||||
#define IQM_CF_OUT_ENA_OFDM__M 0x4
|
||||
#define IQM_FS_ADJ_SEL_B_QAM 0x1
|
||||
#define IQM_FS_ADJ_SEL_B_OFF 0x0
|
||||
#define IQM_FS_ADJ_SEL_B_VSB 0x2
|
||||
#define IQM_RC_ADJ_SEL_B_OFF 0x0
|
||||
#define IQM_RC_ADJ_SEL_B_QAM 0x1
|
||||
#define IQM_RC_ADJ_SEL_B_VSB 0x2
|
||||
|
||||
enum OperationMode {
|
||||
OM_NONE,
|
||||
OM_QAM_ITU_A,
|
||||
OM_QAM_ITU_B,
|
||||
OM_QAM_ITU_C,
|
||||
OM_DVBT
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DRX_POWER_UP = 0,
|
||||
DRX_POWER_MODE_1,
|
||||
DRX_POWER_MODE_2,
|
||||
DRX_POWER_MODE_3,
|
||||
DRX_POWER_MODE_4,
|
||||
DRX_POWER_MODE_5,
|
||||
DRX_POWER_MODE_6,
|
||||
DRX_POWER_MODE_7,
|
||||
DRX_POWER_MODE_8,
|
||||
|
||||
DRX_POWER_MODE_9,
|
||||
DRX_POWER_MODE_10,
|
||||
DRX_POWER_MODE_11,
|
||||
DRX_POWER_MODE_12,
|
||||
DRX_POWER_MODE_13,
|
||||
DRX_POWER_MODE_14,
|
||||
DRX_POWER_MODE_15,
|
||||
DRX_POWER_MODE_16,
|
||||
DRX_POWER_DOWN = 255
|
||||
}DRXPowerMode_t, *pDRXPowerMode_t;
|
||||
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
|
||||
#ifndef DRXK_POWER_DOWN_OFDM
|
||||
#define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1
|
||||
#endif
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
|
||||
#ifndef DRXK_POWER_DOWN_CORE
|
||||
#define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9
|
||||
#endif
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
|
||||
#ifndef DRXK_POWER_DOWN_PLL
|
||||
#define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10
|
||||
#endif
|
||||
|
||||
|
||||
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
|
||||
enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN };
|
||||
enum EDrxkCoefArrayIndex {
|
||||
DRXK_COEF_IDX_MN = 0,
|
||||
DRXK_COEF_IDX_FM ,
|
||||
DRXK_COEF_IDX_L ,
|
||||
DRXK_COEF_IDX_LP ,
|
||||
DRXK_COEF_IDX_BG ,
|
||||
DRXK_COEF_IDX_DK ,
|
||||
DRXK_COEF_IDX_I ,
|
||||
DRXK_COEF_IDX_MAX
|
||||
};
|
||||
enum EDrxkSifAttenuation {
|
||||
DRXK_SIF_ATTENUATION_0DB,
|
||||
DRXK_SIF_ATTENUATION_3DB,
|
||||
DRXK_SIF_ATTENUATION_6DB,
|
||||
DRXK_SIF_ATTENUATION_9DB
|
||||
};
|
||||
enum EDrxkConstellation {
|
||||
DRX_CONSTELLATION_BPSK = 0,
|
||||
DRX_CONSTELLATION_QPSK,
|
||||
DRX_CONSTELLATION_PSK8,
|
||||
DRX_CONSTELLATION_QAM16,
|
||||
DRX_CONSTELLATION_QAM32,
|
||||
DRX_CONSTELLATION_QAM64,
|
||||
DRX_CONSTELLATION_QAM128,
|
||||
DRX_CONSTELLATION_QAM256,
|
||||
DRX_CONSTELLATION_QAM512,
|
||||
DRX_CONSTELLATION_QAM1024,
|
||||
DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
|
||||
DRX_CONSTELLATION_AUTO = DRX_AUTO
|
||||
};
|
||||
enum EDrxkInterleaveMode {
|
||||
DRXK_QAM_I12_J17 = 16,
|
||||
DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN
|
||||
};
|
||||
enum {
|
||||
DRXK_SPIN_A1 = 0,
|
||||
DRXK_SPIN_A2,
|
||||
DRXK_SPIN_A3,
|
||||
DRXK_SPIN_UNKNOWN
|
||||
};
|
||||
|
||||
enum DRXKCfgDvbtSqiSpeed {
|
||||
DRXK_DVBT_SQI_SPEED_FAST = 0,
|
||||
DRXK_DVBT_SQI_SPEED_MEDIUM,
|
||||
DRXK_DVBT_SQI_SPEED_SLOW,
|
||||
DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
|
||||
} ;
|
||||
|
||||
enum DRXFftmode_t {
|
||||
DRX_FFTMODE_2K = 0,
|
||||
DRX_FFTMODE_4K,
|
||||
DRX_FFTMODE_8K,
|
||||
DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
|
||||
DRX_FFTMODE_AUTO = DRX_AUTO
|
||||
};
|
||||
|
||||
enum DRXMPEGStrWidth_t {
|
||||
DRX_MPEG_STR_WIDTH_1,
|
||||
DRX_MPEG_STR_WIDTH_8
|
||||
};
|
||||
|
||||
enum DRXQamLockRange_t {
|
||||
DRX_QAM_LOCKRANGE_NORMAL,
|
||||
DRX_QAM_LOCKRANGE_EXTENDED
|
||||
};
|
||||
|
||||
struct DRXKCfgDvbtEchoThres_t {
|
||||
u16 threshold;
|
||||
enum DRXFftmode_t fftMode;
|
||||
} ;
|
||||
|
||||
struct SCfgAgc
|
||||
{
|
||||
enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */
|
||||
u16 outputLevel; /* range dependent on AGC */
|
||||
u16 minOutputLevel; /* range dependent on AGC */
|
||||
u16 maxOutputLevel; /* range dependent on AGC */
|
||||
u16 speed; /* range dependent on AGC */
|
||||
u16 top; /* rf-agc take over point */
|
||||
u16 cutOffCurrent; /* rf-agc is accelerated if output current
|
||||
is below cut-off current */
|
||||
u16 IngainTgtMax;
|
||||
u16 FastClipCtrlDelay;
|
||||
};
|
||||
|
||||
struct SCfgPreSaw
|
||||
{
|
||||
u16 reference; /* pre SAW reference value, range 0 .. 31 */
|
||||
bool usePreSaw; /* TRUE algorithms must use pre SAW sense */
|
||||
};
|
||||
|
||||
struct DRXKOfdmScCmd_t
|
||||
{
|
||||
u16 cmd; /**< Command number */
|
||||
u16 subcmd; /**< Sub-command parameter*/
|
||||
u16 param0; /**< General purpous param */
|
||||
u16 param1; /**< General purpous param */
|
||||
u16 param2; /**< General purpous param */
|
||||
u16 param3; /**< General purpous param */
|
||||
u16 param4; /**< General purpous param */
|
||||
};
|
||||
|
||||
struct drxk_state {
|
||||
struct dvb_frontend c_frontend;
|
||||
struct dvb_frontend t_frontend;
|
||||
#ifndef USE_API3
|
||||
struct dtv_frontend_properties props;
|
||||
#else
|
||||
struct dvb_frontend_parameters param;
|
||||
#endif
|
||||
struct device *dev;
|
||||
|
||||
struct i2c_adapter *i2c;
|
||||
u8 demod_address;
|
||||
void *priv;
|
||||
|
||||
struct mutex mutex;
|
||||
struct mutex ctlock;
|
||||
|
||||
u32 m_Instance; ///< Channel 1,2,3 or 4
|
||||
|
||||
int m_ChunkSize;
|
||||
u8 Chunk[256];
|
||||
|
||||
bool m_hasLNA;
|
||||
bool m_hasDVBT;
|
||||
bool m_hasDVBC;
|
||||
bool m_hasAudio;
|
||||
bool m_hasATV;
|
||||
bool m_hasOOB;
|
||||
bool m_hasSAWSW; /**< TRUE if mat_tx is available */
|
||||
bool m_hasGPIO1; /**< TRUE if mat_rx is available */
|
||||
bool m_hasGPIO2; /**< TRUE if GPIO is available */
|
||||
bool m_hasIRQN; /**< TRUE if IRQN is available */
|
||||
u16 m_oscClockFreq;
|
||||
u16 m_HICfgTimingDiv;
|
||||
u16 m_HICfgBridgeDelay;
|
||||
u16 m_HICfgWakeUpKey;
|
||||
u16 m_HICfgTimeout;
|
||||
u16 m_HICfgCtrl;
|
||||
s32 m_sysClockFreq ; ///< system clock frequency in kHz
|
||||
|
||||
enum EDrxkState m_DrxkState; ///< State of Drxk (init,stopped,started)
|
||||
enum OperationMode m_OperationMode; ///< digital standards
|
||||
struct SCfgAgc m_vsbRfAgcCfg; ///< settings for VSB RF-AGC
|
||||
struct SCfgAgc m_vsbIfAgcCfg; ///< settings for VSB IF-AGC
|
||||
u16 m_vsbPgaCfg; ///< settings for VSB PGA
|
||||
struct SCfgPreSaw m_vsbPreSawCfg; ///< settings for pre SAW sense
|
||||
s32 m_Quality83percent; ///< MER level (*0.1 dB) for 83% quality indication
|
||||
s32 m_Quality93percent; ///< MER level (*0.1 dB) for 93% quality indication
|
||||
bool m_smartAntInverted;
|
||||
bool m_bDebugEnableBridge;
|
||||
bool m_bPDownOpenBridge; ///< only open DRXK bridge before power-down once it has been accessed
|
||||
bool m_bPowerDown; ///< Power down when not used
|
||||
|
||||
u32 m_IqmFsRateOfs; ///< frequency shift as written to DRXK register (28bit fixpoint)
|
||||
|
||||
bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */
|
||||
bool m_insertRSByte; /**< If TRUE, insert RS byte */
|
||||
bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */
|
||||
bool m_invertDATA; /**< If TRUE, invert DATA signals */
|
||||
bool m_invertERR; /**< If TRUE, invert ERR signal */
|
||||
bool m_invertSTR; /**< If TRUE, invert STR signals */
|
||||
bool m_invertVAL; /**< If TRUE, invert VAL signals */
|
||||
bool m_invertCLK; /**< If TRUE, invert CLK signals */
|
||||
bool m_DVBCStaticCLK;
|
||||
bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will
|
||||
be used, otherwise clockrate will
|
||||
adapt to the bitrate of the TS */
|
||||
u32 m_DVBTBitrate;
|
||||
u32 m_DVBCBitrate;
|
||||
|
||||
u8 m_TSDataStrength;
|
||||
u8 m_TSClockkStrength;
|
||||
|
||||
enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width**/
|
||||
u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case
|
||||
static clockrate is selected */
|
||||
|
||||
//LARGE_INTEGER m_StartTime; ///< Contains the time of the last demod start
|
||||
s32 m_MpegLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
|
||||
s32 m_DemodLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
|
||||
|
||||
bool m_disableTEIhandling;
|
||||
|
||||
bool m_RfAgcPol;
|
||||
bool m_IfAgcPol;
|
||||
|
||||
struct SCfgAgc m_atvRfAgcCfg; ///< settings for ATV RF-AGC
|
||||
struct SCfgAgc m_atvIfAgcCfg; ///< settings for ATV IF-AGC
|
||||
struct SCfgPreSaw m_atvPreSawCfg; ///< settings for ATV pre SAW sense
|
||||
bool m_phaseCorrectionBypass;
|
||||
s16 m_atvTopVidPeak;
|
||||
u16 m_atvTopNoiseTh;
|
||||
enum EDrxkSifAttenuation m_sifAttenuation;
|
||||
bool m_enableCVBSOutput;
|
||||
bool m_enableSIFOutput;
|
||||
bool m_bMirrorFreqSpect;
|
||||
enum EDrxkConstellation m_Constellation; ///< Constellation type of the channel
|
||||
u32 m_CurrSymbolRate; ///< Current QAM symbol rate
|
||||
struct SCfgAgc m_qamRfAgcCfg; ///< settings for QAM RF-AGC
|
||||
struct SCfgAgc m_qamIfAgcCfg; ///< settings for QAM IF-AGC
|
||||
u16 m_qamPgaCfg; ///< settings for QAM PGA
|
||||
struct SCfgPreSaw m_qamPreSawCfg; ///< settings for QAM pre SAW sense
|
||||
enum EDrxkInterleaveMode m_qamInterleaveMode; ///< QAM Interleave mode
|
||||
u16 m_fecRsPlen;
|
||||
u16 m_fecRsPrescale;
|
||||
|
||||
enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
|
||||
|
||||
u16 m_GPIO;
|
||||
u16 m_GPIOCfg;
|
||||
|
||||
struct SCfgAgc m_dvbtRfAgcCfg; ///< settings for QAM RF-AGC
|
||||
struct SCfgAgc m_dvbtIfAgcCfg; ///< settings for QAM IF-AGC
|
||||
struct SCfgPreSaw m_dvbtPreSawCfg; ///< settings for QAM pre SAW sense
|
||||
|
||||
u16 m_agcFastClipCtrlDelay;
|
||||
bool m_adcCompPassed;
|
||||
u16 m_adcCompCoef[64];
|
||||
u16 m_adcState;
|
||||
|
||||
u8 *m_microcode;
|
||||
int m_microcode_length;
|
||||
bool m_DRXK_A1_PATCH_CODE;
|
||||
bool m_DRXK_A1_ROM_CODE;
|
||||
bool m_DRXK_A2_ROM_CODE;
|
||||
bool m_DRXK_A3_ROM_CODE;
|
||||
bool m_DRXK_A2_PATCH_CODE;
|
||||
bool m_DRXK_A3_PATCH_CODE;
|
||||
|
||||
bool m_rfmirror;
|
||||
u8 m_deviceSpin;
|
||||
u32 m_iqmRcRate;
|
||||
|
||||
u16 m_AntennaDVBC;
|
||||
u16 m_AntennaDVBT;
|
||||
u16 m_AntennaSwitchDVBTDVBC;
|
||||
|
||||
DRXPowerMode_t m_currentPowerMode;
|
||||
};
|
||||
|
||||
#define NEVER_LOCK 0
|
||||
#define NOT_LOCKED 1
|
||||
#define DEMOD_LOCK 2
|
||||
#define FEC_LOCK 3
|
||||
#define MPEG_LOCK 4
|
||||
|
||||
#include "drxk_map.h"
|
||||
|
||||
#define DRXK_VERSION_MAJOR 0
|
||||
#define DRXK_VERSION_MINOR 9
|
||||
#define DRXK_VERSION_PATCH 4300
|
||||
|
||||
#define HI_I2C_DELAY 42
|
||||
#define HI_I2C_BRIDGE_DELAY 350
|
||||
#define DRXK_MAX_RETRIES 100
|
||||
|
||||
#define DRIVER_4400 1
|
||||
|
||||
#define DRXX_JTAGID 0x039210D9
|
||||
#define DRXX_J_JTAGID 0x239310D9
|
||||
#define DRXX_K_JTAGID 0x039210D9
|
||||
|
||||
#define DRX_UNKNOWN 254
|
||||
#define DRX_AUTO 255
|
||||
|
||||
#define DRX_SCU_READY 0
|
||||
#define DRXK_MAX_WAITTIME (200)
|
||||
#define SCU_RESULT_OK 0
|
||||
#define SCU_RESULT_UNKSTD -2
|
||||
#define SCU_RESULT_UNKCMD -1
|
||||
|
||||
#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
|
||||
#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
|
||||
#endif
|
||||
|
||||
#define DRXK_8VSB_MPEG_BIT_RATE 19392658UL /*bps*/
|
||||
#define DRXK_DVBT_MPEG_BIT_RATE 32000000UL /*bps*/
|
||||
#define DRXK_QAM16_MPEG_BIT_RATE 27000000UL /*bps*/
|
||||
#define DRXK_QAM32_MPEG_BIT_RATE 33000000UL /*bps*/
|
||||
#define DRXK_QAM64_MPEG_BIT_RATE 40000000UL /*bps*/
|
||||
#define DRXK_QAM128_MPEG_BIT_RATE 46000000UL /*bps*/
|
||||
#define DRXK_QAM256_MPEG_BIT_RATE 52000000UL /*bps*/
|
||||
#define DRXK_MAX_MPEG_BIT_RATE 52000000UL /*bps*/
|
||||
|
||||
#define IQM_CF_OUT_ENA_OFDM__M 0x4
|
||||
#define IQM_FS_ADJ_SEL_B_QAM 0x1
|
||||
#define IQM_FS_ADJ_SEL_B_OFF 0x0
|
||||
#define IQM_FS_ADJ_SEL_B_VSB 0x2
|
||||
#define IQM_RC_ADJ_SEL_B_OFF 0x0
|
||||
#define IQM_RC_ADJ_SEL_B_QAM 0x1
|
||||
#define IQM_RC_ADJ_SEL_B_VSB 0x2
|
||||
|
||||
enum OperationMode {
|
||||
OM_NONE,
|
||||
OM_QAM_ITU_A,
|
||||
OM_QAM_ITU_B,
|
||||
OM_QAM_ITU_C,
|
||||
OM_DVBT
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DRX_POWER_UP = 0,
|
||||
DRX_POWER_MODE_1,
|
||||
DRX_POWER_MODE_2,
|
||||
DRX_POWER_MODE_3,
|
||||
DRX_POWER_MODE_4,
|
||||
DRX_POWER_MODE_5,
|
||||
DRX_POWER_MODE_6,
|
||||
DRX_POWER_MODE_7,
|
||||
DRX_POWER_MODE_8,
|
||||
|
||||
DRX_POWER_MODE_9,
|
||||
DRX_POWER_MODE_10,
|
||||
DRX_POWER_MODE_11,
|
||||
DRX_POWER_MODE_12,
|
||||
DRX_POWER_MODE_13,
|
||||
DRX_POWER_MODE_14,
|
||||
DRX_POWER_MODE_15,
|
||||
DRX_POWER_MODE_16,
|
||||
DRX_POWER_DOWN = 255
|
||||
}DRXPowerMode_t, *pDRXPowerMode_t;
|
||||
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
|
||||
#ifndef DRXK_POWER_DOWN_OFDM
|
||||
#define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1
|
||||
#endif
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
|
||||
#ifndef DRXK_POWER_DOWN_CORE
|
||||
#define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9
|
||||
#endif
|
||||
|
||||
/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
|
||||
#ifndef DRXK_POWER_DOWN_PLL
|
||||
#define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10
|
||||
#endif
|
||||
|
||||
|
||||
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
|
||||
enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN };
|
||||
enum EDrxkCoefArrayIndex {
|
||||
DRXK_COEF_IDX_MN = 0,
|
||||
DRXK_COEF_IDX_FM ,
|
||||
DRXK_COEF_IDX_L ,
|
||||
DRXK_COEF_IDX_LP ,
|
||||
DRXK_COEF_IDX_BG ,
|
||||
DRXK_COEF_IDX_DK ,
|
||||
DRXK_COEF_IDX_I ,
|
||||
DRXK_COEF_IDX_MAX
|
||||
};
|
||||
enum EDrxkSifAttenuation {
|
||||
DRXK_SIF_ATTENUATION_0DB,
|
||||
DRXK_SIF_ATTENUATION_3DB,
|
||||
DRXK_SIF_ATTENUATION_6DB,
|
||||
DRXK_SIF_ATTENUATION_9DB
|
||||
};
|
||||
enum EDrxkConstellation {
|
||||
DRX_CONSTELLATION_BPSK = 0,
|
||||
DRX_CONSTELLATION_QPSK,
|
||||
DRX_CONSTELLATION_PSK8,
|
||||
DRX_CONSTELLATION_QAM16,
|
||||
DRX_CONSTELLATION_QAM32,
|
||||
DRX_CONSTELLATION_QAM64,
|
||||
DRX_CONSTELLATION_QAM128,
|
||||
DRX_CONSTELLATION_QAM256,
|
||||
DRX_CONSTELLATION_QAM512,
|
||||
DRX_CONSTELLATION_QAM1024,
|
||||
DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
|
||||
DRX_CONSTELLATION_AUTO = DRX_AUTO
|
||||
};
|
||||
enum EDrxkInterleaveMode {
|
||||
DRXK_QAM_I12_J17 = 16,
|
||||
DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN
|
||||
};
|
||||
enum {
|
||||
DRXK_SPIN_A1 = 0,
|
||||
DRXK_SPIN_A2,
|
||||
DRXK_SPIN_A3,
|
||||
DRXK_SPIN_UNKNOWN
|
||||
};
|
||||
|
||||
enum DRXKCfgDvbtSqiSpeed {
|
||||
DRXK_DVBT_SQI_SPEED_FAST = 0,
|
||||
DRXK_DVBT_SQI_SPEED_MEDIUM,
|
||||
DRXK_DVBT_SQI_SPEED_SLOW,
|
||||
DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
|
||||
} ;
|
||||
|
||||
enum DRXFftmode_t {
|
||||
DRX_FFTMODE_2K = 0,
|
||||
DRX_FFTMODE_4K,
|
||||
DRX_FFTMODE_8K,
|
||||
DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
|
||||
DRX_FFTMODE_AUTO = DRX_AUTO
|
||||
};
|
||||
|
||||
enum DRXMPEGStrWidth_t {
|
||||
DRX_MPEG_STR_WIDTH_1,
|
||||
DRX_MPEG_STR_WIDTH_8
|
||||
};
|
||||
|
||||
enum DRXQamLockRange_t {
|
||||
DRX_QAM_LOCKRANGE_NORMAL,
|
||||
DRX_QAM_LOCKRANGE_EXTENDED
|
||||
};
|
||||
|
||||
struct DRXKCfgDvbtEchoThres_t {
|
||||
u16 threshold;
|
||||
enum DRXFftmode_t fftMode;
|
||||
} ;
|
||||
|
||||
struct SCfgAgc
|
||||
{
|
||||
enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */
|
||||
u16 outputLevel; /* range dependent on AGC */
|
||||
u16 minOutputLevel; /* range dependent on AGC */
|
||||
u16 maxOutputLevel; /* range dependent on AGC */
|
||||
u16 speed; /* range dependent on AGC */
|
||||
u16 top; /* rf-agc take over point */
|
||||
u16 cutOffCurrent; /* rf-agc is accelerated if output current
|
||||
is below cut-off current */
|
||||
u16 IngainTgtMax;
|
||||
u16 FastClipCtrlDelay;
|
||||
};
|
||||
|
||||
struct SCfgPreSaw
|
||||
{
|
||||
u16 reference; /* pre SAW reference value, range 0 .. 31 */
|
||||
bool usePreSaw; /* TRUE algorithms must use pre SAW sense */
|
||||
};
|
||||
|
||||
struct DRXKOfdmScCmd_t
|
||||
{
|
||||
u16 cmd; /**< Command number */
|
||||
u16 subcmd; /**< Sub-command parameter*/
|
||||
u16 param0; /**< General purpous param */
|
||||
u16 param1; /**< General purpous param */
|
||||
u16 param2; /**< General purpous param */
|
||||
u16 param3; /**< General purpous param */
|
||||
u16 param4; /**< General purpous param */
|
||||
};
|
||||
|
||||
struct drxk_state {
|
||||
struct dvb_frontend c_frontend;
|
||||
struct dvb_frontend t_frontend;
|
||||
#ifndef USE_API3
|
||||
struct dtv_frontend_properties props;
|
||||
#else
|
||||
struct dvb_frontend_parameters param;
|
||||
#endif
|
||||
struct device *dev;
|
||||
|
||||
struct i2c_adapter *i2c;
|
||||
u8 demod_address;
|
||||
void *priv;
|
||||
|
||||
struct mutex mutex;
|
||||
struct mutex ctlock;
|
||||
|
||||
u32 m_Instance; ///< Channel 1,2,3 or 4
|
||||
|
||||
int m_ChunkSize;
|
||||
u8 Chunk[256];
|
||||
|
||||
bool m_hasLNA;
|
||||
bool m_hasDVBT;
|
||||
bool m_hasDVBC;
|
||||
bool m_hasAudio;
|
||||
bool m_hasATV;
|
||||
bool m_hasOOB;
|
||||
bool m_hasSAWSW; /**< TRUE if mat_tx is available */
|
||||
bool m_hasGPIO1; /**< TRUE if mat_rx is available */
|
||||
bool m_hasGPIO2; /**< TRUE if GPIO is available */
|
||||
bool m_hasIRQN; /**< TRUE if IRQN is available */
|
||||
u16 m_oscClockFreq;
|
||||
u16 m_HICfgTimingDiv;
|
||||
u16 m_HICfgBridgeDelay;
|
||||
u16 m_HICfgWakeUpKey;
|
||||
u16 m_HICfgTimeout;
|
||||
u16 m_HICfgCtrl;
|
||||
s32 m_sysClockFreq ; ///< system clock frequency in kHz
|
||||
|
||||
enum EDrxkState m_DrxkState; ///< State of Drxk (init,stopped,started)
|
||||
enum OperationMode m_OperationMode; ///< digital standards
|
||||
struct SCfgAgc m_vsbRfAgcCfg; ///< settings for VSB RF-AGC
|
||||
struct SCfgAgc m_vsbIfAgcCfg; ///< settings for VSB IF-AGC
|
||||
u16 m_vsbPgaCfg; ///< settings for VSB PGA
|
||||
struct SCfgPreSaw m_vsbPreSawCfg; ///< settings for pre SAW sense
|
||||
s32 m_Quality83percent; ///< MER level (*0.1 dB) for 83% quality indication
|
||||
s32 m_Quality93percent; ///< MER level (*0.1 dB) for 93% quality indication
|
||||
bool m_smartAntInverted;
|
||||
bool m_bDebugEnableBridge;
|
||||
bool m_bPDownOpenBridge; ///< only open DRXK bridge before power-down once it has been accessed
|
||||
bool m_bPowerDown; ///< Power down when not used
|
||||
|
||||
u32 m_IqmFsRateOfs; ///< frequency shift as written to DRXK register (28bit fixpoint)
|
||||
|
||||
bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */
|
||||
bool m_insertRSByte; /**< If TRUE, insert RS byte */
|
||||
bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */
|
||||
bool m_invertDATA; /**< If TRUE, invert DATA signals */
|
||||
bool m_invertERR; /**< If TRUE, invert ERR signal */
|
||||
bool m_invertSTR; /**< If TRUE, invert STR signals */
|
||||
bool m_invertVAL; /**< If TRUE, invert VAL signals */
|
||||
bool m_invertCLK; /**< If TRUE, invert CLK signals */
|
||||
bool m_DVBCStaticCLK;
|
||||
bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will
|
||||
be used, otherwise clockrate will
|
||||
adapt to the bitrate of the TS */
|
||||
u32 m_DVBTBitrate;
|
||||
u32 m_DVBCBitrate;
|
||||
|
||||
u8 m_TSDataStrength;
|
||||
u8 m_TSClockkStrength;
|
||||
|
||||
enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width**/
|
||||
u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case
|
||||
static clockrate is selected */
|
||||
|
||||
//LARGE_INTEGER m_StartTime; ///< Contains the time of the last demod start
|
||||
s32 m_MpegLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
|
||||
s32 m_DemodLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
|
||||
|
||||
bool m_disableTEIhandling;
|
||||
|
||||
bool m_RfAgcPol;
|
||||
bool m_IfAgcPol;
|
||||
|
||||
struct SCfgAgc m_atvRfAgcCfg; ///< settings for ATV RF-AGC
|
||||
struct SCfgAgc m_atvIfAgcCfg; ///< settings for ATV IF-AGC
|
||||
struct SCfgPreSaw m_atvPreSawCfg; ///< settings for ATV pre SAW sense
|
||||
bool m_phaseCorrectionBypass;
|
||||
s16 m_atvTopVidPeak;
|
||||
u16 m_atvTopNoiseTh;
|
||||
enum EDrxkSifAttenuation m_sifAttenuation;
|
||||
bool m_enableCVBSOutput;
|
||||
bool m_enableSIFOutput;
|
||||
bool m_bMirrorFreqSpect;
|
||||
enum EDrxkConstellation m_Constellation; ///< Constellation type of the channel
|
||||
u32 m_CurrSymbolRate; ///< Current QAM symbol rate
|
||||
struct SCfgAgc m_qamRfAgcCfg; ///< settings for QAM RF-AGC
|
||||
struct SCfgAgc m_qamIfAgcCfg; ///< settings for QAM IF-AGC
|
||||
u16 m_qamPgaCfg; ///< settings for QAM PGA
|
||||
struct SCfgPreSaw m_qamPreSawCfg; ///< settings for QAM pre SAW sense
|
||||
enum EDrxkInterleaveMode m_qamInterleaveMode; ///< QAM Interleave mode
|
||||
u16 m_fecRsPlen;
|
||||
u16 m_fecRsPrescale;
|
||||
|
||||
enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
|
||||
|
||||
u16 m_GPIO;
|
||||
u16 m_GPIOCfg;
|
||||
|
||||
struct SCfgAgc m_dvbtRfAgcCfg; ///< settings for QAM RF-AGC
|
||||
struct SCfgAgc m_dvbtIfAgcCfg; ///< settings for QAM IF-AGC
|
||||
struct SCfgPreSaw m_dvbtPreSawCfg; ///< settings for QAM pre SAW sense
|
||||
|
||||
u16 m_agcFastClipCtrlDelay;
|
||||
bool m_adcCompPassed;
|
||||
u16 m_adcCompCoef[64];
|
||||
u16 m_adcState;
|
||||
|
||||
u8 *m_microcode;
|
||||
int m_microcode_length;
|
||||
bool m_DRXK_A1_PATCH_CODE;
|
||||
bool m_DRXK_A1_ROM_CODE;
|
||||
bool m_DRXK_A2_ROM_CODE;
|
||||
bool m_DRXK_A3_ROM_CODE;
|
||||
bool m_DRXK_A2_PATCH_CODE;
|
||||
bool m_DRXK_A3_PATCH_CODE;
|
||||
|
||||
bool m_rfmirror;
|
||||
u8 m_deviceSpin;
|
||||
u32 m_iqmRcRate;
|
||||
|
||||
u16 m_AntennaDVBC;
|
||||
u16 m_AntennaDVBT;
|
||||
u16 m_AntennaSwitchDVBTDVBC;
|
||||
|
||||
DRXPowerMode_t m_currentPowerMode;
|
||||
};
|
||||
|
||||
#define NEVER_LOCK 0
|
||||
#define NOT_LOCKED 1
|
||||
#define DEMOD_LOCK 2
|
||||
#define FEC_LOCK 3
|
||||
#define MPEG_LOCK 4
|
||||
|
||||
|
||||
32876
frontends/drxk_map.h
32876
frontends/drxk_map.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
@@ -62,7 +62,7 @@ static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len)
|
||||
}
|
||||
|
||||
static int lnbh25_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
enum fe_sec_voltage voltage)
|
||||
{
|
||||
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
|
||||
u8 oldreg0 = lnbh->reg[0];
|
||||
@@ -106,13 +106,15 @@ 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,
|
||||
fe_sec_tone_mode_t tone)
|
||||
enum fe_sec_tone_mode tone)
|
||||
{
|
||||
/* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lnbh25_init(struct lnbh25 *lnbh)
|
||||
{
|
||||
@@ -146,7 +148,7 @@ struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
|
||||
fe->ops.enable_high_lnb_voltage = lnbh25_enable_high_lnb_voltage;
|
||||
fe->ops.release_sec = lnbh25_release;
|
||||
|
||||
pr_info("LNB25 on %02x\n", lnbh->adr);
|
||||
pr_info("LNBH25 on %02x\n", lnbh->adr);
|
||||
|
||||
return fe;
|
||||
}
|
||||
@@ -154,4 +156,4 @@ EXPORT_SYMBOL(lnbh25_attach);
|
||||
|
||||
MODULE_DESCRIPTION("LNBH25");
|
||||
MODULE_AUTHOR("Ralph Metzler");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -45,7 +45,7 @@ struct lnbp21 {
|
||||
};
|
||||
|
||||
static int lnbp21_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
enum fe_sec_voltage voltage)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
|
||||
@@ -98,7 +98,7 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
}
|
||||
|
||||
static int lnbp21_set_tone(struct dvb_frontend *fe,
|
||||
fe_sec_tone_mode_t tone)
|
||||
enum fe_sec_tone_mode tone)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
|
||||
|
||||
@@ -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;
|
||||
@@ -193,7 +173,8 @@ static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val)
|
||||
if (stat)
|
||||
pr_err("i2c read error 1\n");
|
||||
if (!stat)
|
||||
stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES);
|
||||
stat = i2cread(state, (u8 *) val,
|
||||
MXL_HYDRA_REG_SIZE_IN_BYTES);
|
||||
le32_to_cpus(val);
|
||||
if (stat)
|
||||
pr_err("i2c read error 2\n");
|
||||
@@ -218,10 +199,12 @@ static int send_command(struct mxl *state, u32 size, u8 *buf)
|
||||
mutex_unlock(&state->base->i2c_lock);
|
||||
usleep_range(1000, 2000);
|
||||
mutex_lock(&state->base->i2c_lock);
|
||||
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val);
|
||||
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR,
|
||||
&val);
|
||||
}
|
||||
if (!count) {
|
||||
pr_info("mxl5xx: send_command busy\n");
|
||||
mutex_unlock(&state->base->i2c_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
@@ -246,7 +229,9 @@ static int write_register(struct mxl *state, u32 reg, u32 val)
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data)
|
||||
#if 0
|
||||
static int write_register_block(struct mxl *state, u32 reg,
|
||||
u32 size, u8 *data)
|
||||
{
|
||||
int stat;
|
||||
u8 *buf = state->base->buf;
|
||||
@@ -268,6 +253,7 @@ static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data)
|
||||
mutex_unlock(&state->base->i2c_lock);
|
||||
return stat;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int write_firmware_block(struct mxl *state,
|
||||
u32 reg, u32 size, u8 *regDataPtr)
|
||||
@@ -307,7 +293,8 @@ static int read_register(struct mxl *state, u32 reg, u32 *val)
|
||||
if (stat)
|
||||
pr_err("i2c read error 1\n");
|
||||
if (!stat)
|
||||
stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES);
|
||||
stat = i2cread(state, (u8 *) val,
|
||||
MXL_HYDRA_REG_SIZE_IN_BYTES);
|
||||
mutex_unlock(&state->base->i2c_lock);
|
||||
le32_to_cpus(val);
|
||||
if (stat)
|
||||
@@ -370,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;
|
||||
@@ -390,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;
|
||||
}
|
||||
|
||||
@@ -414,14 +392,27 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
static int cfg_scrambler(struct mxl *state)
|
||||
/* This should maybe go into dvb-core/dvb_math.c */
|
||||
|
||||
static u32 gold2root(u32 gold)
|
||||
{
|
||||
u32 x, g;
|
||||
|
||||
if (gold >= 0x3ffff)
|
||||
gold = 0;
|
||||
for (g = 0, x = 1; g < gold; g++)
|
||||
x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
static int cfg_scrambler(struct mxl *state, u32 gold)
|
||||
{
|
||||
u32 root;
|
||||
u8 buf[26] = {
|
||||
MXL_HYDRA_PLID_CMD_WRITE, 24,
|
||||
0, MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD, 0, 0,
|
||||
@@ -430,11 +421,15 @@ static int cfg_scrambler(struct mxl *state)
|
||||
0, 0, 0, 0, 1, 0, 0, 0,
|
||||
};
|
||||
|
||||
root = gold2root(gold);
|
||||
buf[25] = (root >> 24) & 0xff;
|
||||
buf[24] = (root >> 16) & 0xff;
|
||||
buf[23] = (root >> 8) & 0xff;
|
||||
buf[22] = root & 0xff;
|
||||
|
||||
return send_command(state, sizeof(buf), buf);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static int CfgDemodAbortTune(struct mxl *state)
|
||||
{
|
||||
MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd;
|
||||
@@ -442,10 +437,26 @@ static int CfgDemodAbortTune(struct mxl *state)
|
||||
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
|
||||
|
||||
abortTuneCmd.demodId = state->demod;
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, cmdSize, &abortTuneCmd, cmdBuff);
|
||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE,
|
||||
cmdSize, &abortTuneCmd, cmdBuff);
|
||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||
&cmdBuff[0]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int reset_fec_counter(struct mxl *state)
|
||||
{
|
||||
u32 demodIndex = (u32) state->demod;
|
||||
u8 cmdSize = sizeof(u32);
|
||||
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
|
||||
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD,
|
||||
MXL_CMD_WRITE, cmdSize, &demodIndex, cmdBuff);
|
||||
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)
|
||||
{
|
||||
@@ -490,7 +501,7 @@ static int set_parameters(struct dvb_frontend *fe)
|
||||
demodChanCfg.rollOff = MXL_HYDRA_ROLLOFF_AUTO;
|
||||
demodChanCfg.modulationScheme = MXL_HYDRA_MOD_AUTO;
|
||||
demodChanCfg.pilots = MXL_HYDRA_PILOTS_AUTO;
|
||||
//cfg_scrambler(state);
|
||||
cfg_scrambler(state, p->scrambling_sequence_index);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -504,19 +515,23 @@ static int set_parameters(struct dvb_frontend *fe)
|
||||
demodChanCfg.fecCodeRate = MXL_HYDRA_FEC_AUTO;
|
||||
|
||||
mutex_lock(&state->base->tune_lock);
|
||||
if (time_after(jiffies + msecs_to_jiffies(200), state->base->next_tune))
|
||||
if (time_after(jiffies + msecs_to_jiffies(200),
|
||||
state->base->next_tune))
|
||||
while (time_before(jiffies, state->base->next_tune))
|
||||
msleep(10);
|
||||
state->base->next_tune = jiffies + msecs_to_jiffies(100);
|
||||
state->tuner_in_use = state->tuner;
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE,
|
||||
cmdSize, &demodChanCfg, cmdBuff);
|
||||
stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
|
||||
stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||
&cmdBuff[0]);
|
||||
mutex_unlock(&state->base->tune_lock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int get_stats(struct dvb_frontend *fe);
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
|
||||
@@ -532,16 +547,16 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
mutex_unlock(&state->base->status_lock);
|
||||
|
||||
*status = (regData == 1) ? 0x1f : 0;
|
||||
|
||||
get_stats(fe);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, fe_status_t *status)
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
/* struct dtv_frontend_properties *p = &fe->dtv_property_cache; */
|
||||
int r = 0;
|
||||
|
||||
*delay = HZ / 2;
|
||||
@@ -552,21 +567,19 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
state->tune_time = jiffies;
|
||||
return 0;
|
||||
}
|
||||
if (*status & FE_HAS_LOCK)
|
||||
return 0;
|
||||
|
||||
r = read_status(fe, status);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (*status & FE_HAS_LOCK)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
if (p->delivery_system == SYS_DVBS)
|
||||
p->delivery_system = SYS_DVBS2;
|
||||
else
|
||||
p->delivery_system = SYS_DVBS;
|
||||
set_parameters(fe);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -597,6 +610,7 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
int stat;
|
||||
u32 regData = 0;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
|
||||
mutex_lock(&state->base->status_lock);
|
||||
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
|
||||
@@ -605,23 +619,82 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
®Data);
|
||||
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
|
||||
mutex_unlock(&state->base->status_lock);
|
||||
*snr = (s16) (regData & 0xFFFF);
|
||||
*snr = (s16) (regData & 0xFFFF); /* 100x dB */
|
||||
p->cnr.len = 1;
|
||||
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
p->cnr.stat[0].svalue = 10 * (s64) *snr;
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u32 reg[8], reg2[4];
|
||||
int stat;
|
||||
|
||||
*ber = 0;
|
||||
|
||||
mutex_lock(&state->base->status_lock);
|
||||
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
|
||||
stat = read_register_block(state,
|
||||
(HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET +
|
||||
HYDRA_DMD_STATUS_OFFSET(state->demod)),
|
||||
(7 * sizeof(u32)),
|
||||
(u8 *) ®[0]);
|
||||
stat = read_register_block(
|
||||
state,
|
||||
(HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET +
|
||||
HYDRA_DMD_STATUS_OFFSET(state->demod)),
|
||||
(4 * sizeof(u32)),
|
||||
(u8 *) ®2[0]);
|
||||
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
|
||||
mutex_unlock(&state->base->status_lock);
|
||||
|
||||
|
||||
switch (p->delivery_system) {
|
||||
case SYS_DSS:
|
||||
break;
|
||||
case SYS_DVBS:
|
||||
p->pre_bit_error.len = 1;
|
||||
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
|
||||
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];
|
||||
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;
|
||||
}
|
||||
pr_debug("mxl5xx: ber %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
reg[0], reg[1], reg[2], reg[3], reg[4], reg[5], reg[6]);
|
||||
pr_debug("mxl5xx: ber2 %08x %08x %08x %08x\n",
|
||||
reg[0], reg[1], reg[2], reg[3]);
|
||||
//pre_bit_error, pre_bit_count
|
||||
//post_bit_error, post_bit_count;
|
||||
//block_error block_count;
|
||||
//reset_fec_counter(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
int stat;
|
||||
u32 regData = 0;
|
||||
|
||||
#if 0
|
||||
if (!firmware_is_alive(state))
|
||||
pr_info("FW dead!\n");
|
||||
#endif
|
||||
mutex_lock(&state->base->status_lock);
|
||||
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
|
||||
stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR +
|
||||
@@ -629,7 +702,10 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
®Data);
|
||||
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
|
||||
mutex_unlock(&state->base->status_lock);
|
||||
*strength = (u16) (regData & 0xFFFF);
|
||||
*strength = (u16) (regData & 0xFFFF); /* 10x dBm */
|
||||
p->strength.len = 1;
|
||||
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
p->strength.stat[0].svalue = 10 * (s64) (s16) (regData & 0xFFFF);
|
||||
return stat;
|
||||
}
|
||||
|
||||
@@ -638,17 +714,105 @@ static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe)
|
||||
static int get_stats(struct dvb_frontend *fe)
|
||||
{
|
||||
//struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u16 val;
|
||||
u32 val32;
|
||||
|
||||
read_signal_strength(fe, &val);
|
||||
read_snr(fe, &val);
|
||||
read_ber(fe, &val32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum fe_code_rate conv_fec(MXL_HYDRA_FEC_E fec)
|
||||
{
|
||||
enum fe_code_rate fec2fec[11] = {
|
||||
FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3,
|
||||
FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7,
|
||||
FEC_7_8, FEC_8_9, FEC_9_10
|
||||
};
|
||||
|
||||
if (fec > MXL_HYDRA_FEC_9_10)
|
||||
return FEC_NONE;
|
||||
return fec2fec[fec];
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE];
|
||||
u32 freq;
|
||||
int stat;
|
||||
|
||||
mutex_lock(&state->base->status_lock);
|
||||
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
|
||||
stat = read_register_block(state,
|
||||
(HYDRA_DMD_STANDARD_ADDR_OFFSET +
|
||||
HYDRA_DMD_STATUS_OFFSET(state->demod)),
|
||||
(MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), // 25 * 4 bytes
|
||||
(u8 *) ®Data[0]);
|
||||
// read demod channel parameters
|
||||
stat = read_register_block(state,
|
||||
(HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR +
|
||||
HYDRA_DMD_STATUS_OFFSET(state->demod)),
|
||||
(4), // 4 bytes
|
||||
(u8 *) &freq);
|
||||
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
|
||||
mutex_unlock(&state->base->status_lock);
|
||||
|
||||
pr_debug("mxl5xx: freq=%u delsys=%u srate=%u\n",
|
||||
freq * 1000, regData[DMD_STANDARD_ADDR],
|
||||
regData[DMD_SYMBOL_RATE_ADDR]);
|
||||
p->symbol_rate = regData[DMD_SYMBOL_RATE_ADDR];
|
||||
p->frequency = freq;
|
||||
//p->delivery_system = (MXL_HYDRA_BCAST_STD_E )regData[DMD_STANDARD_ADDR];
|
||||
//p->inversion = (MXL_HYDRA_SPECTRUM_E )regData[DMD_SPECTRUM_INVERSION_ADDR];
|
||||
//freqSearchRangeKHz = (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]);
|
||||
|
||||
p->fec_inner = conv_fec(regData[DMD_FEC_CODE_RATE_ADDR]);
|
||||
switch (p->delivery_system) {
|
||||
case SYS_DSS:
|
||||
break;
|
||||
case SYS_DVBS:
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
switch ((MXL_HYDRA_PILOTS_E )
|
||||
regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) {
|
||||
case MXL_HYDRA_PILOTS_OFF:
|
||||
p->pilot = PILOT_OFF;
|
||||
break;
|
||||
case MXL_HYDRA_PILOTS_ON:
|
||||
p->pilot = PILOT_ON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case SYS_DVBS:
|
||||
switch ((MXL_HYDRA_MODULATION_E)
|
||||
regData[DMD_MODULATION_SCHEME_ADDR]) {
|
||||
case MXL_HYDRA_MOD_QPSK:
|
||||
p->modulation = QPSK;
|
||||
break;
|
||||
case MXL_HYDRA_MOD_8PSK:
|
||||
p->modulation = PSK_8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch ((MXL_HYDRA_ROLLOFF_E)
|
||||
regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) {
|
||||
case MXL_HYDRA_ROLLOFF_0_20:
|
||||
p->rolloff = ROLLOFF_20;
|
||||
break;
|
||||
case MXL_HYDRA_ROLLOFF_0_35:
|
||||
p->rolloff = ROLLOFF_35;
|
||||
break;
|
||||
case MXL_HYDRA_ROLLOFF_0_25:
|
||||
p->rolloff = ROLLOFF_25;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -661,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 = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.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 |
|
||||
@@ -692,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,
|
||||
};
|
||||
|
||||
@@ -749,12 +918,14 @@ static int write_fw_segment(struct mxl *state,
|
||||
u32 origSize = 0;
|
||||
u8 *wBufPtr = NULL;
|
||||
u32 blockSize = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
|
||||
(MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4;
|
||||
(MXL_HYDRA_I2C_HDR_SIZE +
|
||||
MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4;
|
||||
u8 wMsgBuffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
|
||||
(MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)];
|
||||
|
||||
do {
|
||||
size = origSize = (((u32)(dataCount + blockSize)) > totalSize) ?
|
||||
size = origSize =
|
||||
(((u32)(dataCount + blockSize)) > totalSize) ?
|
||||
(totalSize - dataCount) : blockSize;
|
||||
|
||||
if (origSize & 3)
|
||||
@@ -775,8 +946,8 @@ static int write_fw_segment(struct mxl *state,
|
||||
return status;
|
||||
}
|
||||
|
||||
static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr, u32 mbinBufferSize)
|
||||
|
||||
static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr,
|
||||
u32 mbinBufferSize)
|
||||
{
|
||||
int status;
|
||||
u32 index = 0;
|
||||
@@ -801,26 +972,31 @@ static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr, u32 mbinBu
|
||||
__func__, segmentPtr->header.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
segLength = get_big_endian(24, &(segmentPtr->header.len24[0]));
|
||||
segAddress = get_big_endian(32, &(segmentPtr->header.address[0]));
|
||||
segLength = get_big_endian(24,
|
||||
&(segmentPtr->header.len24[0]));
|
||||
segAddress = get_big_endian(32,
|
||||
&(segmentPtr->header.address[0]));
|
||||
|
||||
if (state->base->type == MXL_HYDRA_DEVICE_568) {
|
||||
if ((((segAddress & 0x90760000) == 0x90760000) ||
|
||||
((segAddress & 0x90740000) == 0x90740000)) &&
|
||||
(xcpuFwFlag == MXL_FALSE)) {
|
||||
SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 1);
|
||||
SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N,
|
||||
1);
|
||||
msleep(200);
|
||||
write_register(state, 0x90720000, 0);
|
||||
msleep(10);
|
||||
xcpuFwFlag = MXL_TRUE;
|
||||
}
|
||||
status = write_fw_segment(state, segAddress,
|
||||
segLength, (u8 *) segmentPtr->data);
|
||||
segLength,
|
||||
(u8 *) segmentPtr->data);
|
||||
} else {
|
||||
if (((segAddress & 0x90760000) != 0x90760000) &&
|
||||
((segAddress & 0x90740000) != 0x90740000))
|
||||
status = write_fw_segment(state, segAddress,
|
||||
segLength, (u8 *) segmentPtr->data);
|
||||
segLength,
|
||||
(u8 *) segmentPtr->data);
|
||||
}
|
||||
if (status)
|
||||
return status;
|
||||
@@ -883,14 +1059,17 @@ static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len)
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Disable clock to Baseband, Wideband, SerDes, Alias ext & Transport modules */
|
||||
status = write_register(state, HYDRA_MODULES_CLK_2_REG, HYDRA_DISABLE_CLK_2);
|
||||
/* Disable clock to Baseband, Wideband, SerDes,
|
||||
Alias ext & Transport modules */
|
||||
status = write_register(state, HYDRA_MODULES_CLK_2_REG,
|
||||
HYDRA_DISABLE_CLK_2);
|
||||
if (status)
|
||||
return status;
|
||||
/* Clear Software & Host interrupt status - (Clear on read) */
|
||||
status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, ®Data);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = do_firmware_download(state, mbin, mbin_len);
|
||||
if (status)
|
||||
return status;
|
||||
@@ -925,15 +1104,15 @@ 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 */
|
||||
/* sometimes register values are wrong shortly
|
||||
after first heart beats */
|
||||
msleep(50);
|
||||
|
||||
devSkuCfg.skuType = state->base->sku_type;
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE,
|
||||
cmdSize, &devSkuCfg, cmdBuff);
|
||||
status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
|
||||
status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||
&cmdBuff[0]);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -963,19 +1142,32 @@ static int cfg_ts_pad_mux(struct mxl *state, MXL_BOOL_E enableSerialTS)
|
||||
case MXL_HYDRA_DEVICE_541S:
|
||||
case MXL_HYDRA_DEVICE_561S:
|
||||
case MXL_HYDRA_DEVICE_581S:
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL,
|
||||
padMuxValue);
|
||||
break;
|
||||
|
||||
case MXL_HYDRA_DEVICE_544:
|
||||
@@ -1159,7 +1351,7 @@ static int enable_tuner(struct mxl *state, u32 tuner, u32 enable)
|
||||
if (!count)
|
||||
return -1;
|
||||
read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val);
|
||||
pr_info("mxl5xx: tuner %u ready = %u\n", tuner , (val >> tuner) & 1);
|
||||
/*pr_info("mxl5xx: tuner %u ready = %u\n", tuner , (val >> tuner) & 1);*/
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -1194,8 +1386,10 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
|
||||
{XPT_TS_CLK_PHASE4}, {XPT_TS_CLK_PHASE5},
|
||||
{XPT_TS_CLK_PHASE6}, {XPT_TS_CLK_PHASE7} };
|
||||
MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = {
|
||||
{XPT_LSB_FIRST0}, {XPT_LSB_FIRST1}, {XPT_LSB_FIRST2}, {XPT_LSB_FIRST3},
|
||||
{XPT_LSB_FIRST4}, {XPT_LSB_FIRST5}, {XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} };
|
||||
{XPT_LSB_FIRST0}, {XPT_LSB_FIRST1},
|
||||
{XPT_LSB_FIRST2}, {XPT_LSB_FIRST3},
|
||||
{XPT_LSB_FIRST4}, {XPT_LSB_FIRST5},
|
||||
{XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} };
|
||||
MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = {
|
||||
{XPT_SYNC_FULL_BYTE0}, {XPT_SYNC_FULL_BYTE1},
|
||||
{XPT_SYNC_FULL_BYTE2}, {XPT_SYNC_FULL_BYTE3},
|
||||
@@ -1227,19 +1421,22 @@ 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},
|
||||
{PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL} };
|
||||
{PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL}};
|
||||
MXL_REG_FIELD_T mxl561_xpt_ts_valid[MXL_HYDRA_DEMOD_ID_6] = {
|
||||
{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} };
|
||||
{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}};
|
||||
#endif
|
||||
|
||||
demodId = state->base->ts_map[demodId];
|
||||
|
||||
if (MXL_ENABLE == mpegOutParamPtr->enable) {
|
||||
if (mpegOutParamPtr->mpegMode == MXL_HYDRA_MPEG_MODE_PARALLEL) {
|
||||
if (mpegOutParamPtr->mpegMode ==
|
||||
MXL_HYDRA_MPEG_MODE_PARALLEL) {
|
||||
#if 0
|
||||
for (i = MXL_HYDRA_DEMOD_ID_0; i < MXL_HYDRA_DEMOD_MAX; i++) {
|
||||
mxlStatus |= MxLWare_Hydra_UpdateByMnemonic(devId,
|
||||
@@ -1373,11 +1570,12 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
|
||||
}
|
||||
|
||||
if (mpegOutParamPtr->mpegMode != MXL_HYDRA_MPEG_MODE_PARALLEL) {
|
||||
status |= update_by_mnemonic(state,
|
||||
xpt_enable_output[demodId].regAddr,
|
||||
xpt_enable_output[demodId].lsbPos,
|
||||
xpt_enable_output[demodId].numOfBits,
|
||||
mpegOutParamPtr->enable);
|
||||
status |=
|
||||
update_by_mnemonic(state,
|
||||
xpt_enable_output[demodId].regAddr,
|
||||
xpt_enable_output[demodId].lsbPos,
|
||||
xpt_enable_output[demodId].numOfBits,
|
||||
mpegOutParamPtr->enable);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1397,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;
|
||||
@@ -1415,8 +1614,10 @@ static int config_dis(struct mxl *state, u32 id)
|
||||
|
||||
BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_CFG_MSG_CMD,
|
||||
MXL_CMD_WRITE, cmdSize, &diseqcMsg, cmdBuff);
|
||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
|
||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||
&cmdBuff[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)
|
||||
{
|
||||
@@ -1442,7 +1643,7 @@ static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)
|
||||
|
||||
static int validate_sku(struct mxl *state)
|
||||
{
|
||||
u32 padMuxBond, prcmChipId, prcmSoCId;
|
||||
u32 padMuxBond = 0, prcmChipId = 0, prcmSoCId = 0;
|
||||
int status;
|
||||
u32 type = state->base->type;
|
||||
|
||||
@@ -1677,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;
|
||||
@@ -1717,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;
|
||||
|
||||
@@ -1732,4 +1937,4 @@ EXPORT_SYMBOL_GPL(mxl5xx_attach);
|
||||
|
||||
MODULE_DESCRIPTION("MXL5XX driver");
|
||||
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,5 @@ struct stv0367_cfg {
|
||||
|
||||
|
||||
extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
|
||||
struct stv0367_cfg *cfg,
|
||||
struct dvb_frontend **fe_t);
|
||||
struct stv0367_cfg *cfg);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user