77 Commits

Author SHA1 Message Date
none
4a93d1056a Merge branch 'internal' 2021-06-08 14:02:28 +02:00
none
309713674c remove unused include 2021-06-08 14:02:01 +02:00
none
bfddf62f64 Merge branch 'internal' 2021-06-08 10:49:43 +02:00
none
2b0e5eb9d2 removed, use ddinfo 2021-06-08 10:49:06 +02:00
none
1d96274993 Merge branch 'internal' 2021-06-07 17:12:12 +02:00
none
3ff4d900a5 add more info 2021-06-06 20:24:07 +02:00
none
e1e569975f add FW version to output 2021-06-06 20:23:43 +02:00
none
b9998ee9e2 add new structs 2021-06-06 20:23:06 +02:00
none
dfe6b385a9 rename sx8info to ddinfo and add to Makefile 2021-06-05 22:36:01 +02:00
none
6e926c1452 add DVB-T parameters 2021-06-05 22:32:46 +02:00
none
8039097426 add support for FE_TIMEDOUT 2021-05-26 22:39:27 +02:00
mvoelkel
f3d5adc777 added puncture_rate to modulator stream setup 2021-04-17 21:03:05 +02:00
mvoelkel
e974925430 Merge branch 'internal' of https://github.com/DigitalDevices/internal_dddvb into internal 2021-04-10 19:08:23 +02:00
none
23bdd90595 Merge branch 'internal' 2021-04-09 12:54:23 +02:00
none
7bafb76461 change to floating point for frequency and signal strength
add comments to example config
2021-04-09 12:53:06 +02:00
mvoelkel
9cde52a6d8 Merge branch 'internal' of https://github.com/DigitalDevices/internal_dddvb into internal 2021-04-07 19:59:08 +02:00
none
50e354c49a cleanup 2021-04-07 19:29:53 +02:00
none
03d84ba75a add example modulator config file 2021-04-07 19:29:18 +02:00
none
c4f82de8b0 add modconfig 2021-04-07 19:28:49 +02:00
none
a5ad0b0584 show MCI firmware version 2021-04-07 19:28:12 +02:00
none
3cb3df51cf use correct kernel integer types 2021-04-07 19:27:21 +02:00
none
2311b94970 add modulator MCI commands 2021-04-07 19:25:32 +02:00
none
f12fe91b51 use PCI revision to determine major firmware version 2021-04-07 19:21:24 +02:00
none
35c283bf2f remove test command 2021-04-07 19:20:38 +02:00
none
41a9626be4 remove unnused variable 2021-04-07 19:20:24 +02:00
none
0d66d5bab0 Merge branch 'internal' 2021-03-18 19:03:57 +01:00
none
91af1be97e simple sx8 status info tool 2021-03-18 14:02:26 +01:00
none
a6c3b82f83 make include usable in user space 2021-03-18 13:48:09 +01:00
none
e863a2037a add byte array to union 2021-03-18 13:47:45 +01:00
none
92cd675f5d move ddbridge ioctls to separate file 2021-03-18 12:39:41 +01:00
none
dda8698514 add timeout status 2021-03-18 10:45:53 +01:00
none
fc9a89c870 add per demod lock for more fine-grained locking 2021-03-18 10:44:11 +01:00
none
4b0a0c4ff2 allow explicit setting of roll-off 2021-03-18 10:39:07 +01:00
none
2ac970ef83 typo 2021-03-18 10:36:51 +01:00
none
c3c734b0e8 remove unsused variables and code 2021-03-11 23:23:30 +01:00
none
8380cb185f change direct_mode to module parameter 2021-03-11 23:22:03 +01:00
none
f9eb03a065 remove unused entries 2021-03-11 23:20:31 +01:00
none
f8c97ad3d6 remove init dump, cannot access regs directly on all platforms 2021-03-11 22:43:12 +01:00
none
60646a6b26 experimental diseqc receive code 2021-03-11 22:33:13 +01:00
none
de0e970999 change input locked in fmode=4 and do not send emulated sequence as diseqc 2021-03-11 22:31:52 +01:00
none
cf35c3038b only get status if demod started 2021-03-10 22:03:56 +01:00
none
4c96f54ddf increase L-BAND to 3GHz 2021-03-10 21:46:29 +01:00
none
eb427a8df2 properly handle flash size limits 2021-03-10 21:38:19 +01:00
none
b200ce3596 allow source selection in non-unicable mode 2021-03-10 16:20:44 +01:00
none
31f36de0d7 set default source to undef 2021-03-10 16:20:44 +01:00
mocm
9269270c79 Added install link 2021-03-09 22:14:14 +01:00
drmocm
04fa5041d3 fixes 2021-03-09 22:06:10 +01:00
none
8f4cd19539 Merge branch 'internal' 2021-03-09 22:05:45 +01:00
drmocm
f3cbbf3ba7 Merge branch 'internal' of http://hippo:3000/rjkm/dddvb into internal 2021-03-09 21:40:52 +01:00
none
a2d39f90d5 add module parameter for disabling voltage output in Max cards. 2021-03-09 20:21:09 +01:00
none
7af71dfdcb lock ldpc bitrate adjustment to prevent race condition during tuner stop 2021-03-09 14:23:06 +01:00
drmocm
acb5931ed0 added README.md 2021-03-08 14:29:27 +01:00
none
476a105de7 Merge branch 'internal' 2021-03-01 13:06:05 +01:00
none
b025599e9f dump more buffer bytes in case of misalignment 2021-03-01 12:58:54 +01:00
none
9028e75f63 always use unaligned processing if detected once 2021-03-01 12:58:21 +01:00
none
177e6b0fd6 check if memory is aligned to 4K 2021-03-01 12:57:45 +01:00
none
de82a50b4e Set allocated memory to zero. 2021-03-01 12:57:20 +01:00
none
5714b85238 Merge branch 'internal' 2021-02-25 15:00:30 +01:00
none
01ca1b8805 Detect and report TS misalignment and switch to unaligned processing. 2021-02-25 14:58:42 +01:00
none
28e09191af Do not attach dummy with dvb attach. 2021-02-25 14:57:33 +01:00
none
abb2c56ddc output overflow as warning 2021-02-24 20:30:45 +01:00
none
c6ada48892 remove check for MCI base 2021-02-24 20:27:42 +01:00
none
baf6a090b8 use packet loss function 2021-02-24 20:25:27 +01:00
none
d259d69808 add packet loss function 2021-02-24 20:24:14 +01:00
none
f72c7b2256 print MCI info 2021-02-24 20:22:36 +01:00
none
c82c9d3218 old GCC does not like init in struct 2021-02-24 20:22:08 +01:00
none
1598ab98bc print MCI information at init 2021-02-24 20:21:57 +01:00
none
7efa935a30 remove debug messages 2021-02-24 20:20:10 +01:00
none
fc728ab51e only report I2C errors after probing is done 2021-02-24 20:19:06 +01:00
none
ea41e57ba3 disable master at driver shutdown 2021-02-24 20:17:50 +01:00
none
cd3868afff reenable gain control 2021-02-24 20:17:22 +01:00
none
b72f0365ea correctly check id 2021-02-24 20:16:43 +01:00
none
b3f2580e84 add flash name 2021-02-24 20:16:26 +01:00
none
f1976b5f74 always return if help requested 2021-02-24 20:13:24 +01:00
none
ee6787d2d0 add usage for force option 2021-02-24 20:12:54 +01:00
none
37eb11fb4b set iq_mode to 2 in start_iq() 2021-02-09 17:40:49 +01:00
none
a276a370cb always return lock with SDR mode 2021-02-09 17:30:48 +01:00
25 changed files with 1553 additions and 314 deletions

View File

@@ -6,6 +6,9 @@ We can only accept patches which don't break compilation for older kernels (as f
Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain
incompatiblities to this driver package. incompatiblities to this driver package.
For installation instructions see:
http://support.digital-devices.eu/index.php?article=152
### Prepare for Building ### Prepare for Building
TBD TBD

View File

