51 Commits

Author SHA1 Message Date
Ralph Metzler
ce99c601f8 new release version 0.9.34 2018-07-24 11:58:02 +02:00
Ralph Metzler
43ab548777 Ensure CAM stability after reset
Wait 2 secs in low level CI reset function as some CAMs become crazy
if we talk to them just after the reset (SmarDTV / TDT Premium).

from: faudebert-anevia authored and Richard Bérichon committed on Apr 2, 2012
2018-07-20 13:18:27 +02:00
Ralph Metzler
2808cf0d50 increase maximum number of minors 2018-07-18 09:45:07 +02:00
Ralph Metzler
186ba6d414 change clock phase to prevent cross-talk on some hardware
(this value is better than the previously suggested change to 0xe0)
2018-07-18 09:41:24 +02:00
Ralph Metzler
f570b2e071 add more frontend statistics 2018-06-29 12:48:12 +02:00
Ralph Metzler
32f46389be adjust to latest MCI upstream drivers 2018-06-23 16:52:22 +02:00
Ralph Metzler
4b68bcad91 add MaxM4 ID 2018-06-23 16:47:10 +02:00
Ralph Metzler
1ad4dfacd1 remove leftover smp_load_acquire() for older kernels 2018-06-23 16:46:00 +02:00
Ralph Metzler
f7772c7a88 allow fmode 4 2018-06-23 16:44:16 +02:00
Ralph Metzler
6219e19ece add support for MaxM4 2018-06-23 16:43:29 +02:00
Ralph Metzler
192a4ad20d add wrappers to pacify Sparse 2018-05-28 16:41:11 +02:00
Ralph Metzler
e13cec82e4 Return correct frequency
Signed-off-by: Julian Scheel <julian@jusst.de>
2018-05-28 16:40:43 +02:00
Ralph Metzler
d13416157c remove unused offs 2018-05-28 16:40:02 +02:00
Ralph Metzler
755f502602 set array size to 4 2018-05-28 16:39:42 +02:00
Ralph Metzler
a05d1852a3 Set modulation to QPSK for DVB-S
Signed-off-by: Julian Scheel <julian@jusst.de>
2018-05-28 16:39:21 +02:00
Ralph Metzler
1e15f5474d add templX for sensors on GT link cards 2018-05-25 23:05:26 +02:00
Ralph Metzler
9c1fc648dc stop frontend on sleep and input changes 2018-05-25 23:04:25 +02:00
Ralph Metzler
2e5056c4a1 add temperature attribute for MCI cards 2018-05-25 00:12:31 +02:00
Ralph Metzler
1b89edb4b1 missing parts of previous patch 2018-05-25 00:11:03 +02:00
Ralph Metzler
875a768266 properly support frontend input switching for MAX SX8 2018-05-25 00:09:50 +02:00
Ralph Metzler
09c068c74c remove wrong strength conversion 2018-05-25 00:08:27 +02:00
Ralph Metzler
c471123f17 style cleanup 2018-05-24 11:04:59 +02:00
Ralph Metzler
8dbd33fd82 - make 8PSK/QPSK default (for AUTO mode)
- when selecting modulation, also enable all lower modulations
2018-05-24 11:03:45 +02:00
Ralph Metzler
a978e9455f disable automatic code search 2018-05-18 14:47:19 +02:00
Ralph Metzler
9d8c7d4a63 - separate MCI and SX8 code
- move SX8 code to ddbridge-sx8.c
- adjust SX8 code to latest version from upstream
- add file with skeleton driver for M4
2018-05-15 23:01:39 +02:00
Ralph Metzler
81ed8fed9d change first MCI id value and use seperate ids for each type of MCI card 2018-05-14 04:30:58 +02:00
Ralph Metzler
f24a329f2f remove debug message 2018-05-14 04:27:55 +02:00
Ralph Metzler
5d7f4fcbe8 simplify link structure access 2018-05-14 04:26:51 +02:00
Ralph Metzler
6243397d99 add Octonet Pro 2018-05-14 04:08:21 +02:00
Ralph Metzler
5b86ac7627 limit link to 0-3 2018-05-02 15:45:00 +02:00
Ralph Metzler
c831ccfc9e add check for minimum FPGA firmware version 2018-05-02 15:39:09 +02:00
Ralph Metzler
cad161f939 enable net interface by default 2018-05-02 15:35:28 +02:00
Ralph Metzler
67257ce132 replace mdio_num with mdio_base 2018-04-11 21:20:25 +02:00
Ralph Metzler
bdea58c1b2 replace direct register based mdio with ioctl 2018-04-11 21:18:00 +02:00
Ralph Metzler
29eda9be8e add missing paranthesis 2018-04-09 14:42:39 +02:00
Ralph Metzler
2c3c9bdf08 comment out old debugging messages
can be removed soon
2018-04-07 20:21:58 +02:00
Ralph Metzler
2693c181bc new Octopus Net Pro flash layout 2018-04-07 20:21:15 +02:00
Ralph Metzler
53464162de detect LNBH address to prevent error message in driver 2018-04-07 20:17:38 +02:00
Ralph Metzler
8cbb835de0 add general make rule 2018-04-07 20:16:32 +02:00
Ralph Metzler
d0f7b9be1f uncomment send_burst for legacy hardware and replace some register setting
functions with new version.
2018-03-28 19:47:26 +02:00
Ralph Metzler
6b0feea253 add ULL 2018-03-28 19:46:31 +02:00
Ralph Metzler
bed4be534a add cast 2018-03-28 19:44:15 +02:00
Ralph Metzler
1d7d8bc413 report I2C bus errors 2018-03-28 19:43:04 +02:00
Ralph Metzler
70778b818e always assume adapter_alloc=3 for octopusnet pro 2018-03-28 19:42:03 +02:00
Ralph Metzler
e0fdedbef3 adjust to newer include files and firmware 2018-03-22 19:36:08 +01:00
Ralph Metzler
9acbf467ec add axplanations for bbframe mode 2018-03-22 19:33:35 +01:00
Ralph Metzler
3db30defab use correct MODULE_LINCESE for GPL v2 only according to notice in header 2018-03-22 19:32:17 +01:00
Ralph Metzler
5bf9edba06 add entry for M4 2018-03-22 19:30:45 +01:00
Ralph Metzler
8f0365e36a add file with GPLv2 2018-03-22 19:20:29 +01:00
Ralph Metzler
08a161ba04 remove old code 2018-03-20 22:37:13 +01:00
Ralph Metzler
efbc108939 check on correct link instead of link 0 2018-03-20 22:36:20 +01:00
36 changed files with 2334 additions and 725 deletions

339
COPYING.GPLv2 Normal file
View 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.

View File

@@ -2,7 +2,8 @@ kernelver ?= $(shell uname -r)
KDIR ?= /lib/modules/$(kernelver)/build
PWD := $(shell pwd)
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=m
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules

View File

@@ -15,14 +15,6 @@ setmod2: setmod2.c
setmod3: setmod3.c
$(CC) -o setmod3 setmod3.c -I../include/
flashprog: flashprog.c
$(CC) -o flashprog flashprog.c
%.o: %.c
$(CC) $(CFLAGS) -o $@ $<
ddtest: ddtest.c
$(CC) -o ddtest ddtest.c
ddflash: ddflash.c
$(CC) -o ddflash ddflash.c
pls: pls.c
$(CC) -o pls pls.c

View File

@@ -233,6 +233,10 @@ int main(int argc, char **argv)
fname="DVBBridgeV2A_DD01_0009_SX8.fpga";
printf("Octopus MAXSX8\n");
break;
case 0x000a:
fname="DVBBridgeV2A_DD01_000A_M4.fpga";
printf("Octopus MAXSX8\n");
break;
case 0x0011:
fname="CIBridgeV1B_CIBridgeV1B.fpga";
printf("Octopus CI\n");

View File

@@ -659,6 +659,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;
}

View File

@@ -722,9 +722,10 @@ int mdio(int dev, int argc, char* argv[], uint32_t Flags)
adr = strtoul(argv[0], NULL, 16);
reg = strtoul(argv[1], NULL, 16);
#if 0
writereg(dev, 0x24, adr);
writereg(dev, 0x28, reg);
if(argc > 2) {
if (argc > 2) {
val = strtoul(argv[2], NULL, 16);
writereg(dev, 0x2c, val);
writereg(dev, 0x20, 0x03);
@@ -739,6 +740,23 @@ int mdio(int dev, int argc, char* argv[], uint32_t Flags)
readreg(dev, 0x2c, &val);
printf("%04x\n", val);
}
#else
{
struct ddb_mdio mdio = {
.adr = adr,
.reg = reg,
};
if(argc > 2) {
mdio.val = strtoul(argv[2], NULL, 16);
return ioctl(dev, IOCTL_DDB_WRITE_MDIO, &mdio);
} else {
if (ioctl(dev, IOCTL_DDB_READ_MDIO, &mdio) < 0)
return -1;
printf("%04x\n", mdio.val);
}
}
#endif
return 0;
}

View File

@@ -1,7 +1,7 @@
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
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o
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-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o

View File

@@ -2,8 +2,8 @@
# Makefile for the ddbridge device driver
#
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o

View File

@@ -2,8 +2,8 @@
# Makefile for the ddbridge device driver
#
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o
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-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o

View File

