Merge branch 'internal'

This commit is contained in:
none 2021-03-18 19:03:57 +01:00
commit 0d66d5bab0
16 changed files with 448 additions and 161 deletions

View File

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

View File

@ -119,7 +119,7 @@ static int update_flash(struct ddflash *ddf)
printf("Flash: %s\n", ddf->flash_name);
printf("Version: %08x\n", ddf->id.hw);
printf("REGMAP : %08x\n", ddf->id.regmap);
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
stat |= 1;
return stat;
}

View File

@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen,
return -1;
len = off - fw_off;
lseek(fs, fw_off, SEEK_SET);
#if 0
if (len > maxlen) {
printf("file too big\n");
return -1;
}
#endif
//printf("flash file len %u, compare to %08x in flash: ", len, addr);
for (j = 0; j < len; j += bl, addr += bl) {
if (len - j < bl)
@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
return -4;
}
if (devid == ddf->id.device) {
if (version <= (ddf->id.hw & 0xffffff)) {
printf("%s is older or same version as flash\n", fn);
ret = -3; /* same id but no newer version */
if (version < (ddf->id.hw & 0xffffff)) {
printf("%s is older version than flash\n", fn);
if (!ddf->force)
ret = -3; /* same id but older newer version */
}
if (version == (ddf->id.hw & 0xffffff)) {
printf("%s is same version as flash\n", fn);
if (!ddf->force)
ret = 2; /* same and same version */
}
} else
ret = 1;
@ -1147,7 +1151,7 @@ out:
}
static int update_image(struct ddflash *ddf, char *fn,
uint32_t adr, uint32_t len,
uint32_t adr, uint32_t maxlen,
int has_header, int no_change)
{
int fs, res = 0;
@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn,
printf("File %s not found \n", fn);
return -1;
}
res = flashcmp(ddf, fs, adr, len, fw_off);
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) {
printf("Flash already identical to %s\n", fn);
if (ddf->force) {
@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn,
}
if (res < 0)
goto out;
res = flashwrite(ddf, fs, adr, len, fw_off);
res = flashwrite(ddf, fs, adr, maxlen, fw_off);
if (res == 0) {
res = flashcmp(ddf, fs, adr, len, fw_off);
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
if (res == -2) {
res = 1;
printf("Flash verify OK!\n");

View File

@ -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);
}

123
apps/sx8info.c Normal file
View File

@ -0,0 +1,123 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "../ddbridge/ddbridge-mci.h"
#include "../ddbridge/ddbridge-ioctl.h"
char *Rolloff[8] = {
"0.35",
"0.25",
"0.20",
"0.10",
"0.05",
"0.15",
"rsvd",
"rsvd",
};
void print_info(struct mci_result *res)
{
if (res->status == MCI_DEMOD_STOPPED) {
printf("Demod stopped\n");
return;
}
switch (res->mode) {
case 0:
case M4_MODE_DVBSX:
if (res->dvbs2_signal_info.standard == 2) {
printf("PLS-Code: %u\n", res->dvbs2_signal_info.pls_code);
printf("Roll-Off: %s\n", Rolloff[res->dvbs2_signal_info.roll_off]);
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
printf("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);
printf("Band Power: %.2f dBm\n", (float) res->dvbs2_signal_info.band_power / 100);
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);
printf("\n");
} else {
}
}
}
int mci_info(int dev, uint8_t demod)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = MCI_CMD_GETSIGNALINFO,
.cmd.demod = demod
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("%d %d\n", ret, errno);
return ret;
}
print_info(&msg.res);
return ret;
}
int main(int argc, char*argv[])
{
int fd = -1;
char fn[128];
uint32_t device = 0;
uint8_t demod = 0;
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, "d: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;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
snprintf(fn, 127, "/dev/ddbridge/card%u", device);
fd = open(fn, O_RDWR);
if (fd < 0)
return -1;
mci_info(fd, demod);
}

View File

@ -24,6 +24,7 @@
#include "ddbridge.h"
#include "ddbridge-i2c.h"
#include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#include <media/dvb_net.h>
struct workqueue_struct *ddb_wq;
@ -3187,76 +3188,6 @@ static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg, u32 mdio_base)
return ddbreadl(dev, MDIO_VAL_OFF + mdio_base);
}
#define DDB_MAGIC 'd'
struct ddb_flashio {
__u8 *write_buf;
__u32 write_len;
__u8 *read_buf;
__u32 read_len;
__u32 link;
};
struct ddb_gpio {
__u32 mask;
__u32 data;
};
struct ddb_id {
__u16 vendor;
__u16 device;
__u16 subvendor;
__u16 subdevice;
__u32 hw;
__u32 regmap;
};
struct ddb_reg {
__u32 reg;
__u32 val;
};
struct ddb_mem {
__u32 off;
__u8 *buf;
__u32 len;
};
struct ddb_mdio {
__u8 adr;
__u8 reg;
__u16 val;
};
struct ddb_i2c_msg {
__u8 bus;
__u8 adr;
__u8 *hdr;
__u32 hlen;
__u8 *msg;
__u32 mlen;
};
struct ddb_mci_msg {
__u32 link;
struct mci_command cmd;
struct mci_result res;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
#define DDB_NAME "ddbridge"
static u32 ddb_num;

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

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

View File

@ -392,10 +392,12 @@ 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;

View File

@ -65,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)
@ -79,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;
}
@ -98,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);

View File

@ -60,10 +60,6 @@ static int mci_reset(struct ddb_link *link)
return -1;
}
dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50);
print_hex_dump(KERN_INFO, "ddbridge: MCI INIT INFO: ", DUMP_PREFIX_NONE, 16, 1,
link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE,
16, false);
return 0;
}

View File

@ -359,6 +359,7 @@ struct mci_result {
union {
u32 result[27];
u8 result8[27 * 4];
struct {
u8 Rsvd0[3];
u8 Flags;
@ -758,6 +759,8 @@ struct mci_result {
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
#ifdef __KERNEL__
struct mci_base {
struct list_head mci_list;
void *key;
@ -801,5 +804,6 @@ int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val);
extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg;
#endif
#endif

View File

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

View File

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

49
lib/README.md Normal file
View File

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

View File

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

View File

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