octopro fixes

This commit is contained in:
Ralph Metzler 2016-05-02 16:27:32 +02:00
parent 5633c2f79d
commit 1b0df5fcfa
10 changed files with 523 additions and 442 deletions

View File

@ -1,7 +1,7 @@
/* /*
* ddbridge-core.c: Digital Devices bridge core functions * ddbridge-core.c: Digital Devices bridge core functions
* *
* Copyright (C) 2010-2015 Digital Devices GmbH * Copyright (C) 2010-2016 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de> * Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de> * Ralph Metzler <rjkm@metzlerbros.de>
* *
@ -54,7 +54,7 @@ static int xo2_speed = 2;
module_param(xo2_speed, int, 0444); module_param(xo2_speed, int, 0444);
MODULE_PARM_DESC(xo2_speed, "default transfer speed for xo2 based duoflex, 0=55,1=75,2=90,3=104 MBit/s, default=2, use attribute to change for individual cards"); MODULE_PARM_DESC(xo2_speed, "default transfer speed for xo2 based duoflex, 0=55,1=75,2=90,3=104 MBit/s, default=2, use attribute to change for individual cards");
#ifdef MACH_OCTOPRO #ifdef __arm__
static int alt_dma = 1; static int alt_dma = 1;
#else #else
static int alt_dma; static int alt_dma;
@ -76,18 +76,220 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#include "ddbridge-ns.c" #include "ddbridge-ns.c"
static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) /****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static struct ddb_regset octopus_mod_odma = {
.base = 0x300,
.num = 0x0a,
.size = 0x10,
};
static struct ddb_regset octopus_mod_odma_buf = {
.base = 0x2000,
.num = 0x0a,
.size = 0x100,
};
/****************************************************************************/
static struct ddb_regset octopus_input = {
.base = 0x200,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_output = {
.base = 0x280,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_idma = {
.base = 0x300,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_idma_buf = {
.base = 0x2000,
.num = 0x08,
.size = 0x100,
};
static struct ddb_regset octopus_odma = {
.base = 0x380,
.num = 0x04,
.size = 0x10,
};
static struct ddb_regset octopus_odma_buf = {
.base = 0x2800,
.num = 0x04,
.size = 0x100,
};
static struct ddb_regset octopus_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
/****************************************************************************/
static struct ddb_regset octopro_input = {
.base = 0x400,
.num = 0x14,
.size = 0x10,
};
static struct ddb_regset octopro_output = {
.base = 0x600,
.num = 0x0a,
.size = 0x10,
};
static struct ddb_regset octopro_idma = {
.base = 0x800,
.num = 0x40,
.size = 0x10,
};
static struct ddb_regset octopro_idma_buf = {
.base = 0x4000,
.num = 0x40,
.size = 0x100,
};
static struct ddb_regset octopro_odma = {
.base = 0xc00,
.num = 0x20,
.size = 0x10,
};
static struct ddb_regset octopro_odma_buf = {
.base = 0x8000,
.num = 0x20,
.size = 0x100,
};
static struct ddb_regset octopro_i2c = {
.base = 0x200,
.num = 0x0a,
.size = 0x20,
};
static struct ddb_regset octopro_i2c_buf = {
.base = 0x2000,
.num = 0x0a,
.size = 0x200,
};
static struct ddb_regset octopro_gtl = {
.base = 0xe00,
.num = 0x03,
.size = 0x40,
};
/****************************************************************************/
/****************************************************************************/
static struct ddb_regmap octopus_map = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_idma = 8,
.irq_base_odma = 16,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.idma = &octopus_idma,
.idma_buf = &octopus_idma_buf,
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
.input = &octopus_input,
.output = &octopus_output,
};
static struct ddb_regmap octopro_map = {
.irq_version = 2,
.irq_base_i2c = 32,
.irq_base_idma = 64,
.irq_base_odma = 128,
.irq_base_gtl = 8,
.i2c = &octopro_i2c,
.i2c_buf = &octopro_i2c_buf,
.idma = &octopro_idma,
.idma_buf = &octopro_idma_buf,
.odma = &octopro_odma,
.odma_buf = &octopro_odma_buf,
.input = &octopro_input,
.output = &octopro_output,
.gtl = &octopro_gtl,
};
static struct ddb_regset octopus_mod_channel = {
.base = 0x400,
.num = 0x0c,
.size = 0x40,
};
static struct ddb_regmap octopus_mod_map = {
.irq_version = 1,
.irq_base_odma = 8,
.output = &octopus_output,
.odma = &octopus_mod_odma,
.odma_buf = &octopus_mod_odma_buf,
.channel = &octopus_mod_channel,
};
/****************************************************************************/
static struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 1,
};
static struct ddb_info ddb_ct_8 = {
.type = DDB_OCTOPUS_MAX_CT,
.name = "Digital Devices MAX CT8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 0x0ff,
.board_control_2 = 0xf00,
.ts_quirks = TS_QUIRK_SERIAL,
};
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static void ddb_set_dma_table(struct ddb_io *io)
{ {
u32 i, base; struct ddb *dev = io->port->dev;
struct ddb_dma *dma = io->dma;
u32 i;
u64 mem; u64 mem;
if (!dma) if (!dma)
return; return;
base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100;
for (i = 0; i < dma->num; i++) { for (i = 0; i < dma->num; i++) {
mem = dma->pbuf[i]; mem = dma->pbuf[i];
ddbwritel(dev, mem & 0xffffffff, base + i * 8); ddbwritel(dev, mem & 0xffffffff, dma->bufregs + i * 8);
ddbwritel(dev, mem >> 32, base + i * 8 + 4); ddbwritel(dev, mem >> 32, dma->bufregs + i * 8 + 4);
} }
dma->bufval = (dma->div << 16) | dma->bufval = (dma->div << 16) |
((dma->num & 0x1f) << 11) | ((dma->num & 0x1f) << 11) |
@ -97,11 +299,15 @@ static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
static void ddb_set_dma_tables(struct ddb *dev) static void ddb_set_dma_tables(struct ddb *dev)
{ {
u32 i; u32 i;
for (i = 0; i < dev->link[0].info->port_num * 2; i++) for (i = 0; i < DDB_MAX_PORT; i++) {
ddb_set_dma_table(dev, dev->input[i].dma); if (dev->port[i].input[0])
for (i = 0; i < dev->link[0].info->port_num; i++) ddb_set_dma_table(dev->port[i].input[0]);
ddb_set_dma_table(dev, dev->output[i].dma); if (dev->port[i].input[1])
ddb_set_dma_table(dev->port[i].input[1]);
if (dev->port[i].output)
ddb_set_dma_table(dev->port[i].output);
}
} }
@ -117,7 +323,7 @@ static void ddb_redirect_dma(struct ddb *dev,
u64 mem; u64 mem;
sdma->bufval = ddma->bufval; sdma->bufval = ddma->bufval;
base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; base = sdma->bufregs;
for (i = 0; i < ddma->num; i++) { for (i = 0; i < ddma->num; i++) {
mem = ddma->pbuf[i]; mem = ddma->pbuf[i];
ddbwritel(dev, mem & 0xffffffff, base + i * 8); ddbwritel(dev, mem & 0xffffffff, base + i * 8);
@ -151,7 +357,7 @@ static int ddb_unredirect(struct ddb_port *port)
oredi->dma, iredo->dma); oredi->dma, iredo->dma);
} }
port->input[0]->redo = 0; port->input[0]->redo = 0;
ddb_set_dma_table(port->dev, port->input[0]->dma); ddb_set_dma_table(port->input[0]);
} }
oredi->redi = iredi; oredi->redi = iredi;
port->input[0]->redi = 0; port->input[0]->redi = 0;
@ -159,7 +365,7 @@ static int ddb_unredirect(struct ddb_port *port)
oredi->redo = 0; oredi->redo = 0;
port->output->redi = 0; port->output->redi = 0;
ddb_set_dma_table(oredi->port->dev, oredi->dma); ddb_set_dma_table(oredi);
done: done:
mutex_unlock(&redirect_lock); mutex_unlock(&redirect_lock);
return 0; return 0;
@ -339,33 +545,33 @@ static void ddb_output_start(struct ddb_output *output)
output->dma->cbuf = 0; output->dma->cbuf = 0;
output->dma->coff = 0; output->dma->coff = 0;
output->dma->stat = 0; output->dma->stat = 0;
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
} }
if (output->port->class == DDB_PORT_MOD) if (output->port->class == DDB_PORT_MOD)
ddbridge_mod_output_start(output); ddbridge_mod_output_start(output);
else { else {
ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 0, TS_CONTROL(output));
ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 2, TS_CONTROL(output));
ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 0, TS_CONTROL(output));
ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 0x3c, TS_CONTROL(output));
ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr)); ddbwritel(dev, con2, TS_CONTROL2(output));
} }
if (output->dma) { if (output->dma) {
ddbwritel(dev, output->dma->bufval, ddbwritel(dev, output->dma->bufval,
DMA_BUFFER_SIZE(output->dma->nr)); DMA_BUFFER_SIZE(output->dma));
ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma));
ddbwritel(dev, 1, DMA_BASE_READ); ddbwritel(dev, 1, DMA_BASE_READ);
ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma));
} }
if (output->port->class != DDB_PORT_MOD) { if (output->port->class != DDB_PORT_MOD) {
if (output->port->input[0]->port->class == DDB_PORT_LOOP) if (output->port->input[0]->port->class == DDB_PORT_LOOP)
/*ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr)); /*ddbwritel(dev, 0x15, TS_CONTROL(output));
ddbwritel(dev, 0x45, ddbwritel(dev, 0x45,
TS_OUTPUT_CONTROL(output->nr));*/ TS_CONTROL(output));*/
ddbwritel(dev, (1 << 13) | 0x15, ddbwritel(dev, (1 << 13) | 0x15,
TS_OUTPUT_CONTROL(output->nr)); TS_CONTROL(output));
else else
ddbwritel(dev, 0x11d, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 0x11d, TS_CONTROL(output));
} }
if (output->dma) { if (output->dma) {
output->dma->running = 1; output->dma->running = 1;
@ -382,9 +588,9 @@ static void ddb_output_stop(struct ddb_output *output)
if (output->port->class == DDB_PORT_MOD) if (output->port->class == DDB_PORT_MOD)
ddbridge_mod_output_stop(output); ddbridge_mod_output_stop(output);
else else
ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ddbwritel(dev, 0, TS_CONTROL(output));
if (output->dma) { if (output->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
output->dma->running = 0; output->dma->running = 0;
spin_unlock_irq(&output->dma->lock); spin_unlock_irq(&output->dma->lock);
} }
@ -397,9 +603,9 @@ static void ddb_input_stop(struct ddb_input *input)
if (input->dma) if (input->dma)
spin_lock_irq(&input->dma->lock); spin_lock_irq(&input->dma->lock);
ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr)); ddbwritel(dev, 0, tag | TS_CONTROL(input));
if (input->dma) { if (input->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma));
input->dma->running = 0; input->dma->running = 0;
spin_unlock_irq(&input->dma->lock); spin_unlock_irq(&input->dma->lock);
} }
@ -410,39 +616,36 @@ static void ddb_input_stop(struct ddb_input *input)
static void ddb_input_start(struct ddb_input *input) static void ddb_input_start(struct ddb_input *input)
{ {
struct ddb *dev = input->port->dev; struct ddb *dev = input->port->dev;
u32 tsctrl = TS_INPUT_BASE + input->nr * 0x10;
u32 tsctrl2 = tsctrl + 4;
u32 tag = DDB_LINK_TAG(input->port->lnr);
if (input->dma) { if (input->dma) {
spin_lock_irq(&input->dma->lock); spin_lock_irq(&input->dma->lock);
input->dma->cbuf = 0; input->dma->cbuf = 0;
input->dma->coff = 0; input->dma->coff = 0;
input->dma->stat = 0; input->dma->stat = 0;
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma));
} }
//ddbwritel(dev, 0, tag | TS_INPUT_CONTROL2(input->nr)); ddbwritel(dev, 0, TS_CONTROL(input));
ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr)); ddbwritel(dev, 2, TS_CONTROL(input));
ddbwritel(dev, 2, tag | TS_INPUT_CONTROL(input->nr)); ddbwritel(dev, 0, TS_CONTROL(input));
ddbwritel(dev, 0, tag | TS_INPUT_CONTROL(input->nr));
if (input->dma) { if (input->dma) {
ddbwritel(dev, input->dma->bufval, ddbwritel(dev, input->dma->bufval,
DMA_BUFFER_SIZE(input->dma->nr)); DMA_BUFFER_SIZE(input->dma));
ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma));
ddbwritel(dev, 1, DMA_BASE_WRITE); ddbwritel(dev, 1, DMA_BASE_WRITE);
ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma));
} }
if (dev->link[0].info->type == DDB_OCTONET) if (dev->link[0].info->type == DDB_OCTONET)
ddbwritel(dev, 0x01, tag | TS_INPUT_CONTROL(input->nr)); ddbwritel(dev, 0x01, TS_CONTROL(input));
else else
ddbwritel(dev, 0x09, tag | TS_INPUT_CONTROL(input->nr)); ddbwritel(dev, 0x09, TS_CONTROL(input));
if (input->dma) { if (input->dma) {
input->dma->running = 1; input->dma->running = 1;
spin_unlock_irq(&input->dma->lock); spin_unlock_irq(&input->dma->lock);
} }
/*printk("input_start %u.%u.%u\n", pr_info("input_start %u.%u.%u\n",
dev->nr, input->port->lnr, input->nr); */ dev->nr, input->port->lnr, input->nr);
pr_info("dmaregs = %08x\n", input->dma->regs);
} }
@ -587,7 +790,7 @@ static ssize_t ddb_output_write(struct ddb_output *output,
ddbwritel(dev, ddbwritel(dev,
(output->dma->cbuf << 11) | (output->dma->cbuf << 11) |
(output->dma->coff >> 7), (output->dma->coff >> 7),
DMA_BUFFER_ACK(output->dma->nr)); DMA_BUFFER_ACK(output->dma));
} }
return count - left; return count - left;
} }
@ -597,7 +800,7 @@ static u32 ddb_input_free_bytes(struct ddb_input *input)
{ {
struct ddb *dev = input->port->dev; struct ddb *dev = input->port->dev;
u32 idx, off, stat = input->dma->stat; u32 idx, off, stat = input->dma->stat;
u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma));
idx = (stat >> 11) & 0x1f; idx = (stat >> 11) & 0x1f;
off = (stat & 0x7ff) << 7; off = (stat & 0x7ff) << 7;
@ -671,14 +874,14 @@ static u32 ddb_input_avail(struct ddb_input *input)
{ {
struct ddb *dev = input->port->dev; struct ddb *dev = input->port->dev;
u32 idx, off, stat = input->dma->stat; u32 idx, off, stat = input->dma->stat;
u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma));
idx = (stat >> 11) & 0x1f; idx = (stat >> 11) & 0x1f;
off = (stat & 0x7ff) << 7; off = (stat & 0x7ff) << 7;
if (ctrl & 4) { if (ctrl & 4) {
pr_err("IA %d %d %08x\n", idx, off, ctrl); pr_err("IA %d %d %08x\n", idx, off, ctrl);
ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma));
return 0; return 0;
} }
if (input->dma->cbuf != idx) if (input->dma->cbuf != idx)
@ -720,7 +923,7 @@ static size_t ddb_input_read(struct ddb_input *input,
left -= free; left -= free;
ddbwritel(dev, ddbwritel(dev,
(input->dma->cbuf << 11) | (input->dma->coff >> 7), (input->dma->cbuf << 11) | (input->dma->coff >> 7),
DMA_BUFFER_ACK(input->dma->nr)); DMA_BUFFER_ACK(input->dma));
} }
return count; return count;
} }
@ -926,20 +1129,6 @@ static struct dvb_device dvbdev_mod = {
.fops = &mod_fops, .fops = &mod_fops,
}; };
#if 0
static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
{
int i;
for (i = 0; i < dev->link[0].info->port_num * 2; i++) {
if (dev->input[i].fe == fe)
return &dev->input[i];
}
return NULL;
}
#endif
static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
{ {
struct ddb_input *input = fe->sec_priv; struct ddb_input *input = fe->sec_priv;
@ -2797,7 +2986,7 @@ static void input_write_output(struct ddb_input *input,
struct ddb_output *output) struct ddb_output *output)
{ {
ddbwritel(output->port->dev, ddbwritel(output->port->dev,
input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); input->dma->stat, DMA_BUFFER_ACK(output->dma));
output->dma->cbuf = (input->dma->stat >> 11) & 0x1f; output->dma->cbuf = (input->dma->stat >> 11) & 0x1f;
output->dma->coff = (input->dma->stat & 0x7ff) << 7; output->dma->coff = (input->dma->stat & 0x7ff) << 7;
} }
@ -2806,7 +2995,7 @@ static void output_ack_input(struct ddb_output *output,
struct ddb_input *input) struct ddb_input *input)
{ {
ddbwritel(input->port->dev, ddbwritel(input->port->dev,
output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); output->dma->stat, DMA_BUFFER_ACK(input->dma));
} }
static void input_write_dvb(struct ddb_input *input, static void input_write_dvb(struct ddb_input *input,
@ -2833,15 +3022,20 @@ static void input_write_dvb(struct ddb_input *input,
if (alt_dma) if (alt_dma)
dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
dma2->size, DMA_FROM_DEVICE); dma2->size, DMA_FROM_DEVICE);
#if 0
pr_info("%02x %02x %02x %02x \n",
dma2->vbuf[dma->cbuf][0], dma2->vbuf[dma->cbuf][1],
dma2->vbuf[dma->cbuf][2], dma2->vbuf[dma->cbuf][3]);
#endif
dvb_dmx_swfilter_packets(&dvb->demux, dvb_dmx_swfilter_packets(&dvb->demux,
dma2->vbuf[dma->cbuf], dma2->vbuf[dma->cbuf],
dma2->size / 188); dma2->size / 188);
dma->cbuf = (dma->cbuf + 1) % dma2->num; dma->cbuf = (dma->cbuf + 1) % dma2->num;
if (ack) if (ack)
ddbwritel(dev, (dma->cbuf << 11), ddbwritel(dev, (dma->cbuf << 11),
DMA_BUFFER_ACK(dma->nr)); DMA_BUFFER_ACK(dma));
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
} }
} }
@ -2864,8 +3058,8 @@ static void input_tasklet(unsigned long data)
spin_unlock_irqrestore(&dma->lock, flags); spin_unlock_irqrestore(&dma->lock, flags);
return; return;
} }
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
#if 0 #if 0
if (4 & dma->ctrl) if (4 & dma->ctrl)
@ -2912,8 +3106,8 @@ static void output_handler(unsigned long data)
spin_unlock(&dma->lock); spin_unlock(&dma->lock);
return; return;
} }
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
if (output->redi) if (output->redi)
output_ack_input(output, output->redi); output_ack_input(output, output->redi);
wake_up(&dma->wq); wake_up(&dma->wq);
@ -2925,17 +3119,32 @@ static void output_handler(unsigned long data)
/****************************************************************************/ /****************************************************************************/
static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out) static struct ddb_regmap *io_regmap(struct ddb_io *io, int link)
{ {
#ifndef DDB_USE_WORK struct ddb_info *info;
unsigned long priv = (unsigned long) io;
#endif
if (link)
info = io->port->dev->link[io->port->lnr].info;
else
info = io->port->dev->link[0].info;
if (!info)
return NULL;
return info->regmap;
}
static void ddb_dma_init(struct ddb_io *io, int nr, int out)
{
struct ddb_dma *dma;
struct ddb_regmap *rm = io_regmap(io, 0);
dma = out ? &io->port->dev->odma[nr] : &io->port->dev->idma[nr];
io->dma = dma;
dma->io = io; dma->io = io;
dma->nr = nr;
spin_lock_init(&dma->lock); spin_lock_init(&dma->lock);
init_waitqueue_head(&dma->wq); init_waitqueue_head(&dma->wq);
if (out) { if (out) {
dma->regs = rm->odma->base + rm->odma->size * nr;
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
dma->num = OUTPUT_DMA_BUFS; dma->num = OUTPUT_DMA_BUFS;
dma->size = OUTPUT_DMA_SIZE; dma->size = OUTPUT_DMA_SIZE;
dma->div = OUTPUT_DMA_IRQ_DIV; dma->div = OUTPUT_DMA_IRQ_DIV;
@ -2943,63 +3152,66 @@ static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out)
#ifdef DDB_USE_WORK #ifdef DDB_USE_WORK
INIT_WORK(&dma->work, input_work); INIT_WORK(&dma->work, input_work);
#else #else
tasklet_init(&dma->tasklet, input_tasklet, priv); tasklet_init(&dma->tasklet, input_tasklet, (unsigned long) io);
#endif #endif
dma->regs = rm->idma->base + rm->idma->size * nr;
dma->bufregs = rm->idma_buf->base + rm->idma_buf->size * nr;
dma->num = INPUT_DMA_BUFS; dma->num = INPUT_DMA_BUFS;
dma->size = INPUT_DMA_SIZE; dma->size = INPUT_DMA_SIZE;
dma->div = INPUT_DMA_IRQ_DIV; dma->div = INPUT_DMA_IRQ_DIV;
} }
ddbwritel(io->port->dev, 0, DMA_BUFFER_ACK(dma));
pr_info("init link %u, io %u, dma %u, dmaregs %08x bufregs %08x\n",
io->port->lnr, io->nr, nr, dma->regs, dma->bufregs);
} }
static void ddb_input_init(struct ddb_port *port, int nr, int pnr, static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
int dma_nr, int anr)
{ {
struct ddb *dev = port->dev; struct ddb *dev = port->dev;
struct ddb_input *input = &dev->input[anr]; struct ddb_input *input = &dev->input[anr];
struct ddb_regmap *rm;
if (dev->has_dma) {
dev->handler[0][dma_nr + 8] = input_handler;
dev->handler_data[0][dma_nr + 8] = (unsigned long) input;
}
port->input[pnr] = input; port->input[pnr] = input;
input->nr = nr; input->nr = nr;
input->port = port; input->port = port;
rm = io_regmap(input, 1);
input->regs = DDB_LINK_TAG(port->lnr) |
(rm->input->base + rm->input->size * nr);
pr_info("init link %u, input %u, regs %08x\n", port->lnr, nr, input->regs);
if (dev->has_dma) { if (dev->has_dma) {
input->dma = &dev->dma[dma_nr]; u32 base = rm->irq_base_idma;
ddb_dma_init(input->dma, dma_nr, (void *) input, 0); u32 dma_nr = nr;
if (port->lnr)
dma_nr += 32 + (port->lnr - 1) * 8;
pr_info("init link %u, input %u, handler %u\n", port->lnr, nr, dma_nr + base);
dev->handler[0][dma_nr + base] = input_handler;
dev->handler_data[0][dma_nr + base] = (unsigned long) input;
ddb_dma_init(input, dma_nr, 0);
} }
ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
ddbwritel(dev, 2, TS_INPUT_CONTROL(nr));
ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
if (input->dma)
ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
} }
static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr) static void ddb_output_init(struct ddb_port *port, int nr)
{ {
struct ddb *dev = port->dev; struct ddb *dev = port->dev;
struct ddb_output *output = &dev->output[nr]; struct ddb_output *output = &dev->output[nr];
struct ddb_regmap *rm;
if (dev->has_dma) {
dev->handler[0][dma_nr + 8] = output_handler;
dev->handler_data[0][dma_nr + 8] = (unsigned long) output;
}
port->output = output; port->output = output;
output->nr = nr; output->nr = nr;
output->port = port; output->port = port;
rm = io_regmap(output, 1);
output->regs = DDB_LINK_TAG(port->lnr) |
(rm->output->base + rm->output->size * nr);
pr_info("init link %u, output %u, regs %08x\n", port->lnr, nr, output->regs);
if (dev->has_dma) { if (dev->has_dma) {
output->dma = &dev->dma[dma_nr]; u32 base = rm->irq_base_odma;
ddb_dma_init(output->dma, dma_nr, (void *) output, 1);
dev->handler[0][nr + base] = output_handler;
dev->handler_data[0][nr + base] = (unsigned long) output;
ddb_dma_init(output, nr, 1);
} }
if (output->port->class == DDB_PORT_MOD) {
/*ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));*/
} else {
ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr));
ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
}
if (output->dma)
ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
} }
static int ddb_port_match_i2c(struct ddb_port *port) static int ddb_port_match_i2c(struct ddb_port *port)
@ -3017,9 +3229,23 @@ static int ddb_port_match_i2c(struct ddb_port *port)
return 0; return 0;
} }
static int ddb_port_match_link_i2c(struct ddb_port *port)
{
struct ddb *dev = port->dev;
u32 i;
for (i = 0; i < dev->i2c_num; i++) {
if (dev->i2c[i].link == port->lnr) {
port->i2c = &dev->i2c[i];
return 1;
}
}
return 0;
}
static void ddb_ports_init(struct ddb *dev) static void ddb_ports_init(struct ddb *dev)
{ {
u32 i, l, p, li2c; u32 i, l, p;
struct ddb_port *port; struct ddb_port *port;
struct ddb_info *info; struct ddb_info *info;
struct ddb_regmap *rm; struct ddb_regmap *rm;
@ -3031,9 +3257,6 @@ static void ddb_ports_init(struct ddb *dev)
rm = info->regmap; rm = info->regmap;
if (!rm) if (!rm)
continue; continue;
for (li2c = 0; li2c < dev->i2c_num; li2c++)
if (dev->i2c[li2c].link == l)
break;
for (i = 0; i < info->port_num; i++, p++) { for (i = 0; i < info->port_num; i++, p++) {
port = &dev->port[p]; port = &dev->port[p];
port->dev = dev; port->dev = dev;
@ -3043,12 +3266,9 @@ static void ddb_ports_init(struct ddb *dev)
port->gap = 4; port->gap = 4;
port->obr = ci_bitrate; port->obr = ci_bitrate;
mutex_init(&port->i2c_gate_lock); mutex_init(&port->i2c_gate_lock);
if (!ddb_port_match_i2c(port))
if (!ddb_port_match_i2c(port)) {
if (info->type == DDB_OCTOPUS_MAX) if (info->type == DDB_OCTOPUS_MAX)
port->i2c = &dev->i2c[li2c]; ddb_port_match_link_i2c(port);
}
ddb_port_probe(port); ddb_port_probe(port);
port->dvb[0].adap = &dev->adap[2 * p]; port->dvb[0].adap = &dev->adap[2 * p];
@ -3061,52 +3281,48 @@ static void ddb_ports_init(struct ddb *dev)
port->name = "DuoFlex CI_B"; port->name = "DuoFlex CI_B";
port->i2c = dev->port[p - 1].i2c; port->i2c = dev->port[p - 1].i2c;
} }
pr_info("Port %u: Link %u, Link Port %u (TAB %u): %s\n", pr_info("Port %u: Link %u, Link Port %u (TAB %u): %s\n",
port->pnr, port->lnr, port->nr, port->pnr, port->lnr, port->nr,
port->nr + 1, port->name); port->nr + 1, port->name);
if (port->class == DDB_PORT_CI && if (port->class == DDB_PORT_CI &&
port->type == DDB_CI_EXTERNAL_XO2) { port->type == DDB_CI_EXTERNAL_XO2) {
ddb_input_init(port, 2 * i, 0, 2 * i, 2 * i); ddb_input_init(port, 2 * i, 0, 2 * i);
ddb_output_init(port, i, i + 8); ddb_output_init(port, i);
continue; continue;
} }
if (port->class == DDB_PORT_CI && if (port->class == DDB_PORT_CI &&
port->type == DDB_CI_EXTERNAL_XO2_B) { port->type == DDB_CI_EXTERNAL_XO2_B) {
ddb_input_init(port, 2 * i - 1, 0, ddb_input_init(port, 2 * i - 1, 0, 2 * i - 1);
2 * i - 1, 2 * i - 1); ddb_output_init(port, i);
ddb_output_init(port, i, i + 8);
continue; continue;
} }
if (port->class == DDB_PORT_NONE)
continue;
switch (dev->link[l].info->type) { switch (dev->link[l].info->type) {
case DDB_OCTOPUS_CI: case DDB_OCTOPUS_CI:
if (i >= 2) { if (i >= 2) {
ddb_input_init(port, 2 + i, 0, ddb_input_init(port, 2 + i, 0, 2 + i);
2 + i, 2 + i); ddb_input_init(port, 4 + i, 1, 4 + i);
ddb_input_init(port, 4 + i, 1, ddb_output_init(port, i);
4 + i, 4 + i);
ddb_output_init(port, i, i + 8);
break; break;
} /* fallthrough */ } /* fallthrough */
case DDB_OCTONET: case DDB_OCTONET:
case DDB_OCTOPUS: case DDB_OCTOPUS:
case DDB_OCTOPRO: case DDB_OCTOPRO:
ddb_input_init(port, 2 * i, 0, 2 * i, 2 * i); ddb_input_init(port, 2 * i, 0, 2 * i);
ddb_input_init(port, 2 * i + 1, 1, ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
2 * i + 1, 2 * i + 1); ddb_output_init(port, i);
ddb_output_init(port, i, i + 8);
break; break;
case DDB_OCTOPUS_MAX: case DDB_OCTOPUS_MAX:
case DDB_OCTOPUS_MAX_CT: case DDB_OCTOPUS_MAX_CT:
ddb_input_init(port, 2 * i, 0, 2 * i, 2 * p); ddb_input_init(port, 2 * i, 0, 2 * p);
ddb_input_init(port, 2 * i + 1, ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
1, 2 * i + 1, 2 * p + 1);
break; break;
case DDB_MOD: case DDB_MOD:
ddb_output_init(port, i, i); ddb_output_init(port, i);
dev->handler[0][i + 18] = dev->handler[0][i + 18] =
ddbridge_mod_rate_handler; ddbridge_mod_rate_handler;
dev->handler_data[0][i + 18] = dev->handler_data[0][i + 18] =
@ -3279,24 +3495,53 @@ static irqreturn_t irq_handler(int irq, void *dev_id)
static irqreturn_t irq_handle_v2_n(struct ddb *dev, u32 n) static irqreturn_t irq_handle_v2_n(struct ddb *dev, u32 n)
{ {
u32 reg = INTERRUPT_V2_STATUS_1 + 4 * n; u32 reg = INTERRUPT_V2_STATUS + 4 * n;
u32 s = ddbreadl(dev, reg); u32 s = ddbreadl(dev, reg);
u32 off = n * 32; u32 off = n * 32;
//pr_info("irq_handle_v2_%u s=%08x\n", n, s);
if (!s) if (!s)
return IRQ_NONE; return IRQ_NONE;
ddbwritel(dev, s, reg); ddbwritel(dev, s, reg);
if ((s & 0x000000ff)) { if ((s & 0x000000ff)) {
IRQ_HANDLE(0 + off); IRQ_HANDLE( 0 + off);
IRQ_HANDLE(1 + off); IRQ_HANDLE( 1 + off);
IRQ_HANDLE(2 + off); IRQ_HANDLE( 2 + off);
IRQ_HANDLE(3 + off); IRQ_HANDLE( 3 + off);
IRQ_HANDLE(4 + off); IRQ_HANDLE( 4 + off);
IRQ_HANDLE(5 + off); IRQ_HANDLE( 5 + off);
IRQ_HANDLE(6 + off); IRQ_HANDLE( 6 + off);
IRQ_HANDLE(7 + off); IRQ_HANDLE( 7 + off);
}
if ((s & 0x0000ff00)) {
IRQ_HANDLE( 8 + off);
IRQ_HANDLE( 9 + off);
IRQ_HANDLE(10 + off);
IRQ_HANDLE(11 + off);
IRQ_HANDLE(12 + off);
IRQ_HANDLE(13 + off);
IRQ_HANDLE(14 + off);
IRQ_HANDLE(15 + off);
}
if ((s & 0x00ff0000)) {
IRQ_HANDLE(16 + off);
IRQ_HANDLE(17 + off);
IRQ_HANDLE(18 + off);
IRQ_HANDLE(19 + off);
IRQ_HANDLE(20 + off);
IRQ_HANDLE(21 + off);
IRQ_HANDLE(22 + off);
IRQ_HANDLE(23 + off);
}
if ((s & 0xff000000)) {
IRQ_HANDLE(24 + off);
IRQ_HANDLE(25 + off);
IRQ_HANDLE(26 + off);
IRQ_HANDLE(27 + off);
IRQ_HANDLE(28 + off);
IRQ_HANDLE(29 + off);
IRQ_HANDLE(30 + off);
IRQ_HANDLE(31 + off);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -3310,11 +3555,21 @@ static irqreturn_t irq_handler_v2(int irq, void *dev_id)
if (!s) if (!s)
return IRQ_NONE; return IRQ_NONE;
do { do {
if (s & 0x80000000) if (s & 0x80)
return IRQ_NONE; return IRQ_NONE;
//pr_info("irq_handler_v2 s=%08x\n", s); ddbwritel(dev, s, INTERRUPT_V2_STATUS);
if (s & 0x00000001) if (s & 0x00000001)
irq_handle_v2_n(dev, 0); irq_handle_v2_n(dev, 1);
if (s & 0x00000002) {
//pr_info("irq_handler_v2 s=%08x\n", s);
irq_handle_v2_n(dev, 2);
}
if (s & 0x00000004)
irq_handle_v2_n(dev, 3);
IRQ_HANDLE(8);
IRQ_HANDLE(9);
IRQ_HANDLE(10);
IRQ_HANDLE(11);
} while ((s = 0xffff & ddbreadl(dev, INTERRUPT_V2_STATUS))); } while ((s = 0xffff & ddbreadl(dev, INTERRUPT_V2_STATUS)));
return ret; return ret;
@ -4592,68 +4847,12 @@ static void gtl_irq_handler(unsigned long priv)
#endif #endif
} }
static struct ddb_regset octopus_max_gtl_i2c = {
.base = 0x80,
.num = 0x01,
.size = 0x20,
};
static struct ddb_regset octopus_max_gtl_i2c_buf = {
.base = 0x1000,
.num = 0x01,
.size = 0x200,
};
static struct ddb_regmap octopus_max_gtl_map = {
.i2c = &octopus_max_gtl_i2c,
.i2c_buf = &octopus_max_gtl_i2c_buf,
};
static struct ddb_info octopus_max_gtl = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices Octopus MAX GTL",
.regmap = &octopus_max_gtl_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 1,
};
static struct ddb_regset octopus_maxct_gtl_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_maxct_gtl_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
static struct ddb_regmap octopus_maxct_gtl_map = {
.i2c = &octopus_maxct_gtl_i2c,
.i2c_buf = &octopus_maxct_gtl_i2c_buf,
};
static struct ddb_info octopus_ct_gtl = {
.type = DDB_OCTOPUS_MAX_CT,
.name = "Digital Devices Octopus MAX CT GTL",
.regmap = &octopus_maxct_gtl_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 0xff,
.board_control_2 = 0xf00,
.ts_quirks = TS_QUIRK_SERIAL,
};
static int ddb_gtl_init_link(struct ddb *dev, u32 l) static int ddb_gtl_init_link(struct ddb *dev, u32 l)
{ {
struct ddb_link *link = &dev->link[l]; struct ddb_link *link = &dev->link[l];
u32 regs = dev->link[0].info->regmap->gtl->base + u32 regs = dev->link[0].info->regmap->gtl->base +
(l - 1) * dev->link[0].info->regmap->gtl->size; (l - 1) * dev->link[0].info->regmap->gtl->size;
u32 id; u32 id, base = dev->link[0].info->regmap->irq_base_gtl;
pr_info("Checking GT link %u: regs = %08x\n", l, regs); pr_info("Checking GT link %u: regs = %08x\n", l, regs);
@ -4683,10 +4882,10 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
id = ddbreadl(dev, DDB_LINK_TAG(l) | 8); id = ddbreadl(dev, DDB_LINK_TAG(l) | 8);
switch (id) { switch (id) {
case 0x0007dd01: case 0x0007dd01:
link->info = &octopus_max_gtl; link->info = &ddb_s2_48;
break; break;
case 0x0008dd01: case 0x0008dd01:
link->info = &octopus_ct_gtl; link->info = &ddb_ct_8;
break; break;
default: default:
pr_info("DDBridge: Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.", pr_info("DDBridge: Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.",
@ -4697,8 +4896,8 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
ddbwritel(dev, 1, 0x1a0); ddbwritel(dev, 1, 0x1a0);
dev->handler_data[0][11] = (unsigned long) link; dev->handler_data[0][base + l] = (unsigned long) link;
dev->handler[0][11] = gtl_irq_handler; dev->handler[0][base + l] = gtl_irq_handler;
pr_info("GTL %s\n", dev->link[l].info->name); pr_info("GTL %s\n", dev->link[l].info->name);
pr_info("GTL HW %08x REGMAP %08x\n", pr_info("GTL HW %08x REGMAP %08x\n",
@ -4716,11 +4915,10 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
static int ddb_gtl_init(struct ddb *dev) static int ddb_gtl_init(struct ddb *dev)
{ {
u32 l; u32 l, base = dev->link[0].info->regmap->irq_base_gtl;
dev->handler_data[0][10] = (unsigned long) dev;
dev->handler[0][10] = gtl_link_handler;
dev->handler_data[0][base] = (unsigned long) dev;
dev->handler[0][base] = gtl_link_handler;
for (l = 1; l < dev->link[0].info->regmap->gtl->num + 1; l++) for (l = 1; l < dev->link[0].info->regmap->gtl->num + 1; l++)
ddb_gtl_init_link(dev, l); ddb_gtl_init_link(dev, l);
return 0; return 0;
@ -4806,3 +5004,24 @@ fail:
pr_err("fail1\n"); pr_err("fail1\n");
return -1; return -1;
} }
static void ddb_reset_io(struct ddb *dev, u32 reg)
{
ddbwritel(dev, 0x00, reg);
ddbwritel(dev, 0x02, reg);
ddbwritel(dev, 0x00, reg);
}
static void ddb_reset_ios(struct ddb *dev)
{
u32 i;
struct ddb_regmap *rm = dev->link[0].info->regmap;
if (rm->input)
for (i = 0; i < rm->input->num; i++)
ddb_reset_io(dev, rm->input->base + i * rm->input->size);
if (rm->output)
for (i = 0; i < rm->output->num; i++)
ddb_reset_io(dev, rm->output->base + i * rm->output->size);
usleep_range(5000, 6000);
}

View File

@ -257,7 +257,7 @@ static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
static int ddb_i2c_init(struct ddb *dev) static int ddb_i2c_init(struct ddb *dev)
{ {
int stat = 0; int stat = 0;
u32 i, j, num = 0, l; u32 i, j, num = 0, l, base;
struct ddb_i2c *i2c; struct ddb_i2c *i2c;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct ddb_regmap *regmap; struct ddb_regmap *regmap;
@ -268,12 +268,13 @@ static int ddb_i2c_init(struct ddb *dev)
regmap = dev->link[l].info->regmap; regmap = dev->link[l].info->regmap;
if (!regmap || !regmap->i2c) if (!regmap || !regmap->i2c)
continue; continue;
base = regmap->irq_base_i2c;
for (i = 0; i < regmap->i2c->num; i++) { for (i = 0; i < regmap->i2c->num; i++) {
if (!(dev->link[l].info->i2c_mask & (1 << i))) if (!(dev->link[l].info->i2c_mask & (1 << i)))
continue; continue;
i2c = &dev->i2c[num]; i2c = &dev->i2c[num];
dev->handler_data[l][i] = (unsigned long) i2c; dev->handler_data[l][i + base] = (unsigned long) i2c;
dev->handler[l][i] = i2c_handler; dev->handler[l][i + base] = i2c_handler;
stat = ddb_i2c_add(dev, i2c, regmap, l, i, num); stat = ddb_i2c_add(dev, i2c, regmap, l, i, num);
if (stat) if (stat)
break; break;

View File

@ -201,10 +201,10 @@ static int ns_set_ci(struct dvbnss *nss, u8 ci)
pr_info("input %d.%d to ci %d at port %d\n", pr_info("input %d.%d to ci %d at port %d\n",
input->port->lnr, input->nr, ci, ciport); input->port->lnr, input->nr, ci, ciport);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c, ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c,
TS_OUTPUT_CONTROL(ciport)); TS_CONTROL(dev->port[ciport].output));
usleep_range(1, 5); usleep_range(1, 5);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d, ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d,
TS_OUTPUT_CONTROL(ciport)); TS_CONTROL(dev->port[ciport].output));
dns->fe = dev->port[ciport].input[0]; dns->fe = dev->port[ciport].input[0];
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
/* /*
* ddbridge-regs.h: Digital Devices PCIe bridge driver * ddbridge-regs.h: Digital Devices PCIe bridge driver
* *
* Copyright (C) 2010-2015 Digital Devices GmbH * Copyright (C) 2010-2016 Digital Devices GmbH
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -156,15 +156,12 @@
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* I2C Master Controller */ /* I2C Master Controller */
/*#define I2C_BASE (0x80) */
#define I2C_COMMAND (0x00) #define I2C_COMMAND (0x00)
#define I2C_TIMING (0x04) #define I2C_TIMING (0x04)
#define I2C_TASKLENGTH (0x08) /* High read, low write */ #define I2C_TASKLENGTH (0x08) /* High read, low write */
#define I2C_TASKADDRESS (0x0C) /* High read, low write */ #define I2C_TASKADDRESS (0x0C) /* High read, low write */
#define I2C_MONITOR (0x1C) #define I2C_MONITOR (0x1C)
#define I2C_SPEED_666 (0x02010202) #define I2C_SPEED_666 (0x02010202)
#define I2C_SPEED_400 (0x04030404) #define I2C_SPEED_400 (0x04030404)
#define I2C_SPEED_200 (0x09080909) #define I2C_SPEED_200 (0x09080909)
@ -193,26 +190,17 @@
#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) #define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38)
#define DMA_DIAG_WAITCOUNTER (0x3C) #define DMA_DIAG_WAITCOUNTER (0x3C)
#define TS_INPUT_BASE (0x200) #define TS_CONTROL(_io) (_io->regs + 0x00)
#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00) #define TS_CONTROL2(_io) (_io->regs + 0x04)
#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04)
#define TS_OUTPUT_BASE (0x280)
#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00)
#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* DMA Buffer */ /* DMA Buffer */
#define DMA_BUFFER_BASE (0x300) #define DMA_BUFFER_CONTROL(_dma) (_dma->regs + 0x00)
#define DMA_BUFFER_ACK(_dma) (_dma->regs + 0x04)
#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) #define DMA_BUFFER_CURRENT(_dma) (_dma->regs + 0x08)
#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04) #define DMA_BUFFER_SIZE(_dma) (_dma->regs + 0x0c)
#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
#define DMA_BASE_ADDRESS_TABLE (0x2000)
#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -59,7 +59,7 @@ static void ddb_unmap(struct ddb *dev)
static void __devexit ddb_irq_disable(struct ddb *dev) static void __devexit ddb_irq_disable(struct ddb *dev)
{ {
if ((dev->link[0].ids.regmapid & 0xffff0000) == 0x00020000) { if (dev->link[0].info->regmap->irq_version == 2) {
//ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL); //ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1); ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2); ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2);
@ -131,14 +131,12 @@ static int __devinit ddb_irq_msi(struct ddb *dev, int nr)
if (stat == 0) { if (stat == 0) {
dev->msi = nr; dev->msi = nr;
pr_info("DDBridge: using %d MSI interrupts\n", nr); pr_info("DDBridge: using %d MSI interrupts\n", nr);
} } else if (stat == 1) {
if (stat == 1)
stat = pci_enable_msi(dev->pdev); stat = pci_enable_msi(dev->pdev);
if (stat < 0) { dev->msi = 1;
pr_info("DDBridge: MSI not available.\n");
} else {
dev->msi++;
} }
if (stat < 0)
pr_info("DDBridge: MSI not available.\n");
#endif #endif
} }
return stat; return stat;
@ -185,7 +183,7 @@ static int __devinit ddb_irq_init(struct ddb *dev)
int stat; int stat;
int irq_flag = IRQF_SHARED; int irq_flag = IRQF_SHARED;
if ((dev->link[0].ids.regmapid & 0xffff0000) == 0x00020000) if (dev->link[0].info->regmap->irq_version == 2)
return ddb_irq_init2(dev); return ddb_irq_init2(dev);
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
@ -294,12 +292,8 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid, dev->link[0].ids.regmapid); dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
if (dev->link[0].info->ns_num) { if (dev->link[0].info->ns_num) {
int i;
ddbwritel(dev, 0, ETHER_CONTROL); ddbwritel(dev, 0, ETHER_CONTROL);
for (i = 0; i < 16; i++) ddb_reset_ios(dev);
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
usleep_range(5000, 6000);
} }
ddbwritel(dev, 0, DMA_BASE_READ); ddbwritel(dev, 0, DMA_BASE_READ);
if (dev->link[0].info->type != DDB_MOD) if (dev->link[0].info->type != DDB_MOD)
@ -335,134 +329,6 @@ fail:
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
static struct ddb_regset octopus_input = {
.base = 0x200,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_output = {
.base = 0x280,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_idma = {
.base = 0x300,
.num = 0x08,
.size = 0x10,
};
static struct ddb_regset octopus_idma_buf = {
.base = 0x2000,
.num = 0x08,
.size = 0x100,
};
static struct ddb_regset octopus_odma = {
.base = 0x380,
.num = 0x04,
.size = 0x10,
};
static struct ddb_regset octopus_odma_buf = {
.base = 0x2800,
.num = 0x04,
.size = 0x100,
};
static struct ddb_regset octopus_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
/****************************************************************************/
static struct ddb_regset octopro_input = {
.base = 0x400,
.num = 0x14,
.size = 0x10,
};
static struct ddb_regset octopro_output = {
.base = 0x600,
.num = 0x0a,
.size = 0x10,
};
static struct ddb_regset octopro_idma = {
.base = 0x800,
.num = 0x14,
.size = 0x10,
};
static struct ddb_regset octopro_idma_buf = {
.base = 0x4000,
.num = 0x14,
.size = 0x100,
};
static struct ddb_regset octopro_odma = {
.base = 0xa00,
.num = 0x0a,
.size = 0x10,
};
static struct ddb_regset octopro_odma_buf = {
.base = 0x6000,
.num = 0x0a,
.size = 0x100,
};
static struct ddb_regset octopro_i2c = {
.base = 0x200,
.num = 0x0a,
.size = 0x20,
};
static struct ddb_regset octopro_i2c_buf = {
.base = 0x2000,
.num = 0x0a,
.size = 0x200,
};
/****************************************************************************/
/****************************************************************************/
static struct ddb_regmap octopus_map = {
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.idma[0] = &octopus_idma,
.idma_buf[0] = &octopus_idma_buf,
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
};
static struct ddb_regmap octopro_map = {
.i2c = &octopro_i2c,
.i2c_buf = &octopro_i2c_buf,
.idma[0] = &octopro_idma,
.idma_buf[0] = &octopro_idma_buf,
.odma = &octopro_odma,
.odma_buf = &octopro_odma_buf,
};
static struct ddb_regmap octopus_mod_map = {
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
};
/****************************************************************************/
static struct ddb_info ddb_none = { static struct ddb_info ddb_none = {
.type = DDB_NONE, .type = DDB_NONE,
.name = "unknown Digital Devices PCIe card, install newer driver", .name = "unknown Digital Devices PCIe card, install newer driver",
@ -594,26 +460,6 @@ static struct ddb_info ddb_dvbct = {
/****************************************************************************/ /****************************************************************************/
static struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 1,
};
static struct ddb_info ddb_ct_8 = {
.type = DDB_OCTOPUS_MAX_CT,
.name = "Digital Devices MAX CT8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 0x0ff,
.board_control_2 = 0xf00,
.ts_quirks = TS_QUIRK_SERIAL,
};
static struct ddb_info ddb_mod = { static struct ddb_info ddb_mod = {
.type = DDB_MOD, .type = DDB_MOD,
.name = "Digital Devices DVB-C modulator", .name = "Digital Devices DVB-C modulator",
@ -711,7 +557,7 @@ static __init int module_init_ddbridge(void)
pr_info("Digital Devices PCIE bridge driver " pr_info("Digital Devices PCIE bridge driver "
DDBRIDGE_VERSION DDBRIDGE_VERSION
", Copyright (C) 2010-15 Digital Devices GmbH\n"); ", Copyright (C) 2010-16 Digital Devices GmbH\n");
if (ddb_class_create() < 0) if (ddb_class_create() < 0)
return -1; return -1;
ddb_wq = create_workqueue("ddbridge"); ddb_wq = create_workqueue("ddbridge");

View File

@ -91,10 +91,10 @@
#include "lnbh25.h" #include "lnbh25.h"
#include "mxl5xx.h" #include "mxl5xx.h"
#define DDB_MAX_I2C 16 #define DDB_MAX_I2C 32
#define DDB_MAX_PORT 22 #define DDB_MAX_PORT 32
#define DDB_MAX_INPUT 44 #define DDB_MAX_INPUT 64
#define DDB_MAX_OUTPUT 24 #define DDB_MAX_OUTPUT 32
#define DDB_MAX_LINK 4 #define DDB_MAX_LINK 4
#define DDB_LINK_SHIFT 28 #define DDB_LINK_SHIFT 28
@ -106,18 +106,17 @@ struct ddb_regset {
u32 size; u32 size;
}; };
struct ddb_ports {
u32 base;
u32 num;
u32 size;
};
struct ddb_regmap { struct ddb_regmap {
struct ddb_ports *bc; u32 irq_version;
u32 irq_base_i2c;
u32 irq_base_idma;
u32 irq_base_odma;
u32 irq_base_gtl;
struct ddb_regset *i2c; struct ddb_regset *i2c;
struct ddb_regset *i2c_buf; struct ddb_regset *i2c_buf;
struct ddb_regset *idma[4]; struct ddb_regset *idma;
struct ddb_regset *idma_buf[4]; struct ddb_regset *idma_buf;
struct ddb_regset *odma; struct ddb_regset *odma;
struct ddb_regset *odma_buf; struct ddb_regset *odma_buf;
@ -125,11 +124,11 @@ struct ddb_regmap {
struct ddb_regset *output; struct ddb_regset *output;
struct ddb_regset *channel; struct ddb_regset *channel;
struct ddb_regset *ci; //struct ddb_regset *ci;
struct ddb_regset *pid_filter; //struct ddb_regset *pid_filter;
struct ddb_regset *ns; //struct ddb_regset *ns;
struct ddb_regset *gtl; struct ddb_regset *gtl;
struct ddb_regset *mdio; //struct ddb_regset *mdio;
}; };
struct ddb_ids { struct ddb_ids {
@ -191,7 +190,6 @@ struct ddb_port;
struct ddb_dma { struct ddb_dma {
void *io; void *io;
u32 nr;
u32 regs; u32 regs;
u32 bufregs; u32 bufregs;
@ -424,7 +422,8 @@ struct ddb {
struct ddb_input input[DDB_MAX_INPUT]; struct ddb_input input[DDB_MAX_INPUT];
struct ddb_output output[DDB_MAX_OUTPUT]; struct ddb_output output[DDB_MAX_OUTPUT];
struct dvb_adapter adap[DDB_MAX_INPUT]; struct dvb_adapter adap[DDB_MAX_INPUT];
struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; struct ddb_dma idma[DDB_MAX_INPUT];
struct ddb_dma odma[DDB_MAX_OUTPUT];
void (*handler[4][128])(unsigned long); void (*handler[4][128])(unsigned long);
unsigned long handler_data[4][128]; unsigned long handler_data[4][128];

View File

@ -1,7 +1,7 @@
/* /*
* octonet.c: Digital Devices network tuner driver * octonet.c: Digital Devices network tuner driver
* *
* Copyright (C) 2012-15 Digital Devices GmbH * Copyright (C) 2012-16 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de> * Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de> * Ralph Metzler <rjkm@metzlerbros.de>
* *
@ -34,21 +34,16 @@ MODULE_PARM_DESC(adapter_alloc,
#include "ddbridge-core.c" #include "ddbridge-core.c"
static struct ddb_regset octopus_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
static struct ddb_regmap octopus_net_map = { static struct ddb_regmap octopus_net_map = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_idma = 8,
.i2c = &octopus_i2c, .i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf, .i2c_buf = &octopus_i2c_buf,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.input = &octopus_input,
.output = &octopus_output,
}; };
static struct ddb_regset octopus_gtl = { static struct ddb_regset octopus_gtl = {
@ -58,8 +53,16 @@ static struct ddb_regset octopus_gtl = {
}; };
static struct ddb_regmap octopus_net_gtl = { static struct ddb_regmap octopus_net_gtl = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_idma = 8,
.irq_base_gtl = 10,
.i2c = &octopus_i2c, .i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf, .i2c_buf = &octopus_i2c_buf,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.input = &octopus_input,
.output = &octopus_output,
.gtl = &octopus_gtl, .gtl = &octopus_gtl,
}; };
@ -185,9 +188,7 @@ static int __init octonet_probe(struct platform_device *pdev)
ddbwritel(dev, 0, ETHER_CONTROL); ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS); ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS);
for (i = 0; i < 16; i++) ddb_reset_ios(dev);
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
usleep_range(5000, 6000);
irq = platform_get_irq(dev->pfdev, 0); irq = platform_get_irq(dev->pfdev, 0);
if (irq < 0) if (irq < 0)
@ -236,7 +237,7 @@ static __init int init_octonet(void)
int res; int res;
pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION
", Copyright (C) 2010-15 Digital Devices GmbH\n"); ", Copyright (C) 2010-16 Digital Devices GmbH\n");
res = ddb_class_create(); res = ddb_class_create();
if (res) if (res)
return res; return res;

View File

@ -1054,12 +1054,31 @@ static int set_parameters(struct dvb_frontend *fe)
return stat; return stat;
} }
static int get_frequency_offset(struct stv *state, s32 *off)
{
u8 cfr0, cfr1, cfr2;
s32 derot;
read_reg(state, RSTV0910_P2_CFR2 + state->regoff, &cfr2);
read_reg(state, RSTV0910_P2_CFR2 + state->regoff, &cfr1);
read_reg(state, RSTV0910_P2_CFR2 + state->regoff, &cfr0);
derot = ((u32) cfr2 << 16) | ((u32)cfr1 << 8) | cfr0;
if (derot & (1<<23))
derot |= 0xFF000000;
*off = - (s32) (((s64) derot * (s64) state->base->mclk) >> 24);
pr_info("foff = %d\n", *off);
return 0;
}
static int get_frontend(struct dvb_frontend *fe) static int get_frontend(struct dvb_frontend *fe)
{ {
struct stv *state = fe->demodulator_priv; struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 tmp; u8 tmp;
if (state->ReceiveMode == Mode_DVBS2) { if (state->ReceiveMode == Mode_DVBS2) {
u32 mc; u32 mc;
enum fe_modulation modcod2mod[0x20] = { enum fe_modulation modcod2mod[0x20] = {
@ -1132,6 +1151,9 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
u32 FECLock = 0; u32 FECLock = 0;
u16 val; u16 val;
u32 ber; u32 ber;
s32 foff;
get_frequency_offset(state, &foff);
read_signal_strength(fe, &val); read_signal_strength(fe, &val);
@ -1446,8 +1468,6 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
int i; int i;
read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2); read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2);
//KdPrintEx((MSG_INFO "_%d " __FUNCTION__ " AGCIQIN1 = %02x%02x\n",m_Instance,Reg[0],Reg[1]));
*strength = (((u32) Reg[0]) << 8) | Reg[1]; *strength = (((u32) Reg[0]) << 8) | Reg[1];
for (i = 0; i < 5; i += 1) { for (i = 0; i < 5; i += 1) {
@ -1456,7 +1476,6 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
msleep(3); msleep(3);
} }
Power /= 5; Power /= 5;
bbgain = (465 - Log10x100(Power)) * 10; bbgain = (465 - Log10x100(Power)) * 10;
if (fe->ops.tuner_ops.get_rf_strength) if (fe->ops.tuner_ops.get_rf_strength)
@ -1464,7 +1483,7 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
else else
*strength = 0; *strength = 0;
printk("pwr = %d bb = %d str = %u\n", Power, bbgain, *strength); //printk("pwr = %d bb = %d str = %u\n", Power, bbgain, *strength);
if (bbgain < (s32) *strength) if (bbgain < (s32) *strength)
*strength -= bbgain; *strength -= bbgain;
else else

View File

@ -26,6 +26,10 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#ifndef __user
#define __user
#endif
typedef enum { typedef enum {
// All functions return -2 on "not open" // All functions return -2 on "not open"
OSD_Close=1, // () OSD_Close=1, // ()

View File

@ -30,6 +30,10 @@
#include <time.h> #include <time.h>
#endif #endif
#ifndef __user
#define __user
#endif
typedef enum { typedef enum {
VIDEO_FORMAT_4_3, /* Select 4:3 format */ VIDEO_FORMAT_4_3, /* Select 4:3 format */
VIDEO_FORMAT_16_9, /* Select 16:9 format. */ VIDEO_FORMAT_16_9, /* Select 16:9 format. */