Merge branch 'DigitalDevices:master' into master

This commit is contained in:
CrazyCat 2023-03-22 18:34:32 +02:00 committed by GitHub
commit ce19fe1b3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 5094 additions and 1148 deletions

6
Kbuild
View File

@ -2,6 +2,12 @@
# Makefile for the kernel multimedia device drivers.
#
ifeq ($(KERNEL_DVB_CORE),y)
obj-y := ddbridge/ \
frontends/
else
obj-y := dvb-core/ \
ddbridge/ \
frontends/
endif

View File

@ -1,4 +1,5 @@
kernelver ?= $(shell uname -r)
MDIR ?=
KDIR ?= /lib/modules/$(kernelver)/build
PWD := $(shell pwd)
@ -6,8 +7,11 @@ MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_
KBUILD_EXTMOD = $(PWD)
DDDVB_INC = "-I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/frontends"
ifeq ($(KERNEL_DVB_CORE),y)
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD) -DKERNEL_DVB_CORE=y"
else
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux"
endif
all:
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC)
@ -26,10 +30,11 @@ dep:
DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep)
install: all
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install
depmod -a
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) INSTALL_MOD_PATH=$(MDIR) modules_install
depmod $(kernelver)
clean:
rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
$(MAKE) -C apps clean

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,20 @@
all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3
TARGETS = cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq modtest
all: $(TARGETS)
CFLAGS = -g -Wall -Wno-unused -Wno-format
FFMPEG := $(shell command -v ffmpeg 2> /dev/null)
modtest: modtest.c
$(CC) -o modtest modtest.c -I../include/ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
test.ts:
ifndef FFMPEG
$(error "ffmpeg is not available please install to create test.ts")
endif
ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 \
-f lavfi -i sine=f=440:b=4 -shortest -metadata \
service_provider="DD" -metadata service_name="Test" test.ts
cit: cit.c
$(CC) -o cit cit.c -lpthread
@ -15,6 +31,22 @@ setmod2: setmod2.c
setmod3: setmod3.c
$(CC) -o setmod3 setmod3.c -I../include/
%.o: %.c
$(CC) $(CFLAGS) -o $@ $<
modconfig: modconfig.c
$(CC) -o modconfig modconfig.c -I../include/
clean:
rm cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq
%: %.c
$(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@
%.o: %.c
$(CC) $(CFLAGS) -I../ddbridge -o $@ $<
clean:
for f in $(TARGETS) *.o *~ ; do \
if [ -e "$$f" ]; then \
rm "$$f" || exit 1; \
fi \
done

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)
{

544
apps/ddinfo.c Normal file
View File

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

View File

@ -275,6 +275,7 @@ int main(int argc, char **argv)
case SPANSION_S25FL116K:
case SPANSION_S25FL164K:
case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
break;
}

100
apps/getiq.c Normal file
View File

@ -0,0 +1,100 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "../ddbridge/ddbridge-mci.h"
#include "../ddbridge/ddbridge-ioctl.h"
void print_iq(struct mci_result *res, int fd)
{
dprintf(fd, "%d,%d\n", res->iq_symbol.i, res->iq_symbol.q);
}
int get_iq(int dev, uint32_t link, uint8_t demod, int fd)
{
struct ddb_mci_msg msg = {
.link = link,
.cmd.command = MCI_CMD_GET_IQSYMBOL,
.cmd.demod = demod,
.cmd.get_iq_symbol.tap = 0,
.cmd.get_iq_symbol.point = 0,
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (msg.res.status & 0x80) {
printf("MCI errror %02x\n", msg.res.status);
return ret;
}
print_iq(&msg.res, fd);
return ret;
}
#define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0]))
int main(int argc, char*argv[])
{
char ddbname[80];
int fd = -1, all = 1, i, ret = 0, ddb;
char fn[128];
int32_t device = -1, demod = -1;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"demod", required_argument, 0, 'n'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ad:n:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'n':
demod = strtoul(optarg, NULL, 0);
break;
case 'a':
all = 1;
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
sprintf(ddbname, "/dev/ddbridge/card%d", device);
ddb = open(ddbname, O_RDWR);
if (ddb < 0)
return -3;
for (i = 0; i < 20000; i++)
get_iq(ddb, 0, demod, 1);
}

531
apps/modconfig.c Normal file
View File

@ -0,0 +1,531 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
#include <ctype.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "../ddbridge/ddbridge-mci.h"
#include "../ddbridge/ddbridge-ioctl.h"
struct mconf {
int set_output;
int set_channels;
int fd;
struct mci_command channels;
struct mci_command stream;
struct mci_command output;
};
void strim(char *s)
{
int l = strlen(s);
while (l && isspace(s[l-1]))
l--;
s[l] = 0;
}
void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *))
{
char line[256], csec[80], par[80], val[80], *p;
FILE *f;
if ((f = fopen(fname, "r")) == NULL)
return;
while ((p = fgets(line, sizeof(line), f))) {
if (*p == '\r' || *p == '\n' || *p == '#')
continue;
if (*p == '[') {
if ((p = strtok(line + 1, "]")) == NULL)
continue;
strncpy(csec, p, sizeof(csec));
if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL);
continue;
}
if (!(p = strtok(line, "=")))
continue;
while (isspace(*p))
p++;
strncpy(par, p, sizeof(par));
strim(par);
if (!(p = strtok(NULL, "=")))
continue;
while (isspace(*p))
p++;
strncpy (val, p, sizeof(val));
strim(val);
if (!strcmp(sec, csec) && cb)
cb(priv, par, val);
}
if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL);
fclose(f);
}
struct param_table_entry {
int value;
char* name;
};
struct param_table_entry mod_standard_table[] = {
{ .name = "0", .value = MOD_STANDARD_GENERIC },
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "1", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "2", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "3", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "4", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "DVBC_8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "9", .value = MOD_STANDARD_DVBC_7 },
{ .name = "DVBC_7", .value = MOD_STANDARD_DVBC_7 },
{ .name = "10", .value = MOD_STANDARD_DVBC_6 },
{ .name = "DVBC_6", .value = MOD_STANDARD_DVBC_6 },
{ .name = "11", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "J83B_QAM64", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "12", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "J83B_QAM256", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "13", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "ISDBC_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "J83C_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "14", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "ISDBC_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "J83C_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry stream_format_table[] = {
{ .name = "0", .value = MOD_FORMAT_DEFAULT },
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "1", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "2", .value = MOD_FORMAT_IQ8 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "3", .value = MOD_FORMAT_IDX8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "4", .value = MOD_FORMAT_TS },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = NULL, .value = 0 }
};
struct param_table_entry guard_interval_table[] = {
{ .name = "0", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1", .value = MOD_DVBT_GI_1_16 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "2", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "3", .value = MOD_DVBT_GI_1_4 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry puncture_rate_table[] = {
{ .name = "1", .value = MOD_DVBT_PR_1_2 },
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2", .value = MOD_DVBT_PR_2_3 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3", .value = MOD_DVBT_PR_3_4 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5", .value = MOD_DVBT_PR_5_6 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7", .value = MOD_DVBT_PR_7_8 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry dvbt_constellation_table[] = {
{ .name = "0", .value = MOD_DVBT_QPSK },
{ .name = "qpsk", .value = MOD_DVBT_QPSK },
{ .name = "1", .value = MOD_DVBT_16QAM },
{ .name = "16qam", .value = MOD_DVBT_16QAM },
{ .name = "qam16", .value = MOD_DVBT_16QAM },
{ .name = "2", .value = MOD_DVBT_64QAM },
{ .name = "64qam", .value = MOD_DVBT_64QAM },
{ .name = "qam64", .value = MOD_DVBT_64QAM },
{ .name = NULL, .value = 0 }
};
struct param_table_entry qam_modulation_table[] = {
{ .name = "0", .value = MOD_QAM_DVBC_16 },
{ .name = "qam_dvbc_16", .value = MOD_QAM_DVBC_16 },
{ .name = "1", .value = MOD_QAM_DVBC_32 },
{ .name = "qam_dvbc_32", .value = MOD_QAM_DVBC_32 },
{ .name = "2", .value = MOD_QAM_DVBC_64 },
{ .name = "qam_dvbc_64", .value = MOD_QAM_DVBC_64 },
{ .name = "3", .value = MOD_QAM_DVBC_128 },
{ .name = "qam_dvbc_128", .value = MOD_QAM_DVBC_128 },
{ .name = "4", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_dvbc_256", .value = MOD_QAM_DVBC_256 },
{ .name = "5", .value = MOD_QAM_J83B_64 },
{ .name = "qam_j83b_64", .value = MOD_QAM_J83B_64 },
{ .name = "6", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_j83b_256", .value = MOD_QAM_J83B_256 },
{ .name = "7", .value = MOD_QAM_GENERIC },
{ .name = "qam_generic", .value = MOD_QAM_GENERIC },
{ .name = "8", .value = MOD_QAM_ISDBC_64 },
{ .name = "qam_isdbc_64", .value = MOD_QAM_ISDBC_64 },
{ .name = "9", .value = MOD_QAM_ISDBC_256 },
{ .name = "qam_isdbc_256", .value = MOD_QAM_ISDBC_256 },
{ .name = NULL, .value = 0 }
};
int parse_param(char *val, struct param_table_entry *table, int *value) {
if (value) {
*value = 0;
if (table) {
while (table->name) {
if( !strcasecmp(val,table->name)) {
*value = table->value;
printf("%s=%u\n", val, *value);
return 0;
}
table++;
}
}
}
printf("unknown value %s\n", val);
return -1;
}
void dump(const uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf(" | ");
for (i = 0; i < 16; i++)
if (i + j < l)
putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.');
printf("\n");
}
}
int mci_cmd(int dev, struct mci_command *cmd)
{
int ret;
struct ddb_mci_msg msg;
uint8_t status;
memset(&msg, 0, sizeof(msg));
msg.link = 0;
memcpy(&msg.cmd, cmd, sizeof(msg.cmd));
//dump((const uint8_t *) &msg.cmd, sizeof(msg.cmd));
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno));
return ret;
}
status = msg.res.status;
if (status == MCI_STATUS_OK)
return ret;
if (status == MCI_STATUS_UNSUPPORTED) {
dprintf(2, "Unsupported MCI command\n");
return ret;
}
if (status == MCI_STATUS_INVALID_PARAMETER) {
dprintf(2, "Invalid MCI parameters\n");
return ret;
}
return ret;
}
struct mci_command msg_channels = {
.mod_command = MOD_SETUP_CHANNELS,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_channels[0] = {
.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID,
.standard = MOD_STANDARD_DVBT_8,
.num_channels = 25,
.frequency = 474000000,
},
};
struct mci_command msg_stream = {
.mod_command = MOD_SETUP_STREAM,
.mod_channel = 1,
.mod_stream = 0,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBC_8,
#if 0
.ofdm = {
.fft_size = 1,
.guard_interval = 0,
}
#endif
},
};
struct mci_command msg_output = {
.mod_command = MOD_SETUP_OUTPUT,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_output = {
.connector = MOD_CONNECTOR_F,
.num_channels = 16,
.unit = MOD_UNIT_DBUV,
.channel_power = 5000,
},
};
void output_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
if (!par && !val) {
mc->set_output = 1;
return;
}
if (!strcasecmp(par, "connector")) {
if (!strcasecmp(val, "F")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_F;
} else if (!strcasecmp(val, "SMA")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_SMA;
} else if (!strcasecmp(val, "OFF")) {
mc->output.mod_setup_output.connector = MOD_CONNECTOR_OFF;
} else
printf("invalid connector\n");
} else if (!strcasecmp(par, "power")) {
mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0);
} else if (!strcasecmp(par, "channels")) {
mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "unit")) {
if (!strcasecmp(val, "DBUV")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBUV;
} else if (!strcasecmp(val, "DBM")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBM;
} else
printf("invalid unit\n");
} else
printf("invalid output parameter: %s\n", par);
}
void channels_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
int value;
if (!par && !val) {
mc->set_channels = 1;
return;
}
if (!strcasecmp(par, "frequency")) {
mc->channels.mod_setup_channels[0].frequency = (uint32_t) (strtod(val, NULL) * 1000000.0);
printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency);
} else if (!strcasecmp(par, "channels")) {
mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table, &value))
mc->channels.mod_setup_channels[0].standard = value;
printf("standard = %u\n", value);
} else if (!strcasecmp(par, "offset")) {
mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "bandwidth")) {
mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset =
mc->channels.mod_setup_channels[0].bandwidth / 2;
} else
printf("invalid channels parameter: %s\n", par);
}
void streams_cb(void *priv, char *par, char *val)
{
struct mconf *mc = (struct mconf *) priv;
int value;
if (!par && !val) {
return;
}
if (!strcasecmp(par, "fft_size")) {
mc->stream.mod_setup_stream.ofdm.fft_size = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "guard_interval")) {
if (!parse_param(val, guard_interval_table, &value))
mc->stream.mod_setup_stream.ofdm.guard_interval = value;
} else if (!strcasecmp(par, "puncture_rate")) {
if (!parse_param(val, puncture_rate_table, &value))
mc->stream.mod_setup_stream.ofdm.puncture_rate = value;
} else if (!strcasecmp(par, "constellation")) {
if (!parse_param(val,dvbt_constellation_table,&value))
mc->stream.mod_setup_stream.ofdm.constellation = value;
} else if (!strcasecmp(par, "cell_identifier")) {
mc->stream.mod_setup_stream.ofdm.cell_identifier = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "modulation")) {
if (!parse_param(val, qam_modulation_table, &value))
mc->stream.mod_setup_stream.qam.modulation = value;
} else if (!strcasecmp(par, "rolloff")) {
mc->stream.mod_setup_stream.qam.rolloff = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_stream.standard = value;
} else if (!strcasecmp(par, "stream_format")) {
if (!parse_param(val,stream_format_table,&value))
mc->stream.mod_setup_stream.stream_format = value;
} else if (!strcasecmp(par, "symbol_rate")) {
mc->stream.mod_setup_stream.symbol_rate = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "channel")) {
mc->stream.mod_channel = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "stream")) {
mc->stream.mod_stream = strtol(val, NULL, 10);
printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel);
mci_cmd(mc->fd, &mc->stream);
} else
printf("invalid streams parameter: %s = %s\n", par, val);
}
int mci_lic(int dev)
{
struct ddb_mci_msg msg = {
.cmd.command = CMD_EXPORT_LICENSE,
.cmd.get_bb_header.select = 0,
};
struct mci_result *res = &msg.res;
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (res->bb_header.valid) {
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
}
dump((const uint8_t *)&res->license, sizeof(res->license));
return ret;
}
int main(int argc, char*argv[])
{
int fd = -1;
char fn[128];
uint32_t device = 0;
uint32_t frequency = 0;
char *configname = "modulator.conf";
struct mconf mc;
memset(&mc, 0, sizeof(mc));
mc.channels = msg_channels;
mc.stream = msg_stream;
mc.output = msg_output;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"config", required_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "d:c:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'c':
configname = optarg;
break;
case 'h':
dprintf(2, "modconfig [-d device_number] [-c config_file]\n");
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
//snprintf(fn, 127, "/dev/ddbridge/card%u", device);
snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", device);
fd = open(fn, O_RDWR);
if (fd < 0) {
dprintf(2, "Could not open %s\n", fn);
return -1;
}
//mci_lic(fd);
mc.fd = fd;
parse(configname, "channels", (void *) &mc, channels_cb);
if (mc.set_channels) {
printf("setting channels.\n");
mci_cmd(fd, &mc.channels);
}
parse(configname, "streams", (void *) &mc, streams_cb);
parse(configname, "output", (void *) &mc, output_cb);
if (mc.set_output) {
printf("setting output.\n");
mci_cmd(fd, &mc.output);
}
}

1321
apps/modtest.c Normal file

File diff suppressed because it is too large Load Diff

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

@ -1,10 +1,11 @@
all: ddtest octonet octokey ddflash
all: ddtest octonet octokey ddflash ddupdate
install: all
install -m 0755 ddtest $(DESTDIR)/usr/bin
install -m 0755 octonet $(DESTDIR)/usr/bin
install -m 0755 octokey $(DESTDIR)/usr/bin
install -m 0755 ddflash $(DESTDIR)/usr/bin
install -m 0755 ddupdate $(DESTDIR)/usr/bin
ddflash: ddflash.c flash.h flash.c
$(CC) -o ddflash ddflash.c
@ -12,6 +13,9 @@ ddflash: ddflash.c flash.h flash.c
ddtest: ddtest.c flash.h flash.c
$(CC) -o ddtest ddtest.c
ddupdate: ddupdate.c flash.h flash.c
$(CC) -o ddupdate ddupdate.c
octonet: octonet.c
$(CC) -o octonet octonet.c

View File

@ -38,25 +38,6 @@
#include "flash.h"
#include "flash.c"
static int reboot(uint32_t off)
{
FILE *f;
uint32_t time;
if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL)
return -1;
fscanf(f, "%u", &time);
fclose(f);
if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL)
return -1;
fprintf(f, "%u", time + off);
fclose(f);
system("/sbin/poweroff");
return 0;
}
static int update_flash(struct ddflash *ddf)
{
char *fname;

View File

@ -405,6 +405,9 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SPANSION_S25FL132K: SectorSize = 4096; FlashSize = 0x400000; break;
case SPANSION_S25FL164K: SectorSize = 4096; FlashSize = 0x800000; break;
case WINBOND_W25Q16JV: SectorSize = 4096; FlashSize = 0x200000; break;
case WINBOND_W25Q32JV: SectorSize = 4096; FlashSize = 0x400000; break;
case WINBOND_W25Q64JV: SectorSize = 4096; FlashSize = 0x800000; break;
case WINBOND_W25Q128JV: SectorSize = 4096; FlashSize = 0x1000000; break;
}
if (SectorSize == 0)
return 0;
@ -575,6 +578,9 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SPANSION_S25FL132K:
case SPANSION_S25FL164K:
case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
case WINBOND_W25Q64JV:
case WINBOND_W25Q128JV:
err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x1C); break;
}
@ -1331,6 +1337,9 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
switch(Flash) {
case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
case WINBOND_W25Q64JV:
case WINBOND_W25Q128JV:
read_winbd(dev, Id);
len = 8;
break;

View File

@ -11,7 +11,6 @@
#include <sys/ioctl.h>
#include <linux/types.h>
#include "flash.h"
#include "flash.c"
@ -115,12 +114,12 @@ static int update_flash(struct ddflash *ddf)
if (!fname)
fname = default_fname;
if (name)
printf("Card: %s\n", name);
printf("Card: %s\n", name);
if (ddf->flash_name)
printf("Flash: %s\n", ddf->flash_name);
printf("Version:%08x\n", ddf->id.hw);
//printf("REGMAPa: %08x\n", ddf->id.regmap);
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
printf("Flash: %s\n", ddf->flash_name);
printf("Version: %08x\n", ddf->id.hw);
printf("REGMAP : %08x\n", ddf->id.regmap);
if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
stat |= 1;
return stat;
}
@ -142,7 +141,7 @@ static int update_link(struct ddflash *ddf)
return ret;
}
static int update_card(int ddbnum, char *fname)
static int update_card(int ddbnum, char *fname, int force)
{
struct ddflash ddf;
char ddbname[80];
@ -156,6 +155,7 @@ static int update_card(int ddbnum, char *fname)
ddf.fd = ddb;
ddf.link = 0;
ddf.fname = fname;
ddf.force = force;
links = 1;
for (link = 0; link < links; link++) {
@ -200,24 +200,27 @@ 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"
);
}
int main(int argc, char **argv)
{
int ddbnum = -1, all = 0, i, force = 0;
int ddbnum = -1, all = 0, i, force = 0, reboot_len = -1;
char *fname = 0;
int ret;
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"reboot", optional_argument , NULL, 'r'},
{"help", no_argument , NULL, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"n:havfb:",
"n:havfb:r::",
long_options, &option_index);
if (c==-1)
break;
@ -232,12 +235,23 @@ int main(int argc, char **argv)
case 'a':
all = 1;
break;
case 'f':
force = 1;
break;
case 'v':
verbose++;
break;
case 'r':
if (optarg)
reboot_len = strtol(optarg, NULL, 0);
else
reboot_len = 40;
if (!reboot_len)
reboot(40);
break;
case 'h':
usage();
break;
return 0;
default:
break;
@ -253,17 +267,19 @@ int main(int argc, char **argv)
}
if (!all)
return update_card(ddbnum, fname);
for (i = 0; i < 100; i++) {
int ret = update_card(i, 0);
if (ret == -3) /* could not open, no more cards! */
break;
if (ret < 0)
return i; /* fatal error */
if (verbose >= 1)
printf("card %d up to date\n", i);
}
ret = update_card(ddbnum, fname, force);
else
for (i = 0; i < 100; i++) {
ret = update_card(i, 0, 0);
if (ret == -3) /* could not open, no more cards! */
break;
if (ret < 0)
return i; /* fatal error */
if (verbose >= 1)
printf("card %d up to date\n", i);
}
if (reboot_len > 0)
reboot(reboot_len);
return 0;
}