@@ -26,7 +26,6 @@
#include "ddbridge-i2c.h"
#include "ddbridge-io.h"
#include "dvb_net.h"
#include "ddbridge-mci.h"
struct workqueue_struct *ddb_wq;
@@ -450,13 +449,12 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags)
*con2 = (nco << 16) | gap;
}
static void ddb_output_start(struct ddb_output *output)
static void ddb_output_start_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
u32 con = 0x11c, con2 = 0;
if (output->dma) {
spin_lock_irq(&output->dma->lock);
output->dma->cbuf = 0;
output->dma->coff = 0;
output->dma->stat = 0;
@@ -486,16 +484,24 @@ static void ddb_output_start(struct ddb_output *output)
ddbwritel(dev, con | 1, TS_CONTROL(output));
if (output->dma) {
output->dma->running = 1;
spin_unlock_irq(&output->dma->lock);
}
}
static void ddb_output_stop(struct ddb_output *output)
static void ddb_output_start(struct ddb_output *output)
{
if (output->dma) {
spin_lock_irq(&output->dma->lock);
ddb_output_start_unlocked(output);
spin_unlock_irq(&output->dma->lock);
} else {
ddb_output_start_unlocked(output);
}
}
static void ddb_output_stop_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
if (output->dma)
spin_lock_irq(&output->dma->lock);
if (output->port->class == DDB_PORT_MOD)
ddbridge_mod_output_stop(output);
else
@@ -503,34 +509,49 @@ static void ddb_output_stop(struct ddb_output *output)
if (output->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
output->dma->running = 0;
spin_unlock_irq(&output->dma->lock);
}
}
static void ddb_input_stop(struct ddb_input *input)
static void ddb_output_stop(struct ddb_output *output)
{
if (output->dma) {
spin_lock_irq(&output->dma->lock);
ddb_output_stop_unlocked(output);
spin_unlock_irq(&output->dma->lock);
} else {
ddb_output_stop_unlocked(output);
}
}
static void ddb_input_stop_unlocked(struct ddb_input *input)
{
struct ddb *dev = input->port->dev;
u32 tag = DDB_LINK_TAG(input->port->lnr);
if (input->dma)
spin_lock_irq(&input->dma->lock);
ddbwritel(dev, 0, tag | TS_CONTROL(input));
if (input->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma));
input->dma->running = 0;
spin_unlock_irq(&input->dma->lock);
}
/*printk("input_stop %u.%u.%u\n",
* dev->nr, input->port->lnr, input->nr);
*/
}
static void ddb_input_start(struct ddb_input *input)
static void ddb_input_stop(struct ddb_input *input)
{
if (input->dma) {
spin_lock_irq(&input->dma->lock);
ddb_input_stop_unlocked(input);
spin_unlock_irq(&input->dma->lock);
} else {
ddb_input_stop_unlocked(input);
}
}
static void ddb_input_start_unlocked(struct ddb_input *input)
{
struct ddb *dev = input->port->dev;
if (input->dma) {
spin_lock_irq(&input->dma->lock);
input->dma->cbuf = 0;
input->dma->coff = 0;
input->dma->stat = 0;
@@ -555,7 +576,17 @@ static void ddb_input_start(struct ddb_input *input)
ddbwritel(dev, 0x000fff01, TS_CONTROL2(input));
if (input->dma) {
input->dma->running = 1;
}
}
static void ddb_input_start(struct ddb_input *input)
{
if (input->dma) {
spin_lock_irq(&input->dma->lock);
ddb_input_start_unlocked(input);
spin_unlock_irq(&input->dma->lock);
} else {
ddb_input_start_unlocked(input);
}
}
@@ -1371,11 +1402,19 @@ static struct stv0910_cfg stv0910_p = {
.clk = 30000000,
};
static int has_lnbh25(struct i2c_adapter *i2c, u8 adr)
{
u8 val;
return i2c_read_reg(i2c, adr, 0, &val) ? 0 : 1;
}
static int demod_attach_stv0910(struct ddb_input *input, int type)
{
struct i2c_adapter *i2c = &input->port->i2c->adap;
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
struct stv0910_cfg cfg = stv0910_p;
u8 lnbh_adr = 0x08;
if (stv0910_single)
cfg.single = 1;
@@ -1392,14 +1431,14 @@ static int demod_attach_stv0910(struct ddb_input *input, int type)
"No STV0910 found!\n");
return -ENODEV;
}
if (has_lnbh25(i2c, 0x0d))
lnbh_adr = 0x0c;
if (!dvb_attach(lnbh25_attach, dvb->fe, i2c,
((input->nr & 1) ? 0x0d : 0x0c))) {
if (!dvb_attach(lnbh25_attach, dvb->fe, i2c,
((input->nr & 1) ? 0x09 : 0x08))) {
dev_err(input->port->dev->dev,
"No LNBH25 found!\n");
return -ENODEV;
}
(input->nr & 1) + lnbh_adr)) {
dev_err(input->port->dev->dev,
"No LNBH25 found!\n");
return -ENODEV;
}
return 0;
}
@@ -1521,7 +1560,8 @@ static int dvb_register_adapters(struct ddb *dev)
struct dvb_adapter *adap;
if (adapter_alloc == 3 || dev->link[0].info->type == DDB_MOD ||
dev->link[0].info->type == DDB_OCTONET) {
dev->link[0].info->type == DDB_OCTONET ||
dev->link[0].info->type == DDB_OCTOPRO ) {
port = &dev->port[0];
adap = port->dvb[0].adap;
ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
@@ -1757,8 +1797,9 @@ static int dvb_input_attach(struct ddb_input *input)
if (demod_attach_dummy(input) < 0)
return -ENODEV;
break;
case DDB_TUNER_MCI:
if (ddb_fe_attach_mci(input) < 0)
case DDB_TUNER_MCI_SX8:
case DDB_TUNER_MCI_M4:
if (ddb_fe_attach_mci(input, port->type) < 0)
return -ENODEV;
break;
default:
@@ -1996,6 +2037,7 @@ static void ddb_port_probe(struct ddb_port *port)
{
struct ddb *dev = port->dev;
u32 l = port->lnr;
struct ddb_link *link = &dev->link[l];
u8 id, type;
port->name = "NO MODULE";
@@ -2005,7 +2047,7 @@ static void ddb_port_probe(struct ddb_port *port)
/* Handle missing ports and ports without I2C */
if (dummy_tuner && !port->nr &&
dev->link[0].ids.device == 0x0005) {
link->ids.device == 0x0005) {
port->name = "DUMMY";
port->class = DDB_PORT_TUNER;
port->type = DDB_TUNER_DUMMY;
@@ -2020,7 +2062,7 @@ static void ddb_port_probe(struct ddb_port *port)
}
if (port->nr == 1 && dev->link[l].info->type == DDB_OCTOPUS_CI &&
dev->link[l].info->i2c_mask == 1) {
link->info->i2c_mask == 1) {
port->name = "NO TAB";
port->class = DDB_PORT_NONE;
return;
@@ -2032,7 +2074,7 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
#if 0
if (dev->link[l].info->type == DDB_OCTOPRO_HDIN) {
if (link->info->type == DDB_OCTOPRO_HDIN) {
if (port->nr == 0) {
dev->link[l].info->type = DDB_OCTOPUS;
port->name = "HDIN";
@@ -2041,7 +2083,7 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
#endif
if (dev->link[l].info->type == DDB_OCTOPUS_MAX) {
if (link->info->type == DDB_OCTOPUS_MAX) {
port->name = "DUAL DVB-S2 MAX";
port->type_name = "MXL5XX";
port->class = DDB_PORT_TUNER;
@@ -2052,17 +2094,17 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (dev->link[l].info->type == DDB_OCTOPUS_MCI) {
if (port->nr >= dev->link[l].info->mci)
if (link->info->type == DDB_OCTOPUS_MCI) {
if (port->nr >= link->info->mci_ports)
return;
port->name = "DUAL MCI";
port->type_name = "MCI";
port->class = DDB_PORT_TUNER;
port->type = DDB_TUNER_MCI;
port->type = DDB_TUNER_MCI + link->info->mci_type;
return;
}
if (port->nr > 1 && dev->link[l].info->type == DDB_OCTOPUS_CI) {
if (port->nr > 1 && link->info->type == DDB_OCTOPUS_CI) {
port->name = "CI internal";
port->type_name = "INTERNAL";
port->class = DDB_PORT_CI;
@@ -2147,7 +2189,7 @@ static void ddb_port_probe(struct ddb_port *port)
port->class = DDB_PORT_TUNER;
if (id == 0x51) {
if (port->nr == 0 &&
dev->link[l].info->ts_quirks & TS_QUIRK_REVERSED)
link->info->ts_quirks & TS_QUIRK_REVERSED)
port->type = DDB_TUNER_DVBS_STV0910_PR;
else
port->type = DDB_TUNER_DVBS_STV0910_P;
@@ -2320,11 +2362,6 @@ static void input_write_dvb(struct ddb_input *input,
if (alt_dma)
dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
dma2->size, DMA_FROM_DEVICE);
#if 0
dev_info(dev->dev, "%02x %02x %02x %02x\n",
dma2->vbuf[dma->cbuf][0], dma2->vbuf[dma->cbuf][1],
dma2->vbuf[dma->cbuf][2], dma2->vbuf[dma->cbuf][3]);
#endif
dvb_dmx_swfilter_packets(&dvb->demux,
dma2->vbuf[dma->cbuf],
dma2->size / 188);
@@ -2522,8 +2559,10 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
dma->div = 1;
}
ddbwritel(io->port->dev, 0, DMA_BUFFER_ACK(dma));
#if 0
dev_info(io->port->dev->dev, "init link %u, io %u, dma %u, dmaregs %08x bufregs %08x\n",
io->port->lnr, io->nr, nr, dma->regs, dma->bufregs);
#endif
}
static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
@@ -2548,8 +2587,10 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
if (port->lnr)
dma_nr += 32 + (port->lnr - 1) * 8;
#if 0
dev_info(dev->dev, "init link %u, input %u, handler %u\n",
port->lnr, nr, dma_nr + base);
#endif
ddb_irq_set(dev, 0, dma_nr + base, &input_handler, input);
ddb_dma_init(input, dma_nr, 0, dma_nr + base);
}
@@ -2567,8 +2608,10 @@ static void ddb_output_init(struct ddb_port *port, int nr)
rm = io_regmap(output, 1);
output->regs = DDB_LINK_TAG(port->lnr) |
(rm->output->base + rm->output->size * nr);
#if 0
dev_info(dev->dev, "init link %u, output %u, regs %08x\n",
port->lnr, nr, output->regs);
#endif
if (dev->has_dma) {
const struct ddb_regmap *rm0 = io_regmap(output, 0);
u32 base = rm0->irq_base_odma;
@@ -3174,25 +3217,25 @@ int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len)
return flashio(dev, link, cmd, 4, buf, len);
}
static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val)
static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val, u32 mdio_base)
{
ddbwritel(dev, adr, MDIO_ADR);
ddbwritel(dev, reg, MDIO_REG);
ddbwritel(dev, val, MDIO_VAL);
ddbwritel(dev, 0x03, MDIO_CTRL);
while (ddbreadl(dev, MDIO_CTRL) & 0x02)
ddbwritel(dev, adr, MDIO_ADR_OFF + mdio_base);
ddbwritel(dev, reg, MDIO_REG_OFF + mdio_base);
ddbwritel(dev, val, MDIO_VAL_OFF + mdio_base);
ddbwritel(dev, 0x03, MDIO_CTRL_OFF + mdio_base);
while (ddbreadl(dev, MDIO_CTRL_OFF + mdio_base) & 0x02)
ndelay(500);
return 0;
}
static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg)
static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg, u32 mdio_base)
{
ddbwritel(dev, adr, MDIO_ADR);
ddbwritel(dev, reg, MDIO_REG);
ddbwritel(dev, 0x07, MDIO_CTRL);
while (ddbreadl(dev, MDIO_CTRL) & 0x02)
ddbwritel(dev, adr, MDIO_ADR_OFF + mdio_base);
ddbwritel(dev, reg, MDIO_REG_OFF + mdio_base);
ddbwritel(dev, 0x07, MDIO_CTRL_OFF + mdio_base);
while (ddbreadl(dev, MDIO_CTRL_OFF + mdio_base) & 0x02)
ndelay(500);
return ddbreadl(dev, MDIO_VAL);
return ddbreadl(dev, MDIO_VAL_OFF + mdio_base);
}
#define DDB_MAGIC 'd'
@@ -3368,12 +3411,13 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case IOCTL_DDB_READ_MDIO:
{
struct ddb_mdio mdio;
u32 mdio_base = dev->link[0].info->mdio_base;
if (!dev->link[0].info->mdio_num)
if (!mdio_base)
return -EIO;
if (copy_from_user(&mdio, parg, sizeof(mdio)))
return -EFAULT;
mdio.val = mdio_read(dev, mdio.adr, mdio.reg);
mdio.val = mdio_read(dev, mdio.adr, mdio.reg, mdio_base);
if (copy_to_user(parg, &mdio, sizeof(mdio)))
return -EFAULT;
break;
@@ -3381,12 +3425,13 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case IOCTL_DDB_WRITE_MDIO:
{
struct ddb_mdio mdio;
u32 mdio_base = dev->link[0].info->mdio_base;
if (!dev->link[0].info->mdio_num)
if (!mdio_base)
return -EIO;
if (copy_from_user(&mdio, parg, sizeof(mdio)))
return -EFAULT;
mdio_write(dev, mdio.adr, mdio.reg, mdio.val);
mdio_write(dev, mdio.adr, mdio.reg, mdio.val, mdio_base);
break;
}
case IOCTL_DDB_READ_MEM:
@@ -3565,13 +3610,18 @@ static ssize_t temp_show(struct device *device,
struct device_attribute *attr, char *buf)
{
struct ddb *dev = dev_get_drvdata(device);
struct ddb_link *link = &dev->link[0];
struct ddb_link *link;
struct i2c_adapter *adap;
s32 temp, temp2, temp3;
int i;
u8 tmp[2];
int l = 0;
if (link->info->type == DDB_MOD) {
if (attr->attr.name[4] == 'l')
l = attr->attr.name[5] - 0x30;
link = &dev->link[l];
if (link->info->type == DDB_MOD ) {
if (link->info->version >= 2) {
temp = 0xffff & ddbreadl(dev, TEMPMON2_BOARD);
temp = (temp * 1000) >> 8;
@@ -3601,6 +3651,12 @@ static ssize_t temp_show(struct device *device,
}
return sprintf(buf, "%d %d\n", temp, temp2);
}
if (link->info->type == DDB_OCTOPUS_MCI) {
temp = 0xffff & ddblreadl(link, TEMPMON_SENSOR0);
temp = (temp * 1000) >> 8;
return sprintf(buf, "%d\n", temp);
}
if (!link->info->temp_num)
return sprintf(buf, "no sensor\n");
adap = &dev->i2c[link->info->temp_bus].adap;
@@ -3971,7 +4027,7 @@ static ssize_t fmode_store(struct device *device, struct device_attribute *attr,
if (sscanf(buf, "%u\n", &val) != 1)
return -EINVAL;
if (val > 3)
if (val > 4)
return -EINVAL;
ddb_lnb_init_fmode(dev, &dev->link[num], val);
return count;
@@ -4011,7 +4067,10 @@ static struct device_attribute ddb_attrs[] = {
};
static struct device_attribute ddb_attrs_temp[] = {
__ATTR_RO(temp),
__ATTR_MRO(temp, temp_show),
__ATTR_MRO(templ1, temp_show),
__ATTR_MRO(templ2, temp_show),
__ATTR_MRO(templ3, temp_show),
};
static struct device_attribute ddb_attrs_mod[] = {
@@ -4093,8 +4152,11 @@ static void ddb_device_attrs_del(struct ddb *dev)
dev->link[i].info->tempmon_irq)
device_remove_file(dev->ddb_dev,
&ddb_attrs_fanspeed[i]);
for (i = 0; i < 4; i++)
if (dev->link[i].info &&
dev->link[i].info->temp_num)
device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]);
for (i = 0; i < dev->link[0].info->temp_num; i++)
device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]);
for (i = 0; i < dev->link[0].info->port_num; i++)
device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]);
for (i = 0; i < dev->link[0].info->fan_num; i++)
@@ -4116,9 +4178,11 @@ static int ddb_device_attrs_add(struct ddb *dev)
for (i = 0; ddb_attrs[i].attr.name; i++)
if (device_create_file(dev->ddb_dev, &ddb_attrs[i]))
goto fail;
for (i = 0; i < dev->link[0].info->temp_num; i++)
if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i]))
goto fail;
for (i = 0; i < 4; i++)
if (dev->link[i].info &&
dev->link[i].info->temp_num)
if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i]))
goto fail;
for (i = 0; (i < dev->link[0].info->port_num) && (i < 10); i++)
if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i]))
goto fail;

