mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2023-10-10 13:37:43 +02:00
Merge branch 'internal'
This commit is contained in:
commit
0d66d5bab0
@ -6,6 +6,9 @@ We can only accept patches which don't break compilation for older kernels (as f
|
|||||||
Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain
|
Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain
|
||||||
incompatiblities to this driver package.
|
incompatiblities to this driver package.
|
||||||
|
|
||||||
|
For installation instructions see:
|
||||||
|
|
||||||
|
http://support.digital-devices.eu/index.php?article=152
|
||||||
### Prepare for Building
|
### Prepare for Building
|
||||||
|
|
||||||
TBD
|
TBD
|
||||||
|
@ -119,7 +119,7 @@ static int update_flash(struct ddflash *ddf)
|
|||||||
printf("Flash: %s\n", ddf->flash_name);
|
printf("Flash: %s\n", ddf->flash_name);
|
||||||
printf("Version: %08x\n", ddf->id.hw);
|
printf("Version: %08x\n", ddf->id.hw);
|
||||||
printf("REGMAP : %08x\n", ddf->id.regmap);
|
printf("REGMAP : %08x\n", ddf->id.regmap);
|
||||||
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
|
if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
|
||||||
stat |= 1;
|
stat |= 1;
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen,
|
|||||||
return -1;
|
return -1;
|
||||||
len = off - fw_off;
|
len = off - fw_off;
|
||||||
lseek(fs, fw_off, SEEK_SET);
|
lseek(fs, fw_off, SEEK_SET);
|
||||||
#if 0
|
|
||||||
if (len > maxlen) {
|
if (len > maxlen) {
|
||||||
printf("file too big\n");
|
printf("file too big\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
//printf("flash file len %u, compare to %08x in flash: ", len, addr);
|
//printf("flash file len %u, compare to %08x in flash: ", len, addr);
|
||||||
for (j = 0; j < len; j += bl, addr += bl) {
|
for (j = 0; j < len; j += bl, addr += bl) {
|
||||||
if (len - j < bl)
|
if (len - j < bl)
|
||||||
@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
|
|||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
if (devid == ddf->id.device) {
|
if (devid == ddf->id.device) {
|
||||||
if (version <= (ddf->id.hw & 0xffffff)) {
|
if (version < (ddf->id.hw & 0xffffff)) {
|
||||||
printf("%s is older or same version as flash\n", fn);
|
printf("%s is older version than flash\n", fn);
|
||||||
ret = -3; /* same id but no newer version */
|
if (!ddf->force)
|
||||||
|
ret = -3; /* same id but older newer version */
|
||||||
|
}
|
||||||
|
if (version == (ddf->id.hw & 0xffffff)) {
|
||||||
|
printf("%s is same version as flash\n", fn);
|
||||||
|
if (!ddf->force)
|
||||||
|
ret = 2; /* same and same version */
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -1147,7 +1151,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int update_image(struct ddflash *ddf, char *fn,
|
static int update_image(struct ddflash *ddf, char *fn,
|
||||||
uint32_t adr, uint32_t len,
|
uint32_t adr, uint32_t maxlen,
|
||||||
int has_header, int no_change)
|
int has_header, int no_change)
|
||||||
{
|
{
|
||||||
int fs, res = 0;
|
int fs, res = 0;
|
||||||
@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn,
|
|||||||
printf("File %s not found \n", fn);
|
printf("File %s not found \n", fn);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
res = flashcmp(ddf, fs, adr, len, fw_off);
|
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
|
||||||
if (res == -2) {
|
if (res == -2) {
|
||||||
printf("Flash already identical to %s\n", fn);
|
printf("Flash already identical to %s\n", fn);
|
||||||
if (ddf->force) {
|
if (ddf->force) {
|
||||||
@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn,
|
|||||||
}
|
}
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
goto out;
|
goto out;
|
||||||
res = flashwrite(ddf, fs, adr, len, fw_off);
|
res = flashwrite(ddf, fs, adr, maxlen, fw_off);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
res = flashcmp(ddf, fs, adr, len, fw_off);
|
res = flashcmp(ddf, fs, adr, maxlen, fw_off);
|
||||||
if (res == -2) {
|
if (res == -2) {
|
||||||
res = 1;
|
res = 1;
|
||||||
printf("Flash verify OK!\n");
|
printf("Flash verify OK!\n");
|
||||||
|
@ -113,7 +113,7 @@ int main(int argc, char*argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
printf("too man arguments\n");
|
printf("too many arguments\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
123
apps/sx8info.c
Normal file
123
apps/sx8info.c
Normal 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);
|
||||||
|
}
|
@ -24,6 +24,7 @@
|
|||||||
#include "ddbridge.h"
|
#include "ddbridge.h"
|
||||||
#include "ddbridge-i2c.h"
|
#include "ddbridge-i2c.h"
|
||||||
#include "ddbridge-io.h"
|
#include "ddbridge-io.h"
|
||||||
|
#include "ddbridge-ioctl.h"
|
||||||
#include <media/dvb_net.h>
|
#include <media/dvb_net.h>
|
||||||
|
|
||||||
struct workqueue_struct *ddb_wq;
|
struct workqueue_struct *ddb_wq;
|
||||||
@ -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);
|
return ddbreadl(dev, MDIO_VAL_OFF + mdio_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DDB_MAGIC 'd'
|
|
||||||
|
|
||||||
struct ddb_flashio {
|
|
||||||
__u8 *write_buf;
|
|
||||||
__u32 write_len;
|
|
||||||
__u8 *read_buf;
|
|
||||||
__u32 read_len;
|
|
||||||
__u32 link;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_gpio {
|
|
||||||
__u32 mask;
|
|
||||||
__u32 data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_id {
|
|
||||||
__u16 vendor;
|
|
||||||
__u16 device;
|
|
||||||
__u16 subvendor;
|
|
||||||
__u16 subdevice;
|
|
||||||
__u32 hw;
|
|
||||||
__u32 regmap;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_reg {
|
|
||||||
__u32 reg;
|
|
||||||
__u32 val;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_mem {
|
|
||||||
__u32 off;
|
|
||||||
__u8 *buf;
|
|
||||||
__u32 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_mdio {
|
|
||||||
__u8 adr;
|
|
||||||
__u8 reg;
|
|
||||||
__u16 val;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_i2c_msg {
|
|
||||||
__u8 bus;
|
|
||||||
__u8 adr;
|
|
||||||
__u8 *hdr;
|
|
||||||
__u32 hlen;
|
|
||||||
__u8 *msg;
|
|
||||||
__u32 mlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ddb_mci_msg {
|
|
||||||
__u32 link;
|
|
||||||
struct mci_command cmd;
|
|
||||||
struct mci_result res;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
|
|
||||||
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
|
|
||||||
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
|
|
||||||
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
|
|
||||||
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
|
|
||||||
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
|
|
||||||
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
|
|
||||||
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
|
|
||||||
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
|
|
||||||
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
|
|
||||||
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
|
|
||||||
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
|
|
||||||
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
|
|
||||||
|
|
||||||
#define DDB_NAME "ddbridge"
|
#define DDB_NAME "ddbridge"
|
||||||
|
|
||||||
static u32 ddb_num;
|
static u32 ddb_num;
|
||||||
|
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,10 +392,12 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
struct m4 *state = fe->demodulator_priv;
|
struct m4 *state = fe->demodulator_priv;
|
||||||
struct mci_result res;
|
struct mci_result res;
|
||||||
|
|
||||||
|
*status = 0x00;
|
||||||
|
if (!state->started)
|
||||||
|
return 0;
|
||||||
stat = ddb_mci_get_status(&state->mci, &res);
|
stat = ddb_mci_get_status(&state->mci, &res);
|
||||||
if (stat)
|
if (stat)
|
||||||
return stat;
|
return stat;
|
||||||
*status = 0x00;
|
|
||||||
stat = ddb_mci_get_info(&state->mci);
|
stat = ddb_mci_get_info(&state->mci);
|
||||||
if (stat)
|
if (stat)
|
||||||
return stat;
|
return stat;
|
||||||
|
@ -65,7 +65,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max_set_input_unlocked(struct dvb_frontend *fe, int in);
|
static int max_set_input(struct dvb_frontend *fe, int in);
|
||||||
|
|
||||||
static int max_emulate_switch(struct dvb_frontend *fe,
|
static int max_emulate_switch(struct dvb_frontend *fe,
|
||||||
u8 *cmd, u32 len)
|
u8 *cmd, u32 len)
|
||||||
@ -79,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
input = cmd[3] & 3;
|
input = cmd[3] & 3;
|
||||||
max_set_input_unlocked(fe, input);
|
max_set_input(fe, input);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (fmode == 4)
|
if (fmode == 4)
|
||||||
max_emulate_switch(fe, cmd->msg, cmd->msg_len);
|
if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (dvb->diseqc_send_master_cmd)
|
if (dvb->diseqc_send_master_cmd)
|
||||||
dvb->diseqc_send_master_cmd(fe, cmd);
|
dvb->diseqc_send_master_cmd(fe, cmd);
|
||||||
|
@ -60,10 +60,6 @@ static int mci_reset(struct ddb_link *link)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,6 +359,7 @@ struct mci_result {
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
u32 result[27];
|
u32 result[27];
|
||||||
|
u8 result8[27 * 4];
|
||||||
struct {
|
struct {
|
||||||
u8 Rsvd0[3];
|
u8 Rsvd0[3];
|
||||||
u8 Flags;
|
u8 Flags;
|
||||||
@ -758,6 +759,8 @@ struct mci_result {
|
|||||||
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
|
#define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01)
|
||||||
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
|
#define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01)
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
struct mci_base {
|
struct mci_base {
|
||||||
struct list_head mci_list;
|
struct list_head mci_list;
|
||||||
void *key;
|
void *key;
|
||||||
@ -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_sx8_cfg;
|
||||||
extern struct mci_cfg ddb_max_m4_cfg;
|
extern struct mci_cfg ddb_max_m4_cfg;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,10 @@ static int default_mod = 3;
|
|||||||
module_param(default_mod, int, 0444);
|
module_param(default_mod, int, 0444);
|
||||||
MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)");
|
MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)");
|
||||||
|
|
||||||
|
static int direct_mode;
|
||||||
|
module_param(direct_mode, int, 0444);
|
||||||
|
MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate.");
|
||||||
|
|
||||||
static const u32 MCLK = (1550000000 / 12);
|
static const u32 MCLK = (1550000000 / 12);
|
||||||
|
|
||||||
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
|
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
|
||||||
@ -44,25 +48,19 @@ struct sx8_base {
|
|||||||
struct mci_base mci_base;
|
struct mci_base mci_base;
|
||||||
|
|
||||||
u8 tuner_use_count[SX8_TUNER_NUM];
|
u8 tuner_use_count[SX8_TUNER_NUM];
|
||||||
u32 gain_mode[SX8_TUNER_NUM];
|
|
||||||
|
|
||||||
u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
|
u32 used_ldpc_bitrate[SX8_DEMOD_NUM];
|
||||||
u8 demod_in_use[SX8_DEMOD_NUM];
|
u8 demod_in_use[SX8_DEMOD_NUM];
|
||||||
u32 iq_mode;
|
u32 iq_mode;
|
||||||
u32 burst_size;
|
|
||||||
u32 direct_mode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sx8 {
|
struct sx8 {
|
||||||
struct mci mci;
|
struct mci mci;
|
||||||
|
struct mutex lock;
|
||||||
|
|
||||||
int first_time_lock;
|
int first_time_lock;
|
||||||
int started;
|
int started;
|
||||||
int iq_started;
|
int iq_started;
|
||||||
|
|
||||||
u32 bb_mode;
|
|
||||||
u32 local_frequency;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 dvbs2_bits_per_symbol[] = {
|
static const u8 dvbs2_bits_per_symbol[] = {
|
||||||
@ -126,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)
|
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||||
{
|
{
|
||||||
int stat;
|
int stat = 0;
|
||||||
struct sx8 *state = fe->demodulator_priv;
|
struct sx8 *state = fe->demodulator_priv;
|
||||||
struct mci_base *mci_base = state->mci.base;
|
struct mci_base *mci_base = state->mci.base;
|
||||||
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
||||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||||
struct mci_result res;
|
struct mci_result res;
|
||||||
|
|
||||||
|
*status = 0x00;
|
||||||
|
mutex_lock(&state->lock);
|
||||||
|
if (!state->started && !state->iq_started)
|
||||||
|
goto unlock;
|
||||||
stat = ddb_mci_get_status(&state->mci, &res);
|
stat = ddb_mci_get_status(&state->mci, &res);
|
||||||
if (stat)
|
if (stat)
|
||||||
return stat;
|
goto unlock;
|
||||||
if (sx8_base->iq_mode >= 2) {
|
|
||||||
*status = 0x1f;
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
*status = 0x00;
|
|
||||||
ddb_mci_get_info(&state->mci);
|
ddb_mci_get_info(&state->mci);
|
||||||
if (res.status == SX8_DEMOD_WAIT_MATYPE)
|
if (stat)
|
||||||
*status = 0x0f;
|
goto unlock;
|
||||||
if (res.status == MCI_DEMOD_LOCKED) {
|
if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) {
|
||||||
*status = 0x1f;
|
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI |
|
||||||
if (state->mci.signal_info.dvbs2_signal_info.standard == 2) {
|
FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||||
|
if (res.status == MCI_DEMOD_LOCKED) {
|
||||||
mutex_lock(&mci_base->tuner_lock);
|
mutex_lock(&mci_base->tuner_lock);
|
||||||
if (state->started)
|
if (state->first_time_lock && state->started) {
|
||||||
sx8_base->used_ldpc_bitrate[state->mci.nr] =
|
if (state->mci.signal_info.dvbs2_signal_info.standard == 2) {
|
||||||
p->symbol_rate *
|
sx8_base->used_ldpc_bitrate[state->mci.nr] =
|
||||||
dvbs2_bits_per_symbol[
|
p->symbol_rate *
|
||||||
state->mci.signal_info.
|
dvbs2_bits_per_symbol[
|
||||||
dvbs2_signal_info.pls_code];
|
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);
|
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;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,14 +172,12 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on,
|
|||||||
u8 flags, u8 gain)
|
u8 flags, u8 gain)
|
||||||
{
|
{
|
||||||
struct sx8 *state = fe->demodulator_priv;
|
struct sx8 *state = fe->demodulator_priv;
|
||||||
struct mci_base *mci_base = state->mci.base;
|
|
||||||
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
|
||||||
struct mci_command cmd;
|
struct mci_command cmd;
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.tuner = state->mci.tuner;
|
cmd.tuner = state->mci.tuner;
|
||||||
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
|
cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE;
|
||||||
cmd.sx8_input_enable.flags = flags;//sx8_base->gain_mode[state->mci.tuner];
|
cmd.sx8_input_enable.flags = flags;
|
||||||
cmd.sx8_input_enable.rf_gain = gain;
|
cmd.sx8_input_enable.rf_gain = gain;
|
||||||
return ddb_mci_cmd(&state->mci, &cmd, NULL);
|
return ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
}
|
}
|
||||||
@ -202,9 +207,9 @@ static int stop_iq(struct dvb_frontend *fe)
|
|||||||
state->mci.demod = SX8_DEMOD_NONE;
|
state->mci.demod = SX8_DEMOD_NONE;
|
||||||
}
|
}
|
||||||
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
||||||
|
mutex_unlock(&mci_base->tuner_lock);
|
||||||
sx8_base->iq_mode = 0;
|
sx8_base->iq_mode = 0;
|
||||||
state->iq_started = 0;
|
state->iq_started = 0;
|
||||||
mutex_unlock(&mci_base->tuner_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +219,13 @@ static int stop(struct dvb_frontend *fe)
|
|||||||
struct mci_base *mci_base = state->mci.base;
|
struct mci_base *mci_base = state->mci.base;
|
||||||
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
||||||
struct mci_command cmd;
|
struct mci_command cmd;
|
||||||
u32 input = state->mci.tuner;
|
u32 input;
|
||||||
|
|
||||||
|
input = state->mci.tuner;
|
||||||
if (!state->started)
|
if (!state->started)
|
||||||
return -1;
|
return -1;
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
|
||||||
if (state->mci.demod != SX8_DEMOD_NONE) {
|
if (state->mci.demod != SX8_DEMOD_NONE) {
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.command = MCI_CMD_STOP;
|
cmd.command = MCI_CMD_STOP;
|
||||||
cmd.demod = state->mci.demod;
|
cmd.demod = state->mci.demod;
|
||||||
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
@ -241,8 +247,8 @@ static int stop(struct dvb_frontend *fe)
|
|||||||
}
|
}
|
||||||
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
||||||
sx8_base->iq_mode = 0;
|
sx8_base->iq_mode = 0;
|
||||||
mutex_unlock(&mci_base->tuner_lock);
|
|
||||||
state->started = 0;
|
state->started = 0;
|
||||||
|
mutex_unlock(&mci_base->tuner_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +266,10 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
|
|||||||
u32 bits_per_symbol = 0;
|
u32 bits_per_symbol = 0;
|
||||||
int i = -1, stat = 0;
|
int i = -1, stat = 0;
|
||||||
struct ddb_link *link = state->mci.base->link;
|
struct ddb_link *link = state->mci.base->link;
|
||||||
|
const u8 ro_lut[8] = {
|
||||||
|
8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0,
|
||||||
|
8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0,
|
||||||
|
};
|
||||||
|
|
||||||
if (link->ids.device == 0x000b) {
|
if (link->ids.device == 0x000b) {
|
||||||
/* Mask out higher modulations and MIS for Basic
|
/* Mask out higher modulations and MIS for Basic
|
||||||
@ -287,7 +297,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sx8_base->direct_mode) {
|
if (direct_mode) {
|
||||||
if (p->symbol_rate >= MCLK / 2) {
|
if (p->symbol_rate >= MCLK / 2) {
|
||||||
if (state->mci.nr < 4)
|
if (state->mci.nr < 4)
|
||||||
i = state->mci.nr;
|
i = state->mci.nr;
|
||||||
@ -316,9 +326,8 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
|
|||||||
stat = -EBUSY;
|
stat = -EBUSY;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
modmask &= ((1 << (bits_per_symbol - 1)) - 1);
|
modmask &= ((1 << (bits_per_symbol - 1)) - 1);
|
||||||
if( ((flags & 0x02) != 0) && (modmask == 0)) {
|
if (((flags & 0x02) != 0) && (modmask == 0)) {
|
||||||
stat = -EBUSY;
|
stat = -EBUSY;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
@ -344,11 +353,10 @@ unlock:
|
|||||||
if (stat)
|
if (stat)
|
||||||
return stat;
|
return stat;
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
|
||||||
if (sx8_base->iq_mode) {
|
if (sx8_base->iq_mode) {
|
||||||
cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
|
cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
|
||||||
cmd.demod = state->mci.demod;
|
cmd.demod = state->mci.demod;
|
||||||
cmd.output = p->stream_id & 7;
|
cmd.output = p->stream_id & 0x0f;
|
||||||
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
ddb_mci_tsconfig(&state->mci, ts_config);
|
ddb_mci_tsconfig(&state->mci, ts_config);
|
||||||
}
|
}
|
||||||
@ -364,6 +372,7 @@ unlock:
|
|||||||
cmd.command = MCI_CMD_SEARCH_DVBS;
|
cmd.command = MCI_CMD_SEARCH_DVBS;
|
||||||
cmd.dvbs2_search.flags = flags;
|
cmd.dvbs2_search.flags = flags;
|
||||||
cmd.dvbs2_search.s2_modulation_mask = modmask;
|
cmd.dvbs2_search.s2_modulation_mask = modmask;
|
||||||
|
cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7];
|
||||||
cmd.dvbs2_search.retry = 2;
|
cmd.dvbs2_search.retry = 2;
|
||||||
cmd.dvbs2_search.frequency = p->frequency * 1000;
|
cmd.dvbs2_search.frequency = p->frequency * 1000;
|
||||||
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
|
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
|
||||||
@ -377,6 +386,9 @@ unlock:
|
|||||||
(p->stream_id & 0x80000000))
|
(p->stream_id & 0x80000000))
|
||||||
cmd.output |= 0x80;
|
cmd.output |= 0x80;
|
||||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
|
state->started = 1;
|
||||||
|
state->first_time_lock = 1;
|
||||||
|
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
||||||
if (stat)
|
if (stat)
|
||||||
stop(fe);
|
stop(fe);
|
||||||
return stat;
|
return stat;
|
||||||
@ -395,8 +407,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
|
|||||||
u32 input = state->mci.tuner;
|
u32 input = state->mci.tuner;
|
||||||
int i, stat = 0;
|
int i, stat = 0;
|
||||||
|
|
||||||
|
mutex_lock(&mci_base->tuner_lock);
|
||||||
if (!state->iq_started) {
|
if (!state->iq_started) {
|
||||||
mutex_lock(&mci_base->tuner_lock);
|
|
||||||
if (sx8_base->iq_mode) {
|
if (sx8_base->iq_mode) {
|
||||||
stat = -EBUSY;
|
stat = -EBUSY;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@ -409,17 +421,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
state->mci.demod = 0;
|
state->mci.demod = 0;
|
||||||
/*
|
|
||||||
if (!sx8_base->tuner_use_count[input])
|
|
||||||
mci_set_tuner(fe, input, 1);
|
|
||||||
*/
|
|
||||||
sx8_base->tuner_use_count[input]++;
|
sx8_base->tuner_use_count[input]++;
|
||||||
sx8_base->iq_mode = 2;
|
sx8_base->iq_mode = 2;
|
||||||
unlock:
|
} else {
|
||||||
mutex_unlock(&mci_base->tuner_lock);
|
if ((state->iq_started & 0x07) != state->mci.nr) {
|
||||||
if (stat)
|
stat = -EBUSY;
|
||||||
return stat;
|
goto unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&mci_base->tuner_lock);
|
||||||
|
if (stat)
|
||||||
|
return stat;
|
||||||
mci_set_tuner(fe, input, 1, flags & 0xff, 0);
|
mci_set_tuner(fe, input, 1, flags & 0xff, 0);
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.command = SX8_CMD_START_IQ;
|
cmd.command = SX8_CMD_START_IQ;
|
||||||
@ -431,6 +444,9 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
|
|||||||
cmd.tuner = state->mci.tuner;
|
cmd.tuner = state->mci.tuner;
|
||||||
cmd.demod = state->mci.demod;
|
cmd.demod = state->mci.demod;
|
||||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
|
state->iq_started = 8 | state->mci.nr;
|
||||||
|
state->first_time_lock = 1;
|
||||||
|
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
||||||
if (stat)
|
if (stat)
|
||||||
stop_iq(fe);
|
stop_iq(fe);
|
||||||
ddb_mci_tsconfig(&state->mci, ts_config);
|
ddb_mci_tsconfig(&state->mci, ts_config);
|
||||||
@ -443,7 +459,6 @@ static int set_lna(struct dvb_frontend *fe)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int set_parameters(struct dvb_frontend *fe)
|
static int set_parameters(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
@ -459,6 +474,7 @@ static int set_parameters(struct dvb_frontend *fe)
|
|||||||
state->mci.input->con = ts_mode << 8;
|
state->mci.input->con = ts_mode << 8;
|
||||||
if (iq_mode)
|
if (iq_mode)
|
||||||
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
|
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
|
||||||
|
mutex_lock(&state->lock);
|
||||||
stop(fe);
|
stop(fe);
|
||||||
if (iq_mode < 2) {
|
if (iq_mode < 2) {
|
||||||
u32 mask;
|
u32 mask;
|
||||||
@ -485,19 +501,10 @@ static int set_parameters(struct dvb_frontend *fe)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stat = start(fe, 3, mask, ts_config);
|
stat = start(fe, 3, mask, ts_config);
|
||||||
if (!stat) {
|
|
||||||
state->started = 1;
|
|
||||||
state->first_time_lock = 1;
|
|
||||||
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
stat = start_iq(fe, isi & 0xffffff, 4, ts_config);
|
stat = start_iq(fe, isi & 0xffffff, 4, ts_config);
|
||||||
if (!stat) {
|
|
||||||
state->iq_started = 1;
|
|
||||||
state->first_time_lock = 1;
|
|
||||||
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&state->lock);
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,16 +543,22 @@ static int set_input(struct dvb_frontend *fe, int input)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (state->mci.tuner == input)
|
if (state->mci.tuner == input)
|
||||||
return 0;
|
return 0;
|
||||||
|
mutex_lock(&state->lock);
|
||||||
stop_iq(fe);
|
stop_iq(fe);
|
||||||
stop(fe);
|
stop(fe);
|
||||||
state->mci.tuner = p->input = input;
|
state->mci.tuner = p->input = input;
|
||||||
|
mutex_unlock(&state->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sleep(struct dvb_frontend *fe)
|
static int sleep(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
|
struct sx8 *state = fe->demodulator_priv;
|
||||||
|
|
||||||
|
mutex_lock(&state->lock);
|
||||||
stop_iq(fe);
|
stop_iq(fe);
|
||||||
stop(fe);
|
stop(fe);
|
||||||
|
mutex_unlock(&state->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,6 +604,7 @@ static int init(struct mci *mci)
|
|||||||
state->mci.demod = SX8_DEMOD_NONE;
|
state->mci.demod = SX8_DEMOD_NONE;
|
||||||
mci->fe.ops.xbar[1] = mci->nr;
|
mci->fe.ops.xbar[1] = mci->nr;
|
||||||
mci->fe.dtv_property_cache.input = mci->tuner;
|
mci->fe.dtv_property_cache.input = mci->tuner;
|
||||||
|
mutex_init(&state->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val)
|
|||||||
return write_reg(state, field >> 16, new);
|
return write_reg(state, field >> 16, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_field(struct stv *state, u32 field, u8 *val)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
u8 shift, mask;
|
||||||
|
|
||||||
|
status = read_reg(state, field >> 16, val);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
mask = field & 0xff;
|
||||||
|
shift = (field >> 12) & 0xf;
|
||||||
|
*val = (*val & mask) >> shift;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
#define set_field(_reg, _val) \
|
#define set_field(_reg, _val) \
|
||||||
write_field(state, state->nr ? FSTV0910_P2_##_reg : \
|
write_field(state, state->nr ? FSTV0910_P2_##_reg : \
|
||||||
FSTV0910_P1_##_reg, _val)
|
FSTV0910_P1_##_reg, _val)
|
||||||
|
|
||||||
|
#define get_field(_reg, _val) \
|
||||||
|
read_field(state, state->nr ? FSTV0910_P2_##_reg : \
|
||||||
|
FSTV0910_P1_##_reg, _val)
|
||||||
|
|
||||||
#define set_reg(_reg, _val) \
|
#define set_reg(_reg, _val) \
|
||||||
write_reg(state, state->nr ? RSTV0910_P2_##_reg : \
|
write_reg(state, state->nr ? RSTV0910_P2_##_reg : \
|
||||||
RSTV0910_P1_##_reg, _val)
|
RSTV0910_P1_##_reg, _val)
|
||||||
|
|
||||||
#define get_reg(_reg, _val) \
|
#define get_reg(_reg, _val) \
|
||||||
read_reg(state, state->nr ? RSTV0910_P2_##_reg : \
|
read_reg(state, state->nr ? RSTV0910_P2_##_reg : \
|
||||||
RTV0910_P1_##_reg, _val)
|
RSTV0910_P1_##_reg, _val)
|
||||||
|
|
||||||
static const struct slookup s1_sn_lookup[] = {
|
static const struct slookup s1_sn_lookup[] = {
|
||||||
{ 0, 9242 }, /* C/N= 0dB */
|
{ 0, 9242 }, /* C/N= 0dB */
|
||||||
@ -1112,8 +1130,9 @@ static int init_diseqc(struct stv *state)
|
|||||||
u16 offs = state->nr ? 0x40 : 0; /* Address offset */
|
u16 offs = state->nr ? 0x40 : 0; /* Address offset */
|
||||||
u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32));
|
u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32));
|
||||||
|
|
||||||
/* Disable receiver */
|
write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05);
|
||||||
write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00);
|
//write_reg(state, RSTV0910_P1_DISRXF220 + offs, 0x69); 2b?
|
||||||
|
|
||||||
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */
|
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */
|
||||||
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */
|
write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */
|
||||||
write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq);
|
write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq);
|
||||||
@ -1617,12 +1636,28 @@ static int wait_dis(struct stv *state, u8 flag, u8 val)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int clear_slave(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct stv *state = fe->demodulator_priv;
|
||||||
|
u8 n, d, done;
|
||||||
|
|
||||||
|
get_field(RXEND, &done);
|
||||||
|
get_reg(DISRXBYTES, &n);
|
||||||
|
printk("clear: done = %u, %u fifo bytes\n", done, n);
|
||||||
|
|
||||||
|
for (get_reg(DISRXBYTES, &n); n; n--)
|
||||||
|
get_reg(DISRXFIFO, &d);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int send_master_cmd(struct dvb_frontend *fe,
|
static int send_master_cmd(struct dvb_frontend *fe,
|
||||||
struct dvb_diseqc_master_cmd *cmd)
|
struct dvb_diseqc_master_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct stv *state = fe->demodulator_priv;
|
struct stv *state = fe->demodulator_priv;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
clear_slave(fe);
|
||||||
|
set_field(DISRX_ON, 0);
|
||||||
set_reg(DISTXCFG, 0x3e);
|
set_reg(DISTXCFG, 0x3e);
|
||||||
for (i = 0; i < cmd->msg_len; i++) {
|
for (i = 0; i < cmd->msg_len; i++) {
|
||||||
wait_dis(state, 0x40, 0x00);
|
wait_dis(state, 0x40, 0x00);
|
||||||
@ -1630,12 +1665,59 @@ static int send_master_cmd(struct dvb_frontend *fe,
|
|||||||
}
|
}
|
||||||
set_reg(DISTXCFG, 0x3a);
|
set_reg(DISTXCFG, 0x3a);
|
||||||
wait_dis(state, 0x20, 0x20);
|
wait_dis(state, 0x20, 0x20);
|
||||||
|
set_field(DISRX_ON, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recv_slave_reply(struct dvb_frontend *fe,
|
static int recv_slave_reply(struct dvb_frontend *fe,
|
||||||
struct dvb_diseqc_slave_reply *reply)
|
struct dvb_diseqc_slave_reply *reply)
|
||||||
{
|
{
|
||||||
|
struct stv *state = fe->demodulator_priv;
|
||||||
|
int i, to, flag = 0, max = sizeof(reply->msg);
|
||||||
|
u8 done, val, n = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
get_reg(DISRXBYTES, &val);
|
||||||
|
get_field(RXEND, &done);
|
||||||
|
printk("slave: done = %u, %u fifo bytes\n", done, val);
|
||||||
|
#endif
|
||||||
|
to = reply->timeout;
|
||||||
|
if (to < 0) {
|
||||||
|
to = 100;
|
||||||
|
flag = 1;
|
||||||
|
} else if (to > 5000)
|
||||||
|
to = 100;
|
||||||
|
reply->msg_len = 0;
|
||||||
|
for (i = 0; i < to; i += 10) {
|
||||||
|
get_reg(DISRXBYTES, &val);
|
||||||
|
if (flag && val)
|
||||||
|
break;
|
||||||
|
get_field(RXEND, &done);
|
||||||
|
if (val >= max || done)
|
||||||
|
break;
|
||||||
|
msleep(10);
|
||||||
|
}
|
||||||
|
get_reg(DISRXBYTES, &val);
|
||||||
|
printk("done = %u, %u fifo bytes, i=%u\n", done, val, i);
|
||||||
|
if (i == to && !val)
|
||||||
|
return -EIO;
|
||||||
|
if (done && !val)
|
||||||
|
return -EIO;
|
||||||
|
for (i = 100; i; i--) {
|
||||||
|
get_field(RXEND, &done);
|
||||||
|
|
||||||
|
for (get_reg(DISRXBYTES, &n); n; n--) {
|
||||||
|
if (reply->msg_len == max)
|
||||||
|
return 0;
|
||||||
|
get_reg(DISRXFIFO, &reply->msg[reply->msg_len++]);
|
||||||
|
}
|
||||||
|
if (!n || done)
|
||||||
|
break;
|
||||||
|
msleep(10);
|
||||||
|
}
|
||||||
|
if (!i)
|
||||||
|
return -EIO;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 -`
|
||||||
|
|
@ -271,7 +271,7 @@ int main(int argc, char **argv)
|
|||||||
struct dddvb_fe *fe;
|
struct dddvb_fe *fe;
|
||||||
struct dddvb_params p;
|
struct dddvb_params p;
|
||||||
uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
|
uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
|
||||||
uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0;
|
uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = DDDVB_UNDEF;
|
||||||
uint32_t mtype= DDDVB_UNDEF;
|
uint32_t mtype= DDDVB_UNDEF;
|
||||||
uint32_t verbosity = 0;
|
uint32_t verbosity = 0;
|
||||||
uint32_t get_ts = 1;
|
uint32_t get_ts = 1;
|
||||||
|
@ -288,7 +288,8 @@ static int tune_sat(struct dddvb_fe *fe)
|
|||||||
freq = lofs - freq;
|
freq = lofs - freq;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (freq > 2100000) {
|
|
||||||
|
if (freq > 3000000) {
|
||||||
if (lofs)
|
if (lofs)
|
||||||
hi = (freq > lofs) ? 1 : 0;
|
hi = (freq > lofs) ? 1 : 0;
|
||||||
if (hi)
|
if (hi)
|
||||||
@ -318,14 +319,15 @@ static int tune_sat(struct dddvb_fe *fe)
|
|||||||
fe->scif_slot, fe->scif_freq, ds);
|
fe->scif_slot, fe->scif_freq, ds);
|
||||||
pthread_mutex_unlock(&fe->dd->uni_lock);
|
pthread_mutex_unlock(&fe->dd->uni_lock);
|
||||||
} else {
|
} else {
|
||||||
uint32_t input = lnb;
|
uint32_t input = fe->param.param[PARAM_SRC];
|
||||||
|
|
||||||
//if (input != DDDVB_UNDEF)
|
if (input != DDDVB_UNDEF) {
|
||||||
// input = 3 & (input >> 6);
|
input = 3 & (input >> 6);
|
||||||
//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6));
|
printf("input = %u\n", input);
|
||||||
|
}
|
||||||
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
|
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
|
||||||
//set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);
|
set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);
|
||||||
set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U));
|
//set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, DDDVB_UNDEF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,6 +752,8 @@ int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p)
|
|||||||
memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param));
|
memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param));
|
||||||
fe->n_tune = 1;
|
fe->n_tune = 1;
|
||||||
pthread_mutex_unlock(&fe->mutex);
|
pthread_mutex_unlock(&fe->mutex);
|
||||||
|
while(fe->n_tune) usleep(10000);
|
||||||
|
while(fe->tune != 2) usleep(10000);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user