View File

@ -1,7 +1,28 @@
static int reboot(uint32_t off)
{
FILE *f;
uint32_t time;
if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL)
return -1;
fscanf(f, "%u", &time);
fclose(f);
if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL)
return -1;
fprintf(f, "%u", time + off);
fclose(f);
system("/sbin/poweroff");
return 0;
}
static uint32_t linknr = 0;
int flashio(int ddb, int link,
uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen)
uint8_t *wbuf, uint32_t wlen,
uint8_t *rbuf, uint32_t rlen)
{
struct ddb_flashio fio = {
.write_buf=wbuf,
@ -29,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" },
};
@ -47,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++;
}
@ -118,7 +139,7 @@ int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len)
uint32_t l;
while (len) {
cmd[0] = 3;
cmd[0] = 0x03;
cmd[1] = (addr >> 16) & 0xff;
cmd[2] = (addr >> 8) & 0xff;
cmd[3] = addr & 0xff;
@ -137,12 +158,12 @@ int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len)
return 0;
}
#else
static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
static int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len)
{
uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff};
uint8_t cmd[5]= {0x0b, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff, 0x00};
return flashio(ddb, linknr, cmd, 4, buf, len);
return flashio(ddb, link, cmd, 5, buf, len);
}
#endif
@ -500,10 +521,10 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset,
uint8_t Cmd[260];
int i, j;
if( (BufferSize % 4096) != 0 ) return -1; // Must be multiple of sector size
if ((BufferSize % 4096))
return -1; // Must be multiple of sector size
do
{
do {
Cmd[0] = 0x50; // EWSR
err = flashio(dev,linknr, Cmd,1,NULL,0);
if( err < 0 ) break;
@ -513,8 +534,7 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset,
err = flashio(dev,linknr, Cmd,2,NULL,0);
if( err < 0 ) break;
for(i = 0; i < BufferSize; i += 4096 )
{
for(i = 0; i < BufferSize; i += 4096 ) {
if( (i & 0xFFFF) == 0 )
{
printf(" Erase %08x\n",FlashOffset + i);
@ -588,124 +608,117 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset,
return err;
}
static int flash_wait(int fd, uint32_t link)
{
while (1) {
uint8_t rcmd = 0x05; // RDSR
int err = flashio(fd, link, &rcmd, 1, &rcmd, 1);
if (err < 0)
return err;
if ((rcmd & 0x01) == 0)
break;
}
return 0;
}
int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
uint8_t LockBits, uint32_t fw_off)
uint8_t LockBits, uint32_t fw_off, int be)
{
int err = 0;
uint8_t cmd[260];
int i, j;
uint32_t flen, blen;
int blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
if (blen % 0xff)
blen = (blen + 0xff) & 0xffffff00;
printf("blen = %u, flen = %u\n", blen, flen);
do {
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0);
if (err < 0)
break;
for (i = 0; i < flen; i += 4096) {
if ((i & 0xFFFF) == 0)
printf(" Erase %08x\n", FlashOffset + i);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x20; // Sector erase ( 4Kb)
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
err = flashio(ddf->fd, ddf->link, cmd, 4, NULL, 0);
if (err < 0)
break;
//printf("blen = %u, flen = %u\n", blen, flen);
setbuf(stdout, NULL);
while (1) {
cmd[0] = 0x05; // RDSR
err = flashio(ddf->fd, ddf->link, cmd, 1, &cmd[0], 1);
if (err < 0)
break;
if ((cmd[0] & 0x01) == 0)
break;
}
if (err < 0)
break;
}
if (err < 0)
break;
for (j = blen - 256; j >= 0; j -= 256 ) {
uint32_t len = 256;
ssize_t rlen;
if (lseek(dev, j + fw_off, SEEK_SET) < 0) {
printf("seek error\n");
return -1;
}
if (flen - j < 256) {
len = flen - j;
memset(ddf->buffer, 0xff, 256);
}
rlen = read(dev, ddf->buffer, len);
if (rlen < 0 || rlen != len) {
printf("file read error %d,%d at %u\n", rlen, errno, j);
return -1;
}
//printf ("write %u bytes at %08x\n", len, j);
if ((j & 0xFFFF) == 0)
printf(" Program %08x\n", FlashOffset + j);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x02; // PP
cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
cmd[3] = 0x00;
memcpy(&cmd[4], ddf->buffer, 256);
err = flashio(ddf->fd, ddf->link, cmd, 260, NULL, 0);
if (err < 0)
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(ddf->fd, ddf->link, cmd,1, &cmd[0], 1);
if (err < 0)
break;
if ((cmd[0] & 0x01) == 0)
break;
}
if (err < 0)
break;
}
if (err < 0)
break;
cmd[0] = 0x50; // EWSR
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
return err;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0);
if (err < 0)
return err;
for (i = 0; i < flen; ) {
printf(" Erase %08x\r", FlashOffset + i);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
break;
return err;
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
if (blockerase && ((flen - i) >= 0x10000) ) {
cmd[0] = 0xd8;
i += 0x10000;
} else {
cmd[0] = 0x20; // Sector erase ( 4Kb)
i += 0x1000;
}
err = flashio(ddf->fd, ddf->link, cmd, 4, NULL, 0);
if (err < 0)
return err;
err = flash_wait(ddf->fd, ddf->link);
if (err < 0)
return err;
}
for (j = blen - 256; j >= 0; j -= 256 ) {
uint32_t len = 256;
ssize_t rlen;
cmd[0] = 0x01; // WRSR
cmd[1] = LockBits; // BPx = 0, Lock all blocks
err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0);
} while(0);
if (lseek(dev, j + fw_off, SEEK_SET) < 0) {
printf("seek error\n");
return -1;
}
if (flen - j < 256) {
len = flen - j;
memset(ddf->buffer, 0xff, 256);
}
rlen = read(dev, ddf->buffer, len);
if (rlen < 0 || rlen != len) {
printf("file read error %d,%d at %u\n", rlen, errno, j);
return -1;
}
printf(" Program %08x\r", FlashOffset + j);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
goto out;
cmd[0] = 0x02; // PP
cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
cmd[3] = 0x00;
memcpy(&cmd[4], ddf->buffer, 256);
err = flashio(ddf->fd, ddf->link, cmd, 260, NULL, 0);
if (err < 0)
goto out;
err = flash_wait(ddf->fd, ddf->link);
if (err < 0)
goto out;
}
printf("\n");
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
if (err < 0)
goto out;
cmd[0] = 0x01; // WRSR
cmd[1] = LockBits; // BPx = 0, Lock all blocks
err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0);
out:
return err;
}
@ -845,7 +858,7 @@ static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxle
case SSTI_SST25VF032B:
return flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off);
case SSTI_SST25VF064C:
return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off);
return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off, 0);
case SPANSION_S25FL116K:
case SPANSION_S25FL132K:
case SPANSION_S25FL164K:
@ -853,7 +866,8 @@ static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxle
case WINBOND_W25Q32JV:
case WINBOND_W25Q64JV:
case WINBOND_W25Q128JV:
return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off);
default:
return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off, 1);
}
return -1;
}
@ -892,97 +906,55 @@ static int get_id(struct ddflash *ddf)
return 0;
}
struct devids {
uint16_t id;
char *name;
char *fname;
};
#define DEV(_id, _name, _fname) { .id = _id, .name = _name, .fname = _fname }
static const struct devids ids[] = {
DEV(0x0002, "Octopus 35", "DVBBridgeV1A_DVBBridgeV1A.bit"),
DEV(0x0003, "Octopus", "DVBBridgeV1B_DVBBridgeV1B.fpga"),
DEV(0x0005, "Octopus Classic", "DVBBridgeV2A_DD01_0005_STD.fpga"),
DEV(0x0006, "CineS2 V7", "DVBBridgeV2A_DD01_0006_STD.fpga"),
DEV(0x0007, "Octopus 4/8", "DVBBridgeV2A_DD01_0007_MXL.fpga"),
DEV(0x0008, "Octopus 4/8", "DVBBridgeV2A_DD01_0008_CXD.fpga"),
DEV(0x0009, "Octopus MAXSX8", "DVBBridgeV2A_DD01_0009_SX8.fpga"),
DEV(0x000b, "Octopus MAXSX8 Basic", "DVBBridgeV2A_DD01_000B_SX8.fpga"),
DEV(0x000a, "Octopus MAXM4", "DVBBridgeV2A_DD01_000A_M4.fpga"),
DEV(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"),
DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"),
DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.fpga"),
DEV(0x0020, "Octopus GT Mini", "DVBBridgeV2C_DD01_0020.fpga"),
DEV(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"),
DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"),
DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.fpga"),
DEV(0x0220, "SDRModulator ATV", "SDRModulatorV1A_DD01_0220.fpga"),
DEV(0x0221, "SDRModulator IQ", "SDRModulatorV1A_DD01_0221_IQ.fpga"),
DEV(0x0222, "SDRModulator DVBT", "SDRModulatorV1A_DD01_0222_DVBT.fpga"),
DEV(0x0223, "SDRModulator IQ2", "SDRModulatorV1A_DD01_0223_IQ2.fpga"),
DEV(0x0000, "UNKNOWN", 0),
};
static char *devid2fname(uint16_t devid, char **name)
{
int i;
char *fname = 0;
switch (devid) {
case 0x0002:
fname="DVBBridgeV1A_DVBBridgeV1A.bit";
*name = "Octopus 35";
break;
case 0x0003:
fname="DVBBridgeV1B_DVBBridgeV1B.fpga";
*name = "Octopus";
break;
case 0x0005:
fname="DVBBridgeV2A_DD01_0005_STD.fpga";
*name = "Octopus Classic";
break;
case 0x0006:
fname="DVBBridgeV2A_DD01_0006_STD.fpga";
*name = "CineS2 V7";
break;
case 0x0007:
fname="DVBBridgeV2A_DD01_0007_MXL.fpga";
*name = "Octopus 4/8";
break;
case 0x0008:
fname="DVBBridgeV2A_DD01_0008_CXD.fpga";
*name = "Octopus 4/8";
break;
case 0x0009:
fname="DVBBridgeV2A_DD01_0009_SX8.fpga";
*name = "Octopus MAXSX8";
break;
case 0x000b:
fname="DVBBridgeV2A_DD01_000B_SX8.fpga";
*name = "Octopus MAXSX8 Basic";
break;
case 0x000a:
fname="DVBBridgeV2A_DD01_000A_M4.fpga";
*name = "Octopus MAXM4";
break;
case 0x0011:
fname="DVBBridgeV2B_DD01_0011.fpga";
*name = "Octopus CI";
break;
case 0x0012:
fname="DVBBridgeV2B_DD01_0012_STD.fpga";
*name = "Octopus CI";
break;
case 0x0013:
fname="DVBBridgeV2B_DD01_0013_PRO.fpga";
*name = "Octopus PRO";
break;
case 0x0020:
fname="DVBBridgeV2C_DD01_0020.fpga";
*name = "Octopus GT Mini";
break;
case 0x0201:
fname="DVBModulatorV1B_DVBModulatorV1B.bit";
*name = "Modulator";
break;
case 0x0203:
fname="DVBModulatorV1B_DD01_0203.fpga";
*name = "Modulator Test";
break;
case 0x0210:
fname="DVBModulatorV2A_DD01_0210.fpga";
*name = "Modulator V2";
break;
case 0x0220:
fname="SDRModulatorV1A_DD01_0220.fpga";
*name = "SDRModulator ATV";
break;
case 0x0221:
fname="SDRModulatorV1A_DD01_0221_IQ.fpga";
*name = "SDRModulator IQ";
break;
case 0x0222:
fname="SDRModulatorV1A_DD01_0222_DVBT.fpga";
*name = "SDRModulator DVBT";
break;
default:
*name = "UNKNOWN";
break;
for (i = 0; ; i++) {
const struct devids *id = &ids[i];
if (devid == id->id || !id->id) {
*name = id->name;
fname = id->fname;
break;
}
}
return fname;
}
static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
{
off_t off;
@ -996,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)
@ -1015,9 +985,9 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen,
if (memcmp(buf, buf2, bl)) {
printf("flash differs at %08x (offset %u)\n", addr, j);
dump(buf, bl);
printf("\n");
dump(buf2, bl);
//dump(buf, bl);
//printf("\n");
//dump(buf2, bl);
return addr;
}
}
@ -1080,7 +1050,7 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
unsigned int devid, version, length;
unsigned int cid[8];
int cids = 0;
uint32_t maxlen = 2 * 1024 * 1024, crc;
uint32_t maxlen = 2 * 1024 * 1024, crc, fcrc;
fd = open(fn, O_RDONLY);
if (fd < 0) {
@ -1148,15 +1118,27 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
}
p++;
*fw_off = p;
printf(" CRC = %08x\n", crc);
printf(" devid = %04x\n", devid);
printf(" version = %08x (current image = %08x)\n", version, ddf->id.hw);
fcrc = crc32(buf + p, length, 0xffffffff);
printf(" CRC file = %08x\n", fcrc);
printf(" CRC flash = %08x\n", crc);
printf(" devid = %04x\n", devid);
printf(" version = %08x (current image = %08x)\n", version, ddf->id.hw);
//printf(" length = %u\n", length);
//printf("fsize = %u, p = %u, f-p = %u\n", fsize, p, fsize - p);
if (fcrc != crc) {
printf("CRC error in file %s!\n", fn);
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;
@ -1169,13 +1151,13 @@ 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;
uint32_t fw_off = 0;
printf("File: %s\n", fn);
printf("File: %s\n", fn);
if (has_header) {
int ck;
ck = check_fw(ddf, fn, &fw_off);
@ -1189,17 +1171,24 @@ 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) {
printf("but force enabled!\n");
res = 0;
}
}
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");
} else {
printf("Flash verify ERROR!\n");
}
}

View File

