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
fc043cc914
@ -274,7 +274,7 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
|
|||||||
if (res->status == MCI_DEMOD_LOCKED) {
|
if (res->status == MCI_DEMOD_LOCKED) {
|
||||||
switch (res->mode) {
|
switch (res->mode) {
|
||||||
case 0:
|
case 0:
|
||||||
case M4_MODE_DVBSX:
|
case MX_MODE_DVBSX:
|
||||||
if (res->dvbs2_signal_info.standard != 1) {
|
if (res->dvbs2_signal_info.standard != 1) {
|
||||||
int short_frame = 0, pilots = 0;
|
int short_frame = 0, pilots = 0;
|
||||||
char *modcod = "unknown";
|
char *modcod = "unknown";
|
||||||
@ -308,10 +308,10 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
|
|||||||
}
|
}
|
||||||
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
|
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
|
||||||
break;
|
break;
|
||||||
case M4_MODE_DVBT:
|
case MX_MODE_DVBT:
|
||||||
printf("Locked DVB-T\n");
|
printf("Locked DVB-T\n");
|
||||||
break;
|
break;
|
||||||
case M4_MODE_DVBT2:
|
case MX_MODE_DVBT2:
|
||||||
printf("Locked DVB-T2\n");
|
printf("Locked DVB-T2\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1137,11 +1137,6 @@ void set_dvbc_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (set_property(fd, MODULATOR_PCR_MODE, 0) < 0){
|
|
||||||
fprintf(stderr,"setting pcr mode 0 failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
freq += 8000000;
|
freq += 8000000;
|
||||||
close(fd);
|
close(fd);
|
||||||
free(device);
|
free(device);
|
||||||
|
@ -1362,7 +1362,7 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
|
|||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
printf("%02x ", Id[i]);
|
printf("%02x ", Id[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2cread(int dev, int argc, char* argv[], uint32_t Flags)
|
int i2cread(int dev, int argc, char* argv[], uint32_t Flags)
|
||||||
|
@ -36,6 +36,7 @@ static int update_flash(struct ddflash *ddf)
|
|||||||
char *fname, *default_fname;
|
char *fname, *default_fname;
|
||||||
int res, stat = 0;
|
int res, stat = 0;
|
||||||
char *name = 0, *dname;
|
char *name = 0, *dname;
|
||||||
|
uint32_t imgadr = 0x10000;
|
||||||
|
|
||||||
switch (ddf->id.device) {
|
switch (ddf->id.device) {
|
||||||
case 0x300:
|
case 0x300:
|
||||||
@ -109,6 +110,14 @@ static int update_flash(struct ddflash *ddf)
|
|||||||
return stat;
|
return stat;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
if (!readreg(ddf->fd, (ddf->link << 28) | 0x10, &val)) {
|
||||||
|
//printf("reg0x10=%08x\n", val);
|
||||||
|
if ((val >> 24) == 5)
|
||||||
|
imgadr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
fname = ddf->fname;
|
fname = ddf->fname;
|
||||||
default_fname = devid2fname(ddf->id.device, &name);
|
default_fname = devid2fname(ddf->id.device, &name);
|
||||||
if (!fname)
|
if (!fname)
|
||||||
@ -119,7 +128,8 @@ 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, ddf->size / 2, 1, 0)) == 1)
|
printf("Address: %08x\n", imgadr);
|
||||||
|
if ((res = update_image(ddf, fname, imgadr, ddf->size / 2, 1, 0)) == 1)
|
||||||
stat |= 1;
|
stat |= 1;
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ static int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t le
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int flashdump(int ddb, int link, uint32_t addr, uint32_t len)
|
void flashdump(int ddb, int link, uint32_t addr, uint32_t len)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
@ -630,13 +630,14 @@ int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
|
|||||||
uint8_t cmd[260];
|
uint8_t cmd[260];
|
||||||
int i, j;
|
int i, j;
|
||||||
uint32_t flen, blen;
|
uint32_t flen, blen;
|
||||||
int blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
|
int blockerase;
|
||||||
|
|
||||||
blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
|
blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
|
||||||
if (blen % 0xff)
|
if (blen % 0xff)
|
||||||
blen = (blen + 0xff) & 0xffffff00;
|
blen = (blen + 0xff) & 0xffffff00;
|
||||||
//printf("blen = %u, flen = %u\n", blen, flen);
|
//printf("blen = %u, flen = %u\n", blen, flen);
|
||||||
setbuf(stdout, NULL);
|
setbuf(stdout, NULL);
|
||||||
|
blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
|
||||||
|
|
||||||
cmd[0] = 0x50; // EWSR
|
cmd[0] = 0x50; // EWSR
|
||||||
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
|
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
|
||||||
@ -927,7 +928,10 @@ static const struct devids ids[] = {
|
|||||||
DEV(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"),
|
DEV(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"),
|
||||||
DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"),
|
DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"),
|
||||||
DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.fpga"),
|
DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.fpga"),
|
||||||
|
DEV(0x0014, "Octopus CI M2", "DVBBridgeV3A_DD01_0014_CIM2.fpga"),
|
||||||
DEV(0x0020, "Octopus GT Mini", "DVBBridgeV2C_DD01_0020.fpga"),
|
DEV(0x0020, "Octopus GT Mini", "DVBBridgeV2C_DD01_0020.fpga"),
|
||||||
|
DEV(0x0022, "Octopus MAXM8", "DVBBridgeV3A_DD01_0022_M8.fpga"),
|
||||||
|
DEV(0x0024, "Octopus MAXM8A", "DVBBridgeV3A_DD01_0024_M8A.fpga"),
|
||||||
DEV(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"),
|
DEV(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"),
|
||||||
DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"),
|
DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"),
|
||||||
DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.fpga"),
|
DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.fpga"),
|
||||||
@ -1075,12 +1079,12 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
|
|||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
for (p = 0; p < fsize && buf[p]; p++) {
|
for (p = 0; p < fsize && buf[p]; p++) {
|
||||||
char *key = &buf[p], *val = NULL;
|
char *key = (char *) &buf[p], *val = NULL;
|
||||||
|
|
||||||
for (; p < fsize && buf[p] != 0x0a; p++) {
|
for (; p < fsize && buf[p] != 0x0a; p++) {
|
||||||
if (buf[p] == ':') {
|
if (buf[p] == ':') {
|
||||||
buf[p] = 0;
|
buf[p] = 0;
|
||||||
val = &buf[p + 1];
|
val = (char *) &buf[p + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (val == NULL || p == fsize)
|
if (val == NULL || p == fsize)
|
||||||
|
@ -4,9 +4,7 @@ ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbri
|
|||||||
|
|
||||||
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-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
|
||||||
|
|
||||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o
|
|
||||||
|
|
||||||
ifneq ($(KERNEL_DVB_CORE),y)
|
ifneq ($(KERNEL_DVB_CORE),y)
|
||||||
obj-$(CONFIG_DVB_OCTONET) += octonet.o
|
obj-$(CONFIG_DVB_OCTONET) += octonet.o
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
#
|
#
|
||||||
# Makefile for the ddbridge device driver
|
# Makefile for the ddbridge device driver
|
||||||
#
|
#
|
||||||
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/dvb-frontends -I$(KBUILD_EXTMOD)/tuners
|
|
||||||
|
|
||||||
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
|
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-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
|
||||||
|
|
||||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
||||||
|
|
||||||
obj-$(CONFIG_DVB_OCTONET) += octonet.o
|
obj-$(CONFIG_DVB_OCTONET) += octonet.o
|
||||||
|
|
||||||
#ccflags-y += -Idrivers/media/include/linux/
|
ccflags-y += -Idrivers/media/dvb-frontends/
|
||||||
#ccflags-y += -Idrivers/media/dvb-frontends/
|
ccflags-y += -Idrivers/media/tuners/
|
||||||
#ccflags-y += -Idrivers/media/tuners/
|
|
||||||
|
@ -32,7 +32,7 @@ static int wait_ci_ready(struct ddb_ci *ci)
|
|||||||
ndelay(500);
|
ndelay(500);
|
||||||
do {
|
do {
|
||||||
if (ddbreadl(ci->port->dev,
|
if (ddbreadl(ci->port->dev,
|
||||||
CI_CONTROL(ci->nr)) & CI_READY)
|
CI_CONTROL(ci)) & CI_READY)
|
||||||
break;
|
break;
|
||||||
usleep_range(1, 2);
|
usleep_range(1, 2);
|
||||||
if ((--count) == 0)
|
if ((--count) == 0)
|
||||||
@ -50,7 +50,7 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca,
|
|||||||
if (address > CI_BUFFER_SIZE)
|
if (address > CI_BUFFER_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
|
ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
|
||||||
CI_DO_READ_ATTRIBUTES(ci->nr));
|
CI_DO_READ_ATTRIBUTES(ci));
|
||||||
wait_ci_ready(ci);
|
wait_ci_ready(ci);
|
||||||
val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
|
val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
|
||||||
return val;
|
return val;
|
||||||
@ -62,7 +62,7 @@ static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
|
|||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
||||||
CI_DO_ATTRIBUTE_RW(ci->nr));
|
CI_DO_ATTRIBUTE_RW(ci));
|
||||||
wait_ci_ready(ci);
|
wait_ci_ready(ci);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -75,10 +75,10 @@ static int read_cam_control(struct dvb_ca_en50221 *ca,
|
|||||||
u32 res;
|
u32 res;
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, CI_READ_CMD | address,
|
ddbwritel(ci->port->dev, CI_READ_CMD | address,
|
||||||
CI_DO_IO_RW(ci->nr));
|
CI_DO_IO_RW(ci));
|
||||||
ndelay(500);
|
ndelay(500);
|
||||||
do {
|
do {
|
||||||
res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
|
res = ddbreadl(ci->port->dev, CI_READDATA(ci));
|
||||||
if (res & CI_READY)
|
if (res & CI_READY)
|
||||||
break;
|
break;
|
||||||
usleep_range(1, 2);
|
usleep_range(1, 2);
|
||||||
@ -94,7 +94,7 @@ static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
|
|||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
|
||||||
CI_DO_IO_RW(ci->nr));
|
CI_DO_IO_RW(ci));
|
||||||
wait_ci_ready(ci);
|
wait_ci_ready(ci);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -104,15 +104,15 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
|||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, CI_POWER_ON,
|
ddbwritel(ci->port->dev, CI_POWER_ON,
|
||||||
CI_CONTROL(ci->nr));
|
CI_CONTROL(ci));
|
||||||
msleep(300);
|
msleep(300);
|
||||||
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
|
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
|
||||||
CI_CONTROL(ci->nr));
|
CI_CONTROL(ci));
|
||||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
|
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
|
||||||
CI_CONTROL(ci->nr));
|
CI_CONTROL(ci));
|
||||||
usleep_range(20, 25);
|
usleep_range(20, 25);
|
||||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
|
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
|
||||||
CI_CONTROL(ci->nr));
|
CI_CONTROL(ci));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
|||||||
{
|
{
|
||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
|
ddbwritel(ci->port->dev, 0, CI_CONTROL(ci));
|
||||||
msleep(300);
|
msleep(300);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -128,17 +128,17 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
|||||||
static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
||||||
{
|
{
|
||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
|
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
|
||||||
|
|
||||||
ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
|
ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
|
||||||
CI_CONTROL(ci->nr));
|
CI_CONTROL(ci));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||||
{
|
{
|
||||||
struct ddb_ci *ci = ca->data;
|
struct ddb_ci *ci = ca->data;
|
||||||
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
|
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
|
|
||||||
if (val & CI_CAM_DETECT)
|
if (val & CI_CAM_DETECT)
|
||||||
@ -162,6 +162,8 @@ static struct dvb_ca_en50221 en_templ = {
|
|||||||
static void ci_attach(struct ddb_port *port)
|
static void ci_attach(struct ddb_port *port)
|
||||||
{
|
{
|
||||||
struct ddb_ci *ci;
|
struct ddb_ci *ci;
|
||||||
|
const struct ddb_info *info = port->dev->link[port->lnr].info;
|
||||||
|
u32 off = info->ci_base ? info->ci_base : 0x400;
|
||||||
|
|
||||||
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
|
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
|
||||||
if (!ci)
|
if (!ci)
|
||||||
@ -171,6 +173,7 @@ static void ci_attach(struct ddb_port *port)
|
|||||||
port->en = &ci->en;
|
port->en = &ci->en;
|
||||||
ci->port = port;
|
ci->port = port;
|
||||||
ci->nr = port->nr - 2;
|
ci->nr = port->nr - 2;
|
||||||
|
ci->regs = DDB_LINK_TAG(port->lnr) | (off + 32 * ci->nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DuoFlex Dual CI support */
|
/* DuoFlex Dual CI support */
|
||||||
|
@ -467,7 +467,7 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags)
|
|||||||
gap = output->port->gap;
|
gap = output->port->gap;
|
||||||
max_bitrate = 0;
|
max_bitrate = 0;
|
||||||
}
|
}
|
||||||
if (dev->link[0].info->type == DDB_OCTOPUS_CI && output->port->nr > 1) {
|
if (dev->link[0].info->ci_mask && output->port->nr > 1) {
|
||||||
*con = 0x10c;
|
*con = 0x10c;
|
||||||
if (dev->link[0].ids.regmapid >= 0x10003 && !(flags & 1)) {
|
if (dev->link[0].ids.regmapid >= 0x10003 && !(flags & 1)) {
|
||||||
if (!(flags & 2)) {
|
if (!(flags & 2)) {
|
||||||
@ -1122,6 +1122,9 @@ static int dummy_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
static void dummy_release(struct dvb_frontend *fe)
|
static void dummy_release(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
kfree(fe);
|
kfree(fe);
|
||||||
|
#ifdef CONFIG_MEDIA_ATTACH
|
||||||
|
__module_get(THIS_MODULE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum dvbfe_algo dummy_algo(struct dvb_frontend *fe)
|
static enum dvbfe_algo dummy_algo(struct dvb_frontend *fe)
|
||||||
@ -1170,11 +1173,7 @@ static int demod_attach_dummy(struct ddb_input *input)
|
|||||||
{
|
{
|
||||||
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
|
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
|
||||||
|
|
||||||
#if 0
|
|
||||||
dvb->fe = dvb_attach(dummy_attach);
|
|
||||||
#else
|
|
||||||
dvb->fe = dummy_attach();
|
dvb->fe = dummy_attach();
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,8 +1596,7 @@ static int dvb_register_adapters(struct ddb *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD ||
|
if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD ||
|
||||||
dev->link[0].info->type == DDB_OCTONET ||
|
dev->link[0].info->type == DDB_OCTONET) {
|
||||||
dev->link[0].info->type == DDB_OCTOPRO) {
|
|
||||||
port = &dev->port[0];
|
port = &dev->port[0];
|
||||||
adap = port->dvb[0].adap;
|
adap = port->dvb[0].adap;
|
||||||
ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
|
ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
|
||||||
@ -1840,6 +1838,9 @@ static int dvb_input_attach(struct ddb_input *input)
|
|||||||
break;
|
break;
|
||||||
case DDB_TUNER_MCI_SX8:
|
case DDB_TUNER_MCI_SX8:
|
||||||
case DDB_TUNER_MCI_M4:
|
case DDB_TUNER_MCI_M4:
|
||||||
|
case DDB_TUNER_MCI_M8:
|
||||||
|
case DDB_TUNER_MCI_M8A:
|
||||||
|
case DDB_TUNER_MCI_M2:
|
||||||
if (ddb_fe_attach_mci(input, port->type) < 0)
|
if (ddb_fe_attach_mci(input, port->type) < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
break;
|
break;
|
||||||
@ -2103,7 +2104,7 @@ static void ddb_port_probe(struct ddb_port *port)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI &&
|
if (port->nr == 1 && link->info->ci_mask &&
|
||||||
link->info->i2c_mask == 1) {
|
link->info->i2c_mask == 1) {
|
||||||
port->name = "NO TAB";
|
port->name = "NO TAB";
|
||||||
port->class = DDB_PORT_NONE;
|
port->class = DDB_PORT_NONE;
|
||||||
@ -2131,15 +2132,16 @@ static void ddb_port_probe(struct ddb_port *port)
|
|||||||
port->name = "DUAL MCI";
|
port->name = "DUAL MCI";
|
||||||
port->type_name = "MCI";
|
port->type_name = "MCI";
|
||||||
port->class = DDB_PORT_TUNER;
|
port->class = DDB_PORT_TUNER;
|
||||||
port->type = DDB_TUNER_MCI + link->info->mci_type;
|
port->type = link->info->mci_type;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->nr > 1 && link->info->type == DDB_OCTOPUS_CI) {
|
if (port->nr > 1 && (link->info->ci_mask & (1 << port->nr))) {
|
||||||
port->name = "CI internal";
|
port->name = "CI internal";
|
||||||
port->type_name = "INTERNAL";
|
port->type_name = "INTERNAL";
|
||||||
port->class = DDB_PORT_CI;
|
port->class = DDB_PORT_CI;
|
||||||
port->type = DDB_CI_INTERNAL;
|
port->type = DDB_CI_INTERNAL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!port->i2c)
|
if (!port->i2c)
|
||||||
@ -2717,24 +2719,28 @@ static void ddb_ports_init(struct ddb *dev)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (info->type) {
|
switch (info->type) {
|
||||||
case DDB_OCTOPUS_CI:
|
case DDB_OCTONET:
|
||||||
if (i >= 2) {
|
case DDB_OCTOPUS:
|
||||||
|
if (info->ci_mask & (1 << i)) {
|
||||||
ddb_input_init(port, 2 + i, 0, 2 + i);
|
ddb_input_init(port, 2 + i, 0, 2 + i);
|
||||||
ddb_input_init(port, 4 + i, 1, 4 + i);
|
ddb_input_init(port, 4 + i, 1, 4 + i);
|
||||||
ddb_output_init(port, i);
|
ddb_output_init(port, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fallthrough;
|
ddb_output_init(port, i);
|
||||||
case DDB_OCTONET:
|
ddb_input_init(port, 2 * i, 0, 2 * p);
|
||||||
case DDB_OCTOPUS:
|
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
|
||||||
case DDB_OCTOPRO:
|
|
||||||
ddb_input_init(port, 2 * i, 0, 2 * i);
|
|
||||||
ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
|
|
||||||
ddb_output_init(port, i);
|
ddb_output_init(port, i);
|
||||||
break;
|
break;
|
||||||
case DDB_OCTOPUS_MAX:
|
case DDB_OCTOPUS_MAX:
|
||||||
case DDB_OCTOPUS_MAX_CT:
|
case DDB_OCTOPUS_MAX_CT:
|
||||||
case DDB_OCTOPUS_MCI:
|
case DDB_OCTOPUS_MCI:
|
||||||
|
if (info->ci_mask & (1 << i)) {
|
||||||
|
ddb_input_init(port, 2 + i, 0, 2 + i);
|
||||||
|
ddb_input_init(port, 4 + i, 1, 4 + i);
|
||||||
|
ddb_output_init(port, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ddb_input_init(port, 2 * i, 0, 2 * p);
|
ddb_input_init(port, 2 * i, 0, 2 * p);
|
||||||
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
|
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
|
||||||
break;
|
break;
|
||||||
@ -4050,7 +4056,9 @@ static struct device_attribute ddb_attrs_fanspeed[] = {
|
|||||||
|
|
||||||
static struct class ddb_class = {
|
static struct class ddb_class = {
|
||||||
.name = "ddbridge",
|
.name = "ddbridge",
|
||||||
|
#if (KERNEL_VERSION(6, 4, 0) > LINUX_VERSION_CODE)
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
#endif
|
||||||
.devnode = ddb_devnode,
|
.devnode = ddb_devnode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -246,7 +246,6 @@ static const struct ddb_regmap octopus_map = {
|
|||||||
.odma = &octopus_odma,
|
.odma = &octopus_odma,
|
||||||
.odma_buf = &octopus_odma_buf,
|
.odma_buf = &octopus_odma_buf,
|
||||||
.input = &octopus_input,
|
.input = &octopus_input,
|
||||||
|
|
||||||
.output = &octopus_output,
|
.output = &octopus_output,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -463,23 +462,25 @@ static const struct ddb_info ddb_satixs2v3 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_ci = {
|
static const struct ddb_info ddb_ci = {
|
||||||
.type = DDB_OCTOPUS_CI,
|
.type = DDB_OCTOPUS,
|
||||||
.name = "Digital Devices Octopus CI",
|
.name = "Digital Devices Octopus CI",
|
||||||
.regmap = &octopus_map,
|
.regmap = &octopus_map,
|
||||||
.port_num = 4,
|
.port_num = 4,
|
||||||
.i2c_mask = 0x03,
|
.i2c_mask = 0x03,
|
||||||
|
.ci_mask = 0x0c,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_cis = {
|
static const struct ddb_info ddb_cis = {
|
||||||
.type = DDB_OCTOPUS_CI,
|
.type = DDB_OCTOPUS,
|
||||||
.name = "Digital Devices Octopus CI single",
|
.name = "Digital Devices Octopus CI single",
|
||||||
.regmap = &octopus_map,
|
.regmap = &octopus_map,
|
||||||
.port_num = 3,
|
.port_num = 3,
|
||||||
.i2c_mask = 0x03,
|
.i2c_mask = 0x03,
|
||||||
|
.ci_mask = 0x04,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_ci_s2_pro = {
|
static const struct ddb_info ddb_ci_s2_pro = {
|
||||||
.type = DDB_OCTOPUS_CI,
|
.type = DDB_OCTOPUS,
|
||||||
.name = "Digital Devices Octopus CI S2 Pro",
|
.name = "Digital Devices Octopus CI S2 Pro",
|
||||||
.regmap = &octopus_map,
|
.regmap = &octopus_map,
|
||||||
.port_num = 4,
|
.port_num = 4,
|
||||||
@ -487,10 +488,11 @@ static const struct ddb_info ddb_ci_s2_pro = {
|
|||||||
.board_control = 2,
|
.board_control = 2,
|
||||||
.board_control_2 = 4,
|
.board_control_2 = 4,
|
||||||
.hw_min = 0x010007,
|
.hw_min = 0x010007,
|
||||||
|
.ci_mask = 0x0c,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_ci_s2_pro_a = {
|
static const struct ddb_info ddb_ci_s2_pro_a = {
|
||||||
.type = DDB_OCTOPUS_CI,
|
.type = DDB_OCTOPUS,
|
||||||
.name = "Digital Devices Octopus CI S2 Pro Advanced",
|
.name = "Digital Devices Octopus CI S2 Pro Advanced",
|
||||||
.regmap = &octopus_map,
|
.regmap = &octopus_map,
|
||||||
.port_num = 4,
|
.port_num = 4,
|
||||||
@ -498,6 +500,7 @@ static const struct ddb_info ddb_ci_s2_pro_a = {
|
|||||||
.board_control = 2,
|
.board_control = 2,
|
||||||
.board_control_2 = 4,
|
.board_control_2 = 4,
|
||||||
.hw_min = 0x010007,
|
.hw_min = 0x010007,
|
||||||
|
.ci_mask = 0x0c,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_dvbct = {
|
static const struct ddb_info ddb_dvbct = {
|
||||||
@ -621,24 +624,6 @@ static const struct ddb_info ddb_sdr_dvbt = {
|
|||||||
.tempmon_irq = 8,
|
.tempmon_irq = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_octopro_hdin = {
|
|
||||||
.type = DDB_OCTOPRO_HDIN,
|
|
||||||
.name = "Digital Devices OctopusNet Pro HDIN",
|
|
||||||
.regmap = &octopro_hdin_map,
|
|
||||||
.port_num = 10,
|
|
||||||
.i2c_mask = 0x3ff,
|
|
||||||
.mdio_base = 0x10020,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct ddb_info ddb_octopro = {
|
|
||||||
.type = DDB_OCTOPRO,
|
|
||||||
.name = "Digital Devices OctopusNet Pro",
|
|
||||||
.regmap = &octopro_map,
|
|
||||||
.port_num = 10,
|
|
||||||
.i2c_mask = 0x3ff,
|
|
||||||
.mdio_base = 0x10020,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct ddb_info ddb_s2_48 = {
|
static const struct ddb_info ddb_s2_48 = {
|
||||||
.type = DDB_OCTOPUS_MAX,
|
.type = DDB_OCTOPUS_MAX,
|
||||||
.name = "Digital Devices MAX S8 4/8",
|
.name = "Digital Devices MAX S8 4/8",
|
||||||
@ -647,6 +632,7 @@ static const struct ddb_info ddb_s2_48 = {
|
|||||||
.i2c_mask = 0x01,
|
.i2c_mask = 0x01,
|
||||||
.board_control = 1,
|
.board_control = 1,
|
||||||
.tempmon_irq = 24,
|
.tempmon_irq = 24,
|
||||||
|
.lnb_base = 0x400,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_ct2_8 = {
|
static const struct ddb_info ddb_ct2_8 = {
|
||||||
@ -719,8 +705,9 @@ static const struct ddb_info ddb_s2x_48 = {
|
|||||||
.i2c_mask = 0x00,
|
.i2c_mask = 0x00,
|
||||||
.tempmon_irq = 24,
|
.tempmon_irq = 24,
|
||||||
.mci_ports = 4,
|
.mci_ports = 4,
|
||||||
.mci_type = 0,
|
.mci_type = DDB_TUNER_MCI_SX8,
|
||||||
.temp_num = 1,
|
.temp_num = 1,
|
||||||
|
.lnb_base = 0x400,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_s2x_48_b = {
|
static const struct ddb_info ddb_s2x_48_b = {
|
||||||
@ -731,8 +718,9 @@ static const struct ddb_info ddb_s2x_48_b = {
|
|||||||
.i2c_mask = 0x00,
|
.i2c_mask = 0x00,
|
||||||
.tempmon_irq = 24,
|
.tempmon_irq = 24,
|
||||||
.mci_ports = 4,
|
.mci_ports = 4,
|
||||||
.mci_type = 0,
|
.mci_type = DDB_TUNER_MCI_SX8,
|
||||||
.temp_num = 1,
|
.temp_num = 1,
|
||||||
|
.lnb_base = 0x400,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_m4 = {
|
static const struct ddb_info ddb_m4 = {
|
||||||
@ -743,8 +731,48 @@ static const struct ddb_info ddb_m4 = {
|
|||||||
.i2c_mask = 0x00,
|
.i2c_mask = 0x00,
|
||||||
.tempmon_irq = 24,
|
.tempmon_irq = 24,
|
||||||
.mci_ports = 2,
|
.mci_ports = 2,
|
||||||
.mci_type = 1,
|
.mci_type = DDB_TUNER_MCI_M4,
|
||||||
.temp_num = 1,
|
.temp_num = 1,
|
||||||
|
.lnb_base = 0x400,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ddb_info ddb_m8 = {
|
||||||
|
.type = DDB_OCTOPUS_MCI,
|
||||||
|
.name = "Digital Devices MAX M8",
|
||||||
|
.regmap = &octopus_mci_map,
|
||||||
|
.port_num = 4,
|
||||||
|
.i2c_mask = 0x00,
|
||||||
|
.tempmon_irq = 24,
|
||||||
|
.mci_ports = 4,
|
||||||
|
.mci_type = DDB_TUNER_MCI_M8,
|
||||||
|
.temp_num = 1,
|
||||||
|
.lnb_base = 0x400,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ddb_info ddb_m8a = {
|
||||||
|
.type = DDB_OCTOPUS_MCI,
|
||||||
|
.name = "Digital Devices MAX M8A",
|
||||||
|
.regmap = &octopus_mci_map,
|
||||||
|
.port_num = 4,
|
||||||
|
.tempmon_irq = 24,
|
||||||
|
.mci_ports = 4,
|
||||||
|
.mci_type = DDB_TUNER_MCI_M8A,
|
||||||
|
.temp_num = 1,
|
||||||
|
.lnb_base = 0x400,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ddb_info ddb_ci_m2 = {
|
||||||
|
.type = DDB_OCTOPUS_MCI,
|
||||||
|
.name = "Digital Devices Octopus CI M2",
|
||||||
|
.regmap = &octopus_mci_map,
|
||||||
|
.port_num = 4,
|
||||||
|
.tempmon_irq = 24,
|
||||||
|
.mci_ports = 1,
|
||||||
|
.mci_type = DDB_TUNER_MCI_M2,
|
||||||
|
.temp_num = 1,
|
||||||
|
.ci_mask = 0x0c,
|
||||||
|
.ci_base = 0x400,
|
||||||
|
.lnb_base = 0x480,
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@ -877,7 +905,10 @@ static const struct ddb_device_id ddb_device_ids[] = {
|
|||||||
DDB_DEVID(0x0012, 0x0042, ddb_ci),
|
DDB_DEVID(0x0012, 0x0042, ddb_ci),
|
||||||
DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro),
|
DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro),
|
||||||
DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a),
|
DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a),
|
||||||
|
DDB_DEVID(0x0014, 0x0045, ddb_ci_m2),
|
||||||
DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini),
|
DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini),
|
||||||
|
DDB_DEVID(0x0022, 0x0052, ddb_m8),
|
||||||
|
DDB_DEVID(0x0024, 0x0053, ddb_m8a),
|
||||||
|
|
||||||
/* Modulators */
|
/* Modulators */
|
||||||
DDB_DEVID(0x0201, 0x0001, ddb_mod),
|
DDB_DEVID(0x0201, 0x0001, ddb_mod),
|
||||||
|
@ -72,11 +72,12 @@ static int search_s2(struct dvb_frontend *fe)
|
|||||||
cmd.dvbs2_search.retry = 0;
|
cmd.dvbs2_search.retry = 0;
|
||||||
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;
|
||||||
cmd.dvbs2_search.scrambling_sequence_index = 0; //p->scrambling_sequence_index;
|
cmd.dvbs2_search.scrambling_sequence_index =
|
||||||
|
p->scrambling_sequence_index;
|
||||||
if (p->stream_id != NO_STREAM_ID_FILTER)
|
if (p->stream_id != NO_STREAM_ID_FILTER)
|
||||||
cmd.dvbs2_search.input_stream_id = p->stream_id;
|
cmd.dvbs2_search.input_stream_id = p->stream_id;
|
||||||
cmd.tuner = state->mci.nr;
|
cmd.tuner = state->mci.tuner;
|
||||||
cmd.demod = state->mci.tuner;
|
cmd.demod = state->mci.demod;
|
||||||
cmd.output = state->mci.nr;
|
cmd.output = state->mci.nr;
|
||||||
|
|
||||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
@ -404,7 +405,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
ddb_mci_get_strength(fe);
|
ddb_mci_get_strength(fe);
|
||||||
if (res.status == MCI_DEMOD_WAIT_SIGNAL)
|
if (res.status == MCI_DEMOD_WAIT_SIGNAL)
|
||||||
*status = 0x01;
|
*status = 0x01;
|
||||||
else if (res.status == M4_DEMOD_WAIT_TS)
|
else if (res.status == MX_DEMOD_WAIT_TS)
|
||||||
*status = 0x03;
|
*status = 0x03;
|
||||||
else if (res.status == MCI_DEMOD_TIMEOUT)
|
else if (res.status == MCI_DEMOD_TIMEOUT)
|
||||||
*status = FE_TIMEDOUT;
|
*status = FE_TIMEDOUT;
|
||||||
@ -456,6 +457,9 @@ static void release(struct dvb_frontend *fe)
|
|||||||
kfree(mci_base);
|
kfree(mci_base);
|
||||||
}
|
}
|
||||||
kfree(state);
|
kfree(state);
|
||||||
|
#ifdef CONFIG_MEDIA_ATTACH
|
||||||
|
__module_get(THIS_MODULE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
|
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
|
||||||
@ -525,7 +529,134 @@ static struct mci_cfg ddb_max_m4_cfg = {
|
|||||||
.base_init = base_init,
|
.base_init = base_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner)
|
static struct dvb_frontend_ops m_ops = {
|
||||||
|
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
|
||||||
|
SYS_ISDBC,
|
||||||
|
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
|
||||||
|
SYS_DVBS, SYS_DVBS2, SYS_ISDBS, },
|
||||||
|
.info = {
|
||||||
|
.name = "M_AS",
|
||||||
|
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||||
|
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||||
|
.symbol_rate_min = 100000,
|
||||||
|
.symbol_rate_max = 100000000,
|
||||||
|
.frequency_stepsize_hz = 0,
|
||||||
|
.frequency_tolerance_hz = 0,
|
||||||
|
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
|
||||||
|
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
|
||||||
|
FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_4_5 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
|
||||||
|
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
|
||||||
|
},
|
||||||
|
.release = release,
|
||||||
|
.get_frontend_algo = get_algo,
|
||||||
|
.get_frontend = get_frontend,
|
||||||
|
.read_status = read_status,
|
||||||
|
.tune = tune,
|
||||||
|
.sleep = sleep,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mci_cfg ddb_max_m_cfg = {
|
||||||
|
.type = 0,
|
||||||
|
.fe_ops = &m_ops,
|
||||||
|
.base_size = sizeof(struct m4_base),
|
||||||
|
.state_size = sizeof(struct m4),
|
||||||
|
.init = init,
|
||||||
|
.base_init = base_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops m_s_ops = {
|
||||||
|
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_ISDBS },
|
||||||
|
.info = {
|
||||||
|
.name = "M_S",
|
||||||
|
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||||
|
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||||
|
.symbol_rate_min = 100000,
|
||||||
|
.symbol_rate_max = 100000000,
|
||||||
|
.frequency_stepsize_hz = 0,
|
||||||
|
.frequency_tolerance_hz = 0,
|
||||||
|
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
|
||||||
|
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
|
||||||
|
FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_4_5 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
|
||||||
|
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
|
||||||
|
},
|
||||||
|
.release = release,
|
||||||
|
.get_frontend_algo = get_algo,
|
||||||
|
.get_frontend = get_frontend,
|
||||||
|
.read_status = read_status,
|
||||||
|
.tune = tune,
|
||||||
|
.sleep = sleep,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mci_cfg ddb_max_m_s_cfg = {
|
||||||
|
.type = 0,
|
||||||
|
.fe_ops = &m_s_ops,
|
||||||
|
.base_size = sizeof(struct m4_base),
|
||||||
|
.state_size = sizeof(struct m4),
|
||||||
|
.init = init,
|
||||||
|
.base_init = base_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops m_a_ops = {
|
||||||
|
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
|
||||||
|
SYS_ISDBC,
|
||||||
|
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
|
||||||
|
},
|
||||||
|
.info = {
|
||||||
|
.name = "M_A",
|
||||||
|
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
|
||||||
|
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
|
||||||
|
.symbol_rate_min = 100000,
|
||||||
|
.symbol_rate_max = 100000000,
|
||||||
|
.frequency_stepsize_hz = 0,
|
||||||
|
.frequency_tolerance_hz = 0,
|
||||||
|
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
|
||||||
|
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
|
||||||
|
FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_4_5 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
|
||||||
|
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
|
||||||
|
},
|
||||||
|
.release = release,
|
||||||
|
.get_frontend_algo = get_algo,
|
||||||
|
.get_frontend = get_frontend,
|
||||||
|
.read_status = read_status,
|
||||||
|
.tune = tune,
|
||||||
|
.sleep = sleep,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mci_cfg ddb_max_m_a_cfg = {
|
||||||
|
.type = 0,
|
||||||
|
.fe_ops = &m_a_ops,
|
||||||
|
.base_size = sizeof(struct m4_base),
|
||||||
|
.state_size = sizeof(struct m4),
|
||||||
|
.init = init,
|
||||||
|
.base_init = base_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mci_cfg *ddb_max_cfgs [] = {
|
||||||
|
&ddb_max_m4_cfg,
|
||||||
|
&ddb_max_m_a_cfg,
|
||||||
|
&ddb_max_m_s_cfg,
|
||||||
|
&ddb_max_m_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type)
|
||||||
{
|
{
|
||||||
return ddb_mci_attach(input, &ddb_max_m4_cfg, nr, tuner);
|
return ddb_mci_attach(input, ddb_max_cfgs[type], nr, tuner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(ddb_mx_attach);
|
||||||
|
|
||||||
|
@ -417,7 +417,10 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
|
|||||||
DDB_DEVICE_ANY(0x0011),
|
DDB_DEVICE_ANY(0x0011),
|
||||||
DDB_DEVICE_ANY(0x0012),
|
DDB_DEVICE_ANY(0x0012),
|
||||||
DDB_DEVICE_ANY(0x0013),
|
DDB_DEVICE_ANY(0x0013),
|
||||||
|
DDB_DEVICE_ANY(0x0014),
|
||||||
DDB_DEVICE_ANY(0x0020),
|
DDB_DEVICE_ANY(0x0020),
|
||||||
|
DDB_DEVICE_ANY(0x0022),
|
||||||
|
DDB_DEVICE_ANY(0x0024),
|
||||||
DDB_DEVICE_ANY(0x0201),
|
DDB_DEVICE_ANY(0x0201),
|
||||||
DDB_DEVICE_ANY(0x0203),
|
DDB_DEVICE_ANY(0x0203),
|
||||||
DDB_DEVICE_ANY(0x0210),
|
DDB_DEVICE_ANY(0x0210),
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
/* MAX LNB interface related module parameters */
|
/* MAX LNB interface related module parameters */
|
||||||
|
|
||||||
|
static int delmode;
|
||||||
|
module_param(delmode, int, 0444);
|
||||||
|
MODULE_PARM_DESC(delmode, "frontend delivery system mode");
|
||||||
|
|
||||||
static int fmode;
|
static int fmode;
|
||||||
module_param(fmode, int, 0444);
|
module_param(fmode, int, 0444);
|
||||||
MODULE_PARM_DESC(fmode, "frontend emulation mode");
|
MODULE_PARM_DESC(fmode, "frontend emulation mode");
|
||||||
@ -49,11 +53,12 @@ MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 2
|
|||||||
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
|
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
|
||||||
{
|
{
|
||||||
u32 c, v = 0, tag = DDB_LINK_TAG(link);
|
u32 c, v = 0, tag = DDB_LINK_TAG(link);
|
||||||
|
u32 base = dev->link[link].info->lnb_base;
|
||||||
|
|
||||||
v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb));
|
v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb));
|
||||||
ddbwritel(dev, cmd | v, tag | LNB_CONTROL(lnb));
|
ddbwritel(dev, cmd | v, tag | base | LNB_CONTROL(lnb));
|
||||||
for (c = 0; c < 10; c++) {
|
for (c = 0; c < 10; c++) {
|
||||||
v = ddbreadl(dev, tag | LNB_CONTROL(lnb));
|
v = ddbreadl(dev, tag | base | LNB_CONTROL(lnb));
|
||||||
if ((v & LNB_BUSY) == 0)
|
if ((v & LNB_BUSY) == 0)
|
||||||
break;
|
break;
|
||||||
msleep(20);
|
msleep(20);
|
||||||
@ -91,6 +96,7 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
|
|||||||
struct ddb *dev = port->dev;
|
struct ddb *dev = port->dev;
|
||||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||||
u32 tag = DDB_LINK_TAG(port->lnr);
|
u32 tag = DDB_LINK_TAG(port->lnr);
|
||||||
|
u32 base = dev->link[port->lnr].info->lnb_base;
|
||||||
int i;
|
int i;
|
||||||
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
||||||
|
|
||||||
@ -105,9 +111,9 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
|
|||||||
dvb->diseqc_send_master_cmd(fe, cmd);
|
dvb->diseqc_send_master_cmd(fe, cmd);
|
||||||
|
|
||||||
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
mutex_lock(&dev->link[port->lnr].lnb.lock);
|
||||||
ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(dvb->input));
|
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(dvb->input));
|
||||||
for (i = 0; i < cmd->msg_len; i++)
|
for (i = 0; i < cmd->msg_len; i++)
|
||||||
ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(dvb->input));
|
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(dvb->input));
|
||||||
lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
|
lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
|
||||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||||
return 0;
|
return 0;
|
||||||
@ -117,11 +123,12 @@ static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input,
|
|||||||
struct dvb_diseqc_master_cmd *cmd)
|
struct dvb_diseqc_master_cmd *cmd)
|
||||||
{
|
{
|
||||||
u32 tag = DDB_LINK_TAG(link);
|
u32 tag = DDB_LINK_TAG(link);
|
||||||
|
u32 base = dev->link[link].info->lnb_base;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(input));
|
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(input));
|
||||||
for (i = 0; i < cmd->msg_len; i++)
|
for (i = 0; i < cmd->msg_len; i++)
|
||||||
ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(input));
|
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(input));
|
||||||
lnb_command(dev, link, input, LNB_CMD_DISEQC);
|
lnb_command(dev, link, input, LNB_CMD_DISEQC);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -369,6 +376,7 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|||||||
struct ddb_port *port = input->port;
|
struct ddb_port *port = input->port;
|
||||||
struct ddb *dev = port->dev;
|
struct ddb *dev = port->dev;
|
||||||
u32 tag = DDB_LINK_TAG(port->lnr);
|
u32 tag = DDB_LINK_TAG(port->lnr);
|
||||||
|
u32 base = dev->link[port->lnr].info->lnb_base;
|
||||||
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
|
||||||
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
u32 fmode = dev->link[port->lnr].lnb.fmode;
|
||||||
|
|
||||||
@ -377,14 +385,14 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|||||||
default:
|
default:
|
||||||
case 0:
|
case 0:
|
||||||
case 3:
|
case 3:
|
||||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input));
|
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(dvb->input));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0));
|
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(0));
|
||||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1));
|
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(1));
|
||||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2));
|
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(2));
|
||||||
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3));
|
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(3));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
mutex_unlock(&dev->link[port->lnr].lnb.lock);
|
||||||
@ -501,7 +509,8 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
|
|||||||
/* MAX MCI related functions */
|
/* MAX MCI related functions */
|
||||||
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
|
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
|
||||||
int (**fn_set_input)(struct dvb_frontend *fe, int input));
|
int (**fn_set_input)(struct dvb_frontend *fe, int input));
|
||||||
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner);
|
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type);
|
||||||
|
|
||||||
|
|
||||||
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
||||||
{
|
{
|
||||||
@ -519,11 +528,46 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
|||||||
if (fm >= 3)
|
if (fm >= 3)
|
||||||
tuner = 0;
|
tuner = 0;
|
||||||
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
|
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
|
||||||
|
dvb->input = tuner;
|
||||||
break;
|
break;
|
||||||
case DDB_TUNER_MCI_M4:
|
case DDB_TUNER_MCI_M4:
|
||||||
fm = 0;
|
fm = 0;
|
||||||
dvb->fe = ddb_m4_attach(input, demod, tuner);
|
dvb->fe = ddb_mx_attach(input, demod, tuner, 0);
|
||||||
|
dvb->input = tuner;
|
||||||
break;
|
break;
|
||||||
|
case DDB_TUNER_MCI_M8:
|
||||||
|
fm = 3;
|
||||||
|
dvb->fe = ddb_mx_attach(input, demod, tuner, 1);
|
||||||
|
dvb->input = 0;
|
||||||
|
break;
|
||||||
|
case DDB_TUNER_MCI_M8A:
|
||||||
|
fm = 3;
|
||||||
|
dvb->fe = ddb_mx_attach(input, demod, tuner, 2);
|
||||||
|
dvb->input = 0;
|
||||||
|
break;
|
||||||
|
case DDB_TUNER_MCI_M2:
|
||||||
|
{
|
||||||
|
u32 mode, mmode;
|
||||||
|
|
||||||
|
// delmode: 0 - sat,sat 1-cable,cable/sat
|
||||||
|
switch (delmode & 1) {
|
||||||
|
case 0:
|
||||||
|
mode = 2;
|
||||||
|
mmode = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mode = 1;
|
||||||
|
mmode = demod ? 3 : 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!demod)
|
||||||
|
ddb_mci_cmd_link_simple(link, MCI_CMD_SET_INPUT_CONFIG,
|
||||||
|
0xff, mode | (delmode & 0x10));
|
||||||
|
dvb->fe = ddb_mx_attach(input, demod, tuner, mmode);
|
||||||
|
dvb->input = 0;
|
||||||
|
fm = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -531,7 +575,7 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
|||||||
dev_err(dev->dev, "No MCI card found!\n");
|
dev_err(dev->dev, "No MCI card found!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (input->nr < 4) {
|
if (!input->nr || (input->nr < 4 && type != DDB_TUNER_MCI_M8)) {
|
||||||
lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
|
lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
|
||||||
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
|
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
|
||||||
}
|
}
|
||||||
@ -544,15 +588,10 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
|||||||
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
|
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
|
||||||
dvb->fe->ops.diseqc_send_burst = max_send_burst;
|
dvb->fe->ops.diseqc_send_burst = max_send_burst;
|
||||||
dvb->fe->sec_priv = input;
|
dvb->fe->sec_priv = input;
|
||||||
switch (type) {
|
if (type == DDB_TUNER_MCI_SX8) {
|
||||||
case DDB_TUNER_MCI_M4:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#ifndef KERNEL_DVB_CORE
|
#ifndef KERNEL_DVB_CORE
|
||||||
dvb->fe->ops.set_input = max_set_input;
|
dvb->fe->ops.set_input = max_set_input;
|
||||||
#endif
|
#endif
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
dvb->input = tuner;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,17 @@ int ddb_mci_cmd_link(struct ddb_link *link,
|
|||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ddb_mci_cmd_link_simple(struct ddb_link *link, u8 command, u8 demod, u8 value)
|
||||||
|
{
|
||||||
|
struct mci_command cmd;
|
||||||
|
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.command = command;
|
||||||
|
cmd.demod = demod;
|
||||||
|
cmd.params8[0] = value;
|
||||||
|
return ddb_mci_cmd_link(link, &cmd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void mci_handler(void *priv)
|
static void mci_handler(void *priv)
|
||||||
{
|
{
|
||||||
struct ddb_link *link = (struct ddb_link *) priv;
|
struct ddb_link *link = (struct ddb_link *) priv;
|
||||||
|
@ -96,8 +96,8 @@
|
|||||||
#define SX8_DEMOD_IQ_MODE (1)
|
#define SX8_DEMOD_IQ_MODE (1)
|
||||||
#define SX8_DEMOD_WAIT_MATYPE (3)
|
#define SX8_DEMOD_WAIT_MATYPE (3)
|
||||||
|
|
||||||
#define M4_DEMOD_WAIT_TS (6)
|
#define MX_DEMOD_WAIT_TS (6)
|
||||||
#define M4_DEMOD_C2SCAN (16)
|
#define MX_DEMOD_C2SCAN (16)
|
||||||
|
|
||||||
#define MCI_STATUS_OK (0x00)
|
#define MCI_STATUS_OK (0x00)
|
||||||
#define MCI_STATUS_UNSUPPORTED (0x80)
|
#define MCI_STATUS_UNSUPPORTED (0x80)
|
||||||
@ -113,6 +113,8 @@
|
|||||||
#define MCI_CMD_GETSIGNALINFO (0x03)
|
#define MCI_CMD_GETSIGNALINFO (0x03)
|
||||||
//#define MCI_CMD_RFPOWER (0x04)
|
//#define MCI_CMD_RFPOWER (0x04)
|
||||||
|
|
||||||
|
#define MCI_CMD_SET_INPUT_CONFIG (0x05)
|
||||||
|
|
||||||
#define MCI_CMD_SEARCH_DVBS (0x10)
|
#define MCI_CMD_SEARCH_DVBS (0x10)
|
||||||
#define MCI_CMD_SEARCH_ISDBS (0x11)
|
#define MCI_CMD_SEARCH_ISDBS (0x11)
|
||||||
|
|
||||||
@ -125,6 +127,9 @@
|
|||||||
#define MCI_CMD_SEARCH_ISDBC (0x25)
|
#define MCI_CMD_SEARCH_ISDBC (0x25)
|
||||||
#define MCI_CMD_SEARCH_J83B (0x26)
|
#define MCI_CMD_SEARCH_J83B (0x26)
|
||||||
|
|
||||||
|
#define MCI_CMD_SEARCH_ATSC (0x27)
|
||||||
|
#define MCI_CMD_SEARCH_ATSC3 (0x28)
|
||||||
|
|
||||||
#define MCI_CMD_GET_IQSYMBOL (0x30)
|
#define MCI_CMD_GET_IQSYMBOL (0x30)
|
||||||
|
|
||||||
#define MCI_BANDWIDTH_UNKNOWN (0)
|
#define MCI_BANDWIDTH_UNKNOWN (0)
|
||||||
@ -142,42 +147,45 @@
|
|||||||
#define SX8_CMD_ENABLE_IQOUTPUT (0x44)
|
#define SX8_CMD_ENABLE_IQOUTPUT (0x44)
|
||||||
#define SX8_CMD_DISABLE_IQOUTPUT (0x45)
|
#define SX8_CMD_DISABLE_IQOUTPUT (0x45)
|
||||||
|
|
||||||
#define M4_CMD_GET_L1INFO (0x50)
|
#define MX_CMD_GET_L1INFO (0x50)
|
||||||
#define M4_CMD_GET_IDS (0x51)
|
#define MX_CMD_GET_IDS (0x51)
|
||||||
#define M4_CMD_GET_DVBT_TPS (0x52)
|
#define MX_CMD_GET_DVBT_TPS (0x52)
|
||||||
#define MCI_CMD_GET_BBHEADER (0x53)
|
#define MCI_CMD_GET_BBHEADER (0x53)
|
||||||
#define M4_CMD_GET_ISDBT_TMCC (0x54)
|
#define MX_CMD_GET_ISDBT_TMCC (0x54)
|
||||||
#define M4_CMD_GET_ISDBS_TMCC (0x55)
|
#define MX_CMD_GET_ISDBS_TMCC (0x55)
|
||||||
#define M4_CMD_GET_ISDBC_TSMF (0x56)
|
#define MX_CMD_GET_ISDBC_TSMF (0x56)
|
||||||
|
|
||||||
#define M4_CMD_GET_BBHEADER (MCI_CMD_GET_BBHEADER)
|
#define MX_CMD_GET_BBHEADER (MCI_CMD_GET_BBHEADER)
|
||||||
|
|
||||||
#define M4_L1INFO_SEL_PRE (0)
|
#define MX_L1INFO_SEL_PRE (0)
|
||||||
#define M4_L1INFO_SEL_DSINFO (1)
|
#define MX_L1INFO_SEL_DSINFO (1)
|
||||||
#define M4_L1INFO_SEL_PLPINFO (2)
|
#define MX_L1INFO_SEL_PLPINFO (2)
|
||||||
#define M4_L1INFO_SEL_PLPINFO_C (3)
|
#define MX_L1INFO_SEL_PLPINFO_C (3)
|
||||||
#define M4_L1INFO_SEL_SETID (0x80)
|
#define MX_L1INFO_SEL_SETID (0x80)
|
||||||
|
|
||||||
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
|
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
|
||||||
|
|
||||||
#define M4_MODE_DVBSX (2)
|
#define MX_MODE_DVBSX (2)
|
||||||
#define M4_MODE_DVBC (3)
|
#define MX_MODE_DVBC (3)
|
||||||
#define M4_MODE_DVBT (4)
|
#define MX_MODE_DVBT (4)
|
||||||
#define M4_MODE_DVBT2 (5)
|
#define MX_MODE_DVBT2 (5)
|
||||||
#define M4_MODE_DVBC2 (6)
|
#define MX_MODE_DVBC2 (6)
|
||||||
#define M4_MODE_J83B (7)
|
#define MX_MODE_J83B (7)
|
||||||
#define M4_MODE_ISDBT (8)
|
#define MX_MODE_ISDBT (8)
|
||||||
#define M4_MODE_ISDBC (9)
|
#define MX_MODE_ISDBC (9)
|
||||||
#define M4_MODE_ISDBS (10)
|
#define MX_MODE_ISDBS (10)
|
||||||
|
#define MX_MODE_ISDBS3 (11)
|
||||||
|
#define MX_MODE_ATSC (12)
|
||||||
|
#define MX_MODE_ATSC3 (13)
|
||||||
|
|
||||||
#define M4_DVBC_CONSTELLATION_16QAM (0)
|
#define MX_DVBC_CONSTELLATION_16QAM (0)
|
||||||
#define M4_DVBC_CONSTELLATION_32QAM (1)
|
#define MX_DVBC_CONSTELLATION_32QAM (1)
|
||||||
#define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
|
#define MX_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
|
||||||
#define M4_DVBC_CONSTELLATION_128QAM (3)
|
#define MX_DVBC_CONSTELLATION_128QAM (3)
|
||||||
#define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
|
#define MX_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
|
||||||
|
|
||||||
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
|
#define MX_SIGNALINFO_FLAG_CHANGE (0x01)
|
||||||
#define M4_SIGNALINFO_FLAG_EWS (0x02)
|
#define MX_SIGNALINFO_FLAG_EWS (0x02)
|
||||||
|
|
||||||
#define SX8_ROLLOFF_35 0
|
#define SX8_ROLLOFF_35 0
|
||||||
#define SX8_ROLLOFF_25 1
|
#define SX8_ROLLOFF_25 1
|
||||||
@ -267,6 +275,9 @@
|
|||||||
|
|
||||||
#define CMD_GET_SERIALNUMBER (0xF0)
|
#define CMD_GET_SERIALNUMBER (0xF0)
|
||||||
#define CMD_EXPORT_LICENSE (0xF0)
|
#define CMD_EXPORT_LICENSE (0xF0)
|
||||||
|
#define CMD_IMPORT_LICENSE (0xF1)
|
||||||
|
#define CMD_POWER_DOWN (0xF2)
|
||||||
|
#define CMD_POWER_UP (0xF3)
|
||||||
|
|
||||||
struct mod_setup_channels {
|
struct mod_setup_channels {
|
||||||
u8 flags;
|
u8 flags;
|
||||||
@ -480,6 +491,20 @@ struct mci_command {
|
|||||||
struct mod_setup_channels mod_setup_channels[4];
|
struct mod_setup_channels mod_setup_channels[4];
|
||||||
struct mod_setup_stream mod_setup_stream;
|
struct mod_setup_stream mod_setup_stream;
|
||||||
struct mod_setup_output mod_setup_output;
|
struct mod_setup_output mod_setup_output;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 Cmd;
|
||||||
|
u8 Offset;
|
||||||
|
u8 Length;
|
||||||
|
u8 Rsvd1;
|
||||||
|
u32 Rsvd2[2];
|
||||||
|
u8 Data[96];
|
||||||
|
} sx8_packet_filter;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 ID[8];
|
||||||
|
u8 LK[24];
|
||||||
|
} license;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -968,6 +993,7 @@ struct mci_cfg {
|
|||||||
|
|
||||||
int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result);
|
int ddb_mci_cmd(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);
|
int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result);
|
||||||
|
int ddb_mci_cmd_link_simple(struct ddb_link *link, u8 command, u8 demod, u8 value);
|
||||||
int ddb_mci_get_status(struct mci *mci, struct mci_result *res);
|
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_snr(struct dvb_frontend *fe);
|
||||||
int ddb_mci_get_info(struct mci *mci);
|
int ddb_mci_get_info(struct mci *mci);
|
||||||
|
@ -248,8 +248,7 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define LNB_BASE (0x400)
|
#define LNB_CONTROL(i) ((i) * 0x20 + 0x00)
|
||||||
#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00)
|
|
||||||
#define LNB_CMD (7ULL << 0)
|
#define LNB_CMD (7ULL << 0)
|
||||||
#define LNB_CMD_NOP 0
|
#define LNB_CMD_NOP 0
|
||||||
#define LNB_CMD_INIT 1
|
#define LNB_CMD_INIT 1
|
||||||
@ -265,27 +264,26 @@
|
|||||||
|
|
||||||
#define LNB_INTERRUPT_BASE 4
|
#define LNB_INTERRUPT_BASE 4
|
||||||
|
|
||||||
#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04)
|
#define LNB_STATUS(i) ((i) * 0x20 + 0x04)
|
||||||
#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08)
|
#define LNB_VOLTAGE(i) ((i) * 0x20 + 0x08)
|
||||||
#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c)
|
#define LNB_CONFIG(i) ((i) * 0x20 + 0x0c)
|
||||||
#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
|
#define LNB_BUF_LEVEL(i) ((i) * 0x20 + 0x10)
|
||||||
#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14)
|
#define LNB_BUF_WRITE(i) ((i) * 0x20 + 0x14)
|
||||||
|
|
||||||
#define LNB_SETTING(i) (LNB_BASE + (i) * 0x20 + 0x0c)
|
#define LNB_SETTING(i) ((i) * 0x20 + 0x0c)
|
||||||
#define LNB_FIFO_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
|
#define LNB_FIFO_LEVEL(i) ((i) * 0x20 + 0x10)
|
||||||
#define LNB_RESET_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x10)
|
#define LNB_RESET_FIFO(i) ((i) * 0x20 + 0x10)
|
||||||
#define LNB_WRITE_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x14)
|
#define LNB_WRITE_FIFO(i) ((i) * 0x20 + 0x14)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* CI Interface (only CI-Bridge) */
|
/* CI Interface (only CI-Bridge) */
|
||||||
|
|
||||||
#define CI_BASE (0x400)
|
#define CI_CONTROL(_ci) ((_ci)->regs + 0x00)
|
||||||
#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00)
|
|
||||||
|
|
||||||
#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04)
|
#define CI_DO_ATTRIBUTE_RW(_ci) ((_ci)->regs + 0x04)
|
||||||
#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08)
|
#define CI_DO_IO_RW(_ci) ((_ci)->regs + 0x08)
|
||||||
#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c)
|
#define CI_READDATA(_ci) ((_ci)->regs + 0x0c)
|
||||||
#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10)
|
#define CI_DO_READ_ATTRIBUTES(_ci) ((_ci)->regs + 0x10)
|
||||||
|
|
||||||
#define CI_RESET_CAM (0x00000001)
|
#define CI_RESET_CAM (0x00000001)
|
||||||
#define CI_POWER_ON (0x00000002)
|
#define CI_POWER_ON (0x00000002)
|
||||||
@ -305,8 +303,8 @@
|
|||||||
#define CI_READ_CMD (0x40000000)
|
#define CI_READ_CMD (0x40000000)
|
||||||
#define CI_WRITE_CMD (0x80000000)
|
#define CI_WRITE_CMD (0x80000000)
|
||||||
|
|
||||||
#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14)
|
#define CI_BLOCKIO_SEND(_ci) ((_ci)->regs + 0x14)
|
||||||
#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18)
|
#define CI_BLOCKIO_RECEIVE(_ci) ((_ci)->regs + 0x18)
|
||||||
|
|
||||||
#define CI_BLOCKIO_SEND_COMMAND (0x80000000)
|
#define CI_BLOCKIO_SEND_COMMAND (0x80000000)
|
||||||
#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000)
|
#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000)
|
||||||
|
@ -117,6 +117,9 @@ static void release(struct dvb_frontend *fe)
|
|||||||
kfree(mci_base);
|
kfree(mci_base);
|
||||||
}
|
}
|
||||||
kfree(state);
|
kfree(state);
|
||||||
|
#ifdef CONFIG_MEDIA_ATTACH
|
||||||
|
__module_get(THIS_MODULE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ddb_mci_tsconfig(struct mci *state, u32 config)
|
static int ddb_mci_tsconfig(struct mci *state, u32 config)
|
||||||
@ -491,18 +494,21 @@ static int set_parameters(struct dvb_frontend *fe)
|
|||||||
stop_iq(fe);
|
stop_iq(fe);
|
||||||
switch (p->modulation) {
|
switch (p->modulation) {
|
||||||
case APSK_256:
|
case APSK_256:
|
||||||
|
case APSK_256_L:
|
||||||
mask = 0x7f;
|
mask = 0x7f;
|
||||||
break;
|
break;
|
||||||
case APSK_128:
|
case APSK_128:
|
||||||
mask = 0x3f;
|
mask = 0x3f;
|
||||||
break;
|
break;
|
||||||
case APSK_64:
|
case APSK_64:
|
||||||
|
case APSK_64_L:
|
||||||
mask = 0x1f;
|
mask = 0x1f;
|
||||||
break;
|
break;
|
||||||
case APSK_32:
|
case APSK_32:
|
||||||
mask = 0x0f;
|
mask = 0x0f;
|
||||||
break;
|
break;
|
||||||
case APSK_16:
|
case APSK_16:
|
||||||
|
case APSK_16_L:
|
||||||
mask = 0x07;
|
mask = 0x07;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -147,13 +147,10 @@ struct ddb_info {
|
|||||||
u32 type;
|
u32 type;
|
||||||
#define DDB_NONE 0
|
#define DDB_NONE 0
|
||||||
#define DDB_OCTOPUS 1
|
#define DDB_OCTOPUS 1
|
||||||
#define DDB_OCTOPUS_CI 2
|
|
||||||
#define DDB_MOD 3
|
#define DDB_MOD 3
|
||||||
#define DDB_OCTONET 4
|
#define DDB_OCTONET 4
|
||||||
#define DDB_OCTOPUS_MAX 5
|
#define DDB_OCTOPUS_MAX 5
|
||||||
#define DDB_OCTOPUS_MAX_CT 6
|
#define DDB_OCTOPUS_MAX_CT 6
|
||||||
#define DDB_OCTOPRO 7
|
|
||||||
#define DDB_OCTOPRO_HDIN 8
|
|
||||||
#define DDB_OCTOPUS_MCI 9
|
#define DDB_OCTOPUS_MCI 9
|
||||||
u32 version;
|
u32 version;
|
||||||
char *name;
|
char *name;
|
||||||
@ -175,11 +172,14 @@ struct ddb_info {
|
|||||||
#define TS_QUIRK_ALT_OSC 8
|
#define TS_QUIRK_ALT_OSC 8
|
||||||
u8 mci_ports;
|
u8 mci_ports;
|
||||||
u8 mci_type;
|
u8 mci_type;
|
||||||
|
u8 ci_mask;
|
||||||
|
|
||||||
u32 tempmon_irq;
|
u32 tempmon_irq;
|
||||||
u32 lostlock_irq;
|
u32 lostlock_irq;
|
||||||
u32 mdio_base;
|
u32 mdio_base;
|
||||||
u32 hw_min;
|
u32 hw_min;
|
||||||
|
u32 ci_base;
|
||||||
|
u32 lnb_base;
|
||||||
const struct ddb_regmap *regmap;
|
const struct ddb_regmap *regmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -247,6 +247,7 @@ struct ddb_ci {
|
|||||||
struct dvb_ca_en50221 en;
|
struct dvb_ca_en50221 en;
|
||||||
struct ddb_port *port;
|
struct ddb_port *port;
|
||||||
u32 nr;
|
u32 nr;
|
||||||
|
u32 regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ddb_io {
|
struct ddb_io {
|
||||||
@ -320,6 +321,9 @@ struct ddb_port {
|
|||||||
#define DDB_TUNER_MCI 48
|
#define DDB_TUNER_MCI 48
|
||||||
#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0)
|
#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0)
|
||||||
#define DDB_TUNER_MCI_M4 (DDB_TUNER_MCI + 1)
|
#define DDB_TUNER_MCI_M4 (DDB_TUNER_MCI + 1)
|
||||||
|
#define DDB_TUNER_MCI_M8 (DDB_TUNER_MCI + 2)
|
||||||
|
#define DDB_TUNER_MCI_M8A (DDB_TUNER_MCI + 3)
|
||||||
|
#define DDB_TUNER_MCI_M2 (DDB_TUNER_MCI + 4)
|
||||||
|
|
||||||
struct ddb_input *input[2];
|
struct ddb_input *input[2];
|
||||||
struct ddb_output *output;
|
struct ddb_output *output;
|
||||||
|
@ -489,7 +489,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
|
||||||
|
|
||||||
if (fepriv->max_drift)
|
if (fepriv->max_drift)
|
||||||
dev_warn(fe->dvb->device,
|
dev_warn_once(fe->dvb->device,
|
||||||
"Frontend requested software zigzag, but didn't set the frequency step size\n");
|
"Frontend requested software zigzag, but didn't set the frequency step size\n");
|
||||||
|
|
||||||
/* if we've got no parameters, just keep idling */
|
/* if we've got no parameters, just keep idling */
|
||||||
|
@ -1094,7 +1094,11 @@ static int __init init_dvbdev(void)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0))
|
||||||
dvb_class = class_create(THIS_MODULE, "dvb");
|
dvb_class = class_create(THIS_MODULE, "dvb");
|
||||||
|
#else
|
||||||
|
dvb_class = class_create("dvb");
|
||||||
|
#endif
|
||||||
if (IS_ERR(dvb_class)) {
|
if (IS_ERR(dvb_class)) {
|
||||||
retval = PTR_ERR(dvb_class);
|
retval = PTR_ERR(dvb_class);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -30,7 +30,7 @@ LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t
|
|||||||
pthread_mutex_unlock(&dd->lock);
|
pthread_mutex_unlock(&dd->lock);
|
||||||
if (dddvb_fe_start(fe) < 0) {
|
if (dddvb_fe_start(fe) < 0) {
|
||||||
dbgprintf(DEBUG_SYS, "fe %d busy\n", fe->nr);
|
dbgprintf(DEBUG_SYS, "fe %d busy\n", fe->nr);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
dbgprintf(DEBUG_SYS, "Allocated fe %d = %d/%d, fd=%d\n",
|
dbgprintf(DEBUG_SYS, "Allocated fe %d = %d/%d, fd=%d\n",
|
||||||
fe->nr, fe->anum, fe->fnum, fe->fd);
|
fe->nr, fe->anum, fe->fnum, fe->fd);
|
||||||
@ -40,22 +40,25 @@ LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t
|
|||||||
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc(struct dddvb *dd, uint32_t type)
|
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc(struct dddvb *dd, uint32_t type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dddvb_fe *fe = NULL;
|
struct dddvb_fe *fe = NULL, *tfe;
|
||||||
|
|
||||||
pthread_mutex_lock(&dd->lock);
|
pthread_mutex_lock(&dd->lock);
|
||||||
dbgprintf(DEBUG_SYS, "alloc_fe type %u\n", type);
|
dbgprintf(DEBUG_SYS, "alloc_fe type %u\n", type);
|
||||||
for (i = 0; i < dd->dvbfe_num; i++) {
|
for (i = 0; i < dd->dvbfe_num; i++) {
|
||||||
fe = &dd->dvbfe[i];
|
tfe = &dd->dvbfe[i];
|
||||||
if (fe->state == 0 &&
|
if (tfe->state == 0 &&
|
||||||
(fe->type & (1UL << type))) {
|
(tfe->type & (1UL << type))) {
|
||||||
fe = dddvb_fe_alloc_num(dd, type, i);
|
fe = dddvb_fe_alloc_num(dd, type, i);
|
||||||
if (fe)
|
if (fe)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&dd->lock);
|
pthread_mutex_unlock(&dd->lock);
|
||||||
|
if (!fe)
|
||||||
|
dbgprintf(DEBUG_SYS, "alloc_fe type %u\n failed!", type);
|
||||||
|
else
|
||||||
|
dbgprintf(DEBUG_SYS, "alloc_fe type %u success!\n", type);
|
||||||
return fe;
|
return fe;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBDDDVB_EXPORTED int dddvb_dvb_tune(struct dddvb_fe *fe, struct dddvb_params *p)
|
LIBDDDVB_EXPORTED int dddvb_dvb_tune(struct dddvb_fe *fe, struct dddvb_params *p)
|
||||||
|
Loading…
Reference in New Issue
Block a user