View File

@@ -336,6 +336,7 @@ static const struct ddb_info ddb_v7a = {
.board_control = 2,
.board_control_2 = 4,
.ts_quirks = TS_QUIRK_REVERSED,
.hw_min = 0x010007,
};
static const struct ddb_info ddb_v7 = {
@@ -347,6 +348,7 @@ static const struct ddb_info ddb_v7 = {
.board_control = 2,
.board_control_2 = 4,
.ts_quirks = TS_QUIRK_REVERSED,
.hw_min = 0x010007,
};
static const struct ddb_info ddb_ctv7 = {
@@ -391,6 +393,7 @@ static const struct ddb_info ddb_ci_s2_pro = {
.i2c_mask = 0x01,
.board_control = 2,
.board_control_2 = 4,
.hw_min = 0x010007,
};
static const struct ddb_info ddb_ci_s2_pro_a = {
@@ -401,6 +404,7 @@ static const struct ddb_info ddb_ci_s2_pro_a = {
.i2c_mask = 0x01,
.board_control = 2,
.board_control_2 = 4,
.hw_min = 0x010007,
};
static const struct ddb_info ddb_dvbct = {
@@ -489,7 +493,7 @@ static const struct ddb_info ddb_octopro_hdin = {
.regmap = &octopro_hdin_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.mdio_num = 1,
.mdio_base = 0x10020,
};
static const struct ddb_info ddb_octopro = {
@@ -498,7 +502,7 @@ static const struct ddb_info ddb_octopro = {
.regmap = &octopro_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.mdio_num = 1,
.mdio_base = 0x10020,
};
static const struct ddb_info ddb_s2_48 = {
@@ -578,7 +582,21 @@ static const struct ddb_info ddb_s2x_48 = {
.port_num = 4,
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci = 4,
.mci_ports = 4,
.mci_type = 0,
.temp_num = 1,
};
static const struct ddb_info ddb_m4 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M4",
.regmap = &octopus_map,
.port_num = 2,
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci_ports = 2,
.mci_type = 1,
.temp_num = 1,
};
/****************************************************************************/
@@ -617,7 +635,7 @@ static const struct ddb_info ddb_octonet = {
.port_num = 4,
.i2c_mask = 0x0f,
.ns_num = 12,
.mdio_num = 1,
.mdio_base = 0x20,
};
static const struct ddb_info ddb_octonet_jse = {
@@ -627,7 +645,7 @@ static const struct ddb_info ddb_octonet_jse = {
.port_num = 4,
.i2c_mask = 0x0f,
.ns_num = 15,
.mdio_num = 1,
.mdio_base = 0x20,
};
static const struct ddb_info ddb_octonet_gtl = {
@@ -637,7 +655,7 @@ static const struct ddb_info ddb_octonet_gtl = {
.port_num = 4,
.i2c_mask = 0x05,
.ns_num = 12,
.mdio_num = 1,
.mdio_base = 0x20,
.con_clock = 1,
};
@@ -693,6 +711,7 @@ static const struct ddb_device_id ddb_device_ids[] = {
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(0x0011, 0x0040, ddb_ci),
DDB_DEVID(0x0011, 0x0041, ddb_cis),
DDB_DEVID(0x0012, 0x0042, ddb_ci),

View File

@@ -63,7 +63,10 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
#endif
return -EIO;
}
if (val & 0x70000)
val &= 0x70000;
if (val == 0x20000)
dev_err(dev->dev, "I2C bus errorx\n");
if (val)
return -EIO;
return 0;
}

View File

@@ -62,7 +62,7 @@ u32 ddbreadl(struct ddb *dev, u32 adr)
{
if (unlikely(adr & 0xf0000000)) {
unsigned long flags;
u32 val, l = (adr >> DDB_LINK_SHIFT);
u32 val, l = (adr >> DDB_LINK_SHIFT) & 3;
struct ddb_link *link = &dev->link[l];
spin_lock_irqsave(&link->lock, flags);

449
ddbridge/ddbridge-m4.c Normal file
View File

@@ -0,0 +1,449 @@
/*
* 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-i2c.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;
struct mci_base *mci_base = state->mci.base;
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 mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_DVBS;
cmd.dvbs2_search.flags = 3;
cmd.dvbs2_search.s2_modulation_mask = 3;
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 = 0; //p->scrambling_sequence_index;
cmd.dvbs2_search.input_stream_id = p->stream_id;
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_c(struct dvb_frontend *fe)
{
struct m4 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_DVBC;
switch (p->bandwidth_hz) {
case 6000000:
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_6MHZ;
break;
case 7000000:
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_7MHZ;
break;
default:
cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_8MHZ;
break;
}
cmd.dvbc_search.retry = 2;
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 mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_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 = 2;
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_t2(struct dvb_frontend *fe)
{
struct m4 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
u32 flags = 0;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_DVBT2;
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 = 2;
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 mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
u32 flags = 0;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_DVBC2;
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 = 2;
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 mci_base *mci_base = state->mci.base;
struct m4_base *m4_base = (struct m4_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_command cmd;
int stat;
u32 flags = 0;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_SEARCH_ISDBT;
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 = 2;
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;
stop(fe);
state->t2_signalling_valid = 0;
state->iq_constellation_point = 0;
state->iq_constellation_point_max = 0;
state->iq_constellation_tap = 0;
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_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;
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;
stat = ddb_mci_get_status(&state->mci, &res);
if (stat)
return stat;
*status = 0x00;
ddb_mci_get_info(&state->mci);
ddb_mci_get_strength(fe);
if (res.status == M4_DEMOD_WAIT_SIGNAL)
*status = 0x01;
if (res.status == M4_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);
}
static int 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_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT,
SYS_DVBS, SYS_DVBS2, },
.info = {
.name = "M4",
.frequency_min = 950000, /* DVB-T: 47125000 */
.frequency_max = 865000000, /* DVB-C: 862000000 */
.symbol_rate_min = 100000,
.symbol_rate_max = 100000000,
.frequency_stepsize = 0,
.frequency_tolerance = 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;
}
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,
};

View File

@@ -337,6 +337,13 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev_info(dev->dev, "HW %08x REGMAP %08x\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
if ((dev->link[0].ids.hwid & 0xffffff) <
dev->link[0].info->hw_min) {
u32 min = dev->link[0].info->hw_min;
dev_err(dev->dev, "Update firmware to at least version %u.%u to ensure full functionality!\n",
(min & 0xff0000) >> 16, min & 0xffff);
}
if (dev->link[0].info->ns_num) {
ddbwritel(dev, 0, ETHER_CONTROL);
@@ -408,6 +415,7 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0007),
DDB_DEVICE_ANY(0x0008),
DDB_DEVICE_ANY(0x0009),
DDB_DEVICE_ANY(0x000a),
DDB_DEVICE_ANY(0x0011),
DDB_DEVICE_ANY(0x0012),
DDB_DEVICE_ANY(0x0013),
@@ -459,5 +467,5 @@ 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_LICENSE("GPL v2");
MODULE_VERSION(DDBRIDGE_VERSION);

View File

@@ -24,7 +24,6 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#include "ddbridge-i2c.h"
#include "ddbridge-mci.h"
/* MAX LNB interface related module parameters */
@@ -61,6 +60,24 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
return 0;
}
static int max_set_input_unlocked(struct dvb_frontend *fe, int in);
static int max_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_unlocked(fe, input);
return 0;
}
static int max_send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
{
@@ -74,6 +91,10 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
if (fmode == 2 || fmode == 1)
return 0;
if (fmode == 4)
max_emulate_switch(fe, cmd->msg, cmd->msg_len);
if (dvb->diseqc_send_master_cmd)
dvb->diseqc_send_master_cmd(fe, cmd);
@@ -182,7 +203,8 @@ static int max_set_input_unlocked(struct dvb_frontend *fe, int in)
dvb->input = in;
dev->link[port->lnr].lnb.voltage[dvb->input] |= obit;
}
res = dvb->set_input(fe, in);
if (dvb->set_input)
res = dvb->set_input(fe, in);
return res;
}
@@ -417,7 +439,7 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
demod = input->nr;
tuner = demod & 3;
if (fmode == 3)
if (fmode >= 3)
tuner = 0;
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner);
if (!dvb->fe) {
@@ -445,11 +467,10 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
/* MAX MCI related functions */
static struct mci_cfg maxsx8 = {
extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg;
};
int ddb_fe_attach_mci(struct ddb_input *input)
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
{
struct ddb *dev = input->port->dev;
//struct i2c_adapter *i2c = &input->port->i2c->adap;
@@ -458,26 +479,33 @@ int ddb_fe_attach_mci(struct ddb_input *input)
struct ddb_link *link = &dev->link[port->lnr];
int demod, tuner;
struct mci_cfg cfg;
cfg = maxsx8;
int fm = fmode;
demod = input->nr;
tuner = demod & 3;
if (fmode == 3)
tuner = 0;
#if 0
dvb->fe = dvb_attach(ddb_mci_attach, input, 0, demod);
#else
dvb->fe = ddb_mci_attach(input, 0, demod);
#endif
switch (type) {
case DDB_TUNER_MCI_SX8:
cfg = ddb_max_sx8_cfg;
if (fm >= 3)
tuner = 0;
break;
case DDB_TUNER_MCI_M4:
fm = 0;
cfg = ddb_max_m4_cfg;
break;
default:
return -EINVAL;
}
dvb->fe = ddb_mci_attach(input, &cfg, demod, tuner);
if (!dvb->fe) {
dev_err(dev->dev, "No MAXSX8 found!\n");
dev_err(dev->dev, "No MCI card 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);
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;
@@ -491,4 +519,3 @@ int ddb_fe_attach_mci(struct ddb_input *input)
dvb->input = tuner;
return 0;
}

View File

@@ -1,9 +1,9 @@
/*
* ddbridge-mci.c: Digital Devices microcode interface
*
* Copyright (C) 2017 Digital Devices GmbH
* Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de>
* 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
@@ -27,43 +27,6 @@
static LIST_HEAD(mci_list);
static const u32 MCLK = (1550000000/12);
static const u32 MAX_LDPC_BITRATE = (720000000);
struct mci_base {
struct list_head mci_list;
void *key;
struct ddb_link *link;
struct completion completion;
struct i2c_adapter *i2c;
struct mutex i2c_lock;
struct mutex tuner_lock;
u8 adr;
struct mutex mci_lock;
int count;
u8 tuner_use_count[4];
u8 assigned_demod[8];
u32 used_ldpc_bitrate[8];
u8 demod_in_use[8];
u32 iq_mode;
};
struct mci {
struct mci_base *base;
struct dvb_frontend fe;
int nr;
int demod;
int tuner;
int first_time_lock;
int started;
struct mci_result signal_info;
u32 bb_mode;
};
static int mci_reset(struct mci *state)
{
struct ddb_link *link = state->base->link;
@@ -90,7 +53,7 @@ static int mci_reset(struct mci *state)
return 0;
}
static int mci_config(struct mci *state, u32 config)
int ddb_mci_config(struct mci *state, u32 config)
{
struct ddb_link *link = state->base->link;
@@ -101,9 +64,9 @@ static int mci_config(struct mci *state, u32 config)
}
static int _mci_cmd_unlocked(struct mci *state,
u32 *cmd, u32 cmd_len,
u32 *res, u32 res_len)
static int ddb_mci_cmd_raw_unlocked(struct mci *state,
u32 *cmd, u32 cmd_len,
u32 *res, u32 res_len)
{
struct ddb_link *link = state->base->link;
u32 i, val;
@@ -129,45 +92,216 @@ static int _mci_cmd_unlocked(struct mci *state,
return 0;
}
static int mci_cmd_unlocked(struct mci *state,
struct mci_command *command,
struct mci_result *result)
int ddb_mci_cmd_unlocked(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
u32 *cmd = (u32 *) command;
u32 *res = (u32 *) result;
return _mci_cmd_unlocked(state, cmd, sizeof(*command)/sizeof(u32),
res, sizeof(*result)/sizeof(u32));
return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32),
res, sizeof(*result)/sizeof(u32));
}
static int mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
int ddb_mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
int stat;
mutex_lock(&state->base->mci_lock);
stat = _mci_cmd_unlocked(state,
stat = ddb_mci_cmd_raw_unlocked(state,
(u32 *)command, sizeof(*command)/sizeof(u32),
(u32 *)result, sizeof(*result)/sizeof(u32));
mutex_unlock(&state->base->mci_lock);
return stat;
}
static int _mci_cmd(struct mci *state,
int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len)
{
int stat;
mutex_lock(&state->base->mci_lock);
stat = _mci_cmd_unlocked(state,
(u32 *)command, command_len,
(u32 *)result, result_len);
stat = ddb_mci_cmd_raw_unlocked(state,
(u32 *)command, command_len,
(u32 *)result, result_len);
mutex_unlock(&state->base->mci_lock);
return stat;
}
static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q)
{
int stat;
struct mci_command cmd;
struct mci_result res;
memset(&cmd, 0, sizeof(cmd));
memset(&res, 0, sizeof(res));
cmd.command = MCI_CMD_GET_IQSYMBOL;
cmd.demod = demod;
stat = ddb_mci_cmd(mci, &cmd, &res);
if (!stat) {
*i = res.iq_symbol.i;
*q = res.iq_symbol.q;
}
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_NONE, 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;
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;
if (mci->signal_info.dvbs2_signal_info.standard == 2) {
u32 modcod = (0x7c & pls_code) >> 2;
p->delivery_system = SYS_DVBS2;
p->rolloff =
ro_lut[mci->signal_info.
dvbs2_signal_info.roll_off & 7];
p->pilot = (pls_code & 1) ? PILOT_ON : PILOT_OFF;
p->fec_inner = modcod2fec[modcod];
p->modulation = modcod2mod[modcod];
p->transmission_mode = pls_code;
} 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:
break;
case SYS_DVBT:
break;
case SYS_DVBT2:
break;
case SYS_DVBC2:
break;
case SYS_ISDBT:
break;
}
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->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 =
mci->signal_info.dvbs2_signal_info.channel_power * 10;
}
static void mci_handler(void *priv)
{
struct mci_base *base = (struct mci_base *)priv;
@@ -175,423 +309,6 @@ static void mci_handler(void *priv)
complete(&base->completion);
}
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 mci *state = fe->demodulator_priv;
state->base->count--;
if (state->base->count == 0) {
list_del(&state->base->mci_list);
kfree(state->base);
}
kfree(state);
}
static int get_info(struct dvb_frontend *fe)
{
int stat;
struct mci *state = fe->demodulator_priv;
struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_GETSIGNALINFO;
cmd.demod = state->demod;
stat = mci_cmd(state, &cmd, &state->signal_info);
return stat;
}
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int stat;
struct mci *state = fe->demodulator_priv;
struct mci_command cmd;
u32 val;
struct mci_result *res = (struct mci_result *)&val;
cmd.command = MCI_CMD_GETSTATUS;
cmd.demod = state->demod;
stat = _mci_cmd(state, &cmd, 1, res, 1);
if (stat)
return stat;
*status = 0x00;
if (res->status == SX8_DEMOD_WAIT_MATYPE)
*status = 0x0f;
if (res->status == SX8_DEMOD_LOCKED)
*status = 0x1f;
return stat;
}
static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
{
struct mci *state = fe->demodulator_priv;
struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.tuner = state->tuner;
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
return mci_cmd(state, &cmd, NULL);
}
static int stop(struct dvb_frontend *fe)
{
struct mci *state = fe->demodulator_priv;
struct mci_command cmd;
u32 input = state->tuner;
memset(&cmd, 0, sizeof(cmd));
if (state->demod != 0xff) {
cmd.command = MCI_CMD_STOP;
cmd.demod = state->demod;
mci_cmd(state, &cmd, NULL);
if (state->base->iq_mode) {
cmd.command = MCI_CMD_STOP;
cmd.demod = state->demod;
cmd.output = 0;
mci_cmd(state, &cmd, NULL);
mci_config(state, SX8_TSCONFIG_MODE_NORMAL);
}
}
mutex_lock(&state->base->tuner_lock);
state->base->tuner_use_count[input]--;
if (!state->base->tuner_use_count[input])
mci_set_tuner(fe, input, 0);
state->base->demod_in_use[state->demod] = 0;
state->base->used_ldpc_bitrate[state->nr] = 0;
state->demod = 0xff;
state->base->assigned_demod[state->nr] = 0xff;
state->base->iq_mode = 0;
mutex_unlock(&state->base->tuner_lock);
state->started = 0;
return 0;
}
static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
{
struct mci *state = fe->demodulator_priv;
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->tuner;
u32 bits_per_symbol = 0;
int i, stat = 0;
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(&state->base->tuner_lock);
if (state->base->iq_mode) {
stat = -EBUSY;
goto unlock;
}
for (i = 0; i < 8; i++) {
used_ldpc_bitrate += state->base->used_ldpc_bitrate[i];
if (state->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;
}
i = (p->symbol_rate > MCLK / 2) ? 3 : 7;
while (i >= 0 && state->base->demod_in_use[i])
i--;
if (i < 0) {
stat = -EBUSY;
goto unlock;
}
state->base->demod_in_use[i] = 1;
state->base->used_ldpc_bitrate[state->nr] = p->symbol_rate * bits_per_symbol;
state->demod = state->base->assigned_demod[state->nr] = i;
if (!state->base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
state->base->tuner_use_count[input]++;
state->base->iq_mode = (ts_config > 1);
unlock:
mutex_unlock(&state->base->tuner_lock);
if (stat)
return stat;
memset(&cmd, 0, sizeof(cmd));
if (state->base->iq_mode) {
cmd.command = SX8_CMD_SELECT_IQOUT;
cmd.demod = state->demod;
cmd.output = 0;
mci_cmd(state, &cmd, NULL);
mci_config(state, ts_config);
}
if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000)
flags |= 0x80;
printk("frontend %u: tuner=%u demod=%u\n", state->nr, state->tuner, state->demod);
cmd.command = MCI_CMD_SEARCH_DVBS;
cmd.dvbs2_search.flags = flags;
cmd.dvbs2_search.s2_modulation_mask = modmask & ((1 << (bits_per_symbol - 1)) - 1);
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;
cmd.dvbs2_search.input_stream_id = p->stream_id;
cmd.tuner = state->tuner;
cmd.demod = state->demod;
cmd.output = state->nr;
if (p->stream_id == 0x80000000)
cmd.output |= 0x80;
stat = mci_cmd(state, &cmd, NULL);
if (stat)
stop(fe);
return stat;
}
static int start_iq(struct dvb_frontend *fe, u32 ts_config)
{
struct mci *state = fe->demodulator_priv;
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->tuner;
int i, stat = 0;
mutex_lock(&state->base->tuner_lock);
if (state->base->iq_mode) {
stat = -EBUSY;
goto unlock;
}
for (i = 0; i < 8; i++)
if (state->base->demod_in_use[i])
used_demods++;
if (used_demods > 0) {
stat = -EBUSY;
goto unlock;
}
state->demod = state->base->assigned_demod[state->nr] = 0;
if (!state->base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
state->base->tuner_use_count[input]++;
state->base->iq_mode = (ts_config > 1);
unlock:
mutex_unlock(&state->base->tuner_lock);
if (stat)
return stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = SX8_CMD_START_IQ;
cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
cmd.tuner = state->tuner;
cmd.demod = state->demod;
cmd.output = 7;
mci_config(state, ts_config);
stat = mci_cmd(state, &cmd, NULL);
if (stat)
stop(fe);
return stat;
}
static int set_parameters(struct dvb_frontend *fe)
{
int stat = 0;
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 ts_config, iq_mode = 0, isi;
if (state->started)
stop(fe);
isi = p->stream_id;
if (isi != NO_STREAM_ID_FILTER) {
iq_mode = (isi & 0x30000000) >> 28;
}
switch (iq_mode) {
case 1:
ts_config = (SX8_TSCONFIG_TSHEADER|SX8_TSCONFIG_MODE_IQ);
break;
case 2:
ts_config = (SX8_TSCONFIG_TSHEADER|SX8_TSCONFIG_MODE_IQ);
break;
default:
ts_config = SX8_TSCONFIG_MODE_NORMAL;
break;
}
if (iq_mode != 2) {
u32 flags = 3;
u32 mask = 3;
if (p->modulation == APSK_16 ||
p->modulation == APSK_32) {
flags = 2;
mask = 15;
}
stat = start(fe, flags, mask, ts_config);
} else {
stat = start_iq(fe, ts_config);
}
if (!stat) {
state->started = 1;
state->first_time_lock = 1;
state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL;
}
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 get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
static int set_input(struct dvb_frontend *fe, int input)
{
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
state->tuner = p->input = input;
printk("fe %u, input = %u\n", state->nr, input);
return 0;
}
static int sleep(struct dvb_frontend *fe)
{
struct mci *state = fe->demodulator_priv;
}
static int get_snr(struct dvb_frontend *fe)
{
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
s32 snr;
get_info(fe);
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (s64) state->signal_info.dvbs2_signal_info.signal_to_noise * 100;
return 0;
}
static int get_strength(struct dvb_frontend *fe)
{
struct mci *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
s32 str;
get_info(fe);
str = 100000 - (state->signal_info.dvbs2_signal_info.channel_power * 10 + 108750);
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].svalue = str;
return 0;
}
static struct dvb_frontend_ops mci_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2 },
.info = {
.name = "DVB-S/S2X",
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 0,
.frequency_tolerance = 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,
.tune = tune,
.release = release,
.read_status = read_status,
.set_input = set_input,
};
static struct mci_base *match_base(void *key)
{
struct mci_base *p;
@@ -608,16 +325,16 @@ static int probe(struct mci *state)
return 0;
}
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, int mci_type, int nr)
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 = mci_type ? (void *) port : (void *) link;
void *key = cfg->type ? (void *) port : (void *) link;
state = kzalloc(sizeof(*state), GFP_KERNEL);
state = kzalloc(cfg->state_size, GFP_KERNEL);
if (!state)
return NULL;
@@ -626,7 +343,7 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, int mci_type, int n
base->count++;
state->base = base;
} else {
base = kzalloc(sizeof(*base), GFP_KERNEL);
base = kzalloc(cfg->base_size, GFP_KERNEL);
if (!base)
goto fail;
base->key = key;
@@ -642,14 +359,16 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, int mci_type, int n
goto fail;
}
list_add(&base->mci_list, &mci_list);
if (cfg->base_init)
cfg->base_init(base);
}
state->fe.ops = mci_ops;
memcpy(&state->fe.ops, cfg->fe_ops, sizeof(struct dvb_frontend_ops));
state->fe.demodulator_priv = state;
state->nr = nr;
state->tuner = nr;
state->demod = nr;
state->tuner = tuner;
if (cfg->init)
cfg->init(state);
return &state->fe;
fail:
kfree(state);

View File

@@ -1,9 +1,9 @@
/*
* ddbridge-mci.h: Digital Devices micro code interface
*
* Copyright (C) 2017 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
* Copyright (C) 2017-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
@@ -24,6 +24,22 @@
#ifndef _DDBRIDGE_MCI_H_
#define _DDBRIDGE_MCI_H_
#define SX8_TSINPUT (0x280)
#define MIC_CONTROL (0x500)
#define MIC_PROGMEM_OLD (0x4000)
#define MIC_PROGMEM_OLD_SIZE (0x4000)
#define MIC_PROGMEM (0x8000)
#define MIC_PROGMEM_SIZE (0x8000)
#define MIC_DATAMEM (0x8000)
#define MIC_DATAMEM_SIZE (0x2000)
#define MIC_INTERFACE_IN (0x0600)
#define MIC_INTERFACE_OUT (0x0680)
#define MIC_INTERFACE_VER (0x06F0)
#define MCI_CONTROL (0x500)
#define MCI_COMMAND (0x600)
#define MCI_RESULT (0x680)
@@ -43,6 +59,22 @@
#define SX8_TSCONFIG_MODE_NORMAL (0x00000001)
#define SX8_TSCONFIG_MODE_IQ (0x00000003)
/*
* IQMode only vailable on MaxSX8 on a single tuner
*
* IQ_MODE_SAMPLES
* sampling rate is 1550/24 MHz (64.583 MHz)
* channel agc is frozen, to allow stitching the FFT results together
*
* IQ_MODE_VTM
* sampling rate is the supplied symbolrate
* channel agc is active
*
* in both cases down sampling is done with a RRC Filter (currently fixed to alpha = 0.05)
* which causes some (ca 5%) aliasing at the edges from outside the spectrum
*/
#define SX8_TSCONFIG_TSHEADER (0x00000004)
#define SX8_TSCONFIG_BURST (0x00000008)
@@ -52,114 +84,464 @@
#define SX8_TSCONFIG_BURSTSIZE_8K (0x00000020)
#define SX8_TSCONFIG_BURSTSIZE_16K (0x00000030)
#define SX8_DEMOD_STOPPED (0)
#define SX8_DEMOD_IQ_MODE (1)
#define SX8_DEMOD_WAIT_SIGNAL (2)
#define SX8_DEMOD_WAIT_MATYPE (3)
#define SX8_DEMOD_TIMEOUT (14)
#define SX8_DEMOD_LOCKED (15)
/* additional TS input control bits on MaxSX8 DD01:0009 */
#define TS_INPUT_CONTROL_SIZEMASK (0x00000030)
#define TS_INPUT_CONTROL_SIZE188 (0x00000000)
#define TS_INPUT_CONTROL_SIZE192 (0x00000010)
#define TS_INPUT_CONTROL_SIZE196 (0x00000020)
#define MCI_CMD_STOP (0x01)
#define MCI_CMD_GETSTATUS (0x02)
#define MCI_CMD_GETSIGNALINFO (0x03)
#define MCI_CMD_RFPOWER (0x04)
/********************************************************/
#define SX8_DEMOD_STOPPED (0)
#define SX8_DEMOD_IQ_MODE (1)
#define SX8_DEMOD_WAIT_SIGNAL (2)
#define SX8_DEMOD_WAIT_MATYPE (3)
#define SX8_DEMOD_TIMEOUT (14)
#define SX8_DEMOD_LOCKED (15)
#define M4_DEMOD_STOPPED (0)
#define M4_DEMOD_WAIT_SIGNAL (1)
#define M4_DEMOD_TIMEOUT (14)
#define M4_DEMOD_LOCKED (15)
#define MCI_CMD_STOP (0x01)
#define MCI_CMD_GETSTATUS (0x02)
#define MCI_CMD_GETSIGNALINFO (0x03)
#define MCI_CMD_RFPOWER (0x04)
#define MCI_CMD_SEARCH_DVBS (0x10)
#define MCI_CMD_SEARCH_DVBC (0x20)
#define MCI_CMD_SEARCH_DVBT (0x21)
#define MCI_CMD_SEARCH_DVBT2 (0x22)
#define MCI_CMD_SEARCH_DVBC2 (0x23)
#define MCI_CMD_SEARCH_ISDBT (0x24)
#define MCI_CMD_GET_IQSYMBOL (0x30)
#define MCI_CMD_GET_IQSYMBOL (0x30)
#define SX8_CMD_INPUT_ENABLE (0x40)
#define SX8_CMD_INPUT_DISABLE (0x41)
#define SX8_CMD_START_IQ (0x42)
#define SX8_CMD_STOP_IQ (0x43)
#define SX8_CMD_SELECT_IQOUT (0x44)
#define SX8_CMD_SELECT_TSOUT (0x45)
#define MCI_BANDWIDTH_UNKNOWN (0)
#define MCI_BANDWIDTH_1_7MHZ (1)
#define MCI_BANDWIDTH_5MHZ (5)
#define MCI_BANDWIDTH_6MHZ (6)
#define MCI_BANDWIDTH_7MHZ (7)
#define MCI_BANDWIDTH_8MHZ (8)
#define SX8_ERROR_UNSUPPORTED (0x80)
#define M4_MODE_DVBSX (2)
#define M4_MODE_DVBC (3)
#define M4_MODE_DVBT (4)
#define M4_MODE_DVBT2 (5)
#define M4_MODE_DVBC2 (6)
#define M4_MODE_ISDBT (7)
#define SX8_SUCCESS(status) (status < SX8_ERROR_UNSUPPORTED)
#define SX8_CMD_INPUT_ENABLE (0x40)
#define SX8_CMD_INPUT_DISABLE (0x41)
#define SX8_CMD_START_IQ (0x42)
#define SX8_CMD_STOP_IQ (0x43)
#define SX8_CMD_ENABLE_IQOUTPUT (0x44)
#define SX8_CMD_DISABLE_IQOUTPUT (0x45)
#define SX8_CMD_DIAG_READ8 (0xE0)
#define SX8_CMD_DIAG_READ32 (0xE1)
#define SX8_CMD_DIAG_WRITE8 (0xE2)
#define SX8_CMD_DIAG_WRITE32 (0xE3)
#define M4_CMD_GET_T2_L1INFO (0x50)
#define M4_CMD_GET_C2_L1P2 (0x50)
#define M4_CMD_GET_IDS (0x51)
#define M4_CMD_DIAG_READRF (0xE8)
#define M4_CMD_DIAG_WRITERF (0xE9)
#define MCI_STATUS_OK (0x00)
#define MCI_STATUS_UNSUPPORTED (0x80)
#define MCI_STATUS_RETRY (0xFD)
#define MCI_STATUS_NOT_READY (0xFE)
#define MCI_STATUS_ERROR (0xFF)
#define M4_CMD_DIAG_READX (0xE0)
#define M4_CMD_DIAG_READT (0xE1)
#define M4_CMD_DIAG_WRITEX (0xE2)
#define M4_CMD_DIAG_WRITET (0xE3)
#define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0)
#define M4_CMD_DIAG_READRF (0xE8)
#define M4_CMD_DIAG_WRITERF (0xE9)
/********************************************************/
struct mci_command {
union {
u32 command_word;
struct {
u8 command;
u8 tuner;
u8 demod;
u8 output;
};
};
union {
u32 params[31];
struct {
u8 flags;
u8 s2_modulation_mask;
u8 rsvd1;
u8 retry;
u32 frequency;
u32 symbol_rate;
u8 input_stream_id;
u8 rsvd2[3];
u32 scrambling_sequence_index;
} dvbs2_search;
};
union {
u32 command_word;
struct {
u8 command;
u8 tuner;
u8 demod;
u8 output;
};
};
union {
u32 params[31];
struct {
u8 flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled, 7: InputStreamID*/
/* Bit 0 : QPSK, 1: 8PSK/8APSK, 2 : 16APSK, 3: 32APSK, 4: 64APSK, 5: 128APSK, 6: 256APSK */
u8 s2_modulation_mask;
u8 rsvd1;
u8 retry;
u32 frequency;
u32 symbol_rate;
u8 input_stream_id;
u8 rsvd2[3];
u32 scrambling_sequence_index;
u32 frequency_range;
} dvbs2_search;
struct {
u8 flags;
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
} dvbc_search;
struct {
u8 flags; /* Bit 0: LP Stream */
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
} dvbt_search;
struct {
u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
u32 reserved;
u8 plp;
u8 rsvd2[3];
} dvbt2_search;
struct {
u8 flags;
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
u32 reserved;
u8 plp;
u8 data_slice;
u8 rsvd2[2];
} dvbc2_search;
struct {
u8 flags;
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
} isdbt_search;
struct {
u8 tap;
u8 rsvd;
u16 point;
} get_iq_symbol;
struct {
u8 flags; /* Bit 0 : 0 = VTM, 1 = SCAN. Bit 1: Set Gain */
u8 roll_off;
u8 rsvd1;
u8 rsvd2;
u32 frequency;
u32 symbol_rate; /* Only in VTM mode. */
u16 gain;
} sx8_start_iq;
struct {
/* Bit 1:0 = STVVGLNA Gain. 0 = AGC, 1 = 0dB,
2 = Minimum, 3 = Maximum */
u8 flags;
} sx8_input_enable;
struct {
u8 Offset; // Offset into list, must be multiple of 64
u8 Select; // 0 = Slices, 1 = PLPs (C2 Only)
u8 DataSlice; // DataSlice to get PLPList (C2 Only)
} get_ids;
struct {
u8 select; // 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID
u8 id; // DataSliceID, PLPId
} get_l1_info;
};
};
struct mci_result {
union {
u32 status_word;
struct {
u8 status;
u8 rsvd;
u8 status;
u8 mode;
u16 time;
};
};
union {
u32 result[27];
struct {
u8 standard;
u8 pls_code; /* puncture rate for DVB-S */
u8 roll_off; /* 7-6: rolloff, 5-2: rsrvd, 1:short, 0:pilots */
u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */
u8 pls_code; /* puncture rate for DVB-S */
u8 roll_off; /* 2-0: rolloff */
u8 rsvd;
u32 frequency;
u32 symbol_rate;
s16 channel_power;
s16 band_power;
s16 signal_to_noise;
u32 frequency; /* actual frequency in Hz */
u32 symbol_rate; /* actual symbolrate in Hz */
s16 channel_power; /* channel power in dBm x 100 */
s16 band_power; /*/ band power in dBm x 100 */
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd2;
u32 packet_errors;
u32 ber_numerator;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
} dvbs2_signal_info;
struct {
u8 i_symbol;
u8 q_symbol;
} dvbs2_signal_iq;
u8 modulation;
u8 rsvd1[3];
u32 frequency; /* actual frequency in Hz */
u32 symbol_rate; /* actual symbolrate in Hz */
s16 channel_power; /* channel power in dBm x 100 */
s16 band_power; /* band power in dBm x 100 */
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS */
u32 ber_denominator;
} dvbc_signal_info;
struct {
u8 tps_25_32; /* Constellation (2), Hierarchy (3), Coderate HP (3) */
u8 tps_33_39; /* Coderate LP (3), Guardinterval (2), FFT (2), 0 (1) */
u16 tps_cell_id; /* Cell Identifier */
u32 frequency; /* actual frequency in Hz */
u32 rsvd1;
s16 channel_power; /* channel power in dBm x 100 */
s16 band_power; /* band power in dBm x 100 */
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS */
u32 ber_denominator;
} dvbt_signal_info;
struct {
u32 rsvd0;
u32 frequency; /* actual frequency in Hz */
u32 rsvd1;
s16 channel_power; /* channel power in dBm x 100 */
s16 band_power; /* band power in dBm x 100 */
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS */
u32 ber_denominator;
} dvbt2_signal_info;
struct { // Work in Progress
u32 rsvd0 ; // Cell Identifier
u32 frequency; // actual frequency in Hz
u32 rsvd1; //
s16 channel_power; // channel power in dBm x 100
s16 band_power; // band power in dBm x 100
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreBCH
u32 ber_denominator;
} dvbc2_signal_info;
struct {
u32 rsvd0;
u32 frequency; // actual frequency in Hz
u32 rsvd1; //
s16 channel_power; // channel power in dBm x 100
s16 band_power; // band power in dBm x 100
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreRS
u32 ber_denominator;
u8 tmcc_info[13]; // TMCC B20 - B121
} isdbt_signal_info;
struct {
s16 i;
s16 q;
} iq_symbol;
struct {
u8 t2_l1_pre[37];
u8 t2_l1_post[15];
u8 t2_l1_post_d[19];
u8 t2_l1_post_c[19];
} dvbt2_l1_info;
struct {
u8 NetworkID[2];
u8 C2SystemID[2];
u8 StartFrequency[3];
u8 C2BandWidth[2];
u8 GuardInterval;
u8 C2FrameLength[2];
u8 L1P2ChangeCounter;
u8 NumDataSlices;
u8 NumNotches;
struct {
u8 Start[2];
u8 Width[2];
u8 Reserved3;
} NotchData[15];
u8 ReservedTone;
u8 Reserved4[2]; // EWS 1 bit, C2_Version 4 bit, Rsvd 11 bit
} DVBC2_L1Part2;
struct {
u8 NumIDs;
u8 Offset;
u8 IDs[64];
} DVBC2_IDList;
struct {
u8 SliceID;
u8 TunePosition[2];
u8 OffsetLeft[2];
u8 OffsetRight[2];
u8 TIDepth;
u8 Type;
u8 FECHeaderType;
u8 ConstConf;
u8 LeftNotch;
u8 NumPLP;
u8 Reserved2;
} DVBC2_SliceInfo;
struct {
u8 PLPID;
u8 Bundled;
u8 Type;
u8 PayloadType;
u8 GroupID;
u8 Start[2];
u8 FEC_Type;
u8 Mod;
u8 Cod;
u8 PSISIReprocessing;
u8 TransportstreamID[2];
u8 OrginalNetworkID[2];
u8 Reserved1;
} DVBC2_PLPInfo;
};
u32 version[4];
};
struct mci_cfg {
/* Helper Macros */
/* DVB-T2 L1-Pre Signalling Data ( ETSI EN 302 755 V1.4.1 Chapter 7.2.2 ) */
#define L1PRE_TYPE(p) ((p)[0] & 0xFF)
#define L1PRE_BWT_EXT(p) ((p)[1] & 0x01)
#define L1PRE_S1(p) ((p)[2] & 0x07)
#define L1PRE_S2(p) ((p)[3] & 0x0F)
#define L1PRE_L1_REPETITION_FLAG(p) ((p)[4] & 0x01)
#define L1PRE_GUARD_INTERVAL(p) ((p)[5] & 0x07)
#define L1PRE_PAPR(p) ((p)[6] & 0x0F)
#define L1PRE_L1_MOD(p) ((p)[7] & 0x0F)
#define L1PRE_L1_COD(p) ((p)[8] & 0x03)
#define L1PRE_L1_FEC_TYPE(p) ((p)[9] & 0x03)
#define L1PRE_L1_POST_SIZE(p) (((u32)((p)[10] & 0x03) << 16) | ((u32)(p)[11] << 8) | (p)[12])
#define L1PRE_L1_POST_INFO_SIZE(p) (((u32)((p)[13] & 0x03) << 16) | ((u32)(p)[14] << 8) | (p)[15])
#define L1PRE_PILOT_PATTERN(p) ((p)[16] & 0x0F)
#define L1PRE_TX_ID_AVAILABILITY(p) ((p)[17] & 0xFF)
#define L1PRE_CELL_ID(p) (((u16)(p)[18] << 8) | (p)[19])
#define L1PRE_NETWORK_ID(p) (((u16)(p)[20] << 8) | (p)[21])
#define L1PRE_T2_SYSTEM_ID(p) (((u16)(p)[22] << 8) | (p)[23])
#define L1PRE_NUM_T2_FRAMES(p) ((p)[24] & 0xFF)
#define L1PRE_NUM_DATA_SYMBOLS(p) (((u16)((p)[25] & 0x0F) << 8) | (p)[26])
#define L1PRE_REGEN_FLAG(p) ((p)[27] & 0x07)
#define L1PRE_L1_POST_EXTENSION(p) ((p)[28] & 0x01)
#define L1PRE_NUM_RF(p) ((p)[29] & 0x07)
#define L1PRE_CURRENT_RF_IDX(p) ((p)[30] & 0x07)
#define L1PRE_T2_VERSION(p) ((((p)[31] & 0x03) << 2) | (((p)[32] & 0xC0) >> 6))
#define L1PRE_L1_POST_SCRAMBLED(p) (((p)[32] & 0x20) >> 5)
#define L1PRE_T2_BASE_LITE(p) (((p)[32] & 0x10) >> 4)
/* DVB-T2 L1-Post Signalling Data ( ETSI EN 302 755 V1.4.1 Chapter 7.2.3 ) */
#define L1POST_SUB_SLICES_PER_FRAME(p) (((u16)(p)[ 0] & 0x7F) | (p)[ 1])
#define L1POST_NUM_PLP(p) ((p)[2] & 0xFF)
#define L1POST_NUM_AUX(p) ((p)[3] & 0x0F)
#define L1POST_AUX_CONFIG_RFU(p) ((p)[4] & 0xFF)
#define L1POST_RF_IDX(p) ((p)[5] & 0x07)
#define L1POST_FREQUENCY(p) (((u32)(p)[6] << 24) | ((u32)(p)[7] << 16) | ((u32)(p)[8] << 8) | (p)[9])
#define L1POST_FEF_TYPE(p) ((p)[10] & 0x0F)
#define L1POST_FEF_LENGTH(p) (((u32)(p)[11] << 16) | ((u32)(p)[12] << 8) | (p)[13])
#define L1POST_FEF_INTERVAL(p) ((p)[14] & 0xFF)
/* Repeated for each PLP, */
/* Hardware is restricted to retrieve only values for current data PLP and common PLP */
#define L1POST_PLP_ID(p) ((p)[0] & 0xFF)
#define L1POST_PLP_TYPE(p) ((p)[1] & 0x07)
#define L1POST_PLP_PAYLOAD_TYPE(p) ((p)[2] & 0x1F)
#define L1POST_FF_FLAG(p) ((p)[3] & 0x01)
#define L1POST_FIRST_RF_IDX(p) ((p)[4] & 0x07)
#define L1POST_FIRST_FRAME_IDX(p) ((p)[5] & 0xFF)
#define L1POST_PLP_GROUP_ID(p) ((p)[6] & 0xFF)
#define L1POST_PLP_COD(p) ((p)[7] & 0x07)
#define L1POST_PLP_MOD(p) ((p)[8] & 0x07)
#define L1POST_PLP_ROTATION(p) ((p)[9] & 0x01)
#define L1POST_PLP_FEC_TYPE(p) ((p)[10] & 0x03)
#define L1POST_PLP_NUM_BLOCKS_MAX(p) (((u16)((p)[11] & 0x03) << 8) | (p)[12])
#define L1POST_FRAME_INTERVAL(p) ((p)[13] & 0xFF)
#define L1POST_TIME_IL_LENGTH(p) ((p)[14] & 0xFF)
#define L1POST_TIME_IL_TYPE(p) ((p)[15] & 0x01)
#define L1POST_IN_BAND_A_FLAG(p) ((p)[16] & 0x01)
#define L1POST_IN_BAND_B_FLAG(p) (((p)[17] >> 7) & 0x01)
#define L1POST_RESERVED_1(p) (((u16)((p)[17] & 0x7F) << 4) | ((p)[18] & 0xF0) >> 4)
#define L1POST_PLP_MODE(p) (((p)[18] >> 2) & 0x03)
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
struct mci_base {
struct list_head mci_list;
void *key;
struct ddb_link *link;
struct completion completion;
struct i2c_adapter *i2c;
struct mutex i2c_lock;
struct mutex tuner_lock;
struct mutex mci_lock;
int count;
int type;
};
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, int mci_type, int nr);
struct mci {
struct mci_base *base;
struct dvb_frontend fe;
int nr;
int demod;
int tuner;
struct mci_result signal_info;
};
struct mci_cfg {
int type;
struct dvb_frontend_ops *fe_ops;
u32 base_size;
u32 state_size;
int (*init)(struct mci *mci);
int (*base_init)(struct mci_base *mci_base);
};
int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result);
int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len);
int ddb_mci_config(struct mci *state, u32 config);
int ddb_mci_get_status(struct mci *mci, struct mci_result *res);
int ddb_mci_get_snr(struct dvb_frontend *fe);
int ddb_mci_get_info(struct mci *mci);
int ddb_mci_get_strength(struct dvb_frontend *fe);
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
#endif

View File

@@ -21,12 +21,16 @@
/* Register Definitions */
#define CUR_REGISTERMAP_VERSION_V1 0x00010001
#define CUR_REGISTERMAP_VERSION_V2 0x00020000
#define CUR_REGISTERMAP_VERSION_022X 0x00020001
#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 0x00000000
#define REGISTERMAP_VERSION 0x00000004
#define HARDWARE_VERSION 0x0000
#define REGISTERMAP_VERSION 0x0004
#define DEVICE_ID 0x0008
#define BOARD_ID 0x000C
/* ------------------------------------------------------------------------- */
/* SPI Controller */
@@ -44,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
/* ------------------------------------------------------------------------- */
@@ -148,7 +152,9 @@
#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)
@@ -160,6 +166,9 @@
#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 :
@@ -184,6 +193,7 @@
/* SHORT Temperature in C x 256 (ADM1032 ext) */
#define TEMPMON2_DACCORE (TEMPMON_SENSOR2)
/* ------------------------------------------------------------------------- */
/* I2C Master Controller */
@@ -223,6 +233,10 @@
#define TS_CONTROL(_io) ((_io)->regs + 0x00)
#define TS_CONTROL2(_io) ((_io)->regs + 0x04)
#define TS_INPUT_CONTROL_ENABLE (0x00000001)
#define TS_INPUT_CONTROL_RESET (0x00000002)
#define TS_INPUT_CONTROL_SKIPERROR (0x00000008)
/* ------------------------------------------------------------------------- */
/* DMA Buffer */
@@ -248,12 +262,19 @@
#define LNB_BUSY BIT_ULL(4)
#define LNB_TONE BIT_ULL(15)
#define LNB_INTERRUPT_BASE 4
#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_SETTING(i) (LNB_BASE + (i) * 0x20 + 0x0c)
#define LNB_FIFO_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_RESET_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_WRITE_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x14)
/* ------------------------------------------------------------------------- */
/* CI Interface (only CI-Bridge) */

521
ddbridge/ddbridge-sx8.c Normal file
View File

@@ -0,0 +1,521 @@
/*
* 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-i2c.h"
#include "ddbridge-mci.h"
static const u32 MCLK = (1550000000 / 12);
static const u32 MAX_LDPC_BITRATE = (720000000);
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 gain_mode[SX8_TUNER_NUM];
u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
u8 demod_in_use[SX8_DEMOD_NUM];
u32 iq_mode;
u32 burst_size;
u32 direct_mode;
};
struct sx8 {
struct mci mci;
int first_time_lock;
int started;
u32 bb_mode;
u32 local_frequency;
};
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);
}
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int stat;
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;
stat = ddb_mci_get_status(&state->mci, &res);
if (stat)
return stat;
*status = 0x00;
ddb_mci_get_info(&state->mci);
if (res.status == SX8_DEMOD_WAIT_MATYPE)
*status = 0x0f;
if (res.status == SX8_DEMOD_LOCKED) {
*status = 0x1f;
if (state->mci.signal_info.dvbs2_signal_info.standard == 2) {
sx8_base->used_ldpc_bitrate[state->mci.nr] =
p->symbol_rate *
dvbs2_bits_per_symbol[
state->mci.signal_info.
dvbs2_signal_info.pls_code];
} else
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
}
return stat;
}
static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
{
struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.tuner = state->mci.tuner;
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
cmd.sx8_input_enable.flags = sx8_base->gain_mode[state->mci.tuner];
return ddb_mci_cmd(&state->mci, &cmd, NULL);
}
static int stop(struct dvb_frontend *fe)
{
struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct mci_command cmd;
u32 input = state->mci.tuner;
if (!state->started)
return -1;
memset(&cmd, 0, sizeof(cmd));
if (state->mci.demod != SX8_DEMOD_NONE) {
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_config(&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);
if (state->mci.demod != SX8_DEMOD_NONE) {
sx8_base->demod_in_use[state->mci.demod] = 0;
state->mci.demod = SX8_DEMOD_NONE;
}
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
sx8_base->iq_mode = 0;
mutex_unlock(&mci_base->tuner_lock);
state->started = 0;
return 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;
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 (sx8_base->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++;
}
printk("used_ldpc_bitrate = %u\n", used_ldpc_bitrate);
if ((used_ldpc_bitrate >= MAX_LDPC_BITRATE) ||
((ts_config & SX8_TSCONFIG_MODE_MASK) >
SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) {
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_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 = 0;
ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, ts_config);
}
if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000)
flags |= 0x80;
printk("frontend %u: tuner=%u demod=%u\n", state->mci.nr, state->mci.tuner, state->mci.demod);
cmd.command = MCI_CMD_SEARCH_DVBS;
cmd.dvbs2_search.flags = flags;
cmd.dvbs2_search.s2_modulation_mask = modmask;
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 == 0x80000000)
cmd.output |= 0x80;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
if (stat)
stop(fe);
return stat;
}
static int start_iq(struct dvb_frontend *fe, u32 flags,
u32 roll_off, 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 (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;
if (!sx8_base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
sx8_base->tuner_use_count[input]++;
sx8_base->iq_mode = (ts_config > 1);
unlock:
mutex_unlock(&mci_base->tuner_lock);
if (stat)
return stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = SX8_CMD_START_IQ;
cmd.sx8_start_iq.flags = flags;
cmd.sx8_start_iq.roll_off = roll_off;
cmd.sx8_start_iq.frequency = p->frequency * 1000;
cmd.sx8_start_iq.symbol_rate = p->symbol_rate;
cmd.tuner = state->mci.tuner;
cmd.demod = state->mci.demod;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
if (stat)
stop(fe);
ddb_mci_config(&state->mci, ts_config);
return stat;
}
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;
stop(fe);
isi = p->stream_id;
if (isi != NO_STREAM_ID_FILTER) {
iq_mode = (isi & 0x30000000) >> 28;
}
if (iq_mode)
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
if (iq_mode < 2) {
u32 mask;
switch (p->modulation) {
case APSK_256:
mask = 0x7f;
break;
case APSK_128:
mask = 0x3f;
break;
case APSK_64:
mask = 0x1f;
break;
case APSK_32:
mask = 0x0f;
break;
case APSK_16:
mask = 0x07;
break;
default:
mask = 0x03;
break;
}
stat = start(fe, 3, mask, ts_config);
} else {
stat = start_iq(fe, iq_mode & 1, 4, ts_config);
}
if (!stat) {
state->started = 1;
state->first_time_lock = 1;
state->mci.signal_info.status = SX8_DEMOD_WAIT_SIGNAL;
}
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 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;
printk("fe %u, set input = %u\n", state->mci.nr, input);
if (input >= SX8_TUNER_NUM)
return -EINVAL;
if (state->mci.tuner == input)
return 0;
stop(fe);
state->mci.tuner = p->input = input;
printk("fe %u, input = %u\n", state->mci.nr, input);
return 0;
}
static int sleep(struct dvb_frontend *fe)
{
stop(fe);
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 },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = {
.name = "DVB-S/S2X",
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 0,
.frequency_tolerance = 0,
.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,
.set_input = set_input,
.sleep = sleep,
};
static int init(struct mci *mci)
{
struct sx8 *state = (struct sx8 *) mci;
state->mci.demod = SX8_DEMOD_NONE;
mci->fe.ops.xbar[1] = mci->nr;
mci->fe.dtv_property_cache.input = mci->tuner;
return 0;
}
static int base_init(struct mci_base *mci_base)
{
//struct sx8_base *base = (struct sx8_base *) mci_base;
return 0;
}
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,
};

View File

@@ -92,6 +92,7 @@
#include "mxl5xx.h"
#include "ddbridge-regs.h"
#include "ddbridge-mci.h"
#define DDB_MAX_I2C 32
#define DDB_MAX_PORT 32
@@ -157,24 +158,28 @@ struct ddb_info {
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
#define TS_QUIRK_NO_OUTPUT 4
#define TS_QUIRK_ALT_OSC 8
u8 mci_ports;
u8 mci_type;
u32 tempmon_irq;
u32 lostlock_irq;
u8 mci;
u32 mdio_base;
u32 hw_min;
const struct ddb_regmap *regmap;
};
@@ -302,7 +307,6 @@ struct ddb_port {
#define DDB_CI_EXTERNAL_XO2_B 13
#define DDB_TUNER_DVBS_STV0910_PR 14
#define DDB_TUNER_DVBC2T2I_SONY_P 15
#define DDB_TUNER_MCI 16
#define DDB_TUNER_XO2 32
#define DDB_TUNER_DVBS_STV0910 (DDB_TUNER_XO2 + 0)
@@ -312,6 +316,10 @@ struct ddb_port {
#define DDB_TUNER_ATSC_ST (DDB_TUNER_XO2 + 4)
#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)
struct ddb_input *input[2];
struct ddb_output *output;
struct dvb_ca_en50221 *en;
@@ -516,7 +524,7 @@ struct DDMOD_FLASH {
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
#define DDBRIDGE_VERSION "0.9.33"
#define DDBRIDGE_VERSION "0.9.34"
/* linked function prototypes */
@@ -553,10 +561,12 @@ void ddb_i2c_release(struct ddb *dev);
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);
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

View File

@@ -165,5 +165,5 @@ module_exit(exit_octonet);
MODULE_DESCRIPTION("GPL");
MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung GbR");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DDBRIDGE_VERSION);

View File

@@ -1,15 +1,16 @@
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 is available on supported cards as firmware update.
This feature is currently considered experimental.
This feature is available on supported cards as firmware update and
is currently considered experimental.
Supported hardware:
Cine 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
@@ -80,3 +81,24 @@ 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.

View File

@@ -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 -

View File

@@ -115,7 +115,7 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
rbuf->pread = smp_load_acquire(&rbuf->pwrite;
rbuf->pread = &rbuf->pwrite;
#else
/* dvb_ringbuffer_flush() counts as read operation
* smp_load_acquire() to load write pointer

View File

@@ -59,7 +59,7 @@ static const char * const dnames[] = {
};
#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

View File

@@ -590,6 +590,10 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
}
}
mutex_unlock(&ci->lock);
/* Ensure cam stability after reset */
msleep(2000);
return 0;
}
@@ -780,4 +784,4 @@ EXPORT_SYMBOL(cxd2099_attach);
MODULE_DESCRIPTION("cxd2099");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");

View File

@@ -2690,4 +2690,4 @@ EXPORT_SYMBOL(cxd2843_attach);
MODULE_DESCRIPTION("CXD2843/37/38 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");

View File

@@ -5088,6 +5088,6 @@ error:
MODULE_DESCRIPTION("DRX-K driver");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
EXPORT_SYMBOL(drxk_attach);

View File

@@ -154,4 +154,4 @@ EXPORT_SYMBOL(lnbh25_attach);
MODULE_DESCRIPTION("LNBH25");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");

View File

@@ -686,7 +686,7 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
p->pre_bit_error.stat[0].uvalue = reg[5];
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = reg[6] * 188 * 8;
p->pre_bit_count.stat[0].uvalue = 8 * 188 * (u64)reg[6];
break;
case SYS_DVBS2:
break;
@@ -1945,4 +1945,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");

View File

@@ -2152,7 +2152,7 @@ error:
MODULE_DESCRIPTION("STV0367DD driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
EXPORT_SYMBOL(stv0367_attach);

View File

@@ -649,8 +649,8 @@ static int get_ber_s(struct stv *state, u32 *ber_numerator,
return -1;
if ((regs[0] & 0x80) == 0) {
state->last_ber_denominator = 1 << ((state->ber_scale * 2) +
10 + 3);
state->last_ber_denominator = 1ULL << ((state->ber_scale * 2) +
10 + 3);
state->last_ber_numerator = ((u32)(regs[0] & 0x7f) << 16) |
((u32)regs[1] << 8) | regs[2];
if (state->last_ber_numerator < 256 && state->ber_scale < 6) {
@@ -1169,14 +1169,14 @@ static int probe(struct stv *state)
write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01);
write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh);
write_reg(state, RSTV0910_P1_TSCFGM, 0xC0); /* Manual speed */
write_reg(state, RSTV0910_P1_TSCFGL, 0x20);
write_reg(state, RSTV0910_P1_TSCFGL, 0x60);
write_reg(state, RSTV0910_P1_TSSPEED, state->tsspeed);
write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01);
write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh);
write_reg(state, RSTV0910_P2_TSCFGM, 0xC0); /* Manual speed */
write_reg(state, RSTV0910_P2_TSCFGL, 0x20);
write_reg(state, RSTV0910_P2_TSCFGL, 0x60);
write_reg(state, RSTV0910_P2_TSSPEED, state->tsspeed);
@@ -1298,7 +1298,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
FEC_9_10
};
enum fe_rolloff ro2ro[3] = {
enum fe_rolloff ro2ro[4] = {
ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_15,
};
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
@@ -1329,6 +1329,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
p->fec_inner = FEC_NONE;
break;
}
p->modulation = QPSK;
p->rolloff = ROLLOFF_35;
}
if (state->receive_mode != RCVMODE_NONE) {
@@ -1609,15 +1610,14 @@ static int send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
{
struct stv *state = fe->demodulator_priv;
u16 offs = state->nr ? 0x40 : 0;
int i;
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E);
set_reg(DISTXCFG, 0x3e);
for (i = 0; i < cmd->msg_len; i++) {
wait_dis(state, 0x40, 0x00);
write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]);
set_reg(DISTXFIFO, cmd->msg[i]);
}
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A);
set_reg(DISTXCFG, 0x3a);
wait_dis(state, 0x20, 0x20);
return 0;
}
@@ -1630,23 +1630,20 @@ static int recv_slave_reply(struct dvb_frontend *fe,
static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
{
#if 0
struct stv *state = fe->demodulator_priv;
u16 offs = state->nr ? 0x40 : 0;
u8 value;
if (burst == SEC_MINI_A) {
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3F);
set_reg(DISTXCFG, 0x3f);
value = 0x00;
} else {
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E);
value = 0xFF;
set_reg(DISTXCFG, 0x3e);
value = 0xff;
}
wait_dis(state, 0x40, 0x00);
write_reg(state, RSTV0910_P1_DISTXFIFO + offs, value);
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A);
set_reg(DISTXFIFO, value);
set_reg(DISTXCFG, 0x3a);
wait_dis(state, 0x20, 0x20);
#endif
return 0;
}
@@ -1892,4 +1889,4 @@ EXPORT_SYMBOL_GPL(stv0910_attach);
MODULE_DESCRIPTION("STV0910 DVB-S/S2 demodulator driver");
MODULE_AUTHOR("Ralph und Marcus Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");

View File

@@ -335,7 +335,9 @@ static int set_params(struct dvb_frontend *fe)
static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
*frequency = 0;
struct stv *state = fe->tuner_priv;
*frequency = state->Frequency;
return 0;
}
@@ -751,7 +753,7 @@ EXPORT_SYMBOL_GPL(stv6111_attach);
MODULE_DESCRIPTION("STV6111 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
/*
* Local variables:

View File

@@ -933,7 +933,7 @@ EXPORT_SYMBOL_GPL(tda18212dd_attach);
MODULE_DESCRIPTION("TDA18212 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
/*
* Local variables:

View File

@@ -1326,4 +1326,4 @@ EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
MODULE_DESCRIPTION("TDA18271C2 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");