@ -89,6 +89,7 @@ struct ddflash {
int fd;
uint32_t link;
char *fname;
int force;
struct ddb_id id;
uint32_t version;

View File

@ -147,7 +147,7 @@ int main(int argc, char **argv)
if (gold != 0xffffffff) {
if (gold < 0x3ffff) {
root = gold2root(gold);
printf("gold = %llu (0x%05x) root = %llu (0x%05x)\n",
printf("gold = %u (0x%05x) root = %u (0x%05x)\n",
gold, gold, root, root);
} else
printf("Invalid gold code specified.\n");

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

@ -27,14 +27,16 @@ void proc_ts(int i, uint8_t *buf)
{
uint16_t pid= 0x1fff& ((buf[1] << 8) | buf[2]);
uint8_t ccin = buf[3] & 0x1f;
if( buf[0] == 0x47 && (buf[1] & 0x80) == 0) {
if( pid != 8191 ) {
if (ccin & 0x10) {
if( cc[pid] != 0 ) {
// TODO: 1 repetition allowed
if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) )
if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) ) {
cc_errors += 1;
printf("%04x: %u != %u\n", pid, (cc[pid] + 1) & 0x0F, ccin & 0x0F);
}
}
cc[pid] = ccin;
}

View File

@ -1,12 +1,16 @@
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
#mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o
ifneq ($(KERNEL_DVB_CORE),y)
obj-$(CONFIG_DVB_OCTONET) += octonet.o
endif
#EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
#EXTRA_CFLAGS += -Idrivers/media/common/tuners

View File

@ -3,7 +3,7 @@
#
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o
@ -11,4 +11,5 @@ obj-$(CONFIG_DVB_OCTONET) += octonet.o
ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += -Idrivers/media/dvb-frontends/
ccflags-y += -Idrivers/media/tuners/
ccflags-y += --include=dd_compat.h

View File

@ -105,7 +105,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
ddbwritel(ci->port->dev, CI_POWER_ON,
CI_CONTROL(ci->nr));
msleep(100);
msleep(300);
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
CI_CONTROL(ci->nr));
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
@ -236,7 +236,7 @@ static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
write_creg(ci, 0x01, 0x01);
write_creg(ci, 0x04, 0x04);
msleep(20);
msleep(300);
write_creg(ci, 0x02, 0x02);
write_creg(ci, 0x00, 0x04);
write_creg(ci, 0x18, 0x18);

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;
@ -94,6 +95,70 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/****************************************************************************/
/****************************************************************************/
/* copied from dvb-core/dvbdev.c because kernel version does not export it */
int ddb_dvb_usercopy(struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct file *file,
unsigned int cmd, void *arg))
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
int err = -EINVAL;
/* Copy arguments into temp kernel buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_NONE:
/*
* For this command, the pointer is actually an integer
* argument.
*/
parg = (void *) arg;
break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
break;
}
/* call driver */
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
err = -ENOTTY;
if (err < 0)
goto out;
/* Copy results into user buffer */
switch (_IOC_DIR(cmd))
{
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
err = -EFAULT;
break;
}
out:
kfree(mbuf);
return err;
}
/****************************************************************************/
struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data)
{
@ -281,9 +346,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 +366,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 (((uintptr_t) dma->vbuf[i] & 0xfff))
dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]);
}
return 0;
}
@ -333,7 +400,7 @@ static int ddb_buffers_alloc(struct ddb *dev)
if (dma_alloc(dev->pdev,
port->input[0]->dma, 0) < 0)
return -1;
/* fallthrough */
fallthrough;
case DDB_PORT_MOD:
if (port->output->dma)
if (dma_alloc(dev->pdev,
@ -454,10 +521,11 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags)
*con2 = (nco << 16) | gap;
}
static void ddb_output_start_unlocked(struct ddb_output *output)
static int ddb_output_start_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
u32 con = 0x11c, con2 = 0;
int err = 0;
if (output->dma) {
output->dma->cbuf = 0;
@ -466,7 +534,9 @@ static void ddb_output_start_unlocked(struct ddb_output *output)
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
}
if (output->port->class == DDB_PORT_MOD) {
ddbridge_mod_output_start(output);
#ifndef CONFIG_MACH_OCTONET
err = ddbridge_mod_output_start(output);
#endif
} else {
if (output->port->input[0]->port->class == DDB_PORT_LOOP)
con = (1UL << 13) | 0x14;
@ -489,26 +559,32 @@ static void ddb_output_start_unlocked(struct ddb_output *output)
ddbwritel(dev, con | 1, TS_CONTROL(output));
if (output->dma)
output->dma->running = 1;
return err;
}
static void ddb_output_start(struct ddb_output *output)
static int ddb_output_start(struct ddb_output *output)
{
int err;
if (output->dma) {
spin_lock_irq(&output->dma->lock);
ddb_output_start_unlocked(output);
err = ddb_output_start_unlocked(output);
spin_unlock_irq(&output->dma->lock);
} else {
ddb_output_start_unlocked(output);
err = ddb_output_start_unlocked(output);
}
return err;
}
static void ddb_output_stop_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
#ifndef CONFIG_MACH_OCTONET
if (output->port->class == DDB_PORT_MOD)
ddbridge_mod_output_stop(output);
else
#endif
ddbwritel(dev, 0, TS_CONTROL(output));
if (output->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
@ -527,6 +603,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;
@ -538,11 +626,14 @@ static void ddb_input_stop_unlocked(struct ddb_input *input)
input->dma->running = 0;
if (input->dma->stall_count)
dev_warn(input->port->dev->dev,
"DMA stalled %u times!\n",
"l%ui%u: DMA stalled %u times!\n",
input->port->lnr, input->nr,
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",
"l%ui%u: %u packets lost due to low DMA performance!\n",
input->port->lnr, input->nr,
input->dma->packet_loss);
}
}
@ -918,7 +1009,7 @@ static int ts_open(struct inode *inode, struct file *file)
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
ddb_input_start(input);
else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
ddb_output_start(output);
err = ddb_output_start(output);
return err;
}
@ -977,8 +1068,12 @@ static struct dvb_device dvbdev_ci = {
static long mod_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
}
#ifndef CONFIG_MACH_OCTONET
return ddb_dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
#else
return 0;
#endif
}
static const struct file_operations mod_fops = {
.owner = THIS_MODULE,
@ -1029,13 +1124,19 @@ static void dummy_release(struct dvb_frontend *fe)
kfree(fe);
}
static enum dvbfe_algo dummy_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
static struct dvb_frontend_ops dummy_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 },
.delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "DUMMY DVB-C/C2 DVB-T/T2",
.frequency_stepsize_hz = 166667, /* DVB-T only */
.frequency_min_hz = 47000000, /* DVB-T: 47125000 */
.frequency_max_hz = 865000000, /* DVB-C: 862000000 */
.name = "DUMMY DVB-C",
.frequency_stepsize_hz = 0,
.frequency_tolerance_hz = 0,
.frequency_min_hz = 47000000,
.frequency_max_hz = 865000000,
.symbol_rate_min = 870000,
.symbol_rate_max = 11700000,
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
@ -1048,6 +1149,7 @@ static struct dvb_frontend_ops dummy_ops = {
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.get_frontend_algo = dummy_algo,
.release = dummy_release,
.read_status = dummy_read_status,
};
@ -1068,7 +1170,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;
}
@ -1139,6 +1245,7 @@ static int demod_attach_stv0367dd(struct ddb_input *input)
return 0;
}
#ifdef CONFIG_DVB_DRXK
static int tuner_attach_tda18271(struct ddb_input *input)
{
struct i2c_adapter *i2c = &input->port->i2c->adap;
@ -1157,6 +1264,7 @@ static int tuner_attach_tda18271(struct ddb_input *input)
}
return 0;
}
#endif
static int tuner_attach_tda18212dd(struct ddb_input *input)
{
@ -1426,35 +1534,37 @@ static void dvb_input_detach(struct ddb_input *input)
case 0x41:
if (dvb->fe2)
dvb_unregister_frontend(dvb->fe2);
/* fallthrough */
fallthrough;
case 0x40:
if (dvb->fe)
dvb_unregister_frontend(dvb->fe);
/* fallthrough */
fallthrough;
case 0x30:
dvb_frontend_detach(dvb->fe);
dvb->fe = NULL;
dvb->fe2 = NULL;
/* fallthrough */
fallthrough;
case 0x21:
if (input->port->dev->ns_num)
dvb_netstream_release(&dvb->dvbns);
/* fallthrough */
fallthrough;
case 0x20:
#ifdef CONFIG_DVB_NET
dvb_net_release(&dvb->dvbnet);
/* fallthrough */
#endif
fallthrough;
case 0x12:
dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
&dvb->hw_frontend);
dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
&dvb->mem_frontend);
/* fallthrough */
fallthrough;
case 0x11:
dvb_dmxdev_release(&dvb->dmxdev);
/* fallthrough */
fallthrough;
case 0x10:
dvb_dmx_release(&dvb->demux);
/* fallthrough */
fallthrough;
case 0x01:
break;
}
@ -1620,9 +1730,11 @@ static int dvb_input_attach(struct ddb_input *input)
return ret;
dvb->attached = 0x12;
#ifdef CONFIG_DVB_NET
ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux);
if (ret < 0)
return ret;
#endif
dvb->attached = 0x20;
if (input->port->dev->ns_num) {
@ -1695,7 +1807,7 @@ static int dvb_input_attach(struct ddb_input *input)
osc24 = 0;
else
osc24 = 1;
/* fallthrough */
fallthrough;
case DDB_TUNER_DVBCT2_SONY_P:
case DDB_TUNER_DVBC2T2_SONY_P:
case DDB_TUNER_ISDBT_SONY_P:
@ -1712,7 +1824,7 @@ static int dvb_input_attach(struct ddb_input *input)
break;
case DDB_TUNER_DVBC2T2I_SONY:
osc24 = 1;
/* fallthrough */
fallthrough;
case DDB_TUNER_DVBCT2_SONY:
case DDB_TUNER_DVBC2T2_SONY:
case DDB_TUNER_ISDBT_SONY:
@ -1991,14 +2103,14 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (port->nr == 1 && dev->link[l].info->type == DDB_OCTOPUS_CI &&
if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI &&
link->info->i2c_mask == 1) {
port->name = "NO TAB";
port->class = DDB_PORT_NONE;
return;
}
if (dev->link[l].info->type == DDB_MOD) {
if (link->info->type == DDB_MOD) {
port->name = "MOD";
port->class = DDB_PORT_MOD;
return;
@ -2014,9 +2126,8 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (link->info->type == DDB_OCTOPUS_MCI) {
if (port->nr >= link->info->mci_ports)
return;
if ((link->info->type == DDB_OCTOPUS_MCI) &&
(port->nr < link->info->mci_ports)) {
port->name = "DUAL MCI";
port->type_name = "MCI";
port->class = DDB_PORT_TUNER;
@ -2160,7 +2271,7 @@ static int ddb_port_attach(struct ddb_port *port)
ret = ddb_ci_attach(port, ci_bitrate);
if (ret < 0)
break;
/* fallthrough */
fallthrough;
case DDB_PORT_LOOP:
ret = dvb_register_device(port->dvb[0].adap,
&port->dvb[0].dev,
@ -2277,21 +2388,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),
@ -2301,15 +2427,9 @@ static void input_write_dvb(struct ddb_input *input,
}
}
#ifdef DDB_USE_WORK
static void input_work(struct work_struct *work)
{
struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
#else
static void input_tasklet(unsigned long data)
{
struct ddb_dma *dma = (struct ddb_dma *)data;
#endif
struct ddb_input *input = (struct ddb_input *)dma->io;
struct ddb *dev = input->port->dev;
unsigned long flags;
@ -2321,16 +2441,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)
@ -2351,17 +2462,10 @@ static void input_handler(unsigned long data)
* just copy pointers and ACK. So, there is no need to go
* through the tasklet scheduler.
*/
#ifdef DDB_USE_WORK
if (input->redi)
queue_work(ddb_wq, &dma->work);
else
input_work(&dma->work);
#else
if (input->redi)
tasklet_schedule(&dma->tasklet);
else
input_tasklet(data);
#endif
}
#else
@ -2370,23 +2474,13 @@ static void input_handler(void *data)
struct ddb_input *input = (struct ddb_input *)data;
struct ddb_dma *dma = input->dma;
#ifdef DDB_USE_WORK
queue_work(ddb_wq, &dma->work);
#else
input_tasklet((unsigned long)dma);
#endif
}
#endif
#ifdef DDB_USE_WORK
static void output_work(struct work_struct *work)
{
struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
#else
static void output_tasklet(unsigned long data)
{
struct ddb_dma *dma = (struct ddb_dma *)data;
#endif
struct ddb_output *output = (struct ddb_output *)dma->io;
struct ddb *dev = output->port->dev;
unsigned long flags;
@ -2428,11 +2522,7 @@ static void output_handler(void *data)
struct ddb_output *output = (struct ddb_output *)data;
struct ddb_dma *dma = output->dma;
#ifdef DDB_USE_WORK
queue_work(ddb_wq, &dma->work);
#else
tasklet_schedule(&dma->tasklet);
#endif
}
#endif
@ -2463,11 +2553,7 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
spin_lock_init(&dma->lock);
init_waitqueue_head(&dma->wq);
if (out) {
#ifdef DDB_USE_WORK
INIT_WORK(&dma->work, output_work);
#else
tasklet_init(&dma->tasklet, output_tasklet, (unsigned long)dma);
#endif
dma->regs = rm->odma->base + rm->odma->size * nr;
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
if (io->port->dev->link[0].info->type == DDB_MOD &&
@ -2481,11 +2567,7 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
dma->div = 1;
}
} else {
#ifdef DDB_USE_WORK
INIT_WORK(&dma->work, input_work);
#else
tasklet_init(&dma->tasklet, input_tasklet, (unsigned long)dma);
#endif
dma->regs = rm->idma->base + rm->idma->size * nr;
dma->bufregs = rm->idma_buf->base + rm->idma_buf->size * nr;
dma->num = dma_buf_num;
@ -2507,8 +2589,10 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
rm = io_regmap(input, 1);
input->regs = DDB_LINK_TAG(port->lnr) |
(rm->input->base + rm->input->size * nr);
#if 0
dev_info(dev->dev, "init link %u, input %u, regs %08x\n",
port->lnr, nr, input->regs);
#endif
if (dev->has_dma) {
const struct ddb_regmap *rm0 = io_regmap(input, 0);
u32 base = rm0->irq_base_idma;
@ -2574,7 +2658,7 @@ static int ddb_port_match_link_i2c(struct ddb_port *port)
static void ddb_ports_init(struct ddb *dev)
{
u32 i, l, p;
u32 i, l, p, ports;
struct ddb_port *port;
const struct ddb_info *info;
const struct ddb_regmap *rm;
@ -2586,7 +2670,8 @@ static void ddb_ports_init(struct ddb *dev)
rm = info->regmap;
if (!rm)
continue;
for (i = 0; i < info->port_num; i++, p++) {
ports = info->port_num;
for (i = 0; i < ports; i++, p++) {
port = &dev->port[p];
port->dev = dev;
port->nr = i;
@ -2608,6 +2693,7 @@ static void ddb_ports_init(struct ddb *dev)
port->class = DDB_PORT_CI;
port->type = DDB_CI_EXTERNAL_XO2_B;
port->name = "DuoFlex CI_B";
port->type_name = "CI_XO2_B";
port->i2c = dev->port[p - 1].i2c;
}
dev_info(dev->dev, "Port %u: Link %u, Link Port %u (TAB %u): %s\n",
@ -2629,15 +2715,16 @@ static void ddb_ports_init(struct ddb *dev)
}
if (port->class == DDB_PORT_NONE)
continue;
switch (dev->link[l].info->type) {
switch (info->type) {
case DDB_OCTOPUS_CI:
if (i >= 2) {
ddb_input_init(port, 2 + i, 0, 2 + i);
ddb_input_init(port, 4 + i, 1, 4 + i);
ddb_output_init(port, i);
break;
} /* fallthrough */
}
fallthrough;
case DDB_OCTONET:
case DDB_OCTOPUS:
case DDB_OCTOPRO:
@ -2652,10 +2739,12 @@ static void ddb_ports_init(struct ddb *dev)
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
break;
case DDB_MOD:
#ifndef CONFIG_MACH_OCTONET
ddb_output_init(port, i);
ddb_irq_set(dev, 0, i + rm->irq_base_rate,
&ddbridge_mod_rate_handler,
&dev->output[i]);
#endif
break;
default:
break;
@ -2672,21 +2761,12 @@ void ddb_ports_release(struct ddb *dev)
for (i = 0; i < dev->port_num; i++) {
port = &dev->port[i];
#ifdef DDB_USE_WORK
if (port->input[0] && port->input[0]->dma)
cancel_work_sync(&port->input[0]->dma->work);
if (port->input[1] && port->input[1]->dma)
cancel_work_sync(&port->input[1]->dma->work);
if (port->output && port->output->dma)
cancel_work_sync(&port->output->dma->work);
#else
if (port->input[0] && port->input[0]->dma)
tasklet_kill(&port->input[0]->dma->tasklet);
if (port->input[1] && port->input[1]->dma)
tasklet_kill(&port->input[1]->dma->tasklet);
if (port->output && port->output->dma)
tasklet_kill(&port->output->dma->tasklet);
#endif
}
}
@ -2790,9 +2870,6 @@ irqreturn_t ddb_irq_handler(int irq, void *dev_id)
irq_handle_msg(dev, s);
if (s & 0x0fffff00) {
irq_handle_io(dev, s);
#ifdef DDB_TEST_THREADED
ret = IRQ_WAKE_THREAD;
#endif
}
} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
@ -2840,15 +2917,6 @@ irqreturn_t ddb_irq_handler_v2(int irq, void *dev_id)
return ret;
}
#ifdef DDB_TEST_THREADED
static irqreturn_t irq_thread(int irq, void *dev_id)
{
/* struct ddb *dev = (struct ddb *) dev_id; */
return IRQ_HANDLED;
}
#endif
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
@ -2988,7 +3056,7 @@ static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg)
static long nsd_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
return ddb_dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
}
static const struct file_operations nsd_fops = {
@ -3160,69 +3228,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;
};
#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 DDB_NAME "ddbridge"
static u32 ddb_num;
@ -3301,8 +3306,8 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ddbid.device = dev->link[0].ids.device;
ddbid.subvendor = dev->link[0].ids.subvendor;
ddbid.subdevice = dev->link[0].ids.subdevice;
ddbid.hw = ddbreadl(dev, 0);
ddbid.regmap = ddbreadl(dev, 4);
ddbid.hw = dev->link[0].ids.hwid;
ddbid.regmap = dev->link[0].ids.regmapid;
if (copy_to_user(parg, &ddbid, sizeof(ddbid)))
return -EFAULT;
break;
@ -3433,6 +3438,22 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EIO;
break;
}
case IOCTL_DDB_MCI_CMD:
{
struct ddb_mci_msg msg;
struct ddb_link *link;
int res;
if (copy_from_user(&msg, parg, sizeof(msg)))
return -EFAULT;
if (msg.link > 3)
return -EFAULT;
link = &dev->link[msg.link];
res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res);
if (copy_to_user(parg, &msg, sizeof(msg)))
return -EFAULT;
return res;
}
default:
return -ENOTTY;
}
@ -3693,19 +3714,23 @@ static ssize_t snr_show(struct device *device,
struct ddb *dev = dev_get_drvdata(device);
char snr[32];
int num = attr->attr.name[3] - 0x30;
struct ddb_port *port = &dev->port[num];
struct i2c_adapter *i2c = &port->i2c->adap;
if (dev->port[num].type >= DDB_TUNER_XO2) {
if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0)
switch (port->type) {
case DDB_CI_EXTERNAL_XO2:
case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2I_SONY:
if (i2c_read_regs(i2c, 0x10, 0x10, snr, 16) < 0)
return sprintf(buf, "NO SNR\n");
snr[16] = 0;
} else {
break;
default:
/* serial number at 0x100-0x11f */
if (i2c_read_regs16(&dev->i2c[num].adap,
0x57, 0x100, snr, 32) < 0)
if (i2c_read_regs16(&dev->i2c[num].adap,
0x50, 0x100, snr, 32) < 0)
if (i2c_read_regs16(i2c, 0x57, 0x100, snr, 32) < 0)
if (i2c_read_regs16(i2c, 0x50, 0x100, snr, 32) < 0)
return sprintf(buf, "NO SNR\n");
snr[31] = 0; /* in case it is not terminated on EEPROM */
break;
}
return sprintf(buf, "%s\n", snr);
}
@ -3716,15 +3741,17 @@ static ssize_t snr_store(struct device *device, struct device_attribute *attr,
struct ddb *dev = dev_get_drvdata(device);
int num = attr->attr.name[3] - 0x30;
u8 snr[34] = { 0x01, 0x00 };
struct ddb_port *port = &dev->port[num];
struct i2c_adapter *i2c = &port->i2c->adap;
return 0; /* NOE: remove completely? */
if (count > 31)
return -EINVAL;
if (dev->port[num].type >= DDB_TUNER_XO2)
if (port->type >= DDB_TUNER_XO2)
return -EINVAL;
memcpy(snr + 2, buf, count);
i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
i2c_write(&dev->i2c[num].adap, 0x50, snr, 34);
i2c_write(i2c, 0x57, snr, 34);
i2c_write(i2c, 0x50, snr, 34);
return count;
}
@ -4414,6 +4441,50 @@ static int ddb_init_boards(struct ddb *dev)
usleep_range(2000, 3000);
}
ddb_init_tempmon(link);
if (info->regmap->mci) {
if (link->info->type == DDB_OCTOPUS_MCI ||
((link->info->type == DDB_MOD) &&
(link->ids.regmapid & 0xfff0)) ||
((link->info->type == DDB_MOD) &&
(link->ids.revision == 1)))
mci_init(link);
}
if (l)
continue;
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version == 2) {
u32 lic = ddbreadl(dev, 0x1c) & 7;
if (dev->link[0].ids.revision == 1)
lic = ddbreadl(dev, 0x260) >> 24;
switch (lic) {
case 0:
case 4:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000);
break;
case 1:
case 8:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 2:
case 24:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0001);
break;
case 3:
case 16:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
default:
break;
}
dev_info(dev->dev, "Modulator channels: %u\n", dev->link[0].info->port_num);
}
}
return 0;
}
@ -4440,8 +4511,10 @@ int ddb_init(struct ddb *dev)
if (ddb_i2c_init(dev) < 0)
goto fail;
ddb_ports_init(dev);
#ifndef CONFIG_MACH_OCTONET
if (dev->link[0].info->type == DDB_MOD)
ddbridge_mod_init(dev);
#endif
if (ddb_buffers_alloc(dev) < 0) {
dev_info(dev->dev,
"Could not allocate buffer memory\n");
@ -4508,7 +4581,7 @@ int ddb_exit_ddbridge(int stage, int error)
default:
case 2:
destroy_workqueue(ddb_wq);
/* fallthrough */
fallthrough;
case 1:
ddb_class_destroy();
}

View File