@@ -1,4 +1,4 @@
all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo
cit: cit.c cit: cit.c
$(CC) -o cit cit.c -lpthread $(CC) -o cit cit.c -lpthread
@@ -15,6 +15,12 @@ setmod2: setmod2.c
setmod3: setmod3.c setmod3: setmod3.c
$(CC) -o setmod3 setmod3.c -I../include/ $(CC) -o setmod3 setmod3.c -I../include/
%.o: %.c modconfig: modconfig.c
$(CC) $(CFLAGS) -o $@ $< $(CC) -o modconfig modconfig.c -I../include/
%: %.c
$(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@
%.o: %.c
$(CC) $(CFLAGS) -I../ddbridge -o $@ $<

View File

@@ -10,7 +10,6 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/dvb/dmx.h> #include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
void proc_ts(int i, uint8_t *buf) void proc_ts(int i, uint8_t *buf)
{ {

457
apps/ddinfo.c Normal file
View File

@@ -0,0 +1,457 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "../ddbridge/ddbridge-mci.h"
#include "../ddbridge/ddbridge-ioctl.h"
char *Rolloff[8] = {
"0.35",
"0.25",
"0.20",
"0.10",
"0.05",
"0.15",
"rsvd",
"rsvd",
};
void print_temp(struct mci_result *res)
{
printf("Die temperature = %u\n", res->sx8_bist.temperature);
}
int temp_info(int dev)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = SX8_CMD_GETBIST,
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (msg.res.status & 0x80) {
printf("MCI errror %02x\n", msg.res.status);
return ret;
}
print_temp(&msg.res);
return ret;
}
#define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0]))
char *DemodStatus[] = {
"Idle",
"IQ Mode",
"Wait for Signal",
"DVB-S2 Wait for MATYPE",
"DVB-S2 Wait for FEC",
"DVB-S1 Wait for FEC",
"Wait for TS",
"Unknown 7",
"Unknown 8",
"Unknown 9",
"Unknown 10",
"Unknown 11",
"Unknown 12",
"Unknown 13",
"Timeout",
"Locked",
"C2 Scan",
};
char* S2ModCods[32] = {
/* 0x00 */ "DummyPL" ,
// Legacy S2: index is S2_Modcod * 2 + short
/* 0x01 */ "QPSK 1/4" ,
/* 0x02 */ "QPSK 1/3" ,
/* 0x03 */ "QPSK 2/5" ,
/* 0x04 */ "QPSK 1/2" ,
/* 0x05 */ "QPSK 3/5" ,
/* 0x06 */ "QPSK 2/3" ,
/* 0x07 */ "QPSK 3/4" ,
/* 0x08 */ "QPSK 4/5" ,
/* 0x09 */ "QPSK 5/6" ,
/* 0x0A */ "QPSK 8/9" ,
/* 0x0B */ "QPSK 9/10" ,
/* 0x0C */ "8PSK 3/5" ,
/* 0x0D */ "8PSK 2/3" ,
/* 0x0E */ "8PSK 3/4" ,
/* 0x0F */ "8PSK 5/6" ,
/* 0x10 */ "8PSK 8/9" ,
/* 0x11 */ "8PSK 9/10" ,
/* 0x12 */ "16APSK 2/3" ,
/* 0x13 */ "16APSK 3/4" ,
/* 0x14 */ "16APSK 4/5" ,
/* 0x15 */ "16APSK 5/6" ,
/* 0x16 */ "16APSK 8/9" ,
/* 0x17 */ "16APSK 9/10" ,
/* 0x18 */ "32APSK 3/4" ,
/* 0x19 */ "32APSK 4/5" ,
/* 0x1A */ "32APSK 5/6" ,
/* 0x1B */ "32APSK 8/9" ,
/* 0x1C */ "32APSK 9/10" ,
/* 0x1D */ "rsvd 0x1D" ,
/* 0x1E */ "rsvd 0x1E" ,
/* 0x1F */ "rsvd 0x1F" ,
};
///* 129 */ "VLSNR1" ,
///* 131 */ "VLSNR2" ,
char* S2XModCods[59] = {
/* 0x42 */ "QPSK 13/45" ,
/* 0x43 */ "QPSK 9/20" ,
/* 0x44 */ "QPSK 11/20" ,
/* 0x45 */ "8APSK 5/9-L" ,
/* 0x46 */ "8APSK 26/45-L" ,
/* 0x47 */ "8PSK 23/36" ,
/* 0x48 */ "8PSK 25/36" ,
/* 0x49 */ "8PSK 13/18" ,
/* 0x4A */ "16APSK 1/2-L" ,
/* 0x4B */ "16APSK 8/15-L" ,
/* 0x4C */ "16APSK 5/9-L" ,
/* 0x4D */ "16APSK 26/45" ,
/* 0x4E */ "16APSK 3/5" ,
/* 0x4F */ "16APSK 3/5-L" ,
/* 0x50 */ "16APSK 28/45" ,
/* 0x51 */ "16APSK 23/36" ,
/* 0x52 */ "16APSK 2/3-L" ,
/* 0x53 */ "16APSK 25/36" ,
/* 0x54 */ "16APSK 13/18" ,
/* 0x55 */ "16APSK 7/9" ,
/* 0x56 */ "16APSK 77/90" ,
/* 0x57 */ "32APSK 2/3-L" ,
/* 0x58 */ "rsvd 32APSK" ,
/* 0x59 */ "32APSK 32/45" ,
/* 0x5A */ "32APSK 11/15" ,
/* 0x5B */ "32APSK 7/9" ,
/* 0x5C */ "64APSK 32/45-L" ,
/* 0x5D */ "64APSK 11/15" ,
/* 0x5E */ "rsvd 64APSK" ,
/* 0x5F */ "64APSK 7/9" ,
/* 0x60 */ "rsvd 64APSK" ,
/* 0x61 */ "64APSK 4/5" ,
/* 0x62 */ "rsvd 64APSK" ,
/* 0x63 */ "64APSK 5/6" ,
/* 0x64 */ "128APSK 3/4" ,
/* 0x65 */ "128APSK 7/9" ,
/* 0x66 */ "256APSK 29/45-L" ,
/* 0x67 */ "256APSK 2/3-L" ,
/* 0x68 */ "256APSK 31/45-L" ,
/* 0x69 */ "256APSK 32/45" ,
/* 0x6A */ "256APSK 11/15-L" ,
/* 0x6B */ "256APSK 3/4" ,
/* 0x6C */ "QPSK 11/45-S" ,
/* 0x6D */ "QPSK 4/15-S" ,
/* 0x6E */ "QPSK 14/45-S" ,
/* 0x6F */ "QPSK 7/15-S" ,
/* 0x70 */ "QPSK 8/15-S" ,
/* 0x71 */ "QPSK 32/45-S" ,
/* 0x72 */ "8PSK 7/15-S" ,
/* 0x73 */ "8PSK 8/15-S" ,
/* 0x74 */ "8PSK 26/45-S" ,
/* 0x75 */ "8PSK 32/45-S" ,
/* 0x76 */ "16APSK 7/15-S" ,
/* 0x77 */ "16APSK 8/15-S" ,
/* 0x78 */ "16APSK 26/45-S" ,
/* 0x79 */ "16APSK 3/5-S" ,
/* 0x7A */ "16APSK 32/45-S" ,
/* 0x7B */ "32APSK 2/3-S" ,
/* 0x7C */ "32APSK 32/45-S" ,
};
char* S2Xrsvd[] = {
/* 250 */ "rsvd 8PSK" ,
/* 251 */ "rsvd 16APSK" ,
/* 252 */ "rsvd 32APSK" ,
/* 253 */ "rsvd 64APSK" ,
/* 254 */ "rsvd 256APSK" ,
/* 255 */ "rsvd 1024APSK" ,
};
char* PunctureRates[32] = {
/* 0x00 */ "QPSK 1/2", // DVB-S1
/* 0x01 */ "QPSK 2/3", // DVB-S1
/* 0x02 */ "QPSK 3/4", // DVB-S1
/* 0x03 */ "QPSK 5/6", // DVB-S1
/* 0x04 */ "QPSK 6/7", // DSS
/* 0x05 */ "QPSK 7/8", // DVB-S1
/* 0x06 */ "rsvd 6.0",
/* 0x07 */ "rsvd 7.0",
};
void print_info(struct mci_result *res, uint8_t demod)
{
if (res->status == MCI_DEMOD_STOPPED) {
printf("\nDemod %u: stopped\n", demod);
return;
}
printf("\nDemod %u:\n", demod);
if (res->status == MCI_DEMOD_LOCKED) {
switch (res->mode) {
case M4_MODE_DVBSX:
if (res->dvbs2_signal_info.standard == 2) {
int short_frame = 0;
if ((res->dvbs2_signal_info.pls_code >= 128) ||
((res->dvbs2_signal_info.roll_off & 0x7f) > 2))
printf("Demod Locked: DVB-S2X\n");
else
printf("Demod Locked: DVB-S2\n");
printf("PLS-Code: %u\n", res->dvbs2_signal_info.pls_code);
printf("Roll-Off: %s\n", Rolloff[res->dvbs2_signal_info.roll_off]);
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
printf("\n");
} else {
printf("Demod Locked: DVB-S\n");
printf("PR: %s\n",
PunctureRates[res->dvbs2_signal_info.pls_code & 0x07]);
}
case M4_MODE_DVBT:
printf("Locked DVB-T\n");
break;
case M4_MODE_DVBT2:
printf("Locked DVB-T2\n");
break;
}
printf("SNR: %.2f dB\n", (float) res->dvbs2_signal_info.signal_to_noise / 100);
printf("Packet Errors: %u\n", res->dvbs2_signal_info.packet_errors);
printf("BER Numerator: %u\n", res->dvbs2_signal_info.ber_numerator);
printf("BER Denom.: %u\n", res->dvbs2_signal_info.ber_denominator);
} else {
printf("Demod State: %s\n",
res->status < SIZE_OF_ARRAY(DemodStatus) ? DemodStatus[res->status] : "?");
}
printf("Frequency: %u Hz\n", res->dvbs2_signal_info.frequency);
printf("Symbol Rate: %u Symbols/s\n", res->dvbs2_signal_info.symbol_rate);
printf("Channel Power: %.2f dBm\n", (float) res->dvbs2_signal_info.channel_power / 100);
if (res->dvbs2_signal_info.band_power > -10000)
printf("Band Power: %.2f dBm\n", (float) res->dvbs2_signal_info.band_power / 100);
}
int mci_info(int dev, uint8_t demod)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = MCI_CMD_GETSIGNALINFO,
.cmd.demod = demod
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
print_info(&msg.res, demod);
return ret;
}
static int get_id(int fd, int link, struct ddb_id *id)
{
struct ddb_reg ddbreg;
if (link == 0) {
if (ioctl(fd, IOCTL_DDB_ID, id) < 0)
return -1;
return 0;
}
ddbreg.reg = 8 + (link << 28);
if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0)
return -1;
id->vendor = ddbreg.val;
id->device = ddbreg.val >> 16;
ddbreg.reg = 12 + (link << 28);
if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0)
return -1;
id->subvendor = ddbreg.val;
id->subdevice = ddbreg.val >> 16;
ddbreg.reg = 0 + (link << 28);
if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0)
return -1;
id->hw = ddbreg.val;
ddbreg.reg = 4 + (link << 28);
if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0)
return -1;
id->regmap = ddbreg.val;
return 0;
}
static char *id2name(uint16_t id)
{
switch (id) {
case 0x222:
return "MOD";
case 0x0009:
return "MAX SX8";
case 0x000b:
return "MAX SX8 Basic";
case 0x000a:
return "MAX M4";
default:
return " ";
}
}
static int card_info(int ddbnum, int demod)
{
char ddbname[80];
struct ddb_id ddbid;
int ddb, ret, link, links = 1, i;
struct ddb_id id;
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
ddb = open(ddbname, O_RDWR);
if (ddb < 0)
return -3;
for (link = 0; link < links; link++) {
ret = get_id(ddb, link, &id);
if (ret < 0)
goto out;
if (!link) {
switch (id.device) {
case 0x20:
links = 4;
break;
case 0x300:
case 0x301:
case 0x307:
links = 2;
break;
default:
break;
}
}
printf("\n\nCard %s link %u id %04x (%s):\n",
ddbname, link, id.device, id2name(id.device));
printf("HW %08x REGMAP %08x FW %u.%u\n",
id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff));
switch (id.device) {
case 0x0009:
if (demod >= 0)
mci_info(ddb, demod);
else {
for (i = 0; i < 8; i++)
mci_info(ddb, i);
}
temp_info(ddb);
break;
case 0x000a:
if (demod >= 0)
mci_info(ddb, demod);
else {
for (i = 0; i < 4; i++)
mci_info(ddb, i);
}
break;
default:
break;
}
}
out:
close(ddb);
return ret;
}
int main(int argc, char*argv[])
{
int fd = -1, all = 1, i, ret = 0;
char fn[128];
int32_t device = -1, demod = -1;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"demod", required_argument, 0, 'n'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ad:n:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'n':
demod = strtoul(optarg, NULL, 0);
break;
case 'a':
all = 1;
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
if (device >=0)
ret = card_info(device, demod);
else
for (i = 0; i < 100; i++) {
ret = card_info(i, -1);
if (ret == -3) /* could not open, no more cards! */
break;
if (ret < 0)
return i; /* fatal error */
}
}

392
apps/modconfig.c Normal file
View File

@@ -0,0 +1,392 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
#include <ctype.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "../ddbridge/ddbridge-mci.h"
#include "../ddbridge/ddbridge-ioctl.h"
struct mconf {
int set_output;
int set_channels;
int fd;
struct mci_command channels;
struct mci_command stream;
struct mci_command output;
};
void strim(char *s)
{
int l = strlen(s);
while (l && isspace(s[l-1]))
l--;
s[l] = 0;
}
void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *))
{
char line[256], csec[80], par[80], val[80], *p;
FILE *f;
if ((f = fopen(fname, "r")) == NULL)
return;
while ((p = fgets(line, sizeof(line), f))) {
if (*p == '\r' || *p == '\n' || *p == '#')
continue;
if (*p == '[') {
if ((p = strtok(line + 1, "]")) == NULL)
continue;
strncpy(csec, p, sizeof(csec));
if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL);
continue;
}
if (!(p = strtok(line, "=")))
continue;
while (isspace(*p))
p++;
strncpy(par, p, sizeof(par));
strim(par);
if (!(p = strtok(NULL, "=")))
continue;
while (isspace(*p))
p++;
strncpy (val, p, sizeof(val));
strim(val);
if (!strcmp(sec, csec) && cb)
cb(priv, par, val);
}
if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL);
fclose(f);
}
struct param_table_entry {
int value;
char* name;
};
struct param_table_entry mod_standard_table[] = {
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "0", .value = MOD_STANDARD_GENERIC },
{ .name = "1", .value = MOD_STANDARD_DVBT_8 },
{ .name = "2", .value = MOD_STANDARD_DVBT_7 },
{ .name = "3", .value = MOD_STANDARD_DVBT_6 },
{ .name = "4", .value = MOD_STANDARD_DVBT_5 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry stream_format_table[] = {
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = "0", .value = MOD_FORMAT_DEFAULT },
{ .name = "1", .value = MOD_FORMAT_IQ16 },
{ .name = "2", .value = MOD_FORMAT_IQ8 },
{ .name = "3", .value = MOD_FORMAT_IDX8 },
{ .name = "4", .value = MOD_FORMAT_TS },
{ .name = NULL, .value = 0 }
};
struct param_table_entry guard_interval_table[] = {
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = "0", .value = MOD_DVBT_GI_1_32 },
{ .name = "1", .value = MOD_DVBT_GI_1_16 },
{ .name = "2", .value = MOD_DVBT_GI_1_8 },
{ .name = "3", .value = MOD_DVBT_GI_1_4 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry puncture_rate_table[] = {
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = "1", .value = MOD_DVBT_PR_1_2 },
{ .name = "2", .value = MOD_DVBT_PR_2_3 },
{ .name = "3", .value = MOD_DVBT_PR_3_4 },
{ .name = "5", .value = MOD_DVBT_PR_5_6 },
{ .name = "7", .value = MOD_DVBT_PR_7_8 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry dvbt_constellation_table[] = {
{ .name = "0", .value = MOD_DVBT_QPSK },
{ .name = "qpsk", .value = MOD_DVBT_QPSK },
{ .name = "1", .value = MOD_DVBT_16QAM },
{ .name = "16qam", .value = MOD_DVBT_16QAM },
{ .name = "qam16", .value = MOD_DVBT_16QAM },
{ .name = "2", .value = MOD_DVBT_64QAM },
{ .name = "64qam", .value = MOD_DVBT_64QAM },
{ .name = "qam64", .value = MOD_DVBT_64QAM },
{ .name = NULL, .value = 0 }
};
int parse_param(char *val,struct param_table_entry *table, int *value) {
if (value) {
*value = 0;
if (table) {
while (table->name) {
if( !strcasecmp(val,table->name)) {
*value = table->value;
return 0;
}
table++;
}
}
}
return -1;
}
int mci_cmd(int dev, struct mci_command *cmd)
{
int ret;
struct ddb_mci_msg msg;
uint8_t status;
msg.link = 0;
memcpy(&msg.cmd, cmd, sizeof(msg.cmd));
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
dprintf(2, "mci_cmd error %d\n", errno);
return ret;
}
status = msg.res.status;
if (status == MCI_STATUS_OK)
return ret;
if (status == MCI_STATUS_UNSUPPORTED) {
dprintf(2, "Unsupported MCI command\n");
return ret;
}
if (status == MCI_STATUS_INVALID_PARAMETER) {
dprintf(2, "Invalid MCI parameters\n");
return ret;
}
return ret;
}
struct mci_command msg_channels = {
.mod_command = MOD_SETUP_CHANNELS,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_channels[0] = {
.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID,
.standard = MOD_STANDARD_DVBT_8,
.num_channels = 25,
.frequency = 474000000,
},
};
struct mci_command msg_stream = {
.mod_command = MOD_SETUP_STREAM,
.mod_channel = 1,
.mod_stream = 0,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBT_8,
.fft_size = 1,
.guard_interval = 0,
},
};
struct mci_command msg_output = {
.mod_command = MOD_SETUP_OUTPUT,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_output = {
.connector = MOD_CONNECTOR_F,
.num_channels = 16,
.unit = MOD_UNIT_DBUV,
.channel_power = 5000,
},
};
void output_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
if (!par && !val) {
mc->set_output = 1;
return;
}
if (!strcasecmp(par, "connector")) {
if (!strcasecmp(val, "F")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_F;
} else if (!strcasecmp(val, "SMA")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_SMA;
} else if (!strcasecmp(val, "OFF")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_OFF;
} else
printf("invalid connector\n");
} else if (!strcasecmp(par, "power")) {
mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0);
} else if (!strcasecmp(par, "channels")) {
mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10);
}else if (!strcasecmp(par, "unit")) {
if (!strcasecmp(val, "DBUV")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBUV;
} else if (!strcasecmp(val, "DBM")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBM;
} else
printf("invalid unit\n");
} else
printf("invalid output parameter: %s\n", par);
}
void channels_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
int value;
if (!par && !val) {
mc->set_channels = 1;
return;
}
if (!strcasecmp(par, "frequency")) {
mc->channels.mod_setup_channels[0].frequency = (uint32_t) (strtod(val, NULL) * 1000000.0);
printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency);
} else if (!strcasecmp(par, "channels")) {
mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_channels[0].standard = value;
} else if (!strcasecmp(par, "offset")) {
mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "bandwidth")) {
mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset =
mc->channels.mod_setup_channels[0].bandwidth / 2;
} else
printf("invalid channels parameter: %s\n", par);
}
void streams_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
int value;
if (!par && !val) {
return;
}
if (!strcasecmp(par, "fft_size")) {
mc->stream.mod_setup_stream.fft_size = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "guard_interval")) {
if (!parse_param(val,guard_interval_table,&value))
mc->stream.mod_setup_stream.guard_interval = value;
} else if (!strcasecmp(par, "puncture_rate")) {
if (!parse_param(val,puncture_rate_table,&value))
mc->stream.mod_setup_stream.puncture_rate = value;
} else if (!strcasecmp(par, "constellation")) {
if (!parse_param(val,dvbt_constellation_table,&value))
mc->stream.mod_setup_stream.constellation = value;
} else if (!strcasecmp(par, "cell_identifier")) {
mc->stream.mod_setup_stream.cell_identifier = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_stream.standard = value;
} else if (!strcasecmp(par, "stream_format")) {
if (!parse_param(val,stream_format_table,&value))
mc->stream.mod_setup_stream.stream_format = value;
} else if (!strcasecmp(par, "symbol_rate")) {
mc->stream.mod_setup_stream.symbol_rate = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "channel")) {
mc->stream.mod_channel = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "stream")) {
mc->stream.mod_stream = strtol(val, NULL, 10);
printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel);
mci_cmd(mc->fd, &mc->stream);
} else
printf("invalid streams parameter: %s = %s\n", par, val);
}
int main(int argc, char*argv[])
{
int fd = -1;
char fn[128];
uint32_t device = 0;
uint32_t frequency = 0;
char *configname = "modulator.conf";
struct mconf mc;
memset(&mc, 0, sizeof(mc));
mc.channels = msg_channels;
mc.stream = msg_stream;
mc.output = msg_output;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"config", required_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "d:c:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'c':
configname = optarg;
break;
case 'h':
dprintf(2, "modconfig [-d device_number] [-c config_file]\n");
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
snprintf(fn, 127, "/dev/ddbridge/card%u", device);
fd = open(fn, O_RDWR);
if (fd < 0) {
dprintf(2, "Could not open %s\n", fn);
return -1;
}
mc.fd = fd;
parse(configname, "channels", (void *) &mc, channels_cb);
if (mc.set_channels)
mci_cmd(fd, &mc.channels);
parse(configname, "streams", (void *) &mc, streams_cb);
parse(configname, "output", (void *) &mc, output_cb);
if (mc.set_output)
mci_cmd(fd, &mc.output);
}

