mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
Merge branch 'DigitalDevices:master' into master
This commit is contained in:
commit
ce19fe1b3c
6
Kbuild
6
Kbuild
@ -2,6 +2,12 @@
|
||||
# Makefile for the kernel multimedia device drivers.
|
||||
#
|
||||
|
||||
ifeq ($(KERNEL_DVB_CORE),y)
|
||||
obj-y := ddbridge/ \
|
||||
frontends/
|
||||
|
||||
else
|
||||
obj-y := dvb-core/ \
|
||||
ddbridge/ \
|
||||
frontends/
|
||||
endif
|
13
Makefile
13
Makefile
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
544
apps/ddinfo.c
Normal file
@ -0,0 +1,544 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <getopt.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#include "../ddbridge/ddbridge-mci.h"
|
||||
#include "../ddbridge/ddbridge-ioctl.h"
|
||||
|
||||
char *Rolloff[8] = {
|
||||
"0.35",
|
||||
"0.25",
|
||||
"0.20",
|
||||
"0.10",
|
||||
"0.05",
|
||||
"0.15",
|
||||
"rsvd",
|
||||
"rsvd",
|
||||
};
|
||||
|
||||
void dump(const uint8_t *b, int l)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < l; j += 16, b += 16) {
|
||||
printf("%04x: ", j);
|
||||
for (i = 0; i < 16; i++)
|
||||
if (i + j < l)
|
||||
printf("%02x ", b[i]);
|
||||
else
|
||||
printf(" ");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_temp(struct mci_result *res)
|
||||
{
|
||||
printf("Die temperature = %u\n", res->sx8_bist.temperature);
|
||||
}
|
||||
|
||||
int temp_info(int dev, uint32_t link)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = link,
|
||||
.cmd.command = SX8_CMD_GETBIST,
|
||||
};
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
printf("Error: %d %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
if (msg.res.status & 0x80) {
|
||||
printf("MCI errror %02x\n", msg.res.status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
print_temp(&msg.res);
|
||||
printf("BIST info dump: ");
|
||||
dump((uint8_t *) &msg.res, 16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
char *DemodStatus[] = {
|
||||
"Idle",
|
||||
"IQ Mode",
|
||||
"Wait for Signal",
|
||||
"DVB-S2 Wait for MATYPE",
|
||||
"DVB-S2 Wait for FEC",
|
||||
"DVB-S1 Wait for FEC",
|
||||
"Wait for TS",
|
||||
"Unknown 7",
|
||||
"Unknown 8",
|
||||
"Unknown 9",
|
||||
"Unknown 10",
|
||||
"Unknown 11",
|
||||
"Unknown 12",
|
||||
"Unknown 13",
|
||||
"Timeout",
|
||||
"Locked",
|
||||
"C2 Scan",
|
||||
};
|
||||
|
||||
char* S2ModCods[32] = {
|
||||
/* 0x00 */ "DummyPL" ,
|
||||
|
||||
// Legacy S2: index is S2_Modcod * 2 + short
|
||||
|
||||
/* 0x01 */ "QPSK 1/4" ,
|
||||
/* 0x02 */ "QPSK 1/3" ,
|
||||
/* 0x03 */ "QPSK 2/5" ,
|
||||
/* 0x04 */ "QPSK 1/2" ,
|
||||
/* 0x05 */ "QPSK 3/5" ,
|
||||
/* 0x06 */ "QPSK 2/3" ,
|
||||
/* 0x07 */ "QPSK 3/4" ,
|
||||
/* 0x08 */ "QPSK 4/5" ,
|
||||
/* 0x09 */ "QPSK 5/6" ,
|
||||
/* 0x0A */ "QPSK 8/9" ,
|
||||
/* 0x0B */ "QPSK 9/10" ,
|
||||
|
||||
/* 0x0C */ "8PSK 3/5" ,
|
||||
/* 0x0D */ "8PSK 2/3" ,
|
||||
/* 0x0E */ "8PSK 3/4" ,
|
||||
/* 0x0F */ "8PSK 5/6" ,
|
||||
/* 0x10 */ "8PSK 8/9" ,
|
||||
/* 0x11 */ "8PSK 9/10" ,
|
||||
|
||||
/* 0x12 */ "16APSK 2/3" ,
|
||||
/* 0x13 */ "16APSK 3/4" ,
|
||||
/* 0x14 */ "16APSK 4/5" ,
|
||||
/* 0x15 */ "16APSK 5/6" ,
|
||||
/* 0x16 */ "16APSK 8/9" ,
|
||||
/* 0x17 */ "16APSK 9/10" ,
|
||||
|
||||
/* 0x18 */ "32APSK 3/4" ,
|
||||
/* 0x19 */ "32APSK 4/5" ,
|
||||
/* 0x1A */ "32APSK 5/6" ,
|
||||
/* 0x1B */ "32APSK 8/9" ,
|
||||
/* 0x1C */ "32APSK 9/10" ,
|
||||
|
||||
/* 0x1D */ "rsvd 0x1D" ,
|
||||
/* 0x1E */ "rsvd 0x1E" ,
|
||||
/* 0x1F */ "rsvd 0x1F" ,
|
||||
};
|
||||
|
||||
|
||||
///* 129 */ "VLSNR1" ,
|
||||
///* 131 */ "VLSNR2" ,
|
||||
|
||||
char* S2XModCods[59] = {
|
||||
/* 0x42 */ "QPSK 13/45" ,
|
||||
/* 0x43 */ "QPSK 9/20" ,
|
||||
/* 0x44 */ "QPSK 11/20" ,
|
||||
|
||||
/* 0x45 */ "8APSK 5/9-L" ,
|
||||
/* 0x46 */ "8APSK 26/45-L" ,
|
||||
/* 0x47 */ "8PSK 23/36" ,
|
||||
/* 0x48 */ "8PSK 25/36" ,
|
||||
/* 0x49 */ "8PSK 13/18" ,
|
||||
|
||||
/* 0x4A */ "16APSK 1/2-L" ,
|
||||
/* 0x4B */ "16APSK 8/15-L" ,
|
||||
/* 0x4C */ "16APSK 5/9-L" ,
|
||||
/* 0x4D */ "16APSK 26/45" ,
|
||||
/* 0x4E */ "16APSK 3/5" ,
|
||||
/* 0x4F */ "16APSK 3/5-L" ,
|
||||
/* 0x50 */ "16APSK 28/45" ,
|
||||
/* 0x51 */ "16APSK 23/36" ,
|
||||
/* 0x52 */ "16APSK 2/3-L" ,
|
||||
/* 0x53 */ "16APSK 25/36" ,
|
||||
/* 0x54 */ "16APSK 13/18" ,
|
||||
|
||||
/* 0x55 */ "16APSK 7/9" ,
|
||||
/* 0x56 */ "16APSK 77/90" ,
|
||||
|
||||
/* 0x57 */ "32APSK 2/3-L" ,
|
||||
/* 0x58 */ "rsvd 32APSK" ,
|
||||
/* 0x59 */ "32APSK 32/45" ,
|
||||
/* 0x5A */ "32APSK 11/15" ,
|
||||
/* 0x5B */ "32APSK 7/9" ,
|
||||
|
||||
/* 0x5C */ "64APSK 32/45-L" ,
|
||||
/* 0x5D */ "64APSK 11/15" ,
|
||||
/* 0x5E */ "rsvd 64APSK" ,
|
||||
/* 0x5F */ "64APSK 7/9" ,
|
||||
|
||||
/* 0x60 */ "rsvd 64APSK" ,
|
||||
/* 0x61 */ "64APSK 4/5" ,
|
||||
/* 0x62 */ "rsvd 64APSK" ,
|
||||
/* 0x63 */ "64APSK 5/6" ,
|
||||
|
||||
/* 0x64 */ "128APSK 3/4" ,
|
||||
/* 0x65 */ "128APSK 7/9" ,
|
||||
|
||||
/* 0x66 */ "256APSK 29/45-L" ,
|
||||
/* 0x67 */ "256APSK 2/3-L" ,
|
||||
/* 0x68 */ "256APSK 31/45-L" ,
|
||||
/* 0x69 */ "256APSK 32/45" ,
|
||||
/* 0x6A */ "256APSK 11/15-L" ,
|
||||
/* 0x6B */ "256APSK 3/4" ,
|
||||
|
||||
/* 0x6C */ "QPSK 11/45-S" ,
|
||||
/* 0x6D */ "QPSK 4/15-S" ,
|
||||
/* 0x6E */ "QPSK 14/45-S" ,
|
||||
/* 0x6F */ "QPSK 7/15-S" ,
|
||||
/* 0x70 */ "QPSK 8/15-S" ,
|
||||
/* 0x71 */ "QPSK 32/45-S" ,
|
||||
|
||||
/* 0x72 */ "8PSK 7/15-S" ,
|
||||
/* 0x73 */ "8PSK 8/15-S" ,
|
||||
/* 0x74 */ "8PSK 26/45-S" ,
|
||||
/* 0x75 */ "8PSK 32/45-S" ,
|
||||
|
||||
/* 0x76 */ "16APSK 7/15-S" ,
|
||||
/* 0x77 */ "16APSK 8/15-S" ,
|
||||
/* 0x78 */ "16APSK 26/45-S" ,
|
||||
/* 0x79 */ "16APSK 3/5-S" ,
|
||||
/* 0x7A */ "16APSK 32/45-S" ,
|
||||
|
||||
/* 0x7B */ "32APSK 2/3-S" ,
|
||||
/* 0x7C */ "32APSK 32/45-S" ,
|
||||
};
|
||||
|
||||
char* S2Xrsvd[] = {
|
||||
/* 250 */ "rsvd 8PSK" ,
|
||||
/* 251 */ "rsvd 16APSK" ,
|
||||
/* 252 */ "rsvd 32APSK" ,
|
||||
/* 253 */ "rsvd 64APSK" ,
|
||||
/* 254 */ "rsvd 256APSK" ,
|
||||
/* 255 */ "rsvd 1024APSK" ,
|
||||
};
|
||||
|
||||
char* PunctureRates[32] = {
|
||||
/* 0x00 */ "QPSK 1/2", // DVB-S1
|
||||
/* 0x01 */ "QPSK 2/3", // DVB-S1
|
||||
/* 0x02 */ "QPSK 3/4", // DVB-S1
|
||||
/* 0x03 */ "QPSK 5/6", // DVB-S1
|
||||
/* 0x04 */ "QPSK 6/7", // DSS
|
||||
/* 0x05 */ "QPSK 7/8", // DVB-S1
|
||||
/* 0x06 */ "rsvd 6.0",
|
||||
/* 0x07 */ "rsvd 7.0",
|
||||
};
|
||||
|
||||
int mci_bb(int dev, uint32_t link, uint8_t demod)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = link,
|
||||
.cmd.command = MCI_CMD_GET_BBHEADER,
|
||||
.cmd.demod = demod,
|
||||
.cmd.get_bb_header.select = 0,
|
||||
};
|
||||
struct mci_result *res = &msg.res;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
printf("Error: %d %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
if (res->bb_header.valid) {
|
||||
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
|
||||
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
|
||||
{
|
||||
if (res->status == MCI_DEMOD_STOPPED) {
|
||||
printf("\nDemod %u: stopped\n", demod);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nDemod %u:\n", demod);
|
||||
if (res->status == MCI_DEMOD_LOCKED) {
|
||||
switch (res->mode) {
|
||||
case 0:
|
||||
case 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 */
|
||||
}
|
||||
}
|
@ -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
100
apps/getiq.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <getopt.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#include "../ddbridge/ddbridge-mci.h"
|
||||
#include "../ddbridge/ddbridge-ioctl.h"
|
||||
|
||||
void print_iq(struct mci_result *res, int fd)
|
||||
{
|
||||
dprintf(fd, "%d,%d\n", res->iq_symbol.i, res->iq_symbol.q);
|
||||
}
|
||||
|
||||
int get_iq(int dev, uint32_t link, uint8_t demod, int fd)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = link,
|
||||
.cmd.command = MCI_CMD_GET_IQSYMBOL,
|
||||
.cmd.demod = demod,
|
||||
.cmd.get_iq_symbol.tap = 0,
|
||||
.cmd.get_iq_symbol.point = 0,
|
||||
};
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
printf("Error: %d %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
if (msg.res.status & 0x80) {
|
||||
printf("MCI errror %02x\n", msg.res.status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
print_iq(&msg.res, fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
char ddbname[80];
|
||||
int fd = -1, all = 1, i, ret = 0, ddb;
|
||||
char fn[128];
|
||||
int32_t device = -1, demod = -1;
|
||||
|
||||
while (1) {
|
||||
int cur_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"demod", required_argument, 0, 'n'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, "ad:n:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'd':
|
||||
device = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'n':
|
||||
demod = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'a':
|
||||
all = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
printf("too many arguments\n");
|
||||
exit(1);
|
||||
}
|
||||
sprintf(ddbname, "/dev/ddbridge/card%d", device);
|
||||
ddb = open(ddbname, O_RDWR);
|
||||
if (ddb < 0)
|
||||
return -3;
|
||||
for (i = 0; i < 20000; i++)
|
||||
get_iq(ddb, 0, demod, 1);
|
||||
}
|
531
apps/modconfig.c
Normal file
531
apps/modconfig.c
Normal 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
1321
apps/modtest.c
Normal file
File diff suppressed because it is too large
Load Diff
51
apps/modulator.conf
Normal file
51
apps/modulator.conf
Normal file
@ -0,0 +1,51 @@
|
||||
[output]
|
||||
# connector = OFF, SMA or F
|
||||
connector = F
|
||||
# number of total channels to be used at the same time
|
||||
# use lower number to have fewer channels but stronger signal per channel
|
||||
channels = 16
|
||||
# unit of power in DBUV or DBM
|
||||
unit = DBUV
|
||||
# power output in units of above unit
|
||||
power = 50.0
|
||||
|
||||
|
||||
# define channels:
|
||||
# channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned
|
||||
|
||||
[channels]
|
||||
# standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz
|
||||
standard = 1
|
||||
|
||||
# numbers of channels to allocate, starting from frequency below
|
||||
# this defines 25 channels at 474, 474+8, 474+16, etc. Mhz
|
||||
channels = 25
|
||||
# frequency of channel 0, following channels are spaced according to set standard
|
||||
frequency = 474.0
|
||||
|
||||
|
||||
[streams]
|
||||
# number of streams depends on the card hardware
|
||||
# streams correspond to devices mod0, mod1, ...
|
||||
# channels are defined above in channels section
|
||||
|
||||
# 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4
|
||||
guard_interval = 0
|
||||
# 0 = 2K, 1 = 8K (2K not yet supported)
|
||||
fft_size = 1
|
||||
|
||||
# all following streams will be set according to the last set other parameters
|
||||
|
||||
# example:
|
||||
# this would set mod 1 to 474 MHz and mod0 to 482 MHz (474 + 8 MHz)
|
||||
# both with guard interval 1/32 and 8K FFT
|
||||
# and mod2 to 490MHz, guard interval 1/16 and 8K FFT
|
||||
channel = 1
|
||||
stream = 0
|
||||
#
|
||||
channel = 0
|
||||
stream = 1
|
||||
#
|
||||
guard_interval = 1
|
||||
channel = 2
|
||||
stream = 2
|
@ -1,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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ struct ddflash {
|
||||
int fd;
|
||||
uint32_t link;
|
||||
char *fname;
|
||||
int force;
|
||||
|
||||
struct ddb_id id;
|
||||
uint32_t version;
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
74
ddbridge/ddbridge-ioctl.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef _DDBRIDGE_IOCTL_H_
|
||||
#define _DDBRIDGE_IOCTL_H_
|
||||
|
||||
#define DDB_MAGIC 'd'
|
||||
|
||||
struct ddb_flashio {
|
||||
__u8 *write_buf;
|
||||
__u32 write_len;
|
||||
__u8 *read_buf;
|
||||
__u32 read_len;
|
||||
__u32 link;
|
||||
};
|
||||
|
||||
struct ddb_gpio {
|
||||
__u32 mask;
|
||||
__u32 data;
|
||||
};
|
||||
|
||||
struct ddb_id {
|
||||
__u16 vendor;
|
||||
__u16 device;
|
||||
__u16 subvendor;
|
||||
__u16 subdevice;
|
||||
__u32 hw;
|
||||
__u32 regmap;
|
||||
};
|
||||
|
||||
struct ddb_reg {
|
||||
__u32 reg;
|
||||
__u32 val;
|
||||
};
|
||||
|
||||
struct ddb_mem {
|
||||
__u32 off;
|
||||
__u8 *buf;
|
||||
__u32 len;
|
||||
};
|
||||
|
||||
struct ddb_mdio {
|
||||
__u8 adr;
|
||||
__u8 reg;
|
||||
__u16 val;
|
||||
};
|
||||
|
||||
struct ddb_i2c_msg {
|
||||
__u8 bus;
|
||||
__u8 adr;
|
||||
__u8 *hdr;
|
||||
__u32 hlen;
|
||||
__u8 *msg;
|
||||
__u32 mlen;
|
||||
};
|
||||
|
||||
struct ddb_mci_msg {
|
||||
__u32 link;
|
||||
struct mci_command cmd;
|
||||
struct mci_result res;
|
||||
};
|
||||
|
||||
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
|
||||
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
|
||||
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
|
||||
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
|
||||
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
|
||||
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
|
||||
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
|
||||
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
|
||||
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
|
||||
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
|
||||
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
|
||||
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
|
||||
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
|
||||
|
||||
#endif
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 = {
|
||||
|
@ -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
76
ddbridge/ns.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef _UAPI_DVBNS_H_
|
||||
#define _UAPI_DVBNS_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct dvb_ns_params {
|
||||
__u8 smac[6];
|
||||
__u8 dmac[6];
|
||||
__u8 sip[16];
|
||||
__u8 dip[16];
|
||||
__u16 sport;
|
||||
__u16 dport;
|
||||
__u16 sport2;
|
||||
__u16 dport2;
|
||||
__u8 ssrc[8];
|
||||
__u8 flags;
|
||||
__u8 qos;
|
||||
__u16 vlan;
|
||||
__u8 ttl;
|
||||
};
|
||||
|
||||
#define DVB_NS_IPV6 0x01
|
||||
#define DVB_NS_RTP 0x02
|
||||
#define DVB_NS_RTCP 0x04
|
||||
#define DVB_NS_RTP_TO 0x08
|
||||
#define DVB_NS_VLAN 0x10
|
||||
|
||||
struct dvb_ns_rtcp {
|
||||
__u8 *msg;
|
||||
__u16 len;
|
||||
};
|
||||
|
||||
struct dvb_ns_packet {
|
||||
__u8 *buf;
|
||||
__u8 count;
|
||||
};
|
||||
|
||||
struct dvb_nsd_ts {
|
||||
__u16 pid;
|
||||
__u16 num;
|
||||
__u16 input;
|
||||
__u16 timeout;
|
||||
__u16 len;
|
||||
__u8 *ts;
|
||||
__u8 mode;
|
||||
__u8 table;
|
||||
|
||||
__u8 filter_mask;
|
||||
__u8 section;
|
||||
__u16 section_id;
|
||||
};
|
||||
|
||||
struct dvb_ns_cap {
|
||||
__u8 streams_max;
|
||||
__u8 reserved[127];
|
||||
};
|
||||
|
||||
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
|
||||
#define NS_START _IO('o', 193)
|
||||
#define NS_STOP _IO('o', 194)
|
||||
#define NS_SET_PID _IOW('o', 195, __u16)
|
||||
#define NS_SET_PIDS _IOW('o', 196, __u8 *)
|
||||
#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp)
|
||||
|
||||
#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts)
|
||||
#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts)
|
||||
#define NSD_CANCEL_GET_TS _IO('o', 200)
|
||||
#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts)
|
||||
|
||||
#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet)
|
||||
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
|
||||
#define NS_SET_CI _IOW('o', 204, __u8)
|
||||
|
||||
#define NS_GET_CAP _IOR('o', 204, struct dvb_ns_cap))
|
||||
|
||||
#endif /*_UAPI_DVBNS_H_*/
|
13
docs/firmware
Normal file
13
docs/firmware
Normal file
@ -0,0 +1,13 @@
|
||||
Firmware update:
|
||||
|
||||
Copy the firmware file to the dddvb/apps/ directory and
|
||||
execute "./flashprog".
|
||||
|
||||
The program will try to identify the card version and
|
||||
check if it finds the corresponding firmware file.
|
||||
It will then prompt you to confirm to proceed
|
||||
with the flashing procedure.
|
||||
|
||||
After the update the system needs a power cycle.
|
||||
|
||||
|
27
docs/iq_samples
Normal file
27
docs/iq_samples
Normal file
@ -0,0 +1,27 @@
|
||||
~The Max SX8 can provide IQ samples in real time.
|
||||
|
||||
They are 8 bit signed values embedded in TS packets with PID 0x200.
|
||||
|
||||
API:
|
||||
|
||||
Currently DTV_STREAM_ID is misused.
|
||||
|
||||
0x10000000 - symbols (locked and tracked) at symbol rate
|
||||
0x20000000 - samples at symbol rate
|
||||
(fixed at ADC rate (1550/24=64.583... MHz) if 0x00010000 is set)
|
||||
Max. sample rate is 64.583333 MHz.
|
||||
|
||||
0x00xx0000 - flags
|
||||
Bit 0 : 0 = VTM/SDR, 1 = SCAN,
|
||||
Bit 1: 1 = Disable channel AGC,
|
||||
Bit 2: 1 = Set Gain.
|
||||
|
||||
0x0000xx00 - xx=gain
|
||||
|
||||
0x000000xx - xx=flags
|
||||
Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
|
||||
2 = Medium, 3 = Maximum gain {~ 15dB}
|
||||
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
|
||||
Bit 4: Set RF Gain
|
||||
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
|
||||
Bit 7: Optimize RF Gain and freeze for FFT
|
@ -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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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])
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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, ®, 1, val, count);
|
||||
int ret = i2c_read(state->i2c, adr, ®, 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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
39
include/dd_compat.h
Normal 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
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
49
lib/README.md
Normal 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 -`
|
||||
|
@ -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
|
||||
|
36
lib/config/dddvb.conf.example
Normal file
36
lib/config/dddvb.conf.example
Normal 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
|
37
lib/config/dddvb.conf.example_uni
Normal file
37
lib/config/dddvb.conf.example_uni
Normal 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
|
69
lib/ddzap.c
69
lib/ddzap.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
57
lib/src/ca.c
57
lib/src/ca.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
146
lib/src/dvb.c
146
lib/src/dvb.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user