@ -124,6 +124,32 @@ static const struct ddb_regset octopus_i2c_buf = {
/****************************************************************************/
static const struct ddb_regset max_mci = {
.base = 0x500,
.num = 0x01,
.size = 0x04,
};
static const struct ddb_regset max_mci_buf = {
.base = 0x600,
.num = 0x01,
.size = 0x100,
};
static const struct ddb_regset sdr_mci = {
.base = 0x260,
.num = 0x01,
.size = 0x04,
};
static const struct ddb_regset sdr_mci_buf = {
.base = 0x300,
.num = 0x01,
.size = 0x100,
};
/****************************************************************************/
static const struct ddb_regset octopro_input = {
.base = 0x400,
.num = 0x14,
@ -224,6 +250,25 @@ static const struct ddb_regmap octopus_map = {
.output = &octopus_output,
};
static const struct ddb_regmap octopus_mci_map = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_idma = 8,
.irq_base_odma = 16,
.irq_base_mci = 0,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.idma = &octopus_idma,
.idma_buf = &octopus_idma_buf,
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
.input = &octopus_input,
.output = &octopus_output,
.mci = &max_mci,
.mci_buf = &max_mci_buf,
};
static const struct ddb_regmap octopro_map = {
.irq_version = 2,
.irq_base_i2c = 32,
@ -270,20 +315,28 @@ static const struct ddb_regmap octopus_mod_2_map = {
.irq_version = 2,
.irq_base_odma = 64,
.irq_base_rate = 32,
.irq_base_mci = 10,
.output = &octopus_output,
.odma = &octopus_mod_2_odma,
.odma_buf = &octopus_mod_2_odma_buf,
.channel = &octopus_mod_2_channel,
.mci = &sdr_mci,
.mci_buf = &sdr_mci_buf,
};
static const struct ddb_regmap octopus_sdr_map = {
.irq_version = 2,
.irq_base_odma = 64,
.irq_base_rate = 32,
.irq_base_mci = 10,
.output = &octopus_sdr_output,
.odma = &octopus_mod_2_odma,
.odma_buf = &octopus_mod_2_odma_buf,
.channel = &octopus_mod_2_channel,
.mci = &sdr_mci,
.mci_buf = &sdr_mci_buf,
};
static const struct ddb_regmap gtl_mini = {
@ -508,7 +561,7 @@ static const struct ddb_info ddb_mod_fsm_8 = {
static const struct ddb_info ddb_mod_fsm_4 = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C modulator FSM-8",
.name = "Digital Devices DVB-C modulator FSM-4",
.version = 2,
.regmap = &octopus_mod_2_map,
.port_num = 4,
@ -517,6 +570,17 @@ static const struct ddb_info ddb_mod_fsm_4 = {
.lostlock_irq = 9,
};
static const struct ddb_info ddb_mod_fsm = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C FSM",
.version = 2,
.regmap = &octopus_mod_2_map,
.port_num = 0,
.temp_num = 1,
.tempmon_irq = 8,
.lostlock_irq = 9,
};
static const struct ddb_info ddb_sdr_atv = {
.type = DDB_MOD,
.name = "Digital Devices SDR ATV",
@ -537,12 +601,22 @@ static const struct ddb_info ddb_sdr_iq = {
.tempmon_irq = 8,
};
static const struct ddb_info ddb_sdr_iq2 = {
.type = DDB_MOD,
.name = "Digital Devices SDR IQ2",
.version = 17,
.regmap = &octopus_sdr_map,
.port_num = 4,
.temp_num = 1,
.tempmon_irq = 8,
};
static const struct ddb_info ddb_sdr_dvbt = {
.type = DDB_MOD,
.name = "Digital Devices DVBT",
.version = 18,
.regmap = &octopus_sdr_map,
.port_num = 16,
.port_num = 14,
.temp_num = 1,
.tempmon_irq = 8,
};
@ -568,7 +642,7 @@ static const struct ddb_info ddb_octopro = {
static const struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8",
.regmap = &octopus_map,
.regmap = &octopus_mci_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 1,
@ -635,10 +709,12 @@ static const struct ddb_info ddb_c2t2i_8 = {
.tempmon_irq = 24,
};
/****************************************************************************/
static const struct ddb_info ddb_s2x_48 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX SX8",
.regmap = &octopus_map,
.regmap = &octopus_mci_map,
.port_num = 4,
.i2c_mask = 0x00,
.tempmon_irq = 24,
@ -650,7 +726,7 @@ static const struct ddb_info ddb_s2x_48 = {
static const struct ddb_info ddb_s2x_48_b = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX SX8 Basic",
.regmap = &octopus_map,
.regmap = &octopus_mci_map,
.port_num = 4,
.i2c_mask = 0x00,
.tempmon_irq = 24,
@ -662,7 +738,7 @@ static const struct ddb_info ddb_s2x_48_b = {
static const struct ddb_info ddb_m4 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M4",
.regmap = &octopus_map,
.regmap = &octopus_mci_map,
.port_num = 2,
.i2c_mask = 0x00,
.tempmon_irq = 24,
@ -671,6 +747,8 @@ static const struct ddb_info ddb_m4 = {
.temp_num = 1,
};
/****************************************************************************/
static const struct ddb_info ddb_gtl_mini = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus GT Mini",
@ -806,6 +884,7 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0201, 0x0002, ddb_mod),
DDB_DEVID(0x0201, 0x0004, ddb_mod_4), /* dummy entry ! */
DDB_DEVID(0x0203, 0x0001, ddb_mod),
DDB_DEVID(0x0210, 0x0004, ddb_mod_fsm), /* dummy entry ! */
DDB_DEVID(0x0210, 0x0000, ddb_mod_fsm_4), /* dummy entry ! */
DDB_DEVID(0x0210, 0x0001, ddb_mod_fsm_24),
DDB_DEVID(0x0210, 0x0002, ddb_mod_fsm_16),
@ -813,6 +892,8 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt),
DDB_DEVID(0x0223, 0x0001, ddb_sdr_iq2),
DDB_DEVID(0xffff, 0xffff, ddb_sdr_iq2),
/* testing on OctopusNet Pro */
DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),

View File

@ -139,8 +139,8 @@ void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count)
u32 a = p & 3;
if (a) {
val = ddbreadl(dev, p) >> (8 * a);
while (p & 3 && count) {
val = ddbreadl(dev, p & ~3) >> (8 * a);
while ((p & 3) && count) {
*buf = val & 0xff;
val >>= 8;
p++;
@ -177,7 +177,12 @@ void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count)
void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count)
{
return gtlcpyfrom(dev, dst, adr, count);
/* The possible 64 bit read in memcpy_fromio produces errors
on some platforms, i.e. arm64 rpi4
if (unlikely(adr & 0xf0000000))
return gtlcpyfrom(dev, dst, adr, count);
return memcpy_fromio(dst, dev->regs + adr, count);
return memcpy_fromio(dst, dev->regs + adr, count);
*/
}

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,17 +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 == MCI_DEMOD_LOCKED) {
else if (res.status == M4_DEMOD_WAIT_TS)
*status = 0x03;
else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT;
else if (res.status == MCI_DEMOD_LOCKED) {
*status = 0x1f;
ddb_mci_get_snr(fe);
}
@ -510,7 +516,7 @@ static int base_init(struct mci_base *mci_base)
return 0;
}
struct mci_cfg ddb_max_m4_cfg = {
static struct mci_cfg ddb_max_m4_cfg = {
.type = 0,
.fe_ops = &m4_ops,
.base_size = sizeof(struct m4_base),
@ -518,3 +524,8 @@ struct mci_cfg ddb_max_m4_cfg = {
.init = init,
.base_init = base_init,
};
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner)
{
return ddb_mci_attach(input, &ddb_max_m4_cfg, nr, tuner);
}

View File

@ -84,7 +84,7 @@ int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
/****************************************************************************/
/****************************************************************************/
static void __devexit ddb_irq_disable(struct ddb *dev)
static void ddb_irq_disable(struct ddb *dev)
{
if (dev->link[0].info->regmap->irq_version == 2) {
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
@ -114,7 +114,7 @@ static void __devexit ddb_msi_exit(struct ddb *dev)
#endif
}
static void __devexit ddb_irq_exit(struct ddb *dev)
static void ddb_irq_exit(struct ddb *dev)
{
ddb_irq_disable(dev);
if (dev->msi == 2)
@ -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);
}
@ -254,17 +255,9 @@ static int __devinit ddb_irq_init(struct ddb *dev)
return stat;
}
} else {
#ifdef DDB_TEST_THREADED
stat = request_threaded_irq(pci_irq_vector(dev->pdev, 0),
dev->pdev->irq, ddb_irq_handler,
irq_thread,
irq_flag,
"ddbridge", (void *)dev);
#else
stat = request_irq(pci_irq_vector(dev->pdev, 0),
ddb_irq_handler,
irq_flag, "ddbridge", (void *)dev);
#endif
if (stat < 0)
return stat;
}
@ -290,9 +283,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
pci_set_master(pdev);
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
return -ENODEV;
#if (KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE)
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
#else
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
} else
#endif
return -ENODEV;
dev = vzalloc(sizeof(*dev));
if (!dev)
@ -309,11 +310,11 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.subvendor = id->subvendor;
dev->link[0].ids.subdevice = pdev->subsystem_device;
dev->link[0].ids.devid = (id->device << 16) | id->vendor;
dev->link[0].ids.revision = pdev->revision;
dev->link[0].dev = dev;
dev->link[0].info = get_ddb_info(id->vendor, id->device,
id->subvendor, pdev->subsystem_device);
dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name);
dev->regs_len = pci_resource_len(dev->pdev, 0);
dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
@ -333,14 +334,12 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
dev_info(dev->dev, "HW %08x REGMAP %08x\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
if ((dev->link[0].ids.hwid & 0xffffff) <
dev->link[0].info->hw_min) {
u32 min = dev->link[0].info->hw_min;
dev_err(dev->dev, "Update firmware to at least version %u.%u to ensure full functionality!\n",
(min & 0xff0000) >> 16, min & 0xffff);
(min & 0xff0000) >> 16, min & 0xffff);
}
if (dev->link[0].info->ns_num) {
@ -351,33 +350,27 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
if (dev->link[0].info->type != DDB_MOD)
ddbwritel(dev, 0, DMA_BASE_WRITE);
if (dev->link[0].info->type == DDB_MOD
&& dev->link[0].info->version <= 1) {
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version <= 1) {
if (ddbreadl(dev, 0x1c) == 4)
dev->link[0].info =
get_ddb_info(0xdd01, 0x0201, 0xdd01, 0x0004);
}
if (dev->link[0].info->type == DDB_MOD
&& dev->link[0].info->version == 2) {
u32 lic = ddbreadl(dev, 0x1c) & 7;
switch (lic) {
case 0:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000);
break;
case 1:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 3:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
default:
break;
}
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version == 2) {
if (dev->link[0].ids.revision == 1)
dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
else if ((ddbreadl(dev, 0x1c) & 7) != 7)
dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
}
dev_info(dev->dev, "%s\n", dev->link[0].info->name);
dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
dev->link[0].ids.hwid & 0xffff);
stat = ddb_irq_init(dev);
if (stat < 0)
goto fail0;
@ -402,6 +395,12 @@ fail:
/****************************************************************************/
/****************************************************************************/
#ifndef PCI_DEVICE_SUB
#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
.vendor = (vend), .device = (dev), \
.subvendor = (subvend), .subdevice = (subdev)
#endif
#define DDB_DEVICE_ANY(_device) \
{ PCI_DEVICE_SUB(0xdd01, _device, 0xdd01, PCI_ANY_ID) }
@ -425,6 +424,7 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0220),
DDB_DEVICE_ANY(0x0221),
DDB_DEVICE_ANY(0x0222),
DDB_DEVICE_ANY(0x0223),
DDB_DEVICE_ANY(0x0320),
DDB_DEVICE_ANY(0x0321),
DDB_DEVICE_ANY(0x0322),
@ -435,7 +435,6 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
};
MODULE_DEVICE_TABLE(pci, ddb_id_table);
static pci_ers_result_t ddb_pci_slot_reset(struct pci_dev *dev)
{
pr_info("pci_slot_reset\n");
@ -475,7 +474,6 @@ static const struct pci_error_handlers ddb_error = {
.resume = ddb_pci_resume,
};
static struct pci_driver ddb_pci_driver = {
.name = "ddbridge",
.id_table = ddb_id_table,

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) {
@ -465,7 +472,8 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
tuner = demod & 3;
if (fmode >= 3)
tuner = 0;
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner);
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg,
demod, tuner, &dvb->set_input);
if (!dvb->fe) {
dev_err(dev->dev, "No MXL5XX found!\n");
return -ENODEV;
@ -483,13 +491,17 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
dvb->fe->ops.diseqc_send_burst = max_send_burst;
dvb->fe->sec_priv = input;
dvb->set_input = dvb->fe->ops.set_input;
#ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input;
#endif
dvb->input = tuner;
return 0;
}
/* MAX MCI related functions */
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input));
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner);
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
{
@ -498,25 +510,23 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
struct ddb_port *port = input->port;
struct ddb_link *link = &dev->link[port->lnr];
int demod, tuner;
struct mci_cfg cfg;
int fm = fmode;
demod = input->nr;
tuner = demod & 3;
switch (type) {
case DDB_TUNER_MCI_SX8:
cfg = ddb_max_sx8_cfg;
if (fm >= 3)
tuner = 0;
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
break;
case DDB_TUNER_MCI_M4:
fm = 0;
cfg = ddb_max_m4_cfg;
dvb->fe = ddb_m4_attach(input, demod, tuner);
break;
default:
return -EINVAL;
}
dvb->fe = ddb_mci_attach(input, &cfg, demod, tuner);
if (!dvb->fe) {
dev_err(dev->dev, "No MCI card found!\n");
return -ENODEV;
@ -538,8 +548,9 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
case DDB_TUNER_MCI_M4:
break;
default:
dvb->set_input = dvb->fe->ops.set_input;
#ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input;
#endif
break;
}
dvb->input = tuner;

View File

@ -28,151 +28,192 @@
static LIST_HEAD(mci_list);
static int mci_reset(struct mci *state)
static int mci_reset(struct ddb_link *link)
{
struct ddb_link *link = state->base->link;
const struct ddb_regmap *regmap = link->info->regmap;
u32 control;
u32 status = 0;
u32 timeout = 40;
union {
u32 u[4];
char s[16];
} version;
u32 vaddr;
if (!regmap || !regmap->mci)
return -EINVAL;
control = regmap->mci->base;
vaddr = regmap->mci_buf->base + 0xf0;
ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL);
ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */
msleep(300);
ddblwritel(link, 0, MCI_CONTROL);
if ((link->info->type == DDB_OCTOPUS_MCI) &&
(ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) {
ddblwritel(link, MCI_CONTROL_RESET, control);
ddblwritel(link, 0, control + 4); /* 1= no internal init */
msleep(300);
}
ddblwritel(link, 0, control);
while (1) {
status = ddblreadl(link, MCI_CONTROL);
status = ddblreadl(link, control);
if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY)
break;
if (--timeout == 0)
break;
msleep(50);
}
if ((status & MCI_CONTROL_READY) == 0)
dev_info(link->dev->dev, "MCI control port @ %08x\n", control);
if ((status & MCI_CONTROL_READY) == 0) {
dev_err(link->dev->dev, "MCI init failed!\n");
return -1;
if (link->ids.device == 0x0009 || link->ids.device == 0x000b)
ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG);
}
version.u[0] = ddblreadl(link, vaddr);
version.u[1] = ddblreadl(link, vaddr + 4);
version.u[2] = ddblreadl(link, vaddr + 8);
version.u[3] = ddblreadl(link, vaddr + 12);
dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50);
dev_info(link->dev->dev, "MCI firmware version %s.%d\n", version.s, version.s[15]);
return 0;
}
int ddb_mci_config(struct mci *state, u32 config)
{
struct ddb_link *link = state->base->link;
if (link->ids.device != 0x0009 && link->ids.device != 0x000b)
return -EINVAL;
ddblwritel(link, config, SX8_TSCONFIG);
return 0;
}
static int ddb_mci_cmd_raw_unlocked(struct mci *state,
static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link,
u32 *cmd, u32 cmd_len,
u32 *res, u32 res_len)
{
struct ddb_link *link = state->base->link;
const struct ddb_regmap *regmap = link->info->regmap;
u32 control, command, result;
u32 i, val;
unsigned long stat;
val = ddblreadl(link, MCI_CONTROL);
if (!regmap || ! regmap->mci)
return -EINVAL;
control = regmap->mci->base;
command = regmap->mci_buf->base;
result = command + MCI_COMMAND_SIZE;
val = ddblreadl(link, control);
if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND))
return -EIO;
if (cmd && cmd_len)
for (i = 0; i < cmd_len; i++)
ddblwritel(link, cmd[i], MCI_COMMAND + i * 4);
val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT);
ddblwritel(link, val, MCI_CONTROL);
ddblwritel(link, cmd[i], command + i * 4);
val |= (MCI_CONTROL_START_COMMAND |
MCI_CONTROL_ENABLE_DONE_INTERRUPT);
ddblwritel(link, val, control);
stat = wait_for_completion_timeout(&state->base->completion, HZ);
stat = wait_for_completion_timeout(&link->mci_completion, HZ);
if (stat == 0) {
u32 istat = ddblreadl(link, INTERRUPT_STATUS);
dev_err(state->base->link->dev->dev, "MCI timeout\n");
val = ddblreadl(link, MCI_CONTROL);
dev_err(link->dev->dev, "MCI timeout\n");
val = ddblreadl(link, control);
if (val == 0xffffffff) {
dev_err(state->base->link->dev->dev,
dev_err(link->dev->dev,
"Lost PCIe link!\n");
return -EIO;
} else {
dev_err(state->base->link->dev->dev,
"DDBridge IRS %08x link %u\n", istat, link->nr);
dev_err(link->dev->dev,
"DDBridge IRS %08x link %u\n",
istat, link->nr);
if (istat & 1)
ddblwritel(link, istat, INTERRUPT_ACK);
if (link->nr)
ddbwritel(link->dev, 0xffffff, INTERRUPT_ACK);
ddbwritel(link->dev,
0xffffff, INTERRUPT_ACK);
}
}
//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false);
if (res && res_len)
for (i = 0; i < res_len; i++)
res[i] = ddblreadl(link, MCI_RESULT + i * 4);
res[i] = ddblreadl(link, result + i * 4);
return 0;
}
int ddb_mci_cmd_unlocked(struct mci *state,
struct mci_command *command,
struct mci_result *result)
int ddb_mci_cmd_link(struct ddb_link *link,
struct mci_command *command,
struct mci_result *result)
{
u32 *cmd = (u32 *) command;
u32 *res = (u32 *) result;
return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32),
res, sizeof(*result)/sizeof(u32));
}
int ddb_mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
int stat;
struct mci_result res;
int stat;
if (!link->mci_ok)
return -EFAULT;
if (!result)
result = &res;
mutex_lock(&state->base->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(state,
(u32 *)command, sizeof(*command)/sizeof(u32),
(u32 *)result, sizeof(*result)/sizeof(u32));
mutex_unlock(&state->base->mci_lock);
mutex_lock(&link->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(link,
(u32 *)command,
sizeof(*command)/sizeof(u32),
(u32 *)result,
sizeof(*result)/sizeof(u32));
mutex_unlock(&link->mci_lock);
if (command && result && (result->status & 0x80))
dev_warn(state->base->link->dev->dev,
dev_warn(link->dev->dev,
"mci_command 0x%02x, error=0x%02x\n",
command->command, result->status);
return stat;
}
static void mci_handler(void *priv)
{
struct ddb_link *link = (struct ddb_link *) priv;
complete(&link->mci_completion);
}
int mci_init(struct ddb_link *link)
{
int result;
mutex_init(&link->mci_lock);
init_completion(&link->mci_completion);
result = mci_reset(link);
if (result < 0)
return result;
if (link->ids.device == 0x0009 || link->ids.device == 0x000b)
ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG);
ddb_irq_set(link->dev, link->nr,
link->info->regmap->irq_base_mci,
mci_handler, link);
link->mci_ok = 1;
return result;
}
int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val)
{
struct mci_result result;
struct mci_command command;
command.command_word = cmd;
command.params[0] = val;
return ddb_mci_cmd_link(link, &command, &result);
}
/****************************************************************************/
/****************************************************************************/
int ddb_mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
return ddb_mci_cmd_link(state->base->link, command, result);
}
int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len)
{
struct ddb_link *link = state->base->link;
int stat;
mutex_lock(&state->base->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(state,
mutex_lock(&link->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(link,
(u32 *)command, command_len,
(u32 *)result, result_len);
mutex_unlock(&state->base->mci_lock);
mutex_unlock(&link->mci_lock);
return stat;
}
#if 0
static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q)
{
int stat;
struct mci_command cmd;
struct mci_result res;
memset(&cmd, 0, sizeof(cmd));
memset(&res, 0, sizeof(res));
cmd.command = MCI_CMD_GET_IQSYMBOL;
cmd.demod = demod;
stat = ddb_mci_cmd(mci, &cmd, &res);
if (!stat) {
*i = res.iq_symbol.i;
*q = res.iq_symbol.q;
}
return stat;
}
#endif
int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
{
struct mci_command cmd;
@ -189,7 +230,8 @@ int ddb_mci_get_snr(struct dvb_frontend *fe)
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10;
p->cnr.stat[0].svalue =
(s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10;
return 0;
}
@ -245,7 +287,7 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
};
const enum fe_code_rate dvbs_fec_lut[8] = {
FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_NONE, FEC_7_8, FEC_NONE, FEC_NONE,
FEC_7_8, FEC_7_8, FEC_NONE, FEC_NONE,
};
const enum fe_rolloff ro_lut[8] = {
ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10,
@ -254,6 +296,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->frequency =
mci->signal_info.dvbs2_signal_info.frequency;
p->symbol_rate =
mci->signal_info.dvbs2_signal_info.symbol_rate;
switch (p->delivery_system) {
default:
case SYS_DVBS:
@ -266,6 +310,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->delivery_system =
(mci->signal_info.dvbs2_signal_info.standard == 2) ?
SYS_DVBS2 : SYS_DVBS;
p->inversion = (mci->signal_info.dvbs2_signal_info.roll_off & 0x80) ?
INVERSION_ON : INVERSION_OFF;
if (mci->signal_info.dvbs2_signal_info.standard == 2) {
u32 modcod;
@ -296,6 +342,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
break;
}
case SYS_DVBC_ANNEX_A:
p->modulation =
mci->signal_info.dvbc_signal_info.constellation + 1;
break;
case SYS_DVBT:
break;
@ -306,6 +354,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
case SYS_ISDBT:
break;
}
/* post is correct, we cannot provide both pre and post at the same time */
/* set pre and post the same for now */
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue =
@ -316,6 +366,16 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->pre_bit_count.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_denominator;
p->post_bit_error.len = 1;
p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_error.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_numerator;
p->post_bit_count.len = 1;
p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_count.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_denominator;
p->block_error.len = 1;
p->block_error.stat[0].scale = FE_SCALE_COUNTER;
p->block_error.stat[0].uvalue =
@ -329,17 +389,10 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].svalue =
p->strength.stat[0].svalue = (s64)
mci->signal_info.dvbs2_signal_info.channel_power * 10;
}
static void mci_handler(void *priv)
{
struct mci_base *base = (struct mci_base *)priv;
complete(&base->completion);
}
static struct mci_base *match_base(void *key)
{
struct mci_base *p;
@ -350,13 +403,8 @@ static struct mci_base *match_base(void *key)
return NULL;
}
static int probe(struct mci *state)
{
mci_reset(state);
return 0;
}
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner)
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input,
struct mci_cfg *cfg, int nr, int tuner)
{
struct ddb_port *port = input->port;
struct ddb *dev = port->dev;
@ -380,12 +428,11 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg
base->key = key;
base->count = 1;
base->link = link;
mutex_init(&base->mci_lock);
link->mci_base = base;
mutex_init(&base->tuner_lock);
ddb_irq_set(dev, link->nr, 0, mci_handler, base);
init_completion(&base->completion);
state->base = base;
if (probe(state) < 0) {
if (!link->mci_ok) {
kfree(base);
goto fail;
}

View File

@ -39,11 +39,6 @@
#define MIC_INTERFACE_OUT (0x0680)
#define MIC_INTERFACE_VER (0x06F0)
#define MCI_CONTROL (0x500)
#define MCI_COMMAND (0x600)
#define MCI_RESULT (0x680)
#define MCI_COMMAND_SIZE (0x80)
#define MCI_RESULT_SIZE (0x80)
@ -106,6 +101,8 @@
#define MCI_STATUS_OK (0x00)
#define MCI_STATUS_UNSUPPORTED (0x80)
#define MCI_STATUS_BUSY (0xFA)
#define MCI_STATUS_HARDWARE_ERROR (0xFB)
#define MCI_STATUS_INVALID_PARAMETER (0xFC)
#define MCI_STATUS_RETRY (0xFD)
#define MCI_STATUS_NOT_READY (0xFE)
@ -137,6 +134,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)
@ -159,7 +157,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)
@ -171,13 +169,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)
@ -186,10 +184,132 @@
#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_STANDARD_DVBC_8 (0x08)
#define MOD_STANDARD_DVBC_7 (0x09)
#define MOD_STANDARD_DVBC_6 (0x0A)
#define MOD_STANDARD_J83A_8 (MOD_STANDARD_DVBC_8)
#define MOD_STANDARD_J83A_7 (MOD_STANDARD_DVBC_7)
#define MOD_STANDARD_J83A_6 (MOD_STANDARD_DVBC_6)
#define MOD_STANDARD_J83B_QAM64 (0x0B)
#define MOD_STANDARD_J83B_QAM256 (0x0C)
#define MOD_STANDARD_ISDBC_QAM64 (0x0D)
#define MOD_STANDARD_ISDBC_QAM256 (0x0E)
#define MOD_STANDARD_J83C_QAM64 (MOD_STANDARD_ISDBC_QAM64 )
#define MOD_STANDARD_J83C_QAM256 (MOD_STANDARD_ISDBC_QAM256)
#define MOD_CONNECTOR_OFF (0x00)
#define MOD_CONNECTOR_F (0x01)
#define MOD_CONNECTOR_SMA (0x02)
#define MOD_UNIT_DBUV (0x00)
#define MOD_UNIT_DBM (0x01)
#define MOD_FORMAT_DEFAULT (0x00)
#define MOD_FORMAT_IQ16 (0x01)
#define MOD_FORMAT_IQ8 (0x02)
#define MOD_FORMAT_IDX8 (0x03)
#define MOD_FORMAT_TS (0x04)
#define MOD_DVBT_FFT_8K (0x01)
#define MOD_DVBT_GI_1_32 (0x00)
#define MOD_DVBT_GI_1_16 (0x01)
#define MOD_DVBT_GI_1_8 (0x02)
#define MOD_DVBT_GI_1_4 (0x03)
#define MOD_DVBT_PR_1_2 (0x00)
#define MOD_DVBT_PR_2_3 (0x01)
#define MOD_DVBT_PR_3_4 (0x02)
#define MOD_DVBT_PR_5_6 (0x03)
#define MOD_DVBT_PR_7_8 (0x04)
#define MOD_DVBT_QPSK (0x00)
#define MOD_DVBT_16QAM (0x01)
#define MOD_DVBT_64QAM (0x02)
#define MOD_QAM_DVBC_16 (0x00)
#define MOD_QAM_DVBC_32 (0x01)
#define MOD_QAM_DVBC_64 (0x02)
#define MOD_QAM_DVBC_128 (0x03)
#define MOD_QAM_DVBC_256 (0x04)
#define MOD_QAM_J83B_64 (0x05)
#define MOD_QAM_J83B_256 (0x06)
#define MOD_QAM_GENERIC (0x07)
#define MOD_QAM_ISDBC_64 (0x08)
#define MOD_QAM_ISDBC_256 (0x09)
#define CMD_GET_SERIALNUMBER (0xF0)
#define CMD_EXPORT_LICENSE (0xF0)
struct mod_setup_channels {
u8 flags;
u8 standard;
u8 num_channels;
u8 rsvd;
u32 frequency;
u32 offset; /* used only when Standard == 0 */
u32 bandwidth; /* used only when Standard == 0 */
};
struct mod_ofdm_parameter {
u8 fft_size; /* 0 = 2K, 1 = 8K (2K not yet supported) */
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */
u8 constellation; /* MOD_DVBT_QPSK, MOD_DVBT_16QAM, MOD_DVBT_64QAM */
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
};
struct mod_qam_parameter {
u8 modulation;
u8 rolloff; /* Legal values: 12,13,15,18 */
};
struct mod_setup_stream {
u8 standard;
u8 stream_format;
u8 rsvd1[2];
u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */
union {
struct mod_ofdm_parameter ofdm;
struct mod_qam_parameter qam;
};
};
struct mod_setup_output {
u8 connector; /* 0 = OFF, 1 = F, 2 = SMA */
u8 num_channels; /* max active channels, determines max power for each channel. */
u8 unit; /* 0 = dBµV, 1 = dBm, */
u8 rsvd;
s16 channel_power;
};
/********************************************************/
@ -202,9 +322,16 @@ struct mci_command {
u8 demod;
u8 output;
};
struct {
u8 mod_command;
u8 mod_channel;
u8 mod_stream;
u8 mod_rsvd1;
};
};
union {
u32 params[31];
u8 params8[31*4];
struct {
u8 flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled,
5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */
@ -220,7 +347,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;
@ -241,7 +368,7 @@ struct mci_command {
u8 retry;
u32 frequency;
} dvbc_search;
struct {
u8 flags; /* Bit 0: LP Stream */
u8 bandwidth;
@ -249,7 +376,7 @@ struct mci_command {
u8 retry;
u32 frequency;
} dvbt_search;
struct {
u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */
u8 bandwidth;
@ -260,7 +387,7 @@ struct mci_command {
u8 plp;
u8 rsvd2[3];
} dvbt2_search;
struct {
u8 flags;
u8 bandwidth;
@ -272,15 +399,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 */
@ -292,7 +419,7 @@ struct mci_command {
u16 onid;
u16 tsid;
} isdbc_search;
struct {
u8 flags;
u8 bandwidth;
@ -302,7 +429,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 {
@ -312,43 +439,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;
};
};
@ -361,26 +492,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 rsvd3;
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
u16 signal_loss_counter;/* Counts signal losses and automatic retunes */
u32 rsvd4;
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator;
u32 ber_rsvd1; // Place holder for modulation bit error rate
u32 ber_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 */
@ -394,7 +526,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 {
@ -409,7 +541,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 {
@ -430,8 +562,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 */
@ -460,7 +592,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
@ -469,7 +601,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 {
@ -492,51 +624,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
} DVBT_TPSInfo;
u8 tps_info[7];
// u16 tps_cell_id;
} dvbt_tps_info;
struct {
struct {
u8 Type;
u8 type;
u8 BWExtension;
u8 S1;
u8 S2;
@ -561,7 +693,8 @@ struct mci_result {
u8 CurrentRFIndex;
u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit
u8 CRC32[4];
} DVBT2_L1Pre;
} dvbt2_l1_pre;
struct {
u8 SubSlicesPerFrame[2];
u8 NumPLP;
@ -572,9 +705,9 @@ struct mci_result {
u8 FEFType;
u8 FEFLength[3];
u8 FEFInterval;
} DVBT2_L1Post;
} DVBT2_L1Info;
} dvbt2_l1_post;
} dvbt2_l1_info;
struct {
u8 PLPID;
u8 Type;
@ -593,8 +726,8 @@ struct mci_result {
u8 TimeILType;
u8 InBandAFlag;
u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1
} DVBT2_PLPInfo;
} dvbt2_plp_info;
struct {
u8 NetworkID[2];
u8 C2SystemID[2];
@ -613,13 +746,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];
@ -633,7 +766,7 @@ struct mci_result {
u8 NumPLP;
u8 Reserved2;
} DVBC2_SliceInfo;
struct {
u8 PLPID;
u8 Bundled;
@ -649,20 +782,20 @@ struct mci_result {
u8 OrginalNetworkID[2];
u8 Reserved1;
} DVBC2_PLPInfo;
struct {
u8 Valid;
u8 MATYPE_1;
u8 MATYPE_2;
u8 UPL[2];
u8 DFL[2];
u8 SYNC;
u8 SYNCD[2];
u8 valid;
u8 matype_1;
u8 matype_2;
u8 upl[2];
u8 dfl[2];
u8 sync;
u8 syncd[2];
u8 rsvd;
u8 ISSY[3];
u8 issy[3];
u8 min_input_stream_id;
u8 max_input_stream_id;
} BBHeader;
} bb_header;
struct {
u8 Mode; // FFT Mode 1,2,3
@ -684,9 +817,46 @@ 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 {
u8 cut;
u8 avs_code;
u8 temperature;
u8 rsvd[13];
} sx8_bist;
struct {
u8 status;
u8 offset;
u8 length;
u8 rsvd2;
u32 rsvd3[2];
u8 data[96];
} SX8_packet_filter_status;
struct {
u8 version; /* 0 = none, 1 = SX8 */
u8 flags; /* Bit 0: 1 = Tuner Valid, Bit 1: 1 = Output Valid */
u8 tuner;
u8 output;
} extended_status;
struct {
u8 reserved;
u8 serial_number[17];
} serial_number;
struct {
u8 flags;
u8 serial_number[17];
u16 code;
u8 ID[8];
u8 LK[24];
} license;
};
u32 version[3];
u32 version_rsvd;
u8 version_rsvd;
u8 version_major;
u8 version_minor;
u8 version_sub;
@ -763,13 +933,15 @@ struct mci_result {
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
#ifdef __KERNEL__
struct mci_base {
struct list_head mci_list;
void *key;
struct ddb_link *link;
struct completion completion;
// struct completion completion;
struct mutex tuner_lock;
struct mutex mci_lock;
// struct mutex mci_lock;
int count;
int type;
};
@ -795,16 +967,15 @@ struct mci_cfg {
};
int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result);
int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len);
int ddb_mci_config(struct mci *state, u32 config);
int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result);
int ddb_mci_get_status(struct mci *mci, struct mci_result *res);
int ddb_mci_get_snr(struct dvb_frontend *fe);
int ddb_mci_get_info(struct mci *mci);
int ddb_mci_get_strength(struct dvb_frontend *fe);
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg;
int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val);
#endif
#endif

View File

@ -23,8 +23,13 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#ifdef KERNEL_DVB_CORE
#include "../include/linux/dvb/mod.h"
#else
#include <linux/dvb/mod.h>
#endif
#include <linux/gcd.h>
/****************************************************************************/
@ -164,11 +169,6 @@ static void mod_calc_rateinc(struct ddb_mod *mod)
{
u32 ri;
dev_info(mod->port->dev->dev,
"ibitrate %llu\n", mod->ibitrate);
dev_info(mod->port->dev->dev,
"obitrate %llu\n", mod->obitrate);
if (mod->ibitrate != 0) {
u64 d = mod->obitrate - mod->ibitrate;
@ -195,6 +195,48 @@ static int mod_calc_obitrate(struct ddb_mod *mod)
return 0;
}
static int mod_set_stream(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
u32 stream = output->nr;
struct ddb_mod *mod = &dev->mod[output->nr];
struct ddb_link *link = &dev->link[0];
struct mci_result res;
u32 channel;
struct mci_command cmd = {
.mod_command = MOD_SETUP_STREAM,
.mod_channel = stream,
.mod_stream = stream,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBC_8,
.symbol_rate = mod->symbolrate,
.qam = {
.modulation = mod->modulation - 1,
.rolloff = 13,
}
},
};
if (dev->link[0].info->version != 2)
return 0;
if (dev->link[0].ids.revision != 1)
return 0;
if ((dev->link[0].ids.hwid & 0xffffff) < 9065)
return 0;
if (!mod->frequency && !mod->symbolrate && !mod->modulation)
return 0;
if (mod->frequency)
channel = (mod->frequency - 114000000) / 8000000;
if (!mod->symbolrate)
mod->symbolrate = 6900000;
if (!mod->modulation)
mod->modulation = 5;
cmd.mod_channel = channel;
cmd.mod_setup_stream.symbol_rate = mod->symbolrate;
cmd.mod_setup_stream.qam.modulation = mod->modulation - 1;
return ddb_mci_cmd_link(link, &cmd, &res);
}
static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate)
{
struct ddb *dev = mod->port->dev;
@ -210,6 +252,7 @@ static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate)
}
mod->symbolrate = srate;
mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0;
}
@ -227,6 +270,7 @@ static int mod_set_modulation(struct ddb_mod *mod,
ddbwritel(dev, qamtab[modulation],
CHANNEL_SETTINGS(mod->port->nr));
mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0;
}
@ -241,6 +285,7 @@ static int mod_set_frequency(struct ddb_mod *mod, u32 frequency)
if ((freq < 114) || (freq > 874))
return -EINVAL;
mod->frequency = frequency;
mod_set_stream(mod->port->output);
return 0;
}
@ -322,14 +367,27 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL(output->nr));
udelay(10);
ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
if (dev->link[0].info->version == 2) {
switch (dev->link[0].info->version) {
case 2:
{
u32 Output = (mod->frequency - 114000000) / 8000000;
u32 KF = Symbolrate;
u32 LF = 9000000UL;
u32 d = gcd(KF, LF);
u32 checkLF;
if ((dev->link[0].ids.revision == 1)) {
if ((dev->link[0].info->version == 2)) {
if ((dev->link[0].ids.hwid & 0xffffff) >= 9065) {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
break;
}
} else {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
break;
}
}
ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel));
ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel));
@ -356,16 +414,21 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL_CMD_SETUP))
return -EINVAL;
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
} else if (dev->link[0].info->version <= 1) {
break;
}
case 0:
case 1:
/* QAM: 600 601 602 903 604 = 16 32 64 128 256 */
/* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */
ddbwritel(dev, qamtab[mod->modulation],
CHANNEL_SETTINGS(output->nr));
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB);
} else if (dev->link[0].info->version >= 16) {
break;
default:
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB);
break;
}
if (dev->link[0].info->version < 16) {
mod_set_rateinc(dev, output->nr);
@ -622,7 +685,26 @@ static int mod_set_attenuator(struct ddb *dev, u32 Value)
{
if (Value > 31)
return -EINVAL;
ddbwritel(dev, Value, RF_ATTENUATOR);
if (dev->link[0].ids.revision == 1) {
struct ddb_link *link = &dev->link[0];
struct mci_result res;
struct mci_command cmd = {
.mod_command = MOD_SETUP_OUTPUT,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_output = {
.connector = MOD_CONNECTOR_F,
.num_channels = dev->link[0].info->port_num,
.unit = MOD_UNIT_DBUV,
.channel_power = 9000 - Value * 100,
},
};
if (!link->mci_ok) {
return -EFAULT;
}
return ddb_mci_cmd_link(link, &cmd, &res);
} else
ddbwritel(dev, Value, RF_ATTENUATOR);
return 0;
}
@ -1516,6 +1598,7 @@ static int mod3_set_ari(struct ddb_mod *mod, u32 rate)
static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
{
struct ddb *dev = mod->port->dev;
u32 cic, inc, bypass = 0;
switch (rate) {
@ -1556,19 +1639,52 @@ static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
inc = 0x7684BD82; //1988410754;
cic = 7;
break;
case SYS_DVBS2_22:
case SYS_DVB_22:
inc = 0x72955555; // 1922389333;
cic = 5;
bypass = 2;
break;
case SYS_DVBS2_24:
case SYS_DVB_24:
inc = 0x7d000000;
cic = 5;
bypass = 2;
break;
case SYS_DVB_30:
inc = 0x7d000000;
cic = 4;
bypass = 2;
break;
case SYS_ISDBS_2886:
inc = 0x78400000;
cic = 4;
bypass = 2;
break;
default:
return -EINVAL;
{
u64 a;
if (rate < 1000000)
return -EINVAL;
if (rate > 30720000)
return -EINVAL;
bypass = 2;
if (rate > 24576000)
cic = 4;
else if (rate > 20480000)
cic = 5;
else if (rate > 17554286)
cic = 6;
else if (rate > 15360000)
cic = 7;
else
cic = 8;
a = (1ULL << 31) * rate * 2 * cic;
inc = div_s64(a, 245760000);
break;
}
}
dev_info(dev->dev, "inc = %08x, cic = %u, bypass = %u\n", inc, cic, bypass);
ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr));
ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4),
SDR_CHANNEL_CONFIG(mod->port->nr));
@ -1596,6 +1712,7 @@ static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
case MODULATOR_GAIN:
return mod_set_sdr_gain(mod->port->dev, tvp->u.data);
}
return -EINVAL;
}
@ -1618,7 +1735,11 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
return mod_set_attenuator(mod->port->dev, tvp->u.data);
case MODULATOR_INPUT_BITRATE:
#ifdef KERNEL_DVB_CORE
return mod_set_ibitrate(mod, *(u64 *) &tvp->u.buffer.data[0]);
#else
return mod_set_ibitrate(mod, tvp->u.data64);
#endif
case MODULATOR_GAIN:
if (mod->port->dev->link[0].info->version == 2)
@ -1717,7 +1838,8 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
(struct dtv_properties __user *) parg;
int i, ret = 0;
if (dev->link[0].info->version >= 16 && cmd != FE_SET_PROPERTY)
if (dev->link[0].info->version >= 16 &&
(cmd != FE_SET_PROPERTY && cmd != IOCTL_DDB_MCI_CMD))
return -EINVAL;
mutex_lock(&dev->ioctl_mutex);
switch (cmd) {
@ -1809,6 +1931,27 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
mod->pcr_correction = cp->pcr_correction;
break;
}
case IOCTL_DDB_MCI_CMD:
{
struct ddb_mci_msg *msg =
(struct ddb_mci_msg __user *) parg;
struct ddb_link *link;
if (dev->link[0].ids.revision != 1)
break;
if (msg->link > 3) {
ret = -EFAULT;
break;
}
link = &dev->link[msg->link];
if (!link->mci_ok) {
ret = -EFAULT;
break;
}
ret = ddb_mci_cmd_link(link, &msg->cmd, &msg->res);
break;
}
default:
ret = -EINVAL;
break;
@ -1817,6 +1960,18 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
return ret;
}
static int mod_init_2_1(struct ddb *dev, u32 Frequency)
{
int i, streams = dev->link[0].info->port_num;
dev->mod_base.frequency = Frequency;
for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i];
mod->port = &dev->port[i];
}
return 0;
}
static int mod_init_2(struct ddb *dev, u32 Frequency)
{
int i, status, streams = dev->link[0].info->port_num;
@ -1991,18 +2146,21 @@ static int mod_init_sdr_iq(struct ddb *dev)
ret = rfdac_init(dev);
if (ret)
dev_err(dev->dev, "RFDAC setup failed\n");
ddbwritel(dev, 0x01, 0x240);
//mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000;
for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i];
mod->port = &dev->port[i];
ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i));
if (dev->link[0].ids.revision != 1)
ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i));
}
if (dev->link[0].ids.revision == 1)
return ret;
mod_set_sdr_attenuator(dev, 0);
udelay(10);
mod_set_sdr_gain(dev, 120);
@ -2011,6 +2169,25 @@ static int mod_init_sdr_iq(struct ddb *dev)
int ddbridge_mod_init(struct ddb *dev)
{
dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision);
if (dev->link[0].ids.revision == 1) {
switch (dev->link[0].info->version) {
case 0:
case 1:
return mod_init_1(dev, 722000000);
case 2: /* FSM */
if ((dev->link[0].ids.hwid & 0xffffff) >= 9065)
return mod_init_2_1(dev, 114000000);
return mod_init_2(dev, 114000000);
case 16: /* PAL */
return mod_init_3(dev, 503250000);
case 17: /* raw IQ */
case 18: /* IQ+FFT */
return mod_init_sdr_iq(dev);
default:
return -1;
}
}
switch (dev->link[0].info->version) {
case 0:
case 1:

View File

@ -260,8 +260,8 @@
#define LNB_CMD_DISEQC 6
#define LNB_CMD_SCIF 7
#define LNB_BUSY BIT_ULL(4)
#define LNB_TONE BIT_ULL(15)
#define LNB_BUSY (1ULL << 4)
#define LNB_TONE (1ULL << 15)
#define LNB_INTERRUPT_BASE 4

View File

@ -23,13 +23,24 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#include "ddbridge-i2c.h"
#include "ddbridge-mci.h"
static int default_mod = 3;
module_param(default_mod, int, 0444);
MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)");
static int direct_mode;
module_param(direct_mode, int, 0444);
MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate.");
static u32 sx8_tuner_flags;
module_param(sx8_tuner_flags, int, 0664);
MODULE_PARM_DESC(sx8_tuner_flags, "Change SX8 tuner flags.");
static u32 sx8_tuner_gain;
module_param(sx8_tuner_gain, int, 0664);
MODULE_PARM_DESC(sx8_tuner_gain, "Change SX8 tuner gain.");
static const u32 MCLK = (1550000000 / 12);
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
@ -44,25 +55,19 @@ struct sx8_base {
struct mci_base mci_base;
u8 tuner_use_count[SX8_TUNER_NUM];
u32 gain_mode[SX8_TUNER_NUM];
u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
u8 demod_in_use[SX8_DEMOD_NUM];
u32 iq_mode;
u32 burst_size;
u32 direct_mode;
};
struct sx8 {
struct mci mci;
struct mutex lock;
int first_time_lock;
int started;
int iq_started;
u32 bb_mode;
u32 local_frequency;
};
static const u8 dvbs2_bits_per_symbol[] = {
@ -114,47 +119,73 @@ static void release(struct dvb_frontend *fe)
kfree(state);
}
static int ddb_mci_tsconfig(struct mci *state, u32 config)
{
struct ddb_link *link = state->base->link;
if (link->ids.device != 0x0009 && link->ids.device != 0x000b)
return -EINVAL;
ddblwritel(link, config, SX8_TSCONFIG);
return 0;
}
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{
int stat;
int stat = 0;
struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mci_result res;
*status = 0x00;
mutex_lock(&state->lock);
if (!state->started && !state->iq_started)
goto unlock;
stat = ddb_mci_get_status(&state->mci, &res);
if (stat)
return stat;
*status = 0x00;
goto unlock;
ddb_mci_get_info(&state->mci);
if (res.status == SX8_DEMOD_WAIT_MATYPE)
*status = 0x0f;
if (res.status == 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;
}
static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on,
u8 flags, u8 gain)
{
struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.tuner = state->mci.tuner;
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
cmd.sx8_input_enable.flags = sx8_base->gain_mode[state->mci.tuner];
cmd.sx8_input_enable.flags = flags;
cmd.sx8_input_enable.rf_gain = gain;
return ddb_mci_cmd(&state->mci, &cmd, NULL);
}
@ -172,20 +203,20 @@ static int stop_iq(struct dvb_frontend *fe)
cmd.command = SX8_CMD_STOP_IQ;
cmd.demod = state->mci.demod;
ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
mutex_lock(&mci_base->tuner_lock);
sx8_base->tuner_use_count[input]--;
if (!sx8_base->tuner_use_count[input])
mci_set_tuner(fe, input, 0);
mci_set_tuner(fe, input, 0, 0, 0);
if (state->mci.demod != SX8_DEMOD_NONE) {
sx8_base->demod_in_use[state->mci.demod] = 0;
state->mci.demod = SX8_DEMOD_NONE;
}
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
mutex_unlock(&mci_base->tuner_lock);
sx8_base->iq_mode = 0;
state->iq_started = 0;
mutex_unlock(&mci_base->tuner_lock);
return 0;
}
@ -195,12 +226,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);
@ -209,24 +241,29 @@ static int stop(struct dvb_frontend *fe)
cmd.demod = state->mci.demod;
cmd.output = 0;
ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
}
}
mutex_lock(&mci_base->tuner_lock);
sx8_base->tuner_use_count[input]--;
if (!sx8_base->tuner_use_count[input])
mci_set_tuner(fe, input, 0);
mci_set_tuner(fe, input, 0, 0, 0);
if (state->mci.demod != SX8_DEMOD_NONE) {
sx8_base->demod_in_use[state->mci.demod] = 0;
state->mci.demod = SX8_DEMOD_NONE;
}
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
sx8_base->iq_mode = 0;
mutex_unlock(&mci_base->tuner_lock);
state->started = 0;
mutex_unlock(&mci_base->tuner_lock);
return 0;
}
static const u8 ro_lut[8] = {
8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0,
8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0,
};
static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
{
struct sx8 *state = fe->demodulator_priv;
@ -268,7 +305,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;
@ -290,16 +327,15 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate;
if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE)
free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE;
while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate)
bits_per_symbol--;
if (bits_per_symbol < 2) {
stat = -EBUSY;
goto unlock;
}
modmask &= ((1 << (bits_per_symbol - 1)) - 1);
if( ((flags & 0x02) != 0) && (modmask == 0)) {
if (((flags & 0x02) != 0) && (modmask == 0)) {
stat = -EBUSY;
goto unlock;
}
@ -317,7 +353,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
state->mci.demod = i;
if (!sx8_base->tuner_use_count[input])
mci_set_tuner(fe, input, 1);
mci_set_tuner(fe, input, 1, sx8_tuner_flags, sx8_tuner_gain);
sx8_base->tuner_use_count[input]++;
sx8_base->iq_mode = (ts_config > 1);
unlock:
@ -325,13 +361,12 @@ 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_config(&state->mci, ts_config);
ddb_mci_tsconfig(&state->mci, ts_config);
}
if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000))
flags |= 0x80;
@ -345,6 +380,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;
@ -358,6 +394,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;
@ -365,7 +404,7 @@ unlock:
static int start_iq(struct dvb_frontend *fe, u32 flags,
u32 roll_off, u32 ts_config)
u32 ts_config)
{
struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base;
@ -376,8 +415,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;
@ -390,28 +429,36 @@ 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;
mci_set_tuner(fe, input, 1, flags & 0xff, 0x40);
} else {
if ((state->iq_started & 0x07) != state->mci.nr) {
stat = -EBUSY;
goto unlock;
}
}
unlock:
mutex_unlock(&mci_base->tuner_lock);
if (stat)
return stat;
memset(&cmd, 0, sizeof(cmd));
cmd.command = SX8_CMD_START_IQ;
cmd.sx8_start_iq.flags = flags >> 8;
cmd.sx8_start_iq.roll_off = roll_off;
cmd.sx8_start_iq.flags = (flags >> 16) & 0xff;
cmd.sx8_start_iq.roll_off = 5;
//cmd.sx8_start_iq.roll_off = ro_lut[p->rolloff & 7];
cmd.sx8_start_iq.frequency = p->frequency * 1000;
cmd.sx8_start_iq.symbol_rate = p->symbol_rate;
cmd.sx8_start_iq.gain = flags & 0xff;
cmd.sx8_start_iq.gain = (flags >> 8) & 0xff;
cmd.tuner = state->mci.tuner;
cmd.demod = state->mci.demod;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
state->iq_started = 8 | state->mci.nr;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
if (stat)
stop_iq(fe);
ddb_mci_config(&state->mci, ts_config);
ddb_mci_tsconfig(&state->mci, ts_config);
return stat;
}
@ -421,7 +468,6 @@ static int set_lna(struct dvb_frontend *fe)
return 0;
}
static int set_parameters(struct dvb_frontend *fe)
{
int stat = 0;
@ -437,6 +483,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;
@ -463,19 +510,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 >> 8) & 0xffff, 4, ts_config);
if (!stat) {
state->iq_started = 1;
state->first_time_lock = 1;
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
}
stat = start_iq(fe, isi & 0xffffff, ts_config);
}
mutex_unlock(&state->lock);
return stat;
}
@ -514,16 +552,25 @@ 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;
state->mci.tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
mutex_unlock(&state->lock);
return 0;
}
static int sleep(struct dvb_frontend *fe)
{
struct sx8 *state = fe->demodulator_priv;
mutex_lock(&state->lock);
stop_iq(fe);
stop(fe);
mutex_unlock(&state->lock);
return 0;
}
@ -537,7 +584,6 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static struct dvb_frontend_ops sx8_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2 },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = {
.name = "DVB-S/S2X",
.frequency_min_hz = 950000000,
@ -557,7 +603,10 @@ static struct dvb_frontend_ops sx8_ops = {
.tune = tune,
.release = release,
.read_status = read_status,
#ifndef KERNEL_DVB_CORE
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.set_input = set_input,
#endif
.set_lna = set_lna,
.sleep = sleep,
};
@ -567,8 +616,11 @@ static int init(struct mci *mci)
struct sx8 *state = (struct sx8 *) mci;
state->mci.demod = SX8_DEMOD_NONE;
#ifndef KERNEL_DVB_CORE
mci->fe.ops.xbar[1] = mci->nr;
mci->fe.dtv_property_cache.input = mci->tuner;
#endif
mutex_init(&state->lock);
return 0;
}
@ -579,7 +631,7 @@ static int base_init(struct mci_base *mci_base)
return 0;
}
struct mci_cfg ddb_max_sx8_cfg = {
static struct mci_cfg ddb_max_sx8_cfg = {
.type = 0,
.fe_ops = &sx8_ops,
.base_size = sizeof(struct sx8_base),
@ -587,3 +639,10 @@ struct mci_cfg ddb_max_sx8_cfg = {
.init = init,
.base_init = base_init,
};
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input))
{
*fn_set_input = set_input;
return ddb_mci_attach(input, &ddb_max_sx8_cfg, nr, tuner);
}