51
apps/modulator.conf Normal file
View File

@@ -0,0 +1,51 @@
[output]
# connector = OFF, SMA or F
connector = F
# number of total channels to be used at the same time
# use lower number to have fewer channels but stronger signal per channel
channels = 16
# unit of power in DBUV or DBM
unit = DBUV
# power output in units of above unit
power = 50.0
# define channels:
# channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned
[channels]
# standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz
standard = 1
# numbers of channels to allocate, starting from frequency below
# this defines 25 channels at 474, 474+8, 474+16, etc. Mhz
channels = 25
# frequency of channel 0, following channels are spaced according to set standard
frequency = 474.0
[streams]
# number of streams depends on the card hardware
# streams correspond to devices mod0, mod1, ...
# channels are defined above in channels section
# 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4
guard_interval = 0
# 0 = 2K, 1 = 8K (2K not yet supported)
fft_size = 1
# all following streams will be set according to the last set other parameters
# example:
# this would set mod 1 to 474 MHz and mod0 to 482 MHz (474 + 8 MHz)
# both with guard interval 1/32 and 8K FFT
# and mod2 to 490MHz, guard interval 1/16 and 8K FFT
channel = 1
stream = 0
#
channel = 0
stream = 1
#
guard_interval = 1
channel = 2
stream = 2

View File

@@ -119,7 +119,7 @@ static int update_flash(struct ddflash *ddf)
printf("Flash: %s\n", ddf->flash_name); printf("Flash: %s\n", ddf->flash_name);
printf("Version: %08x\n", ddf->id.hw); printf("Version: %08x\n", ddf->id.hw);
printf("REGMAP : %08x\n", ddf->id.regmap); printf("REGMAP : %08x\n", ddf->id.regmap);
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1) if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
stat |= 1; stat |= 1;
return stat; return stat;
} }
@@ -200,6 +200,7 @@ static int usage()
"-n N\n only update card N (default with N=0)\n\n" "-n N\n only update card N (default with N=0)\n\n"
"-a \n update all cards\n\n" "-a \n update all cards\n\n"
"-b file\n fpga image file override (ignored if -a is used)\n\n" "-b file\n fpga image file override (ignored if -a is used)\n\n"
"-f \n force update\n\n"
"-v \n more verbose (up to -v -v -v)\n\n" "-v \n more verbose (up to -v -v -v)\n\n"
); );
} }
@@ -250,7 +251,7 @@ int main(int argc, char **argv)
break; break;
case 'h': case 'h':
usage(); usage();
break; return 0;
default: default:
break; break;

View File

@@ -50,15 +50,15 @@ struct flash_info flashs[] = {
{ { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" }, { { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" },
{ { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" }, { { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" },
{ { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" }, { { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" },
{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, { { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" },
{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, { { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" },
{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, { { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" },
{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, { { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" },
{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, { { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" },
{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, { { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" },
{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, { { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" },
{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, { { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" },
{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" }, { { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" },
{ { 0x00, 0x00, 0x00 }, UNKNOWN_FLASH, 0, 0, "Unknown" }, { { 0x00, 0x00, 0x00 }, UNKNOWN_FLASH, 0, 0, "Unknown" },
}; };
@@ -68,7 +68,7 @@ static struct flash_info *flash_getinfo(uint8_t *id)
while (f->id[0]) { while (f->id[0]) {
if ((f->id[0] == id[0]) && (f->id[1] == id[1]) && if ((f->id[0] == id[0]) && (f->id[1] == id[1]) &&
((id[0] == 0xff) || (f->id[0] == id[0]))) ((id[2] == 0xff) || (f->id[2] == id[2])))
break; break;
f++; f++;
} }
@@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen,
return -1; return -1;
len = off - fw_off; len = off - fw_off;
lseek(fs, fw_off, SEEK_SET); lseek(fs, fw_off, SEEK_SET);
#if 0
if (len > maxlen) { if (len > maxlen) {
printf("file too big\n"); printf("file too big\n");
return -1; return -1;
} }
#endif
//printf("flash file len %u, compare to %08x in flash: ", len, addr); //printf("flash file len %u, compare to %08x in flash: ", len, addr);
for (j = 0; j < len; j += bl, addr += bl) { for (j = 0; j < len; j += bl, addr += bl) {
if (len - j < bl) if (len - j < bl)
@@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
return -4; return -4;
} }
if (devid == ddf->id.device) { if (devid == ddf->id.device) {
if (version <= (ddf->id.hw & 0xffffff)) { if (version < (ddf->id.hw & 0xffffff)) {
printf("%s is older or same version as flash\n", fn); printf("%s is older version than flash\n", fn);
ret = -3; /* same id but no newer version */ if (!ddf->force)
ret = -3; /* same id but older newer version */
}
if (version == (ddf->id.hw & 0xffffff)) {
printf("%s is same version as flash\n", fn);
if (!ddf->force)
ret = 2; /* same and same version */
} }
} else } else
ret = 1; ret = 1;
@@ -1147,7 +1151,7 @@ out:
} }
static int update_image(struct ddflash *ddf, char *fn, static int update_image(struct ddflash *ddf, char *fn,
uint32_t adr, uint32_t len, uint32_t adr, uint32_t maxlen,
int has_header, int no_change) int has_header, int no_change)
{ {
int fs, res = 0; int fs, res = 0;
@@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn,
printf("File %s not found \n", fn); printf("File %s not found \n", fn);
return -1; return -1;
} }
res = flashcmp(ddf, fs, adr, len, fw_off); res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) { if (res == -2) {
printf("Flash already identical to %s\n", fn); printf("Flash already identical to %s\n", fn);
if (ddf->force) { if (ddf->force) {
@@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn,
} }
if (res < 0) if (res < 0)
goto out; goto out;
res = flashwrite(ddf, fs, adr, len, fw_off); res = flashwrite(ddf, fs, adr, maxlen, fw_off);
if (res == 0) { if (res == 0) {
res = flashcmp(ddf, fs, adr, len, fw_off); res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) { if (res == -2) {
res = 1; res = 1;
printf("Flash verify OK!\n"); printf("Flash verify OK!\n");

View File

@@ -58,7 +58,7 @@ int main(int argc, char*argv[])
struct dvb_mod_params mp; struct dvb_mod_params mp;
struct dvb_mod_channel_params mc; struct dvb_mod_channel_params mc;
uint32_t data; uint32_t data;
int adapter = 0, channel = 0, gain = -1; int32_t adapter = 0, channel = 0, gain = -1;
int32_t base = -1, freq = -1, rate = -1; int32_t base = -1, freq = -1, rate = -1;
char mod_name[128]; char mod_name[128];
@@ -113,7 +113,7 @@ int main(int argc, char*argv[])
} }
} }
if (optind < argc) { if (optind < argc) {
printf("too man arguments\n"); printf("too many arguments\n");
exit(1); exit(1);
} }
@@ -134,6 +134,8 @@ int main(int argc, char*argv[])
//get_property(fd, MODULATOR_ATTENUATOR, &data); //get_property(fd, MODULATOR_ATTENUATOR, &data);
//printf("Modulator attenuator = %u\n", data); //printf("Modulator attenuator = %u\n", data);
if (gain > 0)
set_property(fd, MODULATOR_GAIN, gain);
if (base > 0) if (base > 0)
set_property(fd, MODULATOR_BASE_FREQUENCY, base); set_property(fd, MODULATOR_BASE_FREQUENCY, base);
if (freq > 0) if (freq > 0)

View File

@@ -24,6 +24,7 @@
#include "ddbridge.h" #include "ddbridge.h"
#include "ddbridge-i2c.h" #include "ddbridge-i2c.h"
#include "ddbridge-io.h" #include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#include <media/dvb_net.h> #include <media/dvb_net.h>
struct workqueue_struct *ddb_wq; struct workqueue_struct *ddb_wq;
@@ -281,9 +282,9 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
for (i = 0; i < dma->num; i++) { for (i = 0; i < dma->num; i++) {
if (alt_dma) { if (alt_dma) {
#if (KERNEL_VERSION(4, 13, 0) > LINUX_VERSION_CODE) #if (KERNEL_VERSION(4, 13, 0) > LINUX_VERSION_CODE)
dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT); dma->vbuf[i] = kzalloc(dma->size, __GFP_REPEAT);
#else #else
dma->vbuf[i] = kmalloc(dma->size, __GFP_RETRY_MAYFAIL); dma->vbuf[i] = kzalloc(dma->size, __GFP_RETRY_MAYFAIL);
#endif #endif
if (!dma->vbuf[i]) if (!dma->vbuf[i])
return -ENOMEM; return -ENOMEM;
@@ -301,10 +302,12 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
dma->vbuf[i] = dma_alloc_coherent(&pdev->dev, dma->vbuf[i] = dma_alloc_coherent(&pdev->dev,
dma->size, dma->size,
&dma->pbuf[i], &dma->pbuf[i],
GFP_KERNEL); GFP_KERNEL | __GFP_ZERO);
if (!dma->vbuf[i]) if (!dma->vbuf[i])
return -ENOMEM; return -ENOMEM;
} }
if (((u64)dma->vbuf[i] & 0xfff))
dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]);
} }
return 0; return 0;
} }
@@ -527,6 +530,18 @@ static void ddb_output_stop(struct ddb_output *output)
} }
} }
static void update_loss(struct ddb_dma *dma)
{
struct ddb_input *input = (struct ddb_input *)dma->io;
u32 packet_loss = dma->packet_loss;
u32 cur_counter = ddbreadl(input->port->dev, TS_STAT(input)) & 0xffff;
if (cur_counter < (packet_loss & 0xffff))
packet_loss += 0x10000;
packet_loss = ((packet_loss & 0xffff0000) | cur_counter);
dma->packet_loss = packet_loss;
}
static void ddb_input_stop_unlocked(struct ddb_input *input) static void ddb_input_stop_unlocked(struct ddb_input *input)
{ {
struct ddb *dev = input->port->dev; struct ddb *dev = input->port->dev;
@@ -540,7 +555,8 @@ static void ddb_input_stop_unlocked(struct ddb_input *input)
dev_warn(input->port->dev->dev, dev_warn(input->port->dev->dev,
"DMA stalled %u times!\n", "DMA stalled %u times!\n",
input->dma->stall_count); input->dma->stall_count);
if (input->dma->packet_loss) update_loss(input->dma);
if (input->dma->packet_loss > 1)
dev_warn(input->port->dev->dev, dev_warn(input->port->dev->dev,
"%u packets lost due to low DMA performance!\n", "%u packets lost due to low DMA performance!\n",
input->dma->packet_loss); input->dma->packet_loss);
@@ -1068,7 +1084,11 @@ static int demod_attach_dummy(struct ddb_input *input)
{ {
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
#if 0
dvb->fe = dvb_attach(dummy_attach); dvb->fe = dvb_attach(dummy_attach);
#else
dvb->fe = dummy_attach();
#endif
return 0; return 0;
} }
@@ -2277,21 +2297,36 @@ static void input_write_dvb(struct ddb_input *input,
} }
while (dma->cbuf != ((dma->stat >> 11) & 0x1f) || (4 & dma->ctrl)) { while (dma->cbuf != ((dma->stat >> 11) & 0x1f) || (4 & dma->ctrl)) {
if (4 & dma->ctrl) { if (4 & dma->ctrl) {
/*dev_err(dev->dev, "Overflow dma %d\n", dma->nr);*/ dev_warn(dev->dev, "Overflow dma input %u\n", input->nr);
ack = 1; ack = 1;
} }
if (alt_dma) if (alt_dma)
dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
dma2->size, DMA_FROM_DEVICE); dma2->size, DMA_FROM_DEVICE);
if (raw_stream || input->con) if (raw_stream || input->con) {
dvb_dmx_swfilter_raw(&dvb->demux, dvb_dmx_swfilter_raw(&dvb->demux,
dma2->vbuf[dma->cbuf], dma2->vbuf[dma->cbuf],
dma2->size); dma2->size);
else } else {
dvb_dmx_swfilter_packets(&dvb->demux, if (dma2->unaligned || (dma2->vbuf[dma->cbuf][0] != 0x47)) {
if (!dma2->unaligned) {
dma2->unaligned++;
dev_warn(dev->dev, "Input %u dma buffer unaligned, "
"switching to unaligned processing.\n",
input->nr);
print_hex_dump(KERN_INFO, "TS: ", DUMP_PREFIX_OFFSET, 32, 1,
dma2->vbuf[dma->cbuf],
512, false);
}
dvb_dmx_swfilter(&dvb->demux,
dma2->vbuf[dma->cbuf], dma2->vbuf[dma->cbuf],
dma2->size / 188); dma2->size);
} else
dvb_dmx_swfilter_packets(&dvb->demux,
dma2->vbuf[dma->cbuf],
dma2->size / 188);
}
dma->cbuf = (dma->cbuf + 1) % dma2->num; dma->cbuf = (dma->cbuf + 1) % dma2->num;
if (ack) if (ack)
ddbwritel(dev, (dma->cbuf << 11), ddbwritel(dev, (dma->cbuf << 11),
@@ -2321,16 +2356,7 @@ static void input_tasklet(unsigned long data)
} }
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma)); dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma)); dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
update_loss(dma);
{
u32 packet_loss = dma->packet_loss;
u32 cur_counter = ddbreadl(dev, TS_STAT(input)) & 0xffff;
if (cur_counter < (packet_loss & 0xffff))
packet_loss += 0x10000;
packet_loss = ((packet_loss & 0xffff0000) | cur_counter);
dma->packet_loss = packet_loss;
}
if (4 & dma->ctrl) if (4 & dma->ctrl)
dma->stall_count++; dma->stall_count++;
if (input->redi) if (input->redi)
@@ -3162,76 +3188,6 @@ static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg, u32 mdio_base)
return ddbreadl(dev, MDIO_VAL_OFF + mdio_base); return ddbreadl(dev, MDIO_VAL_OFF + mdio_base);
} }
#define DDB_MAGIC 'd'
struct ddb_flashio {
__u8 *write_buf;
__u32 write_len;
__u8 *read_buf;
__u32 read_len;
__u32 link;
};
struct ddb_gpio {
__u32 mask;
__u32 data;
};
struct ddb_id {
__u16 vendor;
__u16 device;
__u16 subvendor;
__u16 subdevice;
__u32 hw;
__u32 regmap;
};
struct ddb_reg {
__u32 reg;
__u32 val;
};
struct ddb_mem {
__u32 off;
__u8 *buf;
__u32 len;
};
struct ddb_mdio {
__u8 adr;
__u8 reg;
__u16 val;
};
struct ddb_i2c_msg {
__u8 bus;
__u8 adr;
__u8 *hdr;
__u32 hlen;
__u8 *msg;
__u32 mlen;
};
struct ddb_mci_msg {
__u32 link;
struct mci_command cmd;
struct mci_result res;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
#define DDB_NAME "ddbridge" #define DDB_NAME "ddbridge"
static u32 ddb_num; static u32 ddb_num;
@@ -3453,8 +3409,6 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (msg.link > 3) if (msg.link > 3)
return -EFAULT; return -EFAULT;
link = &dev->link[msg.link]; link = &dev->link[msg.link];
if (!link->mci_base)
return -EFAULT;
res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res); res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res);
if (copy_to_user(parg, &msg, sizeof(msg))) if (copy_to_user(parg, &msg, sizeof(msg)))
return -EFAULT; return -EFAULT;

74
ddbridge/ddbridge-ioctl.h Normal file
View File

@@ -0,0 +1,74 @@
#ifndef _DDBRIDGE_IOCTL_H_
#define _DDBRIDGE_IOCTL_H_
#define DDB_MAGIC 'd'
struct ddb_flashio {
__u8 *write_buf;
__u32 write_len;
__u8 *read_buf;
__u32 read_len;
__u32 link;
};
struct ddb_gpio {
__u32 mask;
__u32 data;
};
struct ddb_id {
__u16 vendor;
__u16 device;
__u16 subvendor;
__u16 subdevice;
__u32 hw;
__u32 regmap;
};
struct ddb_reg {
__u32 reg;
__u32 val;
};
struct ddb_mem {
__u32 off;
__u8 *buf;
__u32 len;
};
struct ddb_mdio {
__u8 adr;
__u8 reg;
__u16 val;
};
struct ddb_i2c_msg {
__u8 bus;
__u8 adr;
__u8 *hdr;
__u32 hlen;
__u8 *msg;
__u32 mlen;
};
struct ddb_mci_msg {
__u32 link;
struct mci_command cmd;
struct mci_result res;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
#endif

View File

@@ -392,19 +392,23 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
struct m4 *state = fe->demodulator_priv; struct m4 *state = fe->demodulator_priv;
struct mci_result res; struct mci_result res;
*status = 0x00;
if (!state->started)
return 0;
stat = ddb_mci_get_status(&state->mci, &res); stat = ddb_mci_get_status(&state->mci, &res);
if (stat) if (stat)
return stat; return stat;
*status = 0x00;
stat = ddb_mci_get_info(&state->mci); stat = ddb_mci_get_info(&state->mci);
if (stat) if (stat)
return stat; return stat;
ddb_mci_get_strength(fe); ddb_mci_get_strength(fe);
if (res.status == MCI_DEMOD_WAIT_SIGNAL) if (res.status == MCI_DEMOD_WAIT_SIGNAL)
*status = 0x01; *status = 0x01;
if (res.status == M4_DEMOD_WAIT_TS) else if (res.status == M4_DEMOD_WAIT_TS)
*status = 0x03; *status = 0x03;
if (res.status == MCI_DEMOD_LOCKED) { else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT;
else if (res.status == MCI_DEMOD_LOCKED) {
*status = 0x1f; *status = 0x1f;
ddb_mci_get_snr(fe); ddb_mci_get_snr(fe);
} }

View File

@@ -139,6 +139,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
ddb_buffers_free(dev); ddb_buffers_free(dev);
ddb_unmap(dev); ddb_unmap(dev);
pci_clear_master(pdev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev); pci_disable_device(pdev);
} }
@@ -311,6 +312,7 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.subvendor = id->subvendor; dev->link[0].ids.subvendor = id->subvendor;
dev->link[0].ids.subdevice = pdev->subsystem_device; dev->link[0].ids.subdevice = pdev->subsystem_device;
dev->link[0].ids.devid = (id->device << 16) | id->vendor; dev->link[0].ids.devid = (id->device << 16) | id->vendor;
dev->link[0].ids.revision = pdev->revision;
dev->link[0].dev = dev; dev->link[0].dev = dev;
dev->link[0].info = get_ddb_info(id->vendor, id->device, dev->link[0].info = get_ddb_info(id->vendor, id->device,
@@ -335,8 +337,10 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid = ddbreadl(dev, 0); dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4); dev->link[0].ids.regmapid = ddbreadl(dev, 4);
dev_info(dev->dev, "HW %08x REGMAP %08x\n", dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid); dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
dev->link[0].ids.hwid & 0xffff);
if ((dev->link[0].ids.hwid & 0xffffff) < if ((dev->link[0].ids.hwid & 0xffffff) <
dev->link[0].info->hw_min) { dev->link[0].info->hw_min) {
u32 min = dev->link[0].info->hw_min; u32 min = dev->link[0].info->hw_min;

View File

@@ -40,6 +40,10 @@ static int old_quattro;
module_param(old_quattro, int, 0444); module_param(old_quattro, int, 0444);
MODULE_PARM_DESC(old_quattro, "old quattro LNB input order "); MODULE_PARM_DESC(old_quattro, "old quattro LNB input order ");
static int no_voltage;
module_param(no_voltage, int, 0444);
MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone).");
/* MAX LNB interface related functions */ /* MAX LNB interface related functions */
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
@@ -61,7 +65,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
return 0; return 0;
} }
static int max_set_input_unlocked(struct dvb_frontend *fe, int in); static int max_set_input(struct dvb_frontend *fe, int in);
static int max_emulate_switch(struct dvb_frontend *fe, static int max_emulate_switch(struct dvb_frontend *fe,
u8 *cmd, u32 len) u8 *cmd, u32 len)
@@ -75,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe,
return -1; return -1;
input = cmd[3] & 3; input = cmd[3] & 3;
max_set_input_unlocked(fe, input); max_set_input(fe, input);
return 0; return 0;
} }
@@ -94,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
return 0; return 0;
if (fmode == 4) if (fmode == 4)
max_emulate_switch(fe, cmd->msg, cmd->msg_len); if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len))
return 0;
if (dvb->diseqc_send_master_cmd) if (dvb->diseqc_send_master_cmd)
dvb->diseqc_send_master_cmd(fe, cmd); dvb->diseqc_send_master_cmd(fe, cmd);
@@ -164,6 +169,8 @@ static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input,
{ {
int s = 0; int s = 0;
if (no_voltage)
voltage = SEC_VOLTAGE_OFF;
if (dev->link[link].lnb.oldvoltage[input] == voltage) if (dev->link[link].lnb.oldvoltage[input] == voltage)
return 0; return 0;
switch (voltage) { switch (voltage) {

View File

@@ -34,10 +34,16 @@ static int mci_reset(struct ddb_link *link)
u32 control; u32 control;
u32 status = 0; u32 status = 0;
u32 timeout = 40; u32 timeout = 40;
union {
if (!regmap || ! regmap->mci) u32 u[4];
char s[16];
} version;
u32 vaddr;
if (!regmap || !regmap->mci)
return -EINVAL; return -EINVAL;
control = regmap->mci->base; control = regmap->mci->base;
vaddr = regmap->mci_buf->base + 0xf0;
if ((link->info->type == DDB_OCTOPUS_MCI) && if ((link->info->type == DDB_OCTOPUS_MCI) &&
(ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) {
@@ -55,11 +61,17 @@ static int mci_reset(struct ddb_link *link)
msleep(50); msleep(50);
} }
dev_info(link->dev->dev, "MCI control port @ %08x\n", control); dev_info(link->dev->dev, "MCI control port @ %08x\n", control);
if ((status & MCI_CONTROL_READY) == 0) { if ((status & MCI_CONTROL_READY) == 0) {
dev_err(link->dev->dev, "MCI init failed!\n"); dev_err(link->dev->dev, "MCI init failed!\n");
return -1; return -1;
} }
dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40-timeout)*50); version.u[0] = ddblreadl(link, vaddr);
version.u[1] = ddblreadl(link, vaddr + 4);
version.u[2] = ddblreadl(link, vaddr + 8);
version.u[3] = ddblreadl(link, vaddr + 12);
dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50);
dev_info(link->dev->dev, "MCI firmware version %s.%d\n", version.s, version.s[15]);
return 0; return 0;
} }
@@ -108,6 +120,7 @@ static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link,
0xffffff, INTERRUPT_ACK); 0xffffff, INTERRUPT_ACK);
} }
} }
//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false);
if (res && res_len) if (res && res_len)
for (i = 0; i < res_len; i++) for (i = 0; i < res_len; i++)
res[i] = ddblreadl(link, result + i * 4); res[i] = ddblreadl(link, result + i * 4);
@@ -166,11 +179,10 @@ int mci_init(struct ddb_link *link)
int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val) int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val)
{ {
struct mci_result result; struct mci_result result;
struct mci_command command = { struct mci_command command;
.command_word = cmd,
.params = { val },
};
command.command_word = cmd;
command.params[0] = val;
return ddb_mci_cmd_link(link, &command, &result); return ddb_mci_cmd_link(link, &command, &result);
} }
@@ -209,6 +221,21 @@ int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1); return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1);
} }
static void ddb_mci_print_info(struct mci *mci)
{
struct ddb_link *link = mci->base->link;
const struct ddb_regmap *regmap = link->info->regmap;
struct mci_command cmd;
struct mci_result res;
cmd.command = 0x0f;
if (ddb_mci_cmd_raw(mci, &cmd, 1, &res, 1) < 0)
return;
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE,
16, false);
}
int ddb_mci_get_snr(struct dvb_frontend *fe) int ddb_mci_get_snr(struct dvb_frontend *fe)
{ {
struct mci *mci = fe->demodulator_priv; struct mci *mci = fe->demodulator_priv;

View File

@@ -132,6 +132,7 @@
#define MCI_BANDWIDTH_7MHZ (7) #define MCI_BANDWIDTH_7MHZ (7)
#define MCI_BANDWIDTH_8MHZ (8) #define MCI_BANDWIDTH_8MHZ (8)
#define SX8_CMD_GETBIST (0x0F)
#define SX8_CMD_INPUT_ENABLE (0x40) #define SX8_CMD_INPUT_ENABLE (0x40)
#define SX8_CMD_INPUT_DISABLE (0x41) #define SX8_CMD_INPUT_DISABLE (0x41)
#define SX8_CMD_START_IQ (0x42) #define SX8_CMD_START_IQ (0x42)
@@ -154,7 +155,7 @@
#define M4_L1INFO_SEL_PLPINFO (2) #define M4_L1INFO_SEL_PLPINFO (2)
#define M4_L1INFO_SEL_PLPINFO_C (3) #define M4_L1INFO_SEL_PLPINFO_C (3)
#define M4_L1INFO_SEL_SETID (0x80) #define M4_L1INFO_SEL_SETID (0x80)
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan #define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
#define M4_MODE_DVBSX (2) #define M4_MODE_DVBSX (2)
@@ -166,13 +167,13 @@
#define M4_MODE_ISDBT (8) #define M4_MODE_ISDBT (8)
#define M4_MODE_ISDBC (9) #define M4_MODE_ISDBC (9)
#define M4_MODE_ISDBS (10) #define M4_MODE_ISDBS (10)
#define M4_DVBC_CONSTELLATION_16QAM (0) #define M4_DVBC_CONSTELLATION_16QAM (0)
#define M4_DVBC_CONSTELLATION_32QAM (1) #define M4_DVBC_CONSTELLATION_32QAM (1)
#define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C #define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
#define M4_DVBC_CONSTELLATION_128QAM (3) #define M4_DVBC_CONSTELLATION_128QAM (3)
#define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C #define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
#define M4_SIGNALINFO_FLAG_CHANGE (0x01) #define M4_SIGNALINFO_FLAG_CHANGE (0x01)
#define M4_SIGNALINFO_FLAG_EWS (0x02) #define M4_SIGNALINFO_FLAG_EWS (0x02)
@@ -181,10 +182,86 @@
#define SX8_ROLLOFF_20 2 #define SX8_ROLLOFF_20 2
#define SX8_ROLLOFF_15 5 #define SX8_ROLLOFF_15 5
#define SX8_ROLLOFF_10 3 #define SX8_ROLLOFF_10 3
#define SX8_ROLLOFF_05 4 #define SX8_ROLLOFF_05 4
#define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0) #define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0)
/********************************************************/
#define MOD_SETUP_CHANNELS (0x60)
#define MOD_SETUP_OUTPUT (0x61)
#define MOD_SETUP_STREAM (0x62)
#define MOD_SET_STREAM_CHANNEL (0x63)
#define MOD_SETUP_FLAG_FIRST (0x01)
#define MOD_SETUP_FLAG_LAST (0x02)
#define MOD_SETUP_FLAG_VALID (0x80)
#define MOD_STANDARD_GENERIC (0x00)
#define MOD_STANDARD_DVBT_8 (0x01)
#define MOD_STANDARD_DVBT_7 (0x02)
#define MOD_STANDARD_DVBT_6 (0x03)
#define MOD_STANDARD_DVBT_5 (0x04)
#define MOD_CONNECTOR_OFF (0x00)
#define MOD_CONNECTOR_F (0x01)
#define MOD_CONNECTOR_SMA (0x02)
#define MOD_UNIT_DBUV (0x00)
#define MOD_UNIT_DBM (0x01)
#define MOD_FORMAT_DEFAULT (0x00)
#define MOD_FORMAT_IQ16 (0x01)
#define MOD_FORMAT_IQ8 (0x02)
#define MOD_FORMAT_IDX8 (0x03)
#define MOD_FORMAT_TS (0x04)
#define MOD_DVBT_FFT_8K (0x01)
#define MOD_DVBT_GI_1_32 (0x00)
#define MOD_DVBT_GI_1_16 (0x01)
#define MOD_DVBT_GI_1_8 (0x02)
#define MOD_DVBT_GI_1_4 (0x03)
#define MOD_DVBT_PR_1_2 (0x00)
#define MOD_DVBT_PR_2_3 (0x01)
#define MOD_DVBT_PR_3_4 (0x02)
#define MOD_DVBT_PR_5_6 (0x03)
#define MOD_DVBT_PR_7_8 (0x04)
#define MOD_DVBT_QPSK (0x00)
#define MOD_DVBT_16QAM (0x01)
#define MOD_DVBT_64QAM (0x02)
struct mod_setup_channels {
u8 flags;
u8 standard;
u8 num_channels;
u8 rsvd;
u32 frequency;
u32 offset; /* used only when Standard == 0 */
u32 bandwidth; /* used only when Standard == 0 */
};
struct mod_setup_stream {
u8 standard;
u8 stream_format;
u8 rsvd1[2];
u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */
u8 fft_size; /* 0 = 2K, 1 = 8K (2K yet supported) */
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */
u8 constellation;
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
};
struct mod_setup_output {
u8 connector; /* 0 = OFF, 1 = F, 2 = SMA */
u8 num_channels; /* max active channels, determines max power for each channel. */
u8 unit; /* 0 = dBµV, 1 = dBm, */
u8 rsvd;
s16 channel_power;
};
/********************************************************/ /********************************************************/
@@ -197,6 +274,12 @@ struct mci_command {
u8 demod; u8 demod;
u8 output; u8 output;
}; };
struct {
u8 mod_command;
u8 mod_channel;
u8 mod_stream;
u8 mod_rsvd1;
};
}; };
union { union {
u32 params[31]; u32 params[31];
@@ -215,7 +298,7 @@ struct mci_command {
u32 scrambling_sequence_index; u32 scrambling_sequence_index;
u32 frequency_range; u32 frequency_range;
u8 channel_bonding_config; /* Bit 7: IsSlave, Bit 5..4: MasterDemod, u8 channel_bonding_config; /* Bit 7: IsSlave, Bit 5..4: MasterDemod,
bit 0: Num channels - 2. bit 0: Num channels - 2.
(must be set on all channels to same value) */ (must be set on all channels to same value) */
} dvbs2_search; } dvbs2_search;
@@ -236,7 +319,7 @@ struct mci_command {
u8 retry; u8 retry;
u32 frequency; u32 frequency;
} dvbc_search; } dvbc_search;
struct { struct {
u8 flags; /* Bit 0: LP Stream */ u8 flags; /* Bit 0: LP Stream */
u8 bandwidth; u8 bandwidth;
@@ -244,7 +327,7 @@ struct mci_command {
u8 retry; u8 retry;
u32 frequency; u32 frequency;
} dvbt_search; } dvbt_search;
struct { struct {
u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */ u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */
u8 bandwidth; u8 bandwidth;
@@ -255,7 +338,7 @@ struct mci_command {
u8 plp; u8 plp;
u8 rsvd2[3]; u8 rsvd2[3];
} dvbt2_search; } dvbt2_search;
struct { struct {
u8 flags; u8 flags;
u8 bandwidth; u8 bandwidth;
@@ -267,15 +350,15 @@ struct mci_command {
u8 data_slice; u8 data_slice;
u8 rsvd2[2]; u8 rsvd2[2];
} dvbc2_search; } dvbc2_search;
struct { struct {
u8 flags; u8 flags;
u8 bandwidth; u8 bandwidth;
u8 rsvd1; u8 rsvd1;
u8 retry; u8 retry;
u32 frequency; u32 frequency;
} isdbt_search; } isdbt_search;
struct { struct {
u8 flags; /* Bit 0: 0 = TSID is Transport Stream ID, 1 = TSID is relative stream number */ u8 flags; /* Bit 0: 0 = TSID is Transport Stream ID, 1 = TSID is relative stream number */
/* Bit 2..1: 0 = force single, 1 = force multi, 2 = auto detect */ /* Bit 2..1: 0 = force single, 1 = force multi, 2 = auto detect */
@@ -287,7 +370,7 @@ struct mci_command {
u16 onid; u16 onid;
u16 tsid; u16 tsid;
} isdbc_search; } isdbc_search;
struct { struct {
u8 flags; u8 flags;
u8 bandwidth; u8 bandwidth;
@@ -297,7 +380,7 @@ struct mci_command {
} j83b_search; } j83b_search;
struct { struct {
u8 flags; // Bit 0 : 1 = short info (1st 4 Bytes) u8 flags; /* Bit 0 : 1 = short info (1st 4 Bytes) */
} get_signalinfo; } get_signalinfo;
struct { struct {
@@ -307,43 +390,47 @@ struct mci_command {
} get_iq_symbol; } get_iq_symbol;
struct { struct {
uint8_t flags; /* Bit 0 : 0 = VTM/SDR, 1 = SCAN, u8 flags; /* Bit 0 : 0 = VTM/SDR, 1 = SCAN,
Bit 1: 1 = Disable AGC, Bit 1: 1 = Disable AGC,
Bit 2: 1 = Set Gain. */ Bit 2: 1 = Set Gain. */
uint8_t roll_off; u8 roll_off;
uint8_t rsvd1; u8 rsvd1;
uint8_t rsvd2; u8 rsvd2;
uint32_t frequency; u32 frequency;
uint32_t symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ u32 symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/
uint8_t gain; /* Gain in 0.25 dB Steps */ u8 gain; /* Gain in 0.25 dB Steps */
/* Frequency, symbolrate and gain can be schanged while running */ /* Frequency, symbolrate and gain can be schanged while running */
} sx8_start_iq; } sx8_start_iq;
struct { struct {
uint8_t flags; u8 flags;
/* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) , /* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
2 = Medium, 3 = Maximum gain {~ 15dB} 2 = Medium, 3 = Maximum gain {~ 15dB}
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
Bit 4: Set RF Gain Bit 4: Set RF Gain
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
Bit 7: Optimize RF Gain and freeze for FFT */ Bit 7: Optimize RF Gain and freeze for FFT */
uint8_t rf_gain; /* 0 .. 50 dB */ u8 rf_gain; /* 0 .. 50 dB */
} sx8_input_enable; } sx8_input_enable;
struct { struct {
u8 offset; // Offset into list, must be multiple of 64 u8 offset; /* Offset into list, must be multiple of 64 */
u8 select; // 0 = Slices, 1 = PLPs (C2 Only) u8 select; /* 0 = Slices, 1 = PLPs (C2 Only) */
u8 data_slice; // DataSlice to get PLPList (C2 Only) u8 data_slice; /* DataSlice to get PLPList (C2 Only) */
} get_ids; } get_ids;
struct { struct {
u8 select; // 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID u8 select; /* 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID */
u8 id; // DataSliceID, PLPId u8 id; /* DataSliceID, PLPId */
} get_l1_info; } get_l1_info;
struct { struct {
u8 select; // 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 u8 select; /* 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 */
} get_bb_header; } get_bb_header;
struct mod_setup_channels mod_setup_channels[4];
struct mod_setup_stream mod_setup_stream;
struct mod_setup_output mod_setup_output;
}; };
}; };
@@ -356,26 +443,27 @@ struct mci_result {
u16 time; u16 time;
}; };
}; };
union { union {
u32 result[27]; u32 result[27];
u8 result8[27 * 4];
struct { struct {
u8 Rsvd0[3]; u8 Rsvd0[3];
u8 Flags; u8 Flags;
u32 frequency; // actual frequency in Hz u32 frequency; /* actual frequency in Hz */
u32 rsvd1; u32 rsvd1;
s16 channel_power; // channel power in dBm x 100 s16 channel_power; /* channel power in dBm x 100 */
s16 rsvd2; s16 rsvd2;
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2 s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd3; s16 rsvd3;
u32 rsvd4; u32 rsvd4;
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator; u32 ber_denominator;
u32 ber_rsvd1; // Place holder for modulation bit error rate u32 ber_rsvd1; /* Place holder for modulation bit error rate */
u32 ber_rsvd2; u32 ber_rsvd2;
} common_signal_info; } common_signal_info;
struct { struct {
u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */ u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */
u8 pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */ u8 pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */
@@ -389,7 +477,7 @@ struct mci_result {
s16 rsvd2; s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */ 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_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator; u32 ber_denominator;
} dvbs2_signal_info; } dvbs2_signal_info;
struct { struct {
@@ -404,7 +492,7 @@ struct mci_result {
s16 rsvd2; s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */ 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_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator; u32 ber_denominator;
} isdbs_signal_info; } isdbs_signal_info;
struct { struct {
@@ -425,8 +513,8 @@ struct mci_result {
struct { struct {
u8 modulation1; // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High u8 modulation1; // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High
u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode
u8 Rsvd0; u8 rsvd0;
u8 Flags; u8 flags;
u32 frequency; /* actual frequency in Hz */ u32 frequency; /* actual frequency in Hz */
u32 rsvd1; u32 rsvd1;
s16 channel_power; /* channel power in dBm x 100 */ s16 channel_power; /* channel power in dBm x 100 */
@@ -455,7 +543,7 @@ struct mci_result {
struct { struct {
u8 rsvd0[3]; u8 rsvd0[3];
u8 flags; u8 flags;
u32 frequency; // actual frequency in Hz u32 frequency; // actual frequency in Hz
u32 rsvd1; // u32 rsvd1; //
s16 channel_power; // channel power in dBm x 100 s16 channel_power; // channel power in dBm x 100
@@ -464,7 +552,7 @@ struct mci_result {
s16 rsvd2; s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command) u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreBCH u32 ber_numerator; // Bit error rate: PreBCH
u32 ber_denominator; u32 ber_denominator;
} dvbc2_signal_info; } dvbc2_signal_info;
struct { struct {
@@ -487,51 +575,51 @@ struct mci_result {
} isdbt_signal_info; } isdbt_signal_info;
struct { struct {
u8 Constellation; u8 constellation;
u8 Rsvd0[2]; u8 rsvd0[2];
u8 Flags; u8 flags;
u32 Frequency; // actual frequency in Hz u32 frequency; // actual frequency in Hz
u32 SymbolRate; // actual symbolrate in Hz u32 symbol_rate; // actual symbolrate in Hz
s16 ChannelPower; // channel power in dBm x 100 s16 channel_power; // channel power in dBm x 100
s16 BandPower; // band power in dBm x 100 s16 band_power; // band power in dBm x 100
s16 SignalToNoise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2 s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 Rsvd2; s16 rsvd2;
u32 PacketErrors; // Counter for packet errors. (set to 0 on Start command) u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 BERNumerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X u32 ber_numerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 BERDenominator; u32 ber_denominator;
} ISDBC_SignalInfo; } isdbc_signal_info;
struct { struct {
u8 Constellation; u8 constellation;
u8 Interleaving; u8 interleaving;
u8 Rsvd0; u8 rsvd0;
u8 Flags; u8 flags;
u32 Frequency; // actual frequency in Hz u32 frequency; // actual frequency in Hz
u32 SymbolRate; // actual symbolrate in Hz u32 symbol_rate; // actual symbolrate in Hz
s16 ChannelPower; // channel power in dBm x 100 s16 channel_power; // channel power in dBm x 100
s16 BandPower; // band power in dBm x 100 s16 band_power; // band power in dBm x 100
s16 SignalToNoise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2 s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 Rsvd2; s16 rsvd2;
u32 PacketErrors; // Counter for packet errors. (set to 0 on Start command) u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 BERNumerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X u32 ber_numerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 BERDenominator; u32 ber_denominator;
} J83B_SignalInfo; } j83b_signal_info;
struct { struct {
s16 i; s16 i;
s16 q; s16 q;
} iq_symbol; } iq_symbol;
struct { struct {
u8 TPSInfo[7]; u8 tps_info[7];
// uint16_t TPS_CellID; // Cell Identifier // uint16_t tps_cell_id;
} DVBT_TPSInfo; } DVBT_TPSInfo;
struct { struct {
struct { struct {
u8 Type; u8 type;
u8 BWExtension; u8 BWExtension;
u8 S1; u8 S1;
u8 S2; u8 S2;
@@ -557,6 +645,7 @@ struct mci_result {
u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit
u8 CRC32[4]; u8 CRC32[4];
} DVBT2_L1Pre; } DVBT2_L1Pre;
struct { struct {
u8 SubSlicesPerFrame[2]; u8 SubSlicesPerFrame[2];
u8 NumPLP; u8 NumPLP;
@@ -569,7 +658,7 @@ struct mci_result {
u8 FEFInterval; u8 FEFInterval;
} DVBT2_L1Post; } DVBT2_L1Post;
} DVBT2_L1Info; } DVBT2_L1Info;
struct { struct {
u8 PLPID; u8 PLPID;
u8 Type; u8 Type;
@@ -589,7 +678,7 @@ struct mci_result {
u8 InBandAFlag; u8 InBandAFlag;
u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1 u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1
} DVBT2_PLPInfo; } DVBT2_PLPInfo;
struct { struct {
u8 NetworkID[2]; u8 NetworkID[2];
u8 C2SystemID[2]; u8 C2SystemID[2];
@@ -608,13 +697,13 @@ struct mci_result {
u8 ReservedTone; u8 ReservedTone;
u8 Reserved4[2]; // EWS 1 bit, C2_Version 4 bit, Rsvd 11 bit u8 Reserved4[2]; // EWS 1 bit, C2_Version 4 bit, Rsvd 11 bit
} DVBC2_L1Part2; } DVBC2_L1Part2;
struct { struct {
u8 NumIDs; u8 NumIDs;
u8 Offset; u8 Offset;
u8 IDs[64]; u8 IDs[64];
} DVBC2_IDList; } DVBC2_IDList;
struct { struct {
u8 SliceID; u8 SliceID;
u8 TunePosition[2]; u8 TunePosition[2];
@@ -628,7 +717,7 @@ struct mci_result {
u8 NumPLP; u8 NumPLP;
u8 Reserved2; u8 Reserved2;
} DVBC2_SliceInfo; } DVBC2_SliceInfo;
struct { struct {
u8 PLPID; u8 PLPID;
u8 Bundled; u8 Bundled;
@@ -644,7 +733,7 @@ struct mci_result {
u8 OrginalNetworkID[2]; u8 OrginalNetworkID[2];
u8 Reserved1; u8 Reserved1;
} DVBC2_PLPInfo; } DVBC2_PLPInfo;
struct { struct {
u8 Valid; u8 Valid;
u8 MATYPE_1; u8 MATYPE_1;
@@ -679,6 +768,13 @@ struct mci_result {
u8 Flags; // Bit 5: EWS flag, bit 4: Site Diversity flag, bit 3..1: Site Diversity information, bit 0: Extension flag u8 Flags; // Bit 5: EWS flag, bit 4: Site Diversity flag, bit 3..1: Site Diversity information, bit 0: Extension flag
u8 Extension[8]; // 61 bits, right aligned u8 Extension[8]; // 61 bits, right aligned
} ISDBS_TMCCInfo; } ISDBS_TMCCInfo;
struct {
uint8_t cut;
uint8_t avs_code;
uint8_t temperature;
uint8_t rsvd[13];
} sx8_bist;
}; };
u32 version[3]; u32 version[3];
u8 version_rsvd; u8 version_rsvd;
@@ -758,6 +854,8 @@ struct mci_result {
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01) #define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01) #define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
#ifdef __KERNEL__
struct mci_base { struct mci_base {
struct list_head mci_list; struct list_head mci_list;
void *key; void *key;
@@ -797,9 +895,10 @@ int ddb_mci_get_info(struct mci *mci);
int ddb_mci_get_strength(struct dvb_frontend *fe); int ddb_mci_get_strength(struct dvb_frontend *fe);
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
int mci_init(struct ddb_link *link); int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val); int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val);
extern struct mci_cfg ddb_max_sx8_cfg; extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg; extern struct mci_cfg ddb_max_m4_cfg;
#endif
#endif #endif

View File

@@ -644,7 +644,6 @@ static int mod_set_sdr_attenuator(struct ddb *dev, u32 value)
static int mod_set_sdr_gain(struct ddb *dev, u32 gain) static int mod_set_sdr_gain(struct ddb *dev, u32 gain)
{ {
u32 control = ddbreadl(dev, SDR_CONTROL); u32 control = ddbreadl(dev, SDR_CONTROL);
struct ddb_link *link = &dev->link[0];
if (control & 0x01000000) { if (control & 0x01000000) {
if (gain > 511) if (gain > 511)
@@ -659,8 +658,6 @@ static int mod_set_sdr_gain(struct ddb *dev, u32 gain)
return -EINVAL; return -EINVAL;
ddbwritel(dev, gain, SDR_GAIN_F); ddbwritel(dev, gain, SDR_GAIN_F);
} }
if (link->mci_ok)
mci_cmd_val(link, 0xc0, gain);
return 0; return 0;
} }
@@ -2032,6 +2029,9 @@ static int mod_init_sdr_iq(struct ddb *dev)
ddbwritel(dev, 0x01, 0x240); ddbwritel(dev, 0x01, 0x240);
if (dev->link[0].ids.revision == 1)
return 0;
//mod3_set_base_frequency(dev, 602000000); //mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000; dev->mod_base.frequency = 570000000;
for (i = 0; i < streams; i++) { for (i = 0; i < streams; i++) {

View File

@@ -30,6 +30,10 @@ static int default_mod = 3;
module_param(default_mod, int, 0444); module_param(default_mod, int, 0444);
MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)");
static int direct_mode;
module_param(direct_mode, int, 0444);
MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate.");
static const u32 MCLK = (1550000000 / 12); static const u32 MCLK = (1550000000 / 12);
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
@@ -44,25 +48,19 @@ struct sx8_base {
struct mci_base mci_base; struct mci_base mci_base;
u8 tuner_use_count[SX8_TUNER_NUM]; u8 tuner_use_count[SX8_TUNER_NUM];
u32 gain_mode[SX8_TUNER_NUM];
u32 used_ldpc_bitrate[SX8_DEMOD_NUM]; u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
u8 demod_in_use[SX8_DEMOD_NUM]; u8 demod_in_use[SX8_DEMOD_NUM];
u32 iq_mode; u32 iq_mode;
u32 burst_size;
u32 direct_mode;
}; };
struct sx8 { struct sx8 {
struct mci mci; struct mci mci;
struct mutex lock;
int first_time_lock; int first_time_lock;
int started; int started;
int iq_started; int iq_started;
u32 bb_mode;
u32 local_frequency;
}; };
static const u8 dvbs2_bits_per_symbol[] = { static const u8 dvbs2_bits_per_symbol[] = {
@@ -126,31 +124,47 @@ static int ddb_mci_tsconfig(struct mci *state, u32 config)
static int read_status(struct dvb_frontend *fe, enum fe_status *status) static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{ {
int stat; int stat = 0;
struct sx8 *state = fe->demodulator_priv; struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base; struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_result res; struct mci_result res;
*status = 0x00;
mutex_lock(&state->lock);
if (!state->started && !state->iq_started)
goto unlock;
stat = ddb_mci_get_status(&state->mci, &res); stat = ddb_mci_get_status(&state->mci, &res);
if (stat) if (stat)
return stat; goto unlock;
*status = 0x00;
ddb_mci_get_info(&state->mci); ddb_mci_get_info(&state->mci);
if (res.status == SX8_DEMOD_WAIT_MATYPE) if (stat)
*status = 0x0f; goto unlock;
if (res.status == MCI_DEMOD_LOCKED) { if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) {
*status = 0x1f; *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI |
if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { FE_HAS_CARRIER | FE_HAS_SIGNAL;
sx8_base->used_ldpc_bitrate[state->mci.nr] = if (res.status == MCI_DEMOD_LOCKED) {
p->symbol_rate * mutex_lock(&mci_base->tuner_lock);
dvbs2_bits_per_symbol[ if (state->first_time_lock && state->started) {
state->mci.signal_info. if (state->mci.signal_info.dvbs2_signal_info.standard == 2) {
dvbs2_signal_info.pls_code]; sx8_base->used_ldpc_bitrate[state->mci.nr] =
} else p->symbol_rate *
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; dvbs2_bits_per_symbol[
} state->mci.signal_info.
dvbs2_signal_info.pls_code];
} else
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
state->first_time_lock = 0;
}
mutex_unlock(&mci_base->tuner_lock);
}
} else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT;
else if (res.status >= SX8_DEMOD_WAIT_MATYPE)
*status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
unlock:
mutex_unlock(&state->lock);
return stat; return stat;
} }
@@ -158,14 +172,12 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on,
u8 flags, u8 gain) u8 flags, u8 gain)
{ {
struct sx8 *state = fe->demodulator_priv; 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; struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.tuner = state->mci.tuner; cmd.tuner = state->mci.tuner;
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
cmd.sx8_input_enable.flags = flags;//sx8_base->gain_mode[state->mci.tuner]; cmd.sx8_input_enable.flags = flags;
cmd.sx8_input_enable.rf_gain = gain; cmd.sx8_input_enable.rf_gain = gain;
return ddb_mci_cmd(&state->mci, &cmd, NULL); return ddb_mci_cmd(&state->mci, &cmd, NULL);
} }
@@ -195,9 +207,9 @@ static int stop_iq(struct dvb_frontend *fe)
state->mci.demod = SX8_DEMOD_NONE; state->mci.demod = SX8_DEMOD_NONE;
} }
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
mutex_unlock(&mci_base->tuner_lock);
sx8_base->iq_mode = 0; sx8_base->iq_mode = 0;
state->iq_started = 0; state->iq_started = 0;
mutex_unlock(&mci_base->tuner_lock);
return 0; return 0;
} }
@@ -207,12 +219,13 @@ static int stop(struct dvb_frontend *fe)
struct mci_base *mci_base = state->mci.base; struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct mci_command cmd; struct mci_command cmd;
u32 input = state->mci.tuner; u32 input;
input = state->mci.tuner;
if (!state->started) if (!state->started)
return -1; return -1;
memset(&cmd, 0, sizeof(cmd));
if (state->mci.demod != SX8_DEMOD_NONE) { if (state->mci.demod != SX8_DEMOD_NONE) {
memset(&cmd, 0, sizeof(cmd));
cmd.command = MCI_CMD_STOP; cmd.command = MCI_CMD_STOP;
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_cmd(&state->mci, &cmd, NULL);
@@ -234,8 +247,8 @@ static int stop(struct dvb_frontend *fe)
} }
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
sx8_base->iq_mode = 0; sx8_base->iq_mode = 0;
mutex_unlock(&mci_base->tuner_lock);
state->started = 0; state->started = 0;
mutex_unlock(&mci_base->tuner_lock);
return 0; return 0;
} }
@@ -253,6 +266,10 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
u32 bits_per_symbol = 0; u32 bits_per_symbol = 0;
int i = -1, stat = 0; int i = -1, stat = 0;
struct ddb_link *link = state->mci.base->link; struct ddb_link *link = state->mci.base->link;
const u8 ro_lut[8] = {
8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0,
8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0,
};
if (link->ids.device == 0x000b) { if (link->ids.device == 0x000b) {
/* Mask out higher modulations and MIS for Basic /* Mask out higher modulations and MIS for Basic
@@ -280,7 +297,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
goto unlock; goto unlock;
} }
if (sx8_base->direct_mode) { if (direct_mode) {
if (p->symbol_rate >= MCLK / 2) { if (p->symbol_rate >= MCLK / 2) {
if (state->mci.nr < 4) if (state->mci.nr < 4)
i = state->mci.nr; i = state->mci.nr;
@@ -302,16 +319,15 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate;
if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE)
free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE;
while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate)
bits_per_symbol--; bits_per_symbol--;
if (bits_per_symbol < 2) { if (bits_per_symbol < 2) {
stat = -EBUSY; stat = -EBUSY;
goto unlock; goto unlock;
} }
modmask &= ((1 << (bits_per_symbol - 1)) - 1); modmask &= ((1 << (bits_per_symbol - 1)) - 1);
if( ((flags & 0x02) != 0) && (modmask == 0)) { if (((flags & 0x02) != 0) && (modmask == 0)) {
stat = -EBUSY; stat = -EBUSY;
goto unlock; goto unlock;
} }
@@ -337,11 +353,10 @@ unlock:
if (stat) if (stat)
return stat; return stat;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
if (sx8_base->iq_mode) { if (sx8_base->iq_mode) {
cmd.command = SX8_CMD_ENABLE_IQOUTPUT; cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
cmd.output = p->stream_id & 7; cmd.output = p->stream_id & 0x0f;
ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_tsconfig(&state->mci, ts_config); ddb_mci_tsconfig(&state->mci, ts_config);
} }
@@ -357,6 +372,7 @@ unlock:
cmd.command = MCI_CMD_SEARCH_DVBS; cmd.command = MCI_CMD_SEARCH_DVBS;
cmd.dvbs2_search.flags = flags; cmd.dvbs2_search.flags = flags;
cmd.dvbs2_search.s2_modulation_mask = modmask; cmd.dvbs2_search.s2_modulation_mask = modmask;
cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7];
cmd.dvbs2_search.retry = 2; cmd.dvbs2_search.retry = 2;
cmd.dvbs2_search.frequency = p->frequency * 1000; cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate; cmd.dvbs2_search.symbol_rate = p->symbol_rate;
@@ -370,6 +386,9 @@ unlock:
(p->stream_id & 0x80000000)) (p->stream_id & 0x80000000))
cmd.output |= 0x80; cmd.output |= 0x80;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL); stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
state->started = 1;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
if (stat) if (stat)
stop(fe); stop(fe);
return stat; return stat;
@@ -388,8 +407,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
u32 input = state->mci.tuner; u32 input = state->mci.tuner;
int i, stat = 0; int i, stat = 0;
mutex_lock(&mci_base->tuner_lock);
if (!state->iq_started) { if (!state->iq_started) {
mutex_lock(&mci_base->tuner_lock);
if (sx8_base->iq_mode) { if (sx8_base->iq_mode) {
stat = -EBUSY; stat = -EBUSY;
goto unlock; goto unlock;
@@ -402,17 +421,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
goto unlock; goto unlock;
} }
state->mci.demod = 0; 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->tuner_use_count[input]++;
sx8_base->iq_mode = (ts_config > 1); sx8_base->iq_mode = 2;
unlock: } else {
mutex_unlock(&mci_base->tuner_lock); if ((state->iq_started & 0x07) != state->mci.nr) {
if (stat) stat = -EBUSY;
return stat; goto unlock;
}
} }
unlock:
mutex_unlock(&mci_base->tuner_lock);
if (stat)
return stat;
mci_set_tuner(fe, input, 1, flags & 0xff, 0); mci_set_tuner(fe, input, 1, flags & 0xff, 0);
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.command = SX8_CMD_START_IQ; cmd.command = SX8_CMD_START_IQ;
@@ -424,6 +444,9 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
cmd.tuner = state->mci.tuner; cmd.tuner = state->mci.tuner;
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL); stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
state->iq_started = 8 | state->mci.nr;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
if (stat) if (stat)
stop_iq(fe); stop_iq(fe);
ddb_mci_tsconfig(&state->mci, ts_config); ddb_mci_tsconfig(&state->mci, ts_config);
@@ -436,7 +459,6 @@ static int set_lna(struct dvb_frontend *fe)
return 0; return 0;
} }
static int set_parameters(struct dvb_frontend *fe) static int set_parameters(struct dvb_frontend *fe)
{ {
int stat = 0; int stat = 0;
@@ -452,6 +474,7 @@ static int set_parameters(struct dvb_frontend *fe)
state->mci.input->con = ts_mode << 8; state->mci.input->con = ts_mode << 8;
if (iq_mode) if (iq_mode)
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
mutex_lock(&state->lock);
stop(fe); stop(fe);
if (iq_mode < 2) { if (iq_mode < 2) {
u32 mask; u32 mask;
@@ -478,19 +501,10 @@ static int set_parameters(struct dvb_frontend *fe)
break; break;
} }
stat = start(fe, 3, mask, ts_config); stat = start(fe, 3, mask, ts_config);
if (!stat) {
state->started = 1;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
}
} else { } else {
stat = start_iq(fe, isi & 0xffffff, 4, ts_config); stat = start_iq(fe, isi & 0xffffff, 4, ts_config);
if (!stat) {
state->iq_started = 1;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
}
} }
mutex_unlock(&state->lock);
return stat; return stat;
} }
@@ -529,16 +543,22 @@ static int set_input(struct dvb_frontend *fe, int input)
return -EINVAL; return -EINVAL;
if (state->mci.tuner == input) if (state->mci.tuner == input)
return 0; return 0;
mutex_lock(&state->lock);
stop_iq(fe); stop_iq(fe);
stop(fe); stop(fe);
state->mci.tuner = p->input = input; state->mci.tuner = p->input = input;
mutex_unlock(&state->lock);
return 0; return 0;
} }
static int sleep(struct dvb_frontend *fe) static int sleep(struct dvb_frontend *fe)
{ {
struct sx8 *state = fe->demodulator_priv;
mutex_lock(&state->lock);
stop_iq(fe); stop_iq(fe);
stop(fe); stop(fe);
mutex_unlock(&state->lock);
return 0; return 0;
} }
@@ -584,6 +604,7 @@ static int init(struct mci *mci)
state->mci.demod = SX8_DEMOD_NONE; state->mci.demod = SX8_DEMOD_NONE;
mci->fe.ops.xbar[1] = mci->nr; mci->fe.ops.xbar[1] = mci->nr;
mci->fe.dtv_property_cache.input = mci->tuner; mci->fe.dtv_property_cache.input = mci->tuner;
mutex_init(&state->lock);
return 0; return 0;
} }

View File

@@ -143,6 +143,7 @@ struct ddb_ids {
u32 regmapid; u32 regmapid;
u32 devid; u32 devid;
u32 mac; u32 mac;
u8 revision;
}; };
struct ddb_info { struct ddb_info {
@@ -219,6 +220,7 @@ struct ddb_dma {
u32 stall_count; u32 stall_count;
u32 packet_loss; u32 packet_loss;
u32 unaligned;
}; };
struct ddb_dvb { struct ddb_dvb {

View File

@@ -54,6 +54,7 @@ struct cxd_state {
struct dvb_frontend frontend; struct dvb_frontend frontend;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct mutex mutex; struct mutex mutex;
int repi2cerr;
u8 adrt; u8 adrt;
u8 curbankt; u8 curbankt;
@@ -91,12 +92,13 @@ struct cxd_state {
u8 is24MHz; u8 is24MHz;
}; };
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len, int flag)
{ {
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = adr, .flags = 0, .buf = data, .len = len}; .addr = adr, .flags = 0, .buf = data, .len = len};
if (i2c_transfer(adap, &msg, 1) != 1) { if (i2c_transfer(adap, &msg, 1) != 1) {
pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); if (flag)
pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]);
return -1; return -1;
} }
return 0; return 0;
@@ -113,14 +115,14 @@ static int writeregs(struct cxd_state *state, u8 adr, u8 reg,
} }
data[0] = reg; data[0] = reg;
memcpy(data + 1, regd, len); memcpy(data + 1, regd, len);
return i2c_write(state->i2c, adr, data, len + 1); return i2c_write(state->i2c, adr, data, len + 1, state->repi2cerr);
} }
static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat)
{ {
u8 mm[2] = {reg, dat}; u8 mm[2] = {reg, dat};
return i2c_write(state->i2c, adr, mm, 2); return i2c_write(state->i2c, adr, mm, 2, state->repi2cerr);
} }
static int i2c_read(struct i2c_adapter *adap, static int i2c_read(struct i2c_adapter *adap,
@@ -130,17 +132,19 @@ static int i2c_read(struct i2c_adapter *adap,
.buf = msg, .len = len}, .buf = msg, .len = len},
{ .addr = adr, .flags = I2C_M_RD, { .addr = adr, .flags = I2C_M_RD,
.buf = answ, .len = alen } }; .buf = answ, .len = alen } };
if (i2c_transfer(adap, msgs, 2) != 2) { if (i2c_transfer(adap, msgs, 2) != 2)
pr_err("cxd2843: i2c_read error\n");
return -1; return -1;
}
return 0; return 0;
} }
static int readregs(struct cxd_state *state, u8 adr, u8 reg, static int readregs(struct cxd_state *state, u8 adr, u8 reg,
u8 *val, int count) u8 *val, int count)
{ {
return i2c_read(state->i2c, adr, &reg, 1, val, count); int ret = i2c_read(state->i2c, adr, &reg, 1, val, count);
if (ret && state->repi2cerr)
pr_err("cxd2843: i2c_read error\n");
return ret;
} }
static int readregst_unlocked(struct cxd_state *cxd, u8 bank, static int readregst_unlocked(struct cxd_state *cxd, u8 bank,
@@ -1644,7 +1648,7 @@ static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg)
/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */
state->IF_FS = 0x50; state->IF_FS = 0x50;
state->is24MHz = (cfg->osc == 24000000) ? 1 : 0; state->is24MHz = (cfg->osc == 24000000) ? 1 : 0;
printk("is24Mhz = %u\n", state->is24MHz); printk("is24Mhz = %u, adr = %02x\n", state->is24MHz, cfg->adr);
} }
static int get_tune_settings(struct dvb_frontend *fe, static int get_tune_settings(struct dvb_frontend *fe,
@@ -2646,8 +2650,9 @@ static int probe(struct cxd_state *state)
status = readregsx(state, 0x00, 0xFD, &ChipID, 1); status = readregsx(state, 0x00, 0xFD, &ChipID, 1);
if (status) if (status)
return status; return status;
printk("ChipID = %02X\n", ChipID); state->repi2cerr = 1;
//pr_info("cxd2843: ChipID = %02X\n", ChipID);
switch (ChipID) { switch (ChipID) {
case 0xa4: case 0xa4:
state->type = CXD2843; state->type = CXD2843;
@@ -2682,7 +2687,6 @@ struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
{ {
struct cxd_state *state = NULL; struct cxd_state *state = NULL;
pr_info("attach\n");
state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL);
if (!state) if (!state)
return NULL; return NULL;

View File

@@ -208,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val)
return write_reg(state, field >> 16, new); return write_reg(state, field >> 16, new);
} }
static int read_field(struct stv *state, u32 field, u8 *val)
{
int status;
u8 shift, mask;
status = read_reg(state, field >> 16, val);
if (status)
return status;
mask = field & 0xff;
shift = (field >> 12) & 0xf;
*val = (*val & mask) >> shift;
return status;
}
#define set_field(_reg, _val) \ #define set_field(_reg, _val) \
write_field(state, state->nr ? FSTV0910_P2_##_reg : \ write_field(state, state->nr ? FSTV0910_P2_##_reg : \
FSTV0910_P1_##_reg, _val) FSTV0910_P1_##_reg, _val)
#define get_field(_reg, _val) \
read_field(state, state->nr ? FSTV0910_P2_##_reg : \
FSTV0910_P1_##_reg, _val)
#define set_reg(_reg, _val) \ #define set_reg(_reg, _val) \
write_reg(state, state->nr ? RSTV0910_P2_##_reg : \ write_reg(state, state->nr ? RSTV0910_P2_##_reg : \
RSTV0910_P1_##_reg, _val) RSTV0910_P1_##_reg, _val)
#define get_reg(_reg, _val) \ #define get_reg(_reg, _val) \
read_reg(state, state->nr ? RSTV0910_P2_##_reg : \ read_reg(state, state->nr ? RSTV0910_P2_##_reg : \
RTV0910_P1_##_reg, _val) RSTV0910_P1_##_reg, _val)
static const struct slookup s1_sn_lookup[] = { static const struct slookup s1_sn_lookup[] = {
{ 0, 9242 }, /* C/N= 0dB */ { 0, 9242 }, /* C/N= 0dB */
@@ -1112,8 +1130,9 @@ static int init_diseqc(struct stv *state)
u16 offs = state->nr ? 0x40 : 0; /* Address offset */ u16 offs = state->nr ? 0x40 : 0; /* Address offset */
u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32));
/* Disable receiver */ write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05);
write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); //write_reg(state, RSTV0910_P1_DISRXF220 + offs, 0x69); 2b?
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */
write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq);
@@ -1617,12 +1636,28 @@ static int wait_dis(struct stv *state, u8 flag, u8 val)
return -1; return -1;
} }
static int clear_slave(struct dvb_frontend *fe)
{
struct stv *state = fe->demodulator_priv;
u8 n, d, done;
get_field(RXEND, &done);
get_reg(DISRXBYTES, &n);
printk("clear: done = %u, %u fifo bytes\n", done, n);
for (get_reg(DISRXBYTES, &n); n; n--)
get_reg(DISRXFIFO, &d);
return 0;
}
static int send_master_cmd(struct dvb_frontend *fe, static int send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd) struct dvb_diseqc_master_cmd *cmd)
{ {
struct stv *state = fe->demodulator_priv; struct stv *state = fe->demodulator_priv;
int i; int i;
clear_slave(fe);
set_field(DISRX_ON, 0);
set_reg(DISTXCFG, 0x3e); set_reg(DISTXCFG, 0x3e);
for (i = 0; i < cmd->msg_len; i++) { for (i = 0; i < cmd->msg_len; i++) {
wait_dis(state, 0x40, 0x00); wait_dis(state, 0x40, 0x00);
@@ -1630,12 +1665,59 @@ static int send_master_cmd(struct dvb_frontend *fe,
} }
set_reg(DISTXCFG, 0x3a); set_reg(DISTXCFG, 0x3a);
wait_dis(state, 0x20, 0x20); wait_dis(state, 0x20, 0x20);
set_field(DISRX_ON, 1);
return 0; return 0;
} }
static int recv_slave_reply(struct dvb_frontend *fe, static int recv_slave_reply(struct dvb_frontend *fe,
struct dvb_diseqc_slave_reply *reply) struct dvb_diseqc_slave_reply *reply)
{ {
struct stv *state = fe->demodulator_priv;
int i, to, flag = 0, max = sizeof(reply->msg);
u8 done, val, n = 0;
#if 0
get_reg(DISRXBYTES, &val);
get_field(RXEND, &done);
printk("slave: done = %u, %u fifo bytes\n", done, val);
#endif
to = reply->timeout;
if (to < 0) {
to = 100;
flag = 1;
} else if (to > 5000)
to = 100;
reply->msg_len = 0;
for (i = 0; i < to; i += 10) {
get_reg(DISRXBYTES, &val);
if (flag && val)
break;
get_field(RXEND, &done);
if (val >= max || done)
break;
msleep(10);
}
get_reg(DISRXBYTES, &val);
printk("done = %u, %u fifo bytes, i=%u\n", done, val, i);
if (i == to && !val)
return -EIO;
if (done && !val)
return -EIO;
for (i = 100; i; i--) {
get_field(RXEND, &done);
for (get_reg(DISRXBYTES, &n); n; n--) {
if (reply->msg_len == max)
return 0;
get_reg(DISRXFIFO, &reply->msg[reply->msg_len++]);
}
if (!n || done)
break;
msleep(10);
}
if (!i)
return -EIO;
return 0; return 0;
} }

View File

@@ -447,18 +447,13 @@ static int attach_init(struct tda_state *state)
if (!state->m_isMaster) if (!state->m_isMaster)
state->m_bLTEnable = false; state->m_bLTEnable = false;
/*pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID,
state->m_isMaster ? "master" : "slave");*/
if (state->m_ID != 18212) if (state->m_ID != 18212)
return -1; return -1;
stat = read_reg(state, POWER_STATE_1 , &PowerState); stat = read_reg(state, POWER_STATE_1 , &PowerState);
if (stat < 0) if (stat < 0)
return stat; return stat;
/*pr_info("tda18212dd: PowerState %02x\n", PowerState);*/
if (state->m_isMaster) { if (state->m_isMaster) {
if (PowerState & 0x02) { if (PowerState & 0x02) {
/* msleep for XTAL Calibration /* msleep for XTAL Calibration
@@ -539,7 +534,6 @@ static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel)
if (*pPowerLevel > 110) if (*pPowerLevel > 110)
*pPowerLevel = 110; *pPowerLevel = 110;
} while (0); } while (0);
/* pr_info("PL %d\n", *pPowerLevel); */
return status; return status;
} }
@@ -806,7 +800,6 @@ static int set_params(struct dvb_frontend *fe)
bw = (p->bandwidth_hz + 999999) / 1000000; bw = (p->bandwidth_hz + 999999) / 1000000;
state->m_Frequency = p->frequency; state->m_Frequency = p->frequency;
/*pr_info("tuner bw=%u freq=%u\n", bw, state->m_Frequency);*/
if (p->delivery_system == SYS_DVBT || if (p->delivery_system == SYS_DVBT ||
p->delivery_system == SYS_DVBT2 || p->delivery_system == SYS_DVBT2 ||
p->delivery_system == SYS_ISDBT || p->delivery_system == SYS_ISDBT ||

49
lib/README.md Normal file
View File

@@ -0,0 +1,49 @@
# LIBDDDVB
The libdddvb provides a userspace library to simplify tuning and
CI use. It detects DVB cards and their capabilities and selects
free frontends depending on a given delivery system.
In order to install the libdddvb library you need the dvben50221.
On an Ubuntu and other Debian based system you can install it like this:
`sudo apt-get install dvb-apps`
After that you can build the libdddvb:
`git clone https://github.com/DigitalDevices/dddvb.git`
`cd dddvb/lib/; make`
`sudo make install`
If your distribution does not include a dvb-apps package, you can follow the
instructions at
https://www.linuxtv.org/wiki/index.php/LinuxTV_dvb-apps
on how to build it yourself.
# DDZAP
You can now use the example program ddzap to see how the library
is used or to test your cards.
A typical usage example would be the tuning of a
sattelite channel with a given LNB configuration.
`ddzap -d S2 -p h -f 11494000 -s 22000000 -c ~/dddvb/lib/config/`
where you would use the example configuration file for a unicable LNB
given in the sources. If you leave out the `-c` option a standard universal
LNB is assumed to be connected.
Additionally you can use ddzap to open the /dev/dvb/adaptorX/dvrY device
that corresponds to the tuner that was automatically selected by the library
and pipe it to a media player, e.g.
`ddzap -d S2 -p h -f 11494000 -s 22000000 -c /home/dmocm/ddzapconf/ -o|vlc -`

View File

@@ -271,7 +271,7 @@ int main(int argc, char **argv)
struct dddvb_fe *fe; struct dddvb_fe *fe;
struct dddvb_params p; struct dddvb_params p;
uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF; uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0; uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = DDDVB_UNDEF;
uint32_t mtype= DDDVB_UNDEF; uint32_t mtype= DDDVB_UNDEF;
uint32_t verbosity = 0; uint32_t verbosity = 0;
uint32_t get_ts = 1; uint32_t get_ts = 1;

View File

@@ -288,7 +288,8 @@ static int tune_sat(struct dddvb_fe *fe)
freq = lofs - freq; freq = lofs - freq;
} }
#endif #endif
if (freq > 2100000) {
if (freq > 3000000) {
if (lofs) if (lofs)
hi = (freq > lofs) ? 1 : 0; hi = (freq > lofs) ? 1 : 0;
if (hi) if (hi)
@@ -318,14 +319,15 @@ static int tune_sat(struct dddvb_fe *fe)
fe->scif_slot, fe->scif_freq, ds); fe->scif_slot, fe->scif_freq, ds);
pthread_mutex_unlock(&fe->dd->uni_lock); pthread_mutex_unlock(&fe->dd->uni_lock);
} else { } else {
uint32_t input = lnb; uint32_t input = fe->param.param[PARAM_SRC];
//if (input != DDDVB_UNDEF) if (input != DDDVB_UNDEF) {
// input = 3 & (input >> 6); input = 3 & (input >> 6);
//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6)); printf("input = %u\n", input);
}
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi); diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
//set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);
set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U)); //set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, DDDVB_UNDEF);
} }
} }
@@ -750,6 +752,8 @@ int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p)
memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param)); memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param));
fe->n_tune = 1; fe->n_tune = 1;
pthread_mutex_unlock(&fe->mutex); pthread_mutex_unlock(&fe->mutex);
while(fe->n_tune) usleep(10000);
while(fe->tune != 2) usleep(10000);
return ret; return ret;
} }