From 4d087a3b8c9c2fc90c55dc99d57bc3a1df9ab067 Mon Sep 17 00:00:00 2001 From: internal <> Date: Mon, 31 Jul 2023 22:29:08 +0200 Subject: [PATCH] change lnb and ci bases to be configurable --- ddbridge/ddbridge-ci.c | 31 +++++++++++++++++-------------- ddbridge/ddbridge-core.c | 32 ++++++++++++++++++-------------- ddbridge/ddbridge-hw.c | 38 +++++++++++++------------------------- ddbridge/ddbridge-max.c | 26 +++++++++++++++----------- ddbridge/ddbridge-regs.h | 36 +++++++++++++++++------------------- ddbridge/ddbridge.h | 7 ++++--- 6 files changed, 84 insertions(+), 86 deletions(-) diff --git a/ddbridge/ddbridge-ci.c b/ddbridge/ddbridge-ci.c index 365f8fc..d7a36aa 100644 --- a/ddbridge/ddbridge-ci.c +++ b/ddbridge/ddbridge-ci.c @@ -32,7 +32,7 @@ static int wait_ci_ready(struct ddb_ci *ci) ndelay(500); do { if (ddbreadl(ci->port->dev, - CI_CONTROL(ci->nr)) & CI_READY) + CI_CONTROL(ci)) & CI_READY) break; usleep_range(1, 2); if ((--count) == 0) @@ -50,7 +50,7 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca, if (address > CI_BUFFER_SIZE) return -1; 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); val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); return val; @@ -62,7 +62,7 @@ static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, struct ddb_ci *ci = ca->data; 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); return 0; } @@ -75,10 +75,10 @@ static int read_cam_control(struct dvb_ca_en50221 *ca, u32 res; ddbwritel(ci->port->dev, CI_READ_CMD | address, - CI_DO_IO_RW(ci->nr)); + CI_DO_IO_RW(ci)); ndelay(500); do { - res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); + res = ddbreadl(ci->port->dev, CI_READDATA(ci)); if (res & CI_READY) break; 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; 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); return 0; } @@ -104,15 +104,15 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) struct ddb_ci *ci = ca->data; ddbwritel(ci->port->dev, CI_POWER_ON, - CI_CONTROL(ci->nr)); + CI_CONTROL(ci)); msleep(300); 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, - CI_CONTROL(ci->nr)); + CI_CONTROL(ci)); usleep_range(20, 25); ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, - CI_CONTROL(ci->nr)); + CI_CONTROL(ci)); return 0; } @@ -120,7 +120,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) { 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); 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) { 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, - CI_CONTROL(ci->nr)); + CI_CONTROL(ci)); return 0; } static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { 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; if (val & CI_CAM_DETECT) @@ -162,6 +162,8 @@ static struct dvb_ca_en50221 en_templ = { static void ci_attach(struct ddb_port *port) { 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); if (!ci) @@ -171,6 +173,7 @@ static void ci_attach(struct ddb_port *port) port->en = &ci->en; ci->port = port; ci->nr = port->nr - 2; + ci->regs = DDB_LINK_TAG(port->lnr) | (off + 32 * ci->nr); } /* DuoFlex Dual CI support */ diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index c654a32..2726887 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -467,7 +467,7 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags) gap = output->port->gap; 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; if (dev->link[0].ids.regmapid >= 0x10003 && !(flags & 1)) { if (!(flags & 2)) { @@ -1596,8 +1596,7 @@ static int dvb_register_adapters(struct ddb *dev) } if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD || - dev->link[0].info->type == DDB_OCTONET || - dev->link[0].info->type == DDB_OCTOPRO) { + dev->link[0].info->type == DDB_OCTONET) { port = &dev->port[0]; adap = port->dvb[0].adap; ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, @@ -2102,7 +2101,7 @@ static void ddb_port_probe(struct ddb_port *port) return; } - if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI && + if (port->nr == 1 && link->info->ci_mask && link->info->i2c_mask == 1) { port->name = "NO TAB"; port->class = DDB_PORT_NONE; @@ -2130,15 +2129,16 @@ static void ddb_port_probe(struct ddb_port *port) port->name = "DUAL MCI"; port->type_name = "MCI"; port->class = DDB_PORT_TUNER; - port->type = DDB_TUNER_MCI + link->info->mci_type; + port->type = link->info->mci_type; 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->type_name = "INTERNAL"; port->class = DDB_PORT_CI; port->type = DDB_CI_INTERNAL; + return; } if (!port->i2c) @@ -2716,24 +2716,28 @@ static void ddb_ports_init(struct ddb *dev) continue; switch (info->type) { - case DDB_OCTOPUS_CI: - if (i >= 2) { + case DDB_OCTONET: + case DDB_OCTOPUS: + 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; } - fallthrough; - case DDB_OCTONET: - case DDB_OCTOPUS: - 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_input_init(port, 2 * i, 0, 2 * p); + ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1); ddb_output_init(port, i); break; case DDB_OCTOPUS_MAX: case DDB_OCTOPUS_MAX_CT: 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 + 1, 1, 2 * p + 1); break; diff --git a/ddbridge/ddbridge-hw.c b/ddbridge/ddbridge-hw.c index b69aa43..c4e8291 100644 --- a/ddbridge/ddbridge-hw.c +++ b/ddbridge/ddbridge-hw.c @@ -246,7 +246,6 @@ static const struct ddb_regmap octopus_map = { .odma = &octopus_odma, .odma_buf = &octopus_odma_buf, .input = &octopus_input, - .output = &octopus_output, }; @@ -463,23 +462,25 @@ static const struct ddb_info ddb_satixs2v3 = { }; static const struct ddb_info ddb_ci = { - .type = DDB_OCTOPUS_CI, + .type = DDB_OCTOPUS, .name = "Digital Devices Octopus CI", .regmap = &octopus_map, .port_num = 4, .i2c_mask = 0x03, + .ci_mask = 0x0c, }; static const struct ddb_info ddb_cis = { - .type = DDB_OCTOPUS_CI, + .type = DDB_OCTOPUS, .name = "Digital Devices Octopus CI single", .regmap = &octopus_map, .port_num = 3, .i2c_mask = 0x03, + .ci_mask = 0x04, }; static const struct ddb_info ddb_ci_s2_pro = { - .type = DDB_OCTOPUS_CI, + .type = DDB_OCTOPUS, .name = "Digital Devices Octopus CI S2 Pro", .regmap = &octopus_map, .port_num = 4, @@ -487,10 +488,11 @@ static const struct ddb_info ddb_ci_s2_pro = { .board_control = 2, .board_control_2 = 4, .hw_min = 0x010007, + .ci_mask = 0x0c, }; 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", .regmap = &octopus_map, .port_num = 4, @@ -498,6 +500,7 @@ static const struct ddb_info ddb_ci_s2_pro_a = { .board_control = 2, .board_control_2 = 4, .hw_min = 0x010007, + .ci_mask = 0x0c, }; static const struct ddb_info ddb_dvbct = { @@ -621,24 +624,6 @@ static const struct ddb_info ddb_sdr_dvbt = { .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 = { .type = DDB_OCTOPUS_MAX, .name = "Digital Devices MAX S8 4/8", @@ -647,6 +632,7 @@ static const struct ddb_info ddb_s2_48 = { .i2c_mask = 0x01, .board_control = 1, .tempmon_irq = 24, + .lnb_base = 0x400, }; static const struct ddb_info ddb_ct2_8 = { @@ -719,8 +705,9 @@ static const struct ddb_info ddb_s2x_48 = { .i2c_mask = 0x00, .tempmon_irq = 24, .mci_ports = 4, - .mci_type = 0, + .mci_type = DDB_TUNER_MCI_SX8, .temp_num = 1, + .lnb_base = 0x400, }; 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, .tempmon_irq = 24, .mci_ports = 4, - .mci_type = 0, + .mci_type = DDB_TUNER_MCI_SX8, .temp_num = 1, + .lnb_base = 0x400, }; static const struct ddb_info ddb_m4 = { diff --git a/ddbridge/ddbridge-max.c b/ddbridge/ddbridge-max.c index b79a479..dcbdea6 100644 --- a/ddbridge/ddbridge-max.c +++ b/ddbridge/ddbridge-max.c @@ -49,11 +49,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) { 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)); - ddbwritel(dev, cmd | v, tag | LNB_CONTROL(lnb)); + ddbwritel(dev, cmd | v, tag | base | LNB_CONTROL(lnb)); 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) break; msleep(20); @@ -91,6 +92,7 @@ static int max_send_master_cmd(struct dvb_frontend *fe, struct ddb *dev = port->dev; struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; u32 tag = DDB_LINK_TAG(port->lnr); + u32 base = dev->link[port->lnr].info->lnb_base; int i; u32 fmode = dev->link[port->lnr].lnb.fmode; @@ -105,9 +107,9 @@ static int max_send_master_cmd(struct dvb_frontend *fe, dvb->diseqc_send_master_cmd(fe, cmd); 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++) - 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); mutex_unlock(&dev->link[port->lnr].lnb.lock); return 0; @@ -117,11 +119,12 @@ static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input, struct dvb_diseqc_master_cmd *cmd) { u32 tag = DDB_LINK_TAG(link); + u32 base = dev->link[link].info->lnb_base; 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++) - 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); return 0; } @@ -369,6 +372,7 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) struct ddb_port *port = input->port; struct ddb *dev = port->dev; 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]; u32 fmode = dev->link[port->lnr].lnb.fmode; @@ -377,14 +381,14 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) default: case 0: case 3: - ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input)); + ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(dvb->input)); break; case 1: case 2: - ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0)); - ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1)); - ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2)); - ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3)); + ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(0)); + ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(1)); + ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(2)); + ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(3)); break; } mutex_unlock(&dev->link[port->lnr].lnb.lock); diff --git a/ddbridge/ddbridge-regs.h b/ddbridge/ddbridge-regs.h index 73f172e..888b684 100644 --- a/ddbridge/ddbridge-regs.h +++ b/ddbridge/ddbridge-regs.h @@ -248,8 +248,7 @@ /* ------------------------------------------------------------------------- */ -#define LNB_BASE (0x400) -#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00) +#define LNB_CONTROL(i) ((i) * 0x20 + 0x00) #define LNB_CMD (7ULL << 0) #define LNB_CMD_NOP 0 #define LNB_CMD_INIT 1 @@ -265,27 +264,26 @@ #define LNB_INTERRUPT_BASE 4 -#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04) -#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08) -#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c) -#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) -#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14) +#define LNB_STATUS(i) ((i) * 0x20 + 0x04) +#define LNB_VOLTAGE(i) ((i) * 0x20 + 0x08) +#define LNB_CONFIG(i) ((i) * 0x20 + 0x0c) +#define LNB_BUF_LEVEL(i) ((i) * 0x20 + 0x10) +#define LNB_BUF_WRITE(i) ((i) * 0x20 + 0x14) -#define LNB_SETTING(i) (LNB_BASE + (i) * 0x20 + 0x0c) -#define LNB_FIFO_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) -#define LNB_RESET_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x10) -#define LNB_WRITE_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x14) +#define LNB_SETTING(i) ((i) * 0x20 + 0x0c) +#define LNB_FIFO_LEVEL(i) ((i) * 0x20 + 0x10) +#define LNB_RESET_FIFO(i) ((i) * 0x20 + 0x10) +#define LNB_WRITE_FIFO(i) ((i) * 0x20 + 0x14) /* ------------------------------------------------------------------------- */ /* CI Interface (only CI-Bridge) */ -#define CI_BASE (0x400) -#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) +#define CI_CONTROL(_ci) ((_ci)->regs + 0x00) -#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) -#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) -#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) -#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) +#define CI_DO_ATTRIBUTE_RW(_ci) ((_ci)->regs + 0x04) +#define CI_DO_IO_RW(_ci) ((_ci)->regs + 0x08) +#define CI_READDATA(_ci) ((_ci)->regs + 0x0c) +#define CI_DO_READ_ATTRIBUTES(_ci) ((_ci)->regs + 0x10) #define CI_RESET_CAM (0x00000001) #define CI_POWER_ON (0x00000002) @@ -305,8 +303,8 @@ #define CI_READ_CMD (0x40000000) #define CI_WRITE_CMD (0x80000000) -#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) -#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) +#define CI_BLOCKIO_SEND(_ci) ((_ci)->regs + 0x14) +#define CI_BLOCKIO_RECEIVE(_ci) ((_ci)->regs + 0x18) #define CI_BLOCKIO_SEND_COMMAND (0x80000000) #define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index b1d3a14..75030f7 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -147,13 +147,10 @@ struct ddb_info { u32 type; #define DDB_NONE 0 #define DDB_OCTOPUS 1 -#define DDB_OCTOPUS_CI 2 #define DDB_MOD 3 #define DDB_OCTONET 4 #define DDB_OCTOPUS_MAX 5 #define DDB_OCTOPUS_MAX_CT 6 -#define DDB_OCTOPRO 7 -#define DDB_OCTOPRO_HDIN 8 #define DDB_OCTOPUS_MCI 9 u32 version; char *name; @@ -175,11 +172,14 @@ struct ddb_info { #define TS_QUIRK_ALT_OSC 8 u8 mci_ports; u8 mci_type; + u8 ci_mask; u32 tempmon_irq; u32 lostlock_irq; u32 mdio_base; u32 hw_min; + u32 ci_base; + u32 lnb_base; const struct ddb_regmap *regmap; }; @@ -247,6 +247,7 @@ struct ddb_ci { struct dvb_ca_en50221 en; struct ddb_port *port; u32 nr; + u32 regs; }; struct ddb_io {