View File

@ -23,9 +23,6 @@
#ifndef _DDBRIDGE_H_
#define _DDBRIDGE_H_
#define DDB_USE_WORK
/*#define DDB_TEST_THREADED*/
#include <linux/version.h>
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
@ -114,6 +111,7 @@ struct ddb_regmap {
u32 irq_base_odma;
u32 irq_base_gtl;
u32 irq_base_rate;
u32 irq_base_mci;
const struct ddb_regset *i2c;
const struct ddb_regset *i2c_buf;
@ -127,6 +125,9 @@ struct ddb_regmap {
const struct ddb_regset *channel;
const struct ddb_regset *gtl;
const struct ddb_regset *mci;
const struct ddb_regset *mci_buf;
};
struct ddb_ids {
@ -139,6 +140,7 @@ struct ddb_ids {
u32 regmapid;
u32 devid;
u32 mac;
u8 revision;
};
struct ddb_info {
@ -200,11 +202,7 @@ struct ddb_dma {
u32 div;
u32 bufval;
#ifdef DDB_USE_WORK
struct work_struct work;
#else
struct tasklet_struct tasklet;
#endif
spinlock_t lock; /* DMA lock */
wait_queue_head_t wq;
int running;
@ -215,6 +213,7 @@ struct ddb_dma {
u32 stall_count;
u32 packet_loss;
u32 unaligned;
};
struct ddb_dvb {
@ -427,6 +426,9 @@ struct ddb_link {
struct ddb_irq irq[256];
struct mci_base *mci_base;
struct completion mci_completion;
struct mutex mci_lock;
int mci_ok;
};
struct ddb {

View File

@ -26,6 +26,9 @@
#include <linux/net.h>
#include "dvb_netstream.h"
int ddb_dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, unsigned int cmd, void *arg));
static ssize_t ns_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
@ -211,7 +214,7 @@ static int do_ioctl(struct file *file, unsigned int cmd, void *parg)
static long ns_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, do_ioctl);
return ddb_dvb_usercopy(file, cmd, arg, do_ioctl);
}
static const struct file_operations ns_fops = {

View File

@ -36,7 +36,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <asm/uaccess.h>
#include <linux/dvb/ns.h>
#include "ns.h"
#include <media/dvbdev.h>

76
ddbridge/ns.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _UAPI_DVBNS_H_
#define _UAPI_DVBNS_H_
#include <linux/types.h>
struct dvb_ns_params {
__u8 smac[6];
__u8 dmac[6];
__u8 sip[16];
__u8 dip[16];
__u16 sport;
__u16 dport;
__u16 sport2;
__u16 dport2;
__u8 ssrc[8];
__u8 flags;
__u8 qos;
__u16 vlan;
__u8 ttl;
};
#define DVB_NS_IPV6 0x01
#define DVB_NS_RTP 0x02
#define DVB_NS_RTCP 0x04
#define DVB_NS_RTP_TO 0x08
#define DVB_NS_VLAN 0x10
struct dvb_ns_rtcp {
__u8 *msg;
__u16 len;
};
struct dvb_ns_packet {
__u8 *buf;
__u8 count;
};
struct dvb_nsd_ts {
__u16 pid;
__u16 num;
__u16 input;
__u16 timeout;
__u16 len;
__u8 *ts;
__u8 mode;
__u8 table;
__u8 filter_mask;
__u8 section;
__u16 section_id;
};
struct dvb_ns_cap {
__u8 streams_max;
__u8 reserved[127];
};
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
#define NS_START _IO('o', 193)
#define NS_STOP _IO('o', 194)
#define NS_SET_PID _IOW('o', 195, __u16)
#define NS_SET_PIDS _IOW('o', 196, __u8 *)
#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp)
#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts)
#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts)
#define NSD_CANCEL_GET_TS _IO('o', 200)
#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts)
#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet)
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
#define NS_SET_CI _IOW('o', 204, __u8)
#define NS_GET_CAP _IOR('o', 204, struct dvb_ns_cap))
#endif /*_UAPI_DVBNS_H_*/

13
docs/firmware Normal file
View File

@ -0,0 +1,13 @@
Firmware update:
Copy the firmware file to the dddvb/apps/ directory and
execute "./flashprog".
The program will try to identify the card version and
check if it finds the corresponding firmware file.
It will then prompt you to confirm to proceed
with the flashing procedure.
After the update the system needs a power cycle.

27
docs/iq_samples Normal file
View File

@ -0,0 +1,27 @@
~The Max SX8 can provide IQ samples in real time.
They are 8 bit signed values embedded in TS packets with PID 0x200.
API:
Currently DTV_STREAM_ID is misused.
0x10000000 - symbols (locked and tracked) at symbol rate
0x20000000 - samples at symbol rate
(fixed at ADC rate (1550/24=64.583... MHz) if 0x00010000 is set)
Max. sample rate is 64.583333 MHz.
0x00xx0000 - flags
Bit 0 : 0 = VTM/SDR, 1 = SCAN,
Bit 1: 1 = Disable channel AGC,
Bit 2: 1 = Set Gain.
0x0000xx00 - xx=gain
0x000000xx - xx=flags
Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
2 = Medium, 3 = Maximum gain {~ 15dB}
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
Bit 4: Set RF Gain
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
Bit 7: Optimize RF Gain and freeze for FFT

View File

@ -28,3 +28,7 @@ devices in any way.
adapter_alloc=3 is rcommended when using redirect
The ci device will then show up in the same adapter directory and most
software will then assume it belongs to the frontend in the same directory.
Redirect between cards in different IOMMU groups will not work!
Disable IOMMU if you have this problem.

View File

@ -13,4 +13,3 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
obj-$(CONFIG_DVB_CORE) += dvb-core.o
EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux

View File

@ -11,3 +11,4 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
obj-$(CONFIG_DVB_CORE) += dvb-core.o
ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += --include=dd_compat.h

View File

@ -479,6 +479,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
#ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx;
#endif
struct dvb_ringbuffer *buffer;
int ret;
@ -766,7 +769,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
secfeed,
dvb_dmxdev_section_callback);
if (ret < 0) {
if (!*secfeed) {
pr_err("DVB (%s): could not alloc feed\n",
__func__);
return ret;

View File

@ -194,10 +194,10 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount);
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount);
u8 *ebuf, int ecount, u8 flags);
/**
* Safely find needle in haystack.
* findstr - Safely find needle in haystack.
*
* @haystack: Buffer to look in.
* @hlen: Number of bytes in haystack.
@ -377,7 +377,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
if (ret)
return ret;
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2);
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
if (ret != 2)
return -EIO;
ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@ -629,8 +629,8 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
* @ca: CA instance.
* @slot: Slot to read from.
* @ebuf: If non-NULL, the data will be written to this buffer. If NULL,
* the data will be added into the buffering system as a normal
* fragment.
* the data will be added into the buffering system as a normal
* fragment.
* @ecount: Size of ebuf. Ignored if ebuf is NULL.
*
* return: Number of bytes read, or < 0 on error
@ -783,20 +783,20 @@ exit:
* @ca: CA instance.
* @slot: Slot to write to.
* @buf: The data in this buffer is treated as a complete link-level packet to
* be written.
* be written.
* @bytes_write: Size of ebuf.
*
* return: Number of bytes written, or < 0 on error.
*/
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *buf, int bytes_write)
u8 *buf, int bytes_write, u8 flags)
{
struct dvb_ca_slot *sl = &ca->slot_info[slot];
int status;
int i;
dprintk("%s\n", __func__);
flags=0;
/* sanity check */
if (bytes_write > sl->link_buf_size)
return -EINVAL;
@ -824,7 +824,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
/* OK, set HC bit */
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
IRQEN | CMDREG_HC);
IRQEN | CMDREG_HC | flags);
if (status)
goto exit;
@ -894,7 +894,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
buf[0], (buf[1] & 0x80) == 0, bytes_write);
exit:
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | flags);
exitnowrite:
return status;
@ -1013,7 +1013,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
/* EN50221 thread functions */
/**
* Wake up the DVB CA thread
* dvb_ca_en50221_thread_wakeup - Wake up the DVB CA thread
*
* @ca: CA instance.
*/
@ -1027,7 +1027,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
}
/**
* Update the delay used by the thread.
* dvb_ca_en50221_thread_update_delay - Update the delay used by the thread.
*
* @ca: CA instance.
*/
@ -1085,7 +1085,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
}
/**
* Poll if the CAM is gone.
* dvb_ca_en50221_poll_cam_gone - Poll if the CAM is gone.
*
* @ca: CA instance.
* @slot: Slot to process.
@ -1116,7 +1116,8 @@ static int dvb_ca_en50221_poll_cam_gone(struct dvb_ca_private *ca, int slot)
}
/**
* Thread state machine for one CA slot to perform the data transfer.
* dvb_ca_en50221_thread_state_machine - Thread state machine for one CA slot
* to perform the data transfer.
*
* @ca: CA instance.
* @slot: Slot to process.
@ -1268,7 +1269,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
dvb_ca_en50221_thread_update_delay(ca);
pr_info("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
ca->dvbdev->adapter->num);
ca->dvbdev->adapter->num);
break;
case DVB_CA_SLOTSTATE_RUNNING:
@ -1347,13 +1348,14 @@ static int dvb_ca_en50221_thread(void *data)
/* EN50221 IO interface functions */
/**
* Real ioctl implementation.
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
* dvb_ca_en50221_io_do_ioctl - Real ioctl implementation.
*
* @file: File concerned.
* @cmd: IOCTL command.
* @parg: Associated argument.
*
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
*
* return: 0 on success, <0 on error.
*/
static int dvb_ca_en50221_io_do_ioctl(struct file *file,
@ -1407,7 +1409,9 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
err = -EINVAL;
goto out_unlock;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
slot = array_index_nospec(slot, ca->slot_count);
#endif
info->type = CA_CI_LINK;
info->flags = 0;
sl = &ca->slot_info[slot];
@ -1431,7 +1435,7 @@ out_unlock:
}
/**
* Wrapper for ioctl implementation.
* dvb_ca_en50221_io_ioctl - Wrapper for ioctl implementation.
*
* @file: File concerned.
* @cmd: IOCTL command.
@ -1446,7 +1450,7 @@ static long dvb_ca_en50221_io_ioctl(struct file *file,
}
/**
* Implementation of write() syscall.
* dvb_ca_en50221_io_write - Implementation of write() syscall.
*
* @file: File structure.
* @buf: Source buffer.
@ -1529,7 +1533,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
mutex_lock(&sl->slot_lock);
status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
fraglen + 2);
fraglen + 2, 0);
mutex_unlock(&sl->slot_lock);
if (status == (fraglen + 2)) {
written = 1;
@ -1603,7 +1607,7 @@ nextslot:
}
/**
* Implementation of read() syscall.
* dvb_ca_en50221_io_read - Implementation of read() syscall.
*
* @file: File structure.
* @buf: Destination buffer.
@ -1714,7 +1718,7 @@ exit:
}
/**
* Implementation of file open syscall.
* dvb_ca_en50221_io_open - Implementation of file open syscall.
*
* @inode: Inode concerned.
* @file: File concerned.
@ -1764,7 +1768,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
}
/**
* Implementation of file close syscall.
* dvb_ca_en50221_io_release - Implementation of file close syscall.
*
* @inode: Inode concerned.
* @file: File concerned.
@ -1793,7 +1797,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
}
/**
* Implementation of poll() syscall.
* dvb_ca_en50221_io_poll - Implementation of poll() syscall.
*
* @file: File concerned.
* @wait: poll wait table.
@ -1855,7 +1859,7 @@ static const struct dvb_device dvbdev_ca = {
/* Initialisation/shutdown functions */
/**
* Initialise a new DVB CA EN50221 interface device.
* dvb_ca_en50221_init - Initialise a new DVB CA EN50221 interface device.
*
* @dvb_adapter: DVB adapter to attach the new CA device to.
* @pubca: The dvb_ca instance.
@ -1947,7 +1951,7 @@ exit:
EXPORT_SYMBOL(dvb_ca_en50221_init);
/**
* Release a DVB CA EN50221 interface device.
* dvb_ca_en50221_release - Release a DVB CA EN50221 interface device.
*
* @pubca: The associated dvb_ca instance.
*/

View File

@ -20,6 +20,7 @@
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
#include <linux/sched/signal.h>
#include <linux/nospec.h>
#else
#include <linux/sched.h>
#endif
@ -487,6 +488,10 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
if (fepriv->max_drift)
dev_warn(fe->dvb->device,
"Frontend requested software zigzag, but didn't set the frequency step size\n");
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3 * HZ;
@ -990,6 +995,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
fe->ops.info.symbol_rate_max);
return -EINVAL;
}
break;
default:
break;
}
@ -1065,108 +1071,100 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
return 0;
}
#define _DTV_CMD(n, s, b) \
[n] = { \
.name = #n, \
.cmd = n, \
.set = s,\
.buffer = b \
}
#define _DTV_CMD(n) \
[n] = #n
struct dtv_cmds_h {
char *name; /* A display name for debugging purposes */
__u32 cmd; /* A unique ID */
/* Flags */
__u32 set:1; /* Either a set or get property */
__u32 buffer:1; /* Does this property use the buffer? */
__u32 reserved:30; /* Align */
};
static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE, 1, 0),
_DTV_CMD(DTV_CLEAR, 1, 0),
static char *dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE),
_DTV_CMD(DTV_CLEAR),
/* Set */
_DTV_CMD(DTV_FREQUENCY, 1, 0),
_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0),
_DTV_CMD(DTV_MODULATION, 1, 0),
_DTV_CMD(DTV_INVERSION, 1, 0),
_DTV_CMD(DTV_DISEQC_MASTER, 1, 1),
_DTV_CMD(DTV_SYMBOL_RATE, 1, 0),
_DTV_CMD(DTV_INNER_FEC, 1, 0),
_DTV_CMD(DTV_VOLTAGE, 1, 0),
_DTV_CMD(DTV_TONE, 1, 0),
_DTV_CMD(DTV_PILOT, 1, 0),
_DTV_CMD(DTV_ROLLOFF, 1, 0),
_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0),
_DTV_CMD(DTV_HIERARCHY, 1, 0),
_DTV_CMD(DTV_CODE_RATE_HP, 1, 0),
_DTV_CMD(DTV_CODE_RATE_LP, 1, 0),
_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0),
_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0),
_DTV_CMD(DTV_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_FREQUENCY),
_DTV_CMD(DTV_BANDWIDTH_HZ),
_DTV_CMD(DTV_MODULATION),
_DTV_CMD(DTV_INVERSION),
_DTV_CMD(DTV_DISEQC_MASTER),
_DTV_CMD(DTV_SYMBOL_RATE),
_DTV_CMD(DTV_INNER_FEC),
_DTV_CMD(DTV_VOLTAGE),
_DTV_CMD(DTV_TONE),
_DTV_CMD(DTV_PILOT),
_DTV_CMD(DTV_ROLLOFF),
_DTV_CMD(DTV_DELIVERY_SYSTEM),
_DTV_CMD(DTV_HIERARCHY),
_DTV_CMD(DTV_CODE_RATE_HP),
_DTV_CMD(DTV_CODE_RATE_LP),
_DTV_CMD(DTV_GUARD_INTERVAL),
_DTV_CMD(DTV_TRANSMISSION_MODE),
_DTV_CMD(DTV_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING),
_DTV_CMD(DTV_STREAM_ID, 1, 0),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, 1, 0),
_DTV_CMD(DTV_LNA, 1, 0),
_DTV_CMD(DTV_INPUT, 1, 0),
_DTV_CMD(DTV_STREAM_ID),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX),
_DTV_CMD(DTV_LNA),
_DTV_CMD(DTV_INPUT),
/* Get */
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
_DTV_CMD(DTV_API_VERSION, 0, 0),
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY),
_DTV_CMD(DTV_API_VERSION),
_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
_DTV_CMD(DTV_ENUM_DELSYS),
_DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
_DTV_CMD(DTV_ATSCMH_PARADE_ID),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE),
_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
_DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
_DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
_DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
_DTV_CMD(DTV_ATSCMH_FIC_VER),
_DTV_CMD(DTV_ATSCMH_NOG),
_DTV_CMD(DTV_ATSCMH_TNOG),
_DTV_CMD(DTV_ATSCMH_SGN),
_DTV_CMD(DTV_ATSCMH_PRC),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC),
_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D),
/* Statistics API */
_DTV_CMD(DTV_STAT_SIGNAL_STRENGTH, 0, 0),
_DTV_CMD(DTV_STAT_CNR, 0, 0),
_DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_SIGNAL_STRENGTH),
_DTV_CMD(DTV_STAT_CNR),
_DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT),
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT),
};
static char *dtv_cmd_name(u32 cmd)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
cmd = array_index_nospec(cmd, DTV_MAX_COMMAND);
#endif
return dtv_cmds[cmd];
}
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
@ -1349,8 +1347,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
struct file *file)
{
int ncaps;
unsigned int len = 1;
switch(tvp->cmd) {
switch (tvp->cmd) {
case DTV_ENUM_DELSYS:
ncaps = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
@ -1358,6 +1357,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
ncaps++;
}
tvp->u.buffer.len = ncaps;
len = ncaps;
break;
case DTV_FREQUENCY:
tvp->u.data = c->frequency;
@ -1543,27 +1543,51 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
/* Fill quality measures */
case DTV_STAT_SIGNAL_STRENGTH:
tvp->u.st = c->strength;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_CNR:
tvp->u.st = c->cnr;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_PRE_ERROR_BIT_COUNT:
tvp->u.st = c->pre_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_PRE_TOTAL_BIT_COUNT:
tvp->u.st = c->pre_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_POST_ERROR_BIT_COUNT:
tvp->u.st = c->post_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_POST_TOTAL_BIT_COUNT:
tvp->u.st = c->post_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_ERROR_BLOCK_COUNT:
tvp->u.st = c->block_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_TOTAL_BLOCK_COUNT:
tvp->u.st = c->block_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
default:
dev_dbg(fe->dvb->device,
@ -1572,18 +1596,13 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
return -EINVAL;
}
if (!dtv_cmds[tvp->cmd].buffer)
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) = 0x%08x\n",
__func__, tvp->cmd, dtv_cmds[tvp->cmd].name,
tvp->u.data);
else
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
__func__,
tvp->cmd, dtv_cmds[tvp->cmd].name,
tvp->u.buffer.len,
tvp->u.buffer.len, tvp->u.buffer.data);
if (len < 1)
len = 1;
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
__func__, tvp->cmd, dtv_cmd_name(tvp->cmd),
tvp->u.buffer.len, tvp->u.buffer.len, tvp->u.buffer.data);
return 0;
}
@ -1806,6 +1825,53 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
return emulate_delivery_system(fe, delsys);
}
static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_frontend_tune_settings fetunesettings = { 0 };
/* get frontend-specific tuning settings */
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = fepriv->step_size + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
}
/**
* dtv_property_process_set - Sets a single DTV property
* @fe: Pointer to &struct dvb_frontend
@ -1834,7 +1900,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
else
dev_dbg(fe->dvb->device,
"%s: SET cmd 0x%08x (%s) to 0x%08x\n",
__func__, cmd, dtv_cmds[cmd].name, data);
__func__, cmd, dtv_cmd_name(cmd), data);
switch (cmd) {
case DTV_CLEAR:
/*
@ -2204,7 +2270,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_tune_settings fetunesettings;
u32 rolloff = 0;
if (dvb_frontend_check_parameters(fe) < 0)
@ -2282,46 +2347,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
c->code_rate_LP = FEC_AUTO;
/* get frontend-specific tuning settings */
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = (dvb_frontend_get_stepsize(fe) * 2) + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
prepare_tuning_algo_parameters(fe);
fepriv->state = FESTATE_RETUNE;
@ -2336,7 +2362,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
struct dtv_properties *tvps)
{
@ -3028,13 +3053,13 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num, fe->id, fe->ops.info.name);
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num, fepriv->dvbdev->id, fe->ops.info.name);
/*
* Initialize the cache to the proper values according with the
* first supported delivery system (ops->delsys[0])

View File

@ -215,7 +215,7 @@ static int ule_exthdr_padding(struct dvb_net_priv *p)
}
/*
* Handle ULE extension headers.
* Handle ULE extension headers.
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
* Returns: >= 0: nr. of bytes consumed by next extension header
* -1: Mandatory extension header that is not recognized or TEST SNDU; discard.
@ -553,7 +553,7 @@ static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h)
h->priv->ule_sndu_type_1 = 1;
h->ts_remain -= 1;
h->from_where += 1;
/* fallthrough */
fallthrough;
case 0:
h->new_ts = 1;
h->ts += TS_SZ;
@ -1018,7 +1018,7 @@ static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static int dvb_net_filter_sec_set(struct net_device *dev,
struct dmx_section_filter **secfilter,
u8 *mac, u8 *mac_mask)
const u8 *mac, u8 *mac_mask)
{
struct dvb_net_priv *priv = netdev_priv(dev);
int ret;
@ -1062,7 +1062,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev);
struct dmx_demux *demux = priv->demux;
unsigned char *mac = (unsigned char *) dev->dev_addr;
const unsigned char *mac = (unsigned char *) dev->dev_addr;
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex);
@ -1282,8 +1282,11 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
struct dvb_net_priv *priv = netdev_priv(dev);
struct sockaddr *addr=p;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
#else
eth_hw_addr_set(dev, addr->sa_data);
#endif
if (netif_running(dev))
schedule_work(&priv->restart_net_feed_wq);
@ -1381,8 +1384,11 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
dvbnet->dvbdev->adapter->num, if_num);
net->addr_len = 6;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
#else
eth_hw_addr_set(net, dvbnet->dvbdev->adapter->proposed_mac);
#endif
dvbnet->device[if_num] = net;
priv = netdev_priv(net);

View File

@ -391,7 +391,9 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
}
consumed = (idx - rbuf->pread) % rbuf->size;
consumed = idx - rbuf->pread;
if (consumed < 0)
consumed += rbuf->size;
while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {

View File

@ -79,13 +79,17 @@ static const char * const dnames[] = {
static const u8 minor_type[] = {
[DVB_DEVICE_VIDEO] = 0,
[DVB_DEVICE_AUDIO] = 1,
[DVB_DEVICE_SEC] = 2,
[DVB_DEVICE_SEC] = 2,
[DVB_DEVICE_FRONTEND] = 3,
[DVB_DEVICE_DEMUX] = 4,
[DVB_DEVICE_DVR] = 5,
[DVB_DEVICE_CA] = 6,
[DVB_DEVICE_NET] = 7,
[DVB_DEVICE_OSD] = 8,
[DVB_DEVICE_CI] = 9,
[DVB_DEVICE_MOD] = 10,
[DVB_DEVICE_NS] = 11,
[DVB_DEVICE_NSD] = 12,
};
#define nums2minor(num, type, id) \
@ -248,6 +252,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
if (dvbdev->adapter->conn) {
media_device_unregister_entity(dvbdev->adapter->conn);
kfree(dvbdev->adapter->conn);
dvbdev->adapter->conn = NULL;
kfree(dvbdev->adapter->conn_pads);
dvbdev->adapter->conn_pads = NULL;
@ -346,7 +351,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
if (npads) {
dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
GFP_KERNEL);
if (!dvbdev->pads){
if (!dvbdev->pads) {
kfree(dvbdev->entity);
return -ENOMEM;
}
@ -512,6 +517,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
break;
if (minor == MAX_DVB_MINORS) {
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
up_write(&minor_rwsem);
@ -532,6 +538,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
__func__);
dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
@ -546,6 +553,10 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
if (IS_ERR(clsdev)) {
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
return PTR_ERR(clsdev);
}
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
@ -687,7 +698,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
ret = media_device_register_entity(mdev, conn);
if (ret)
return ret;
if (!ntuner) {
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_CONN_RF,
@ -987,7 +998,7 @@ struct i2c_client *dvb_module_probe(const char *module_name,
unsigned char addr,
void *platform_data)
{
struct i2c_client *client;
struct i2c_client *client;
struct i2c_board_info *board_info;
board_info = kzalloc(sizeof(*board_info), GFP_KERNEL);

View File

@ -4,6 +4,7 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/
ccflags-y += --include=dd_compat.h
# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
ifdef CONFIG_DVB_RTL2832_SDR

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

@ -1566,7 +1566,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B:
status = -1;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
CHK_ERROR(MPEGTSStop(state));
CHK_ERROR(PowerDownQAM(state));
@ -1589,7 +1589,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B:
status = -1;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
state->m_OperationMode = oMode;
CHK_ERROR(SetQAMStandard(state,oMode));
@ -1765,7 +1765,7 @@ static int MPEGTSDtoSetup(struct drxk_state *state, enum OperationMode oMode)
fecOcRcnCtlRate = 0xC00000;
staticCLK = state->m_DVBTStaticCLK;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
fecOcTmdMode = 0x0004;
fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */
@ -2804,12 +2804,12 @@ static int DVBTScCommand(struct drxk_state *state,
case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
/* All commands using 1 parameters */
/* fall through */
fallthrough;
case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
case OFDM_SC_RA_RAM_CMD_USER_IO:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
/* All commands using 0 parameters */
/* fall through */
fallthrough;
case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
case OFDM_SC_RA_RAM_CMD_NULL:
/* Write command */
@ -3218,7 +3218,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
/* try first guess DRX_FFTMODE_8K */
/* fall through */
fallthrough;
case TRANSMISSION_MODE_8K:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
break;
@ -3237,7 +3237,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
case GUARD_INTERVAL_AUTO:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
/* try first guess DRX_GUARD_1DIV4 */
/* fall through */
fallthrough;
case GUARD_INTERVAL_1_4:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
break;
@ -3265,7 +3265,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
// transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO;
//break;
/* fall through */
fallthrough;
case HIERARCHY_1:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
break;
@ -3288,7 +3288,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
/* try first guess DRX_CONSTELLATION_QAM64 */
/* fall through */
fallthrough;
case QAM_64:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
break;
@ -3311,8 +3311,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
WR16(devAddr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI));
break;
case DRX_PRIORITY_UNKNOWN : /* fall through */
default:
case DRX_PRIORITY_UNKNOWN:
default:
return (DRX_STS_INVALID_ARG);
break;
}
@ -3332,7 +3332,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
/* try first guess DRX_CODERATE_2DIV3 */
/* fall through */
fallthrough;
case FEC_2_3 :
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
break;

View File

@ -786,7 +786,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
default:
break;
}
/* fallthrough */
fallthrough;
case SYS_DVBS:
switch ((MXL_HYDRA_MODULATION_E)
regData[DMD_MODULATION_SCHEME_ADDR]) {
@ -825,13 +825,15 @@ static int set_input(struct dvb_frontend *fe, int input)
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
state->tuner = p->input = input;
state->tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
return 0;
}
static struct dvb_frontend_ops mxl_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = {
.name = "MXL5XX",
.frequency_min_hz = 300000000,
@ -856,7 +858,10 @@ static struct dvb_frontend_ops mxl_ops = {
.read_signal_strength = read_signal_strength,
.read_ucblocks = read_ucblocks,
.get_frontend = get_frontend,
#ifndef KERNEL_DVB_CORE
.set_input = set_input,
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
#endif
.diseqc_send_master_cmd = send_master_cmd,
};
@ -1873,7 +1878,8 @@ static int probe(struct mxl *state, struct mxl5xx_cfg *cfg)
struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner)
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
struct mxl *state;
struct mxl_base *base;
@ -1913,9 +1919,12 @@ struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
list_add(&base->mxllist, &mxllist);
}
state->fe.ops = mxl_ops;
#ifndef KERNEL_DVB_CORE
state->fe.ops.xbar[1] = demod;
state->fe.demodulator_priv = state;
state->fe.dtv_property_cache.input = tuner;
#endif
state->fe.demodulator_priv = state;
*fn_set_input = set_input;
list_add(&state->mxl, &base->mxls);
return &state->fe;

View File

@ -23,12 +23,15 @@ struct mxl5xx_cfg {
extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner);
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int));
#else
static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner)
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;

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

39
include/dd_compat.h Normal file
View File

@ -0,0 +1,39 @@
#include <linux/version.h>
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
#define __devexit
#define __devinit
#define __devinitconst
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef fallthrough
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif
#endif
#ifdef KERNEL_DVB_CORE
#define DVB_DEVICE_CI 0
#define DVB_DEVICE_MOD 6
#define DVB_DEVICE_NS 7
#define DVB_DEVICE_NSD 8
#define SYS_DVBC2 19
#define ROLLOFF_15 4
#define ROLLOFF_10 5
#define ROLLOFF_5 6
#define FEC_1_4 13
#define FEC_1_3 14
#define APSK_64 14
#define APSK_128 15
#define APSK_256 16
#endif

View File

@ -44,8 +44,10 @@ enum mod_output_rate {
SYS_ISDBT_6 = 16,
SYS_J83B_64_6 = 24,
SYS_J83B_256_6 = 25,
SYS_DVBS2_22 = 32,
SYS_DVBS2_24 = 33,
SYS_DVB_22 = 32,
SYS_DVB_24 = 33,
SYS_DVB_30 = 34,
SYS_ISDBS_2886 = 48,
};

View File

@ -27,11 +27,15 @@
#define DVB_MAJOR 212
#if 0
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
#else
#define DVB_MAX_ADAPTERS 64
#endif
#endif
#define DVB_MAX_ADAPTERS 64
#define DVB_UNSET (-1)
@ -326,7 +330,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
int dvb_generic_open(struct inode *inode, struct file *file);
/**
* dvb_generic_close - Digital TV close function, used by DVB devices
* dvb_generic_release - Digital TV close function, used by DVB devices
*
* @inode: pointer to &struct inode.
* @file: pointer to &struct file.
@ -421,11 +425,12 @@ void dvb_module_release(struct i2c_client *client);
/* Legacy generic DVB attach function. */
#ifdef CONFIG_MEDIA_ATTACH
/**
* dvb_attach - attaches a DVB frontend into the DVB core.
*
* @FUNCTION: function on a frontend module to be called.
* @ARGS...: @FUNCTION arguments.
* @ARGS: @FUNCTION arguments.
*
* This ancillary function loads a frontend module in runtime and runs
* the @FUNCTION function there, with @ARGS.

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

@ -17,3 +17,7 @@ Tuner5=5,984
Tuner6=6,1020
Tuner7=7,1056
Tuner8=8,1092
Tuner9=1,1210
Tuner10=2,1420
Tuner11=3,1680
Tuner12=4,2040

View File

@ -0,0 +1,36 @@
[scif]
# SCIF Settings
# Manufacturer = nn : Index to selected manaufacturer (only used in config webpage)
# Unit = nn : Index to selected unit (only used in config webpage)
# Type = nn : Type of unit: 1: EN 50494, 2: TS 50607
# TunerN = Slot,Frequency[,Pin] Slot = 1..nn, Frequency = 950..2150, Pin = 0-255
# Slot = 0 (no SCIF)
# Slot = 1..8 for EN 50494, 1..32 for TS 50607
Type=0
Tuner1=0
Tuner2=0
Tuner3=0
Tuner4=0
Tuner5=0
Tuner6=0
Tuner7=0
Tuner8=0
[LNB]
#
# LNB 1 Setting
#
Tuner=1
Source=1
LOF1=9750
LOF2=10600
LOFS=11700
[LNB]
#
# LNB 2 Setting
#
Tuner=2
Source=1
LOF1=9750
LOF2=10600
LOFS=11700

View File

@ -0,0 +1,37 @@
[CA]
family=unix
[scif]
# SCIF Settings
# Manufacturer = nn : Index to selected manaufacturer (only used in config webpage)
# Unit = nn : Index to selected unit (only used in config webpage)
# Type = nn : Type of unit: 1: EN 50494, 2: TS 50607
# TunerN = Slot,Frequency[,Pin] Slot = 1..nn, Frequency = 950..2150, Pin = 0-255
# Slot = 0 (no SCIF)
# Slot = 1..8 for EN 50494, 1..32 for TS 50607
Manufacturer=0
Unit=8
Type=2
Tuner1=1,1210
Tuner2=2,1420
Tuner3=3,1680
Tuner4=4,2040
Tuner5=5,984
Tuner6=6,1020
Tuner7=7,1056
Tuner8=8,1092
Tuner9=9,1128
Tuner10=10,1164
Tuner11=11,1256
Tuner12=12,1292
Tuner13=13,1328
Tuner14=14,1364
Tuner15=15,1458
Tuner16=16,1494
Tuner17=17,1530
Tuner18=18,1566
Tuner19=19,1602
Tuner20=20,1638
Tuner21=21,1716
Tuner22=22,1752
Tuner23=23,1788
Tuner24=24,1824

View File

@ -12,6 +12,7 @@
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <inttypes.h>
char line_start[16] = "";
char line_end[16] = "\r";
@ -203,7 +204,7 @@ void proc_ts(int i, uint8_t *buf)
if (ccin & 0x10) {
if ( cc[pid]) {
// TODO: 1 repetition allowed
if( ( ccin & 0x10 ) != 0 && (((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) )
if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)))
cc_errors += 1;
}
cc[pid] = ccin;
@ -271,7 +272,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;
@ -308,20 +309,22 @@ int main(int argc, char **argv)
{"tscheck", no_argument, 0, 't'},
{"tscheck_l", required_argument, 0, 'a'},
{"nodvr", no_argument , 0, 'q'},
{"pam", no_argument , 0, 'a'},
{"pam", no_argument , 0, 'P'},
{"pam_color", no_argument , 0, 'e'},
{"help", no_argument , 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:q",
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:qP",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'e':
odvr = 2;
color = strtoul(optarg, NULL, 0);
case 'P':
odvr = 2;
break;
case 'o':
fout = stderr;
@ -341,7 +344,7 @@ int main(int argc, char **argv)
break;
}
fprintf(fout,"performing continuity check\n");
odvr = 2;
odvr = 3;
break;
case 'c':
config = strdup(optarg);
@ -414,6 +417,8 @@ int main(int argc, char **argv)
delsys = SYS_ISDBC;
if (!strcmp(optarg, "ISDBT"))
delsys = SYS_ISDBT;
if (!strcmp(optarg, "ISDBS"))
delsys = SYS_ISDBS;
break;
case 'p':
if (!strcmp(optarg, "h") || !strcmp(optarg, "H"))
@ -425,12 +430,18 @@ int main(int argc, char **argv)
get_ts = 0;
break;
case 'h':
fprintf(fout,"ddzap [-d delivery_system] [-p polarity] [-c config_dir] [-f frequency(Hz)]\n"
fprintf(fout,"ddzap [-d delivery_system] [-p polarity] [-c config_dir]\n"
" [-f frequency(Hz for terr./kHz for SAT)]\n"
" [-m 16APSK/32APSK/64APSK/128APSK/256APSK]\n"
" (only needed for higher modulations than 8PSK) on some cards\n"
" [-b bandwidth(Hz)] [-s symbol_rate(Hz)]\n"
" [-g gold_code] [-r root_code] [-i id] [-n device_num]\n"
" [-o (write dvr to stdout)]\n"
" [-l (tuner source for unicable)]\n"
" [-t [display line](continuity check)]\n"
" [-t (continuity check)]\n"
" [-a [display line] (display continuity check in line)]\n"
" [-P (output IQ diagram as pam)]\n"
" [-e [color] (use color for pam 0=green)]\n"
"\n"
" delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
" polarity = h/H,v/V\n"
@ -501,8 +512,10 @@ int main(int argc, char **argv)
str = dddvb_get_strength(fe);
cnr = dddvb_get_cnr(fe);
printf("stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
stat, (long long int)str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000));
printf("stat=%02x, str=%" PRId64 ".%03u dBm, "
"snr=%" PRId64 ".%03u dB\n",
stat, str/1000, abs(str%1000),
cnr/1000, abs(cnr%1000));
sleep(1);
}
} else {
@ -521,7 +534,8 @@ int main(int argc, char **argv)
cnr = dddvb_get_cnr(fe);
fprintf(stderr,"stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
stat,(long long int) str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000));
stat, (long long int) str/1000, (long long int) abs(str%1000),
(long long int) cnr/1000, (long long int)abs(cnr%1000));
sleep(1);
}
fprintf(stderr,"got lock on %s\n", fe->name);
@ -531,29 +545,28 @@ int main(int argc, char **argv)
if ((fd = open(filename ,O_RDONLY)) < 0){
fprintf(stderr,"Error opening input file:%s\n",filename);
}
if (odvr > 0){
switch (odvr){
case 1:
while(1){
read(fd,buf,BUFFSIZE);
write(fileno(stdout),buf,BUFFSIZE);
}
break;
case 2:
fprintf(stderr,"writing pamdata\n");
init_pamdata(&iq,color);
while(1){
pam_read_data(fd, &iq);
pam_write(STDOUT_FILENO, &iq);
}
break;
switch (odvr){
case 1:
while(1){
read(fd,buf,BUFFSIZE);
write(fileno(stdout),buf,BUFFSIZE);
}
} else {
break;
case 2:
fprintf(stderr,"writing pamdata\n");
init_pamdata(&iq,color);
while(1){
pam_read_data(fd, &iq);
pam_write(STDOUT_FILENO, &iq);
}
break;
case 3:
if( line >= 0 && line < 64 ){
snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
strncpy(line_end,"\0338",sizeof(line_end)-1);
}
tscheck(fd);
break;
}
}
}

View File

@ -14,9 +14,11 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <net/if.h>
#include <net/ethernet.h>
@ -66,6 +68,32 @@ int streamsock(const char *port, int family, struct sockaddr *sadr)
return sock;
}
int unixsock(const char *path)
{
unlink(path);
struct sockaddr_un sa;
size_t hlen = offsetof(struct sockaddr_un, sun_path);
size_t pathlen = strlen(path);
if (pathlen > sizeof(sa.sun_path))
return(-1);
memset(&sa, 0, hlen);
sa.sun_family = AF_UNIX;
if (pathlen > 0)
memcpy(sa.sun_path, path, pathlen);
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
return(-1);
if (bind(sock, (struct sockaddr *) &sa, (socklen_t) (hlen + pathlen)) == -1) {
close(sock);
return(-1);
}
return(sock);
}
static int ai_callback(void *arg, uint8_t slot_id, uint16_t session_number,
uint8_t application_type, uint16_t application_manufacturer,
uint16_t manufacturer_code, uint8_t menu_string_length,
@ -357,10 +385,17 @@ static void handle_ci(struct dddvb_ca *ca)
int len;
int sock, i;
struct sockaddr sadr;
char port[6];
char port[6], path[32];
snprintf(port, sizeof(port), "%u", (uint16_t) (8888 + ca->nr));
sock = streamsock(port, AF_INET, &sadr);
if (ca->dd->cam_family == 1) {
snprintf(port, sizeof(port), "%u", (uint16_t) (8888 + ca->nr));
sock = streamsock(port, AF_INET, &sadr);
} else if (ca->dd->cam_family == 2) {
snprintf(path, sizeof(path), "/var/run/resiplayer/cam%u", ca->nr);
sock = unixsock(path);
} else {
sock = -1;
}
if (listen(sock, 4) < 0) {
dbgprintf(DEBUG_CA, "listen error");
return;
@ -466,6 +501,8 @@ static int mmi_close_callback(void *arg, uint8_t slot_id, uint16_t snum,
struct dddvb_ca *ca = arg;
ca->mmi_state = MMI_STATE_CLOSED;
if (ca->dd->cam_proto == 2)
sendstringx(ca->sock, "CLOSE", 0, NULL);
return 0;
}
@ -492,6 +529,8 @@ static int mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t snu
en50221_app_mmi_display_reply(ca->stdcam->mmi_resource, snum,
MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK, &reply);
ca->mmi_state = MMI_STATE_OPEN;
if (ca->dd->cam_proto == 2)
sendstringx(ca->sock, "OPEN", 0, NULL);
return 0;
}
@ -502,7 +541,10 @@ static int mmi_enq_callback(void *arg, uint8_t slot_id, uint16_t snum,
struct dddvb_ca *ca = arg;
if (ca->sock >= 0) {
if (ca->dd->cam_proto == 1)
sendstring(ca->sock, "%.*s: ", text_size, text);
if (ca->dd->cam_proto == 2)
sendstringx(ca->sock, "ENQ", text_size, text);
}
//mmi_enq_blind = blind_answer;
//mmi_enq_length = expected_answer_length;
@ -520,7 +562,7 @@ static int mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t snum,
uint32_t i;
struct dddvb_ca *ca = arg;
if (ca->sock >= 0) {
if ((ca->sock >= 0) && (ca->dd->cam_proto == 1)) {
if (title->text_length)
sendstring(ca->sock, "%.*s\n", title->text_length, title->text);
if (sub_title->text_length)
@ -530,6 +572,13 @@ static int mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t snum,
if (bottom->text_length)
sendstring(ca->sock, "%.*s\n", bottom->text_length, bottom->text);
}
if (ca->dd->cam_proto == 2) {
sendstringx(ca->sock, "MENU", title->text_length, title->text);
sendstringx(ca->sock, "MSUB", sub_title->text_length, sub_title->text);
for (i = 0; i < item_count; i++)
sendstringx(ca->sock, "ITEM", items[i].text_length, items[i].text);
sendstringx(ca->sock, "MEND", bottom->text_length, bottom->text);
}
ca->mmi_state = MMI_STATE_MENU;
return 0;
}

View File

@ -41,7 +41,7 @@ int parse_config(struct dddvb *dd, char *name, char *sec,
memcpy(fname + config_len, "dddvb.conf", 11);
if ((f = fopen (fname, "r")) == NULL) {
printf("config file %s not found\n", fname);
dprintf(2, "config file %s not found\n", fname);
return -1;
}

View File

@ -8,7 +8,7 @@ LIBDDDVB_EXPORTED struct dddvb *global_dd = NULL;
LIBDDDVB_EXPORTED pthread_mutex_t dddvb_mutex = PTHREAD_MUTEX_INITIALIZER;
void __attribute__ ((constructor)) setup(void) {
printf("SETUP\n");
//printf("SETUP\n");
}
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t type, uint32_t num)

View File

@ -152,6 +152,9 @@ struct dddvb {
struct dddvb_fe dvbfe[DDDVB_MAX_DVB_FE];
struct dddvb_ca dvbca[DDDVB_MAX_DVB_CA];
unsigned int cam_family;
unsigned int cam_proto;
unsigned int cam_port;
unsigned int get_ts:1;
};

View File

@ -111,6 +111,7 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
{ .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO },
{ .cmd = DTV_SYMBOL_RATE, .u.data = sr },
{ .cmd = DTV_INNER_FEC, .u.data = FEC_AUTO },
{ .cmd = DTV_ROLLOFF, .u.data = ROLLOFF_AUTO },
};
struct dtv_properties c;
int ret;
@ -128,7 +129,7 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
}
if (input != DDDVB_UNDEF)
set_property(fd, DTV_INPUT, input);
fprintf(stderr, "bw =%u\n", fe->param.param[PARAM_BW_HZ]);
//fprintf(stderr, "bw =%u\n", fe->param.param[PARAM_BW_HZ]);
if (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF)
set_property(fd, DTV_BANDWIDTH_HZ, fe->param.param[PARAM_BW_HZ]);
if (fe->param.param[PARAM_ISI] != DDDVB_UNDEF)
@ -181,7 +182,16 @@ static int diseqc(int fd, int sat, int hor, int band)
return 0;
}
static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
static int set_vol_tone(int fd, int hor, int band)
{
if (ioctl(fd, FE_SET_TONE, band ? SEC_TONE_ON : SEC_TONE_OFF))
perror("FE_SET_TONE failed");
if (ioctl(fd, FE_SET_VOLTAGE, hor ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13) == -1)
perror("FE_SET_VOLTAGE failed");
dbgprintf(DEBUG_DVB, "set_vol_tone hor=%u, band=%u\n", hor, band);
}
static int set_en50494(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
int sat, int hor, int band,
uint32_t slot, uint32_t ubfreq,
fe_delivery_system_t ds)
@ -193,8 +203,10 @@ static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
uint16_t t;
uint32_t input = 3 & (sat >> 6);
int fd = fe->fd;
uint32_t freq = (freq_khz + 2000) / 4000;
int32_t fdiff = freq_khz - freq * 1000;
t = (freq + ubfreq + 2) / 4 - 350;
t = (freq_khz / 1000 + ubfreq + 2) / 4 - 350;
hor &= 1;
cmd.msg[3] = ((t & 0x0300) >> 8) |
@ -218,7 +230,7 @@ static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3], cmd.msg[4]);
}
static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
static int set_en50607(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
int sat, int hor, int band,
uint32_t slot, uint32_t ubfreq,
fe_delivery_system_t ds)
@ -227,11 +239,13 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
.msg = {0x70, 0x00, 0x00, 0x00, 0x00},
.msg_len = 4
};
uint32_t freq = (freq_khz + 500) / 1000;
int32_t fdiff = freq_khz - freq * 1000;
uint32_t t = freq - 100;
uint32_t input = 3 & (sat >> 6);
int fd = fe->fd;
//printf("input = %u, sat = %u\n", input, sat&0x3f);
dbgprintf(DEBUG_DVB, "input = %u, sat = %u\n", input, sat&0x3f);
hor &= 1;
cmd.msg[1] = slot << 3;
cmd.msg[1] |= ((t >> 8) & 0x07);
@ -250,11 +264,11 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13) == -1)
perror("FE_SET_VOLTAGE failed");
set_fe_input(fe, ubfreq * 1000, sr, ds, input);
set_fe_input(fe, ubfreq * 1000 + fdiff, sr, ds, input);
dbgprintf(DEBUG_DVB, "EN50607 %02x %02x %02x %02x\n",
cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3]);
dbgprintf(DEBUG_DVB, "EN50607 freq %u sr %u hor %u\n",
freq, sr, hor);
dbgprintf(DEBUG_DVB, "EN50607 freq %u ubfreq %u fdiff %d sr %u hor %u\n",
freq, ubfreq, fdiff, sr, hor);
}
@ -288,13 +302,20 @@ 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)
freq -= fe->lof2[lnbc];
else
freq -= fe->lof1[lnbc];
if (lofs > 10000000) {
if (hi)
freq -= fe->lof2[lnbc];
else
freq -= fe->lof1[lnbc];
} else {
if (hi)
freq = fe->lof2[lnbc] - freq;
else
freq = fe->lof1[lnbc] - freq;
}
}
dbgprintf(DEBUG_DVB, "tune_sat IF=%u\n", freq);
if (fe->first) {
@ -307,23 +328,28 @@ static int tune_sat(struct dddvb_fe *fe)
dbgprintf(DEBUG_DVB, "scif_type = %u\n", fe->scif_type);
if (fe->scif_type == 1) {
pthread_mutex_lock(&fe->dd->uni_lock);
set_en50494(fe, freq / 1000, fe->param.param[PARAM_SR],
set_en50494(fe, freq, fe->param.param[PARAM_SR],
lnb, fe->param.param[PARAM_POL], hi,
fe->scif_slot, fe->scif_freq, ds);
pthread_mutex_unlock(&fe->dd->uni_lock);
} else if (fe->scif_type == 2) {
pthread_mutex_lock(&fe->dd->uni_lock);
set_en50607(fe, freq / 1000, fe->param.param[PARAM_SR],
set_en50607(fe, freq, fe->param.param[PARAM_SR],
lnb, fe->param.param[PARAM_POL], hi,
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)
if (input != DDDVB_UNDEF) {
input = 3 & (input >> 6);
//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6));
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
dbgprintf(DEBUG_DVB, "input = %u\n", input);
set_property(fe->fd, DTV_INPUT, input);
}
if (fe->scif_type == 3)
set_vol_tone(fe->fd, fe->param.param[PARAM_POL], hi);
else
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);
}
}
@ -346,7 +372,7 @@ static int tune_c(struct dddvb_fe *fe)
struct dtv_properties c;
int ret;
printf("tune_c()\n");
dbgprintf(DEBUG_DVB, "tune_c()\n");
set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_A);
c.num = ARRAY_SIZE(p);
@ -373,7 +399,7 @@ static int tune_j83b(struct dddvb_fe *fe)
struct dtv_properties c;
int ret;
printf("tune_j83b()\n");
dbgprintf(DEBUG_DVB, "tune_j83b()\n");
set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B);
c.num = ARRAY_SIZE(p);
@ -509,11 +535,37 @@ static int tune_isdbt(struct dddvb_fe *fe)
return 0;
}
static int tune_isdbs(struct dddvb_fe *fe)
{
struct dtv_property p[] = {
{ .cmd = DTV_CLEAR },
{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ]},
//{ .cmd = DTV_SYMBOL_RATE, .u.data = fe->param.param[PARAM_SR] },
//{ .cmd = DTV_TUNE },
};
struct dtv_properties c;
int ret;
set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_ISDBS);
c.num = ARRAY_SIZE(p);
c.props = p;
ret = ioctl(fe->fd, FE_SET_PROPERTY, &c);
if (ret < 0) {
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
return -1;
}
if (fe->param.param[PARAM_ISI] != DDDVB_UNDEF)
set_property(fe->fd, DTV_STREAM_ID, fe->param.param[PARAM_ISI]);
set_property(fe->fd, DTV_TUNE, 0);
return 0;
}
static int tune(struct dddvb_fe *fe)
{
int ret;
printf("tune()\n");
dbgprintf(DEBUG_DVB, "tune()\n");
switch (fe->param.param[PARAM_MSYS]) {
case SYS_DVBS:
case SYS_DVBS2:
@ -537,6 +589,9 @@ static int tune(struct dddvb_fe *fe)
case SYS_ISDBT:
ret = tune_isdbt(fe);
break;
case SYS_ISDBS:
ret = tune_isdbs(fe);
break;
default:
break;
}
@ -571,7 +626,6 @@ static int open_fe(struct dddvb_fe *fe)
sprintf(fname, "/dev/dvb/adapter%d/frontend%d", fe->anum, fe->fnum);
fe->fd = open(fname, O_RDWR);
printf("open = %d\n", fe->fd);
if (fe->fd < 0)
return -1;
return 0;
@ -678,7 +732,7 @@ void dddvb_fe_handle(struct dddvb_fe *fe)
} else {
max = 1;
nolock++;
if (nolock > 100)
if (nolock > 10)
fe->tune = 1;
}
break;
@ -720,6 +774,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;
}
@ -924,6 +980,31 @@ void lnb_config(struct dddvb *dd, char *name, char *val)
}
}
void ca_config(struct dddvb *dd, char *name, char *val)
{
if (!name || !val)
return;
char *p = strpbrk(val, "\r\n");
if (p)
*p = 0;
if (!strcasecmp(name, "family")) {
if (!strcasecmp(val, "tcp")) {
dd->cam_family = 1;
} else if (!strcasecmp(val, "unix")) {
dd->cam_family = 2;
}
return;
}
if (!strcasecmp(name, "proto")) {
dd->cam_proto = strtoul(val, NULL, 10);
return;
}
if (!strcasecmp(name, "port")) {
dd->cam_port = strtoul(val, NULL, 10);
return;
}
}
int dddvb_dvb_init(struct dddvb *dd)
{
pthread_mutex_init(&dd->uni_lock, 0);
@ -931,6 +1012,23 @@ int dddvb_dvb_init(struct dddvb *dd)
parse_config(dd, "", "scif", &scif_config);
set_lnb(dd, 0, 0, 9750000, 10600000, 11700000);
parse_config(dd, "", "LNB", &lnb_config);
parse_config(dd, "", "CA", &ca_config);
{
if (dd->cam_family == 0)
dd->cam_family = 1;
if (dd->cam_proto == 0) {
switch (dd->cam_family) {
case 1:
dd->cam_proto = 1;
break;
case 2:
dd->cam_proto = 2;
break;
}
}
if (dd->cam_port == 0)
dd->cam_port = 8888;
}
scan_dvbca(dd);
}

View File

@ -329,7 +329,7 @@ static void calc_lq(struct dddvb_fe *fe)
{
struct dtv_fe_stats st;
int64_t str, snr;
uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0;
uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0, freq, rate;
get_property(fe->fd, DTV_TRANSMISSION_MODE, &fe->pls_code);
dbgprintf(DEBUG_DVB, "fe%d: pls=0x%02x\n", fe->nr, fe->pls_code);
@ -362,6 +362,10 @@ static void calc_lq(struct dddvb_fe *fe)
dbgprintf(DEBUG_DVB, "fe%d: snr=%lld ber=%llu/%llu\n",
fe->nr, snr, ber_num, ber_den);
dbgprintf(DEBUG_DVB, "fe%d: fec=%u mod=%u\n", fe->nr, fec, mod);
get_property(fe->fd, DTV_FREQUENCY, &freq);
dbgprintf(DEBUG_DVB, "fe%d: actual frequency=%u\n", fe->nr, freq);
get_property(fe->fd, DTV_SYMBOL_RATE, &rate);
dbgprintf(DEBUG_DVB, "fe%d: actual symbol rate=%u\n", fe->nr, rate);
switch (fe->n_param.param[PARAM_MSYS]) {
case SYS_DVBS:
quality = dvbsq(snr, fec, ber_num, ber_den);

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
int sendlen(int sock, char *buf, int len)
@ -12,7 +13,7 @@ int sendlen(int sock, char *buf, int len)
for (todo = len; todo; todo -= done, buf += done)
if ((done = send(sock, buf, todo, 0)) < 0) {
printf("sendlen error\n");
dprintf(2, "sendlen error\n");
return done;
}
return len;
@ -33,6 +34,34 @@ int sendstring(int sock, char *fmt, ...)
return len;
}
int sendstringx(int sock, const char *label, uint32_t text_length, const uint8_t *text)
{
if (sock < 0)
return(-1);
uint8_t buf[strlen(label) + 1 + text_length * 3 + 2];
strcpy(buf, label);
int len = strlen(buf);
buf[len++] = 0x20;
while (text_length--) {
int c = *text++;
if (c == 0x5C) {
buf[len++] = 0x5C;
buf[len++] = 0x5C;
} else if ((c < 0x20) || (c > 0x7E)) {
buf[len++] = 0x5C;
snprintf(buf+len, 3, "%02X", c);
len += 2;
} else {
buf[len++] = (uint8_t) c;
}
}
buf[len++] = 0x0A;
sendlen(sock, buf, len);
return(len);
}
time_t mtime(time_t *t)
{
struct timespec ts;

View File

@ -4,5 +4,6 @@
time_t mtime(time_t *t);
int sendlen(int sock, char *buf, int len);
int sendstring(int sock, char *fmt, ...);
int sendstringx(int sock, const char *label, uint32_t text_length, const uint8_t *text);
#endif /* _DDDVB_TOOLS_H_ */