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
incompatiblities to this driver package.
For installation instructions see:
http://support.digital-devices.eu/index.php?article=152
### Prepare for Building
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
$(CC) -o cit cit.c -lpthread
@@ -15,6 +15,12 @@ setmod2: setmod2.c
setmod3: setmod3.c
$(CC) -o setmod3 setmod3.c -I../include/
%.o: %.c
$(CC) $(CFLAGS) -o $@ $<
modconfig: modconfig.c
$(CC) -o modconfig modconfig.c -I../include/
%: %.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 <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
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("Version: %08x\n", ddf->id.hw);
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;
return stat;
}
@@ -200,6 +200,7 @@ static int usage()
"-n N\n only update card N (default with N=0)\n\n"
"-a \n update all cards\n\n"
"-b file\n fpga image file override (ignored if -a is used)\n\n"
"-f \n force update\n\n"
"-v \n more verbose (up to -v -v -v)\n\n"
);
}
@@ -250,7 +251,7 @@ int main(int argc, char **argv)
break;
case 'h':
usage();
break;
return 0;
default:
break;

View File

@@ -50,15 +50,15 @@ struct flash_info flashs[] = {
{ { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" },
{ { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" },
{ { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" },
{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" },
{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" },
{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" },
{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" },
{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" },
{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" },
{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" },
{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" },
{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" },
{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" },
{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" },
{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" },
{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" },
{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" },
{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" },
{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" },
{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" },
{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" },
{ { 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]) {
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;
f++;
}
@@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen,
return -1;
len = off - fw_off;
lseek(fs, fw_off, SEEK_SET);
#if 0
if (len > maxlen) {
printf("file too big\n");
return -1;
}
#endif
//printf("flash file len %u, compare to %08x in flash: ", len, addr);
for (j = 0; j < len; j += bl, addr += bl) {
if (len - j < bl)
@@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
return -4;
}
if (devid == ddf->id.device) {
if (version <= (ddf->id.hw & 0xffffff)) {
printf("%s is older or same version as flash\n", fn);
ret = -3; /* same id but no newer version */
if (version < (ddf->id.hw & 0xffffff)) {
printf("%s is older version than flash\n", fn);
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
ret = 1;
@@ -1147,7 +1151,7 @@ out:
}
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 fs, res = 0;
@@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn,
printf("File %s not found \n", fn);
return -1;
}
res = flashcmp(ddf, fs, adr, len, fw_off);
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) {
printf("Flash already identical to %s\n", fn);
if (ddf->force) {
@@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn,
}
if (res < 0)
goto out;
res = flashwrite(ddf, fs, adr, len, fw_off);
res = flashwrite(ddf, fs, adr, maxlen, fw_off);
if (res == 0) {
res = flashcmp(ddf, fs, adr, len, fw_off);
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) {
res = 1;
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_channel_params mc;
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;
char mod_name[128];
@@ -113,7 +113,7 @@ int main(int argc, char*argv[])
}
}
if (optind < argc) {
printf("too man arguments\n");
printf("too many arguments\n");
exit(1);
}
@@ -134,6 +134,8 @@ int main(int argc, char*argv[])
//get_property(fd, MODULATOR_ATTENUATOR, &data);
//printf("Modulator attenuator = %u\n", data);
if (gain > 0)
set_property(fd, MODULATOR_GAIN, gain);
if (base > 0)
set_property(fd, MODULATOR_BASE_FREQUENCY, base);
if (freq > 0)

View File

@@ -24,6 +24,7 @@
#include "ddbridge.h"
#include "ddbridge-i2c.h"
#include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#include <media/dvb_net.h>
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++) {
if (alt_dma) {
#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
dma->vbuf[i] = kmalloc(dma->size, __GFP_RETRY_MAYFAIL);
dma->vbuf[i] = kzalloc(dma->size, __GFP_RETRY_MAYFAIL);
#endif
if (!dma->vbuf[i])
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->size,
&dma->pbuf[i],
GFP_KERNEL);
GFP_KERNEL | __GFP_ZERO);
if (!dma->vbuf[i])
return -ENOMEM;
}
if (((u64)dma->vbuf[i] & 0xfff))
dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]);
}
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)
{
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,
"DMA stalled %u times!\n",
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,
"%u packets lost due to low DMA performance!\n",
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];
#if 0
dvb->fe = dvb_attach(dummy_attach);
#else
dvb->fe = dummy_attach();
#endif
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)) {
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;
}
if (alt_dma)
dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
dma2->size, DMA_FROM_DEVICE);
if (raw_stream || input->con)
if (raw_stream || input->con) {
dvb_dmx_swfilter_raw(&dvb->demux,
dma2->vbuf[dma->cbuf],
dma2->size);
else
dvb_dmx_swfilter_packets(&dvb->demux,
} else {
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->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;
if (ack)
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->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(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;
}
update_loss(dma);
if (4 & dma->ctrl)
dma->stall_count++;
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);
}
#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"
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)
return -EFAULT;
link = &dev->link[msg.link];
if (!link->mci_base)
return -EFAULT;
res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res);
if (copy_to_user(parg, &msg, sizeof(msg)))
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 mci_result res;
*status = 0x00;
if (!state->started)
return 0;
stat = ddb_mci_get_status(&state->mci, &res);
if (stat)
return stat;
*status = 0x00;
stat = ddb_mci_get_info(&state->mci);
if (stat)
return stat;
ddb_mci_get_strength(fe);
if (res.status == MCI_DEMOD_WAIT_SIGNAL)
*status = 0x01;
if (res.status == M4_DEMOD_WAIT_TS)
else if (res.status == M4_DEMOD_WAIT_TS)
*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;
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_unmap(dev);
pci_clear_master(pdev);
pci_set_drvdata(pdev, NULL);
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.subdevice = pdev->subsystem_device;
dev->link[0].ids.devid = (id->device << 16) | id->vendor;
dev->link[0].ids.revision = pdev->revision;
dev->link[0].dev = dev;
dev->link[0].info = get_ddb_info(id->vendor, id->device,
@@ -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.regmapid = ddbreadl(dev, 4);
dev_info(dev->dev, "HW %08x REGMAP %08x\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
dev->link[0].ids.hwid & 0xffff);
if ((dev->link[0].ids.hwid & 0xffffff) <
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_PARM_DESC(old_quattro, "old quattro LNB input order ");
static int no_voltage;
module_param(no_voltage, int, 0444);
MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone).");
/* MAX LNB interface related functions */
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
@@ -61,7 +65,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
return 0;
}
static int max_set_input_unlocked(struct dvb_frontend *fe, int in);
static int max_set_input(struct dvb_frontend *fe, int in);
static int max_emulate_switch(struct dvb_frontend *fe,
u8 *cmd, u32 len)
@@ -75,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe,
return -1;
input = cmd[3] & 3;
max_set_input_unlocked(fe, input);
max_set_input(fe, input);
return 0;
}
@@ -94,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
return 0;
if (fmode == 4)
max_emulate_switch(fe, cmd->msg, cmd->msg_len);
if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len))
return 0;
if (dvb->diseqc_send_master_cmd)
dvb->diseqc_send_master_cmd(fe, cmd);
@@ -164,6 +169,8 @@ static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input,
{
int s = 0;
if (no_voltage)
voltage = SEC_VOLTAGE_OFF;
if (dev->link[link].lnb.oldvoltage[input] == voltage)
return 0;
switch (voltage) {

View File

@@ -34,10 +34,16 @@ static int mci_reset(struct ddb_link *link)
u32 control;
u32 status = 0;
u32 timeout = 40;
if (!regmap || ! regmap->mci)
union {
u32 u[4];
char s[16];
} version;
u32 vaddr;
if (!regmap || !regmap->mci)
return -EINVAL;
control = regmap->mci->base;
vaddr = regmap->mci_buf->base + 0xf0;
if ((link->info->type == DDB_OCTOPUS_MCI) &&
(ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) {
@@ -55,11 +61,17 @@ static int mci_reset(struct ddb_link *link)
msleep(50);
}
dev_info(link->dev->dev, "MCI control port @ %08x\n", control);
if ((status & MCI_CONTROL_READY) == 0) {
dev_err(link->dev->dev, "MCI init failed!\n");
return -1;
}
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;
}
@@ -108,6 +120,7 @@ static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link,
0xffffff, INTERRUPT_ACK);
}
}
//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false);
if (res && res_len)
for (i = 0; i < res_len; i++)
res[i] = ddblreadl(link, result + i * 4);
@@ -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)
{
struct mci_result result;
struct mci_command command = {
.command_word = cmd,
.params = { val },
};
struct mci_command command;
command.command_word = cmd;
command.params[0] = val;
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);
}
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)
{
struct mci *mci = fe->demodulator_priv;

View File

@@ -132,6 +132,7 @@
#define MCI_BANDWIDTH_7MHZ (7)
#define MCI_BANDWIDTH_8MHZ (8)
#define SX8_CMD_GETBIST (0x0F)
#define SX8_CMD_INPUT_ENABLE (0x40)
#define SX8_CMD_INPUT_DISABLE (0x41)
#define SX8_CMD_START_IQ (0x42)
@@ -154,7 +155,7 @@
#define M4_L1INFO_SEL_PLPINFO (2)
#define M4_L1INFO_SEL_PLPINFO_C (3)
#define M4_L1INFO_SEL_SETID (0x80)
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
#define M4_MODE_DVBSX (2)
@@ -166,13 +167,13 @@
#define M4_MODE_ISDBT (8)
#define M4_MODE_ISDBC (9)
#define M4_MODE_ISDBS (10)
#define M4_DVBC_CONSTELLATION_16QAM (0)
#define M4_DVBC_CONSTELLATION_32QAM (1)
#define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
#define M4_DVBC_CONSTELLATION_128QAM (3)
#define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
#define M4_SIGNALINFO_FLAG_EWS (0x02)
@@ -181,10 +182,86 @@
#define SX8_ROLLOFF_20 2
#define SX8_ROLLOFF_15 5
#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 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 output;
};
struct {
u8 mod_command;
u8 mod_channel;
u8 mod_stream;
u8 mod_rsvd1;
};
};
union {
u32 params[31];
@@ -215,7 +298,7 @@ struct mci_command {
u32 scrambling_sequence_index;
u32 frequency_range;
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) */
} dvbs2_search;
@@ -236,7 +319,7 @@ struct mci_command {
u8 retry;
u32 frequency;
} dvbc_search;
struct {
u8 flags; /* Bit 0: LP Stream */
u8 bandwidth;
@@ -244,7 +327,7 @@ struct mci_command {
u8 retry;
u32 frequency;
} dvbt_search;
struct {
u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */
u8 bandwidth;
@@ -255,7 +338,7 @@ struct mci_command {
u8 plp;
u8 rsvd2[3];
} dvbt2_search;
struct {
u8 flags;
u8 bandwidth;
@@ -267,15 +350,15 @@ struct mci_command {
u8 data_slice;
u8 rsvd2[2];
} dvbc2_search;
struct {
u8 flags;
u8 flags;
u8 bandwidth;
u8 rsvd1;
u8 retry;
u32 frequency;
} isdbt_search;
struct {
u8 flags; /* Bit 0: 0 = TSID is Transport Stream ID, 1 = TSID is relative stream number */
/* Bit 2..1: 0 = force single, 1 = force multi, 2 = auto detect */
@@ -287,7 +370,7 @@ struct mci_command {
u16 onid;
u16 tsid;
} isdbc_search;
struct {
u8 flags;
u8 bandwidth;
@@ -297,7 +380,7 @@ struct mci_command {
} j83b_search;
struct {
u8 flags; // Bit 0 : 1 = short info (1st 4 Bytes)
u8 flags; /* Bit 0 : 1 = short info (1st 4 Bytes) */
} get_signalinfo;
struct {
@@ -307,43 +390,47 @@ struct mci_command {
} get_iq_symbol;
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 2: 1 = Set Gain. */
uint8_t roll_off;
uint8_t rsvd1;
uint8_t rsvd2;
uint32_t frequency;
uint32_t 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 roll_off;
u8 rsvd1;
u8 rsvd2;
u32 frequency;
u32 symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/
u8 gain; /* Gain in 0.25 dB Steps */
/* Frequency, symbolrate and gain can be schanged while running */
} sx8_start_iq;
struct {
uint8_t flags;
/* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
u8 flags;
/* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
2 = Medium, 3 = Maximum gain {~ 15dB}
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
Bit 4: Set RF Gain
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
Bit 7: Optimize RF Gain and freeze for FFT */
uint8_t rf_gain; /* 0 .. 50 dB */
u8 rf_gain; /* 0 .. 50 dB */
} sx8_input_enable;
struct {
u8 offset; // Offset into list, must be multiple of 64
u8 select; // 0 = Slices, 1 = PLPs (C2 Only)
u8 data_slice; // DataSlice to get PLPList (C2 Only)
u8 offset; /* Offset into list, must be multiple of 64 */
u8 select; /* 0 = Slices, 1 = PLPs (C2 Only) */
u8 data_slice; /* DataSlice to get PLPList (C2 Only) */
} get_ids;
struct {
u8 select; // 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID
u8 id; // DataSliceID, PLPId
u8 select; /* 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID */
u8 id; /* DataSliceID, PLPId */
} get_l1_info;
struct {
u8 select; // 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2
u8 select; /* 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 */
} get_bb_header;
struct mod_setup_channels mod_setup_channels[4];
struct mod_setup_stream mod_setup_stream;
struct mod_setup_output mod_setup_output;
};
};
@@ -356,26 +443,27 @@ struct mci_result {
u16 time;
};
};
union {
u32 result[27];
u8 result8[27 * 4];
struct {
u8 Rsvd0[3];
u8 Flags;
u32 frequency; // actual frequency in Hz
u32 frequency; /* actual frequency in Hz */
u32 rsvd1;
s16 channel_power; // channel power in dBm x 100
s16 channel_power; /* channel power in dBm x 100 */
s16 rsvd2;
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd3;
u32 rsvd4;
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
u32 ber_rsvd1; // Place holder for modulation bit error rate
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
u32 ber_rsvd1; /* Place holder for modulation bit error rate */
u32 ber_rsvd2;
} common_signal_info;
struct {
u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */
u8 pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */
@@ -389,7 +477,7 @@ struct mci_result {
s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
u32 ber_denominator;
} dvbs2_signal_info;
struct {
@@ -404,7 +492,7 @@ struct mci_result {
s16 rsvd2;
u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
u32 ber_denominator;
} isdbs_signal_info;
struct {
@@ -425,8 +513,8 @@ struct mci_result {
struct {
u8 modulation1; // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High
u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode
u8 Rsvd0;
u8 Flags;
u8 rsvd0;
u8 flags;
u32 frequency; /* actual frequency in Hz */
u32 rsvd1;
s16 channel_power; /* channel power in dBm x 100 */
@@ -455,7 +543,7 @@ struct mci_result {
struct {
u8 rsvd0[3];
u8 flags;
u32 frequency; // actual frequency in Hz
u32 rsvd1; //
s16 channel_power; // channel power in dBm x 100
@@ -464,7 +552,7 @@ struct mci_result {
s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreBCH
u32 ber_denominator;
u32 ber_denominator;
} dvbc2_signal_info;
struct {
@@ -487,51 +575,51 @@ struct mci_result {
} isdbt_signal_info;
struct {
u8 Constellation;
u8 Rsvd0[2];
u8 Flags;
u32 Frequency; // actual frequency in Hz
u32 SymbolRate; // actual symbolrate in Hz
s16 ChannelPower; // channel power in dBm x 100
s16 BandPower; // band power in dBm x 100
s16 SignalToNoise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 Rsvd2;
u32 PacketErrors; // Counter for packet errors. (set to 0 on Start command)
u32 BERNumerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 BERDenominator;
} ISDBC_SignalInfo;
u8 constellation;
u8 rsvd0[2];
u8 flags;
u32 frequency; // actual frequency in Hz
u32 symbol_rate; // actual symbolrate in Hz
s16 channel_power; // channel power in dBm x 100
s16 band_power; // band power in dBm x 100
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 ber_denominator;
} isdbc_signal_info;
struct {
u8 Constellation;
u8 Interleaving;
u8 Rsvd0;
u8 Flags;
u32 Frequency; // actual frequency in Hz
u32 SymbolRate; // actual symbolrate in Hz
s16 ChannelPower; // channel power in dBm x 100
s16 BandPower; // band power in dBm x 100
s16 SignalToNoise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 Rsvd2;
u32 PacketErrors; // Counter for packet errors. (set to 0 on Start command)
u32 BERNumerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 BERDenominator;
} J83B_SignalInfo;
u8 constellation;
u8 interleaving;
u8 rsvd0;
u8 flags;
u32 frequency; // actual frequency in Hz
u32 symbol_rate; // actual symbolrate in Hz
s16 channel_power; // channel power in dBm x 100
s16 band_power; // band power in dBm x 100
s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2
s16 rsvd2;
u32 packet_errors; // Counter for packet errors. (set to 0 on Start command)
u32 ber_numerator; // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X
u32 ber_denominator;
} j83b_signal_info;
struct {
s16 i;
s16 q;
} iq_symbol;
struct {
u8 TPSInfo[7];
// uint16_t TPS_CellID; // Cell Identifier
u8 tps_info[7];
// uint16_t tps_cell_id;
} DVBT_TPSInfo;
struct {
struct {
u8 Type;
u8 type;
u8 BWExtension;
u8 S1;
u8 S2;
@@ -557,6 +645,7 @@ struct mci_result {
u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit
u8 CRC32[4];
} DVBT2_L1Pre;
struct {
u8 SubSlicesPerFrame[2];
u8 NumPLP;
@@ -569,7 +658,7 @@ struct mci_result {
u8 FEFInterval;
} DVBT2_L1Post;
} DVBT2_L1Info;
struct {
u8 PLPID;
u8 Type;
@@ -589,7 +678,7 @@ struct mci_result {
u8 InBandAFlag;
u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1
} DVBT2_PLPInfo;
struct {
u8 NetworkID[2];
u8 C2SystemID[2];
@@ -608,13 +697,13 @@ struct mci_result {
u8 ReservedTone;
u8 Reserved4[2]; // EWS 1 bit, C2_Version 4 bit, Rsvd 11 bit
} DVBC2_L1Part2;
struct {
u8 NumIDs;
u8 Offset;
u8 IDs[64];
} DVBC2_IDList;
struct {
u8 SliceID;
u8 TunePosition[2];
@@ -628,7 +717,7 @@ struct mci_result {
u8 NumPLP;
u8 Reserved2;
} DVBC2_SliceInfo;
struct {
u8 PLPID;
u8 Bundled;
@@ -644,7 +733,7 @@ struct mci_result {
u8 OrginalNetworkID[2];
u8 Reserved1;
} DVBC2_PLPInfo;
struct {
u8 Valid;
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 Extension[8]; // 61 bits, right aligned
} ISDBS_TMCCInfo;
struct {
uint8_t cut;
uint8_t avs_code;
uint8_t temperature;
uint8_t rsvd[13];
} sx8_bist;
};
u32 version[3];
u8 version_rsvd;
@@ -758,6 +854,8 @@ struct mci_result {
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
#ifdef __KERNEL__
struct mci_base {
struct list_head mci_list;
void *key;
@@ -797,9 +895,10 @@ int ddb_mci_get_info(struct mci *mci);
int ddb_mci_get_strength(struct dvb_frontend *fe);
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, 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_m4_cfg;
#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)
{
u32 control = ddbreadl(dev, SDR_CONTROL);
struct ddb_link *link = &dev->link[0];
if (control & 0x01000000) {
if (gain > 511)
@@ -659,8 +658,6 @@ static int mod_set_sdr_gain(struct ddb *dev, u32 gain)
return -EINVAL;
ddbwritel(dev, gain, SDR_GAIN_F);
}
if (link->mci_ok)
mci_cmd_val(link, 0xc0, gain);
return 0;
}
@@ -2032,6 +2029,9 @@ static int mod_init_sdr_iq(struct ddb *dev)
ddbwritel(dev, 0x01, 0x240);
if (dev->link[0].ids.revision == 1)
return 0;
//mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000;
for (i = 0; i < streams; i++) {

View File

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

View File

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

View File

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

View File

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

View File

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

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_params p;
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 verbosity = 0;
uint32_t get_ts = 1;

View File

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