From 17b3e1ed260d95adf6292844d97598c973baf900 Mon Sep 17 00:00:00 2001 From: Ralph Metzler Date: Sun, 27 Aug 2017 22:09:43 +0200 Subject: [PATCH] move ci support to separate file --- ddbridge/Kbuild | 4 +- ddbridge/Makefile | 4 +- ddbridge/Makefile.kernel | 4 +- ddbridge/ddbridge-ci.c | 350 +++++++++++++++++++++++++++++++++++++++ ddbridge/ddbridge-core.c | 330 +----------------------------------- ddbridge/ddbridge.h | 2 + 6 files changed, 359 insertions(+), 335 deletions(-) create mode 100644 ddbridge/ddbridge-ci.c diff --git a/ddbridge/Kbuild b/ddbridge/Kbuild index 510e7d0..4e2bb79 100644 --- a/ddbridge/Kbuild +++ b/ddbridge/Kbuild @@ -1,7 +1,7 @@ EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.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-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 +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 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o obj-$(CONFIG_DVB_OCTONET) += octonet.o diff --git a/ddbridge/Makefile b/ddbridge/Makefile index 7c27f43..8ddac6f 100644 --- a/ddbridge/Makefile +++ b/ddbridge/Makefile @@ -2,8 +2,8 @@ # Makefile for the ddbridge device driver # -ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o -octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o +ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o +octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o obj-$(CONFIG_DVB_OCTONET) += octonet.o diff --git a/ddbridge/Makefile.kernel b/ddbridge/Makefile.kernel index b413e9e..bef5174 100644 --- a/ddbridge/Makefile.kernel +++ b/ddbridge/Makefile.kernel @@ -2,8 +2,8 @@ # Makefile for the ddbridge device driver # -ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.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-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 +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 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o obj-$(CONFIG_DVB_OCTONET) += octonet.o diff --git a/ddbridge/ddbridge-ci.c b/ddbridge/ddbridge-ci.c new file mode 100644 index 0000000..99b2e2c --- /dev/null +++ b/ddbridge/ddbridge-ci.c @@ -0,0 +1,350 @@ +/* + * ddbridge-i2c.c: Digital Devices bridge i2c driver + * + * Copyright (C) 2010-2017 Digital Devices GmbH + * Ralph Metzler + * Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, point your browser to + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "ddbridge.h" +#include "ddbridge-io.h" +#include "ddbridge-i2c.h" + +/* Octopus CI internal CI interface */ + +static int wait_ci_ready(struct ddb_ci *ci) +{ + u32 count = 10; + + ndelay(500); + do { + if (ddbreadl(ci->port->dev, + CI_CONTROL(ci->nr)) & CI_READY) + break; + usleep_range(1, 2); + if ((--count) == 0) + return -1; + } while (1); + return 0; +} + +static int read_attribute_mem(struct dvb_ca_en50221 *ca, + int slot, int address) +{ + struct ddb_ci *ci = ca->data; + u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); + + if (address > CI_BUFFER_SIZE) + return -1; + ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, + CI_DO_READ_ATTRIBUTES(ci->nr)); + wait_ci_ready(ci); + val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); + return val; +} + +static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, + int address, u8 value) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, + CI_DO_ATTRIBUTE_RW(ci->nr)); + wait_ci_ready(ci); + return 0; +} + +static int read_cam_control(struct dvb_ca_en50221 *ca, + int slot, u8 address) +{ + u32 count = 100; + struct ddb_ci *ci = ca->data; + u32 res; + + ddbwritel(ci->port->dev, CI_READ_CMD | address, + CI_DO_IO_RW(ci->nr)); + ndelay(500); + do { + res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); + if (res & CI_READY) + break; + usleep_range(1, 2); + if ((--count) == 0) + return -1; + } while (1); + return 0xff & res; +} + +static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, + u8 address, u8 value) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, + CI_DO_IO_RW(ci->nr)); + wait_ci_ready(ci); + return 0; +} + +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)); + msleep(100); + ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, + CI_CONTROL(ci->nr)); + ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, + CI_CONTROL(ci->nr)); + usleep_range(20, 25); + ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, + CI_CONTROL(ci->nr)); + return 0; +} + +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)); + msleep(300); + return 0; +} + +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)); + + ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, + CI_CONTROL(ci->nr)); + 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)); + int stat = 0; + + if (val & CI_CAM_DETECT) + stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; + if (val & CI_CAM_READY) + stat |= DVB_CA_EN50221_POLL_CAM_READY; + return stat; +} + +static struct dvb_ca_en50221 en_templ = { + .read_attribute_mem = read_attribute_mem, + .write_attribute_mem = write_attribute_mem, + .read_cam_control = read_cam_control, + .write_cam_control = write_cam_control, + .slot_reset = slot_reset, + .slot_shutdown = slot_shutdown, + .slot_ts_enable = slot_ts_enable, + .poll_slot_status = poll_slot_status, +}; + +static void ci_attach(struct ddb_port *port) +{ + struct ddb_ci *ci = 0; + + ci = kzalloc(sizeof(*ci), GFP_KERNEL); + if (!ci) + return; + memcpy(&ci->en, &en_templ, sizeof(en_templ)); + ci->en.data = ci; + port->en = &ci->en; + ci->port = port; + ci->nr = port->nr - 2; +} + +/* DuoFlex Dual CI support */ + +static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) +{ + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + ci->port->creg = (ci->port->creg & ~mask) | data; + return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); +} + +static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, + int slot, int address) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + int res; + u8 val; + + res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); + return res ? res : val; +} + +static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, + int address, u8 value) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + return i2c_write_reg16(i2c, adr, 0x8000 | address, value); +} + +static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, + int slot, u8 address) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + u8 val; + int res; + + res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); + return res ? res : val; +} + +static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, + u8 address, u8 value) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); +} + +static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + write_creg(ci, 0x01, 0x01); + write_creg(ci, 0x04, 0x04); + msleep(20); + write_creg(ci, 0x02, 0x02); + write_creg(ci, 0x00, 0x04); + write_creg(ci, 0x18, 0x18); + return 0; +} + +static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + /*i2c_write_reg(i2c, adr, 0x03, 0x60);*/ + /*i2c_write_reg(i2c, adr, 0x00, 0xc0);*/ + write_creg(ci, 0x10, 0xff); + write_creg(ci, 0x08, 0x08); + return 0; +} + +static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + write_creg(ci, 0x00, 0x10); + return 0; +} + +static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + u8 val = 0; + int stat = 0; + + i2c_read_reg(i2c, adr, 0x01, &val); + + if (val & 2) + stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; + if (val & 1) + stat |= DVB_CA_EN50221_POLL_CAM_READY; + return stat; +} + +static struct dvb_ca_en50221 en_xo2_templ = { + .read_attribute_mem = read_attribute_mem_xo2, + .write_attribute_mem = write_attribute_mem_xo2, + .read_cam_control = read_cam_control_xo2, + .write_cam_control = write_cam_control_xo2, + .slot_reset = slot_reset_xo2, + .slot_shutdown = slot_shutdown_xo2, + .slot_ts_enable = slot_ts_enable_xo2, + .poll_slot_status = poll_slot_status_xo2, +}; + +static void ci_xo2_attach(struct ddb_port *port) +{ + struct ddb_ci *ci = 0; + struct i2c_adapter *i2c; + + ci = kzalloc(sizeof(*ci), GFP_KERNEL); + if (!ci) + return; + memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); + ci->en.data = ci; + port->en = &ci->en; + ci->port = port; + ci->nr = port->nr - 2; + ci->port->creg = 0; + i2c = &ci->port->i2c->adap; + write_creg(ci, 0x10, 0xff); + write_creg(ci, 0x08, 0x08); +} + +static struct cxd2099_cfg cxd_cfg = { + .bitrate = 72000, + .adr = 0x40, + .polarity = 1, + .clock_mode = 1, + .max_i2c = 512, +}; + +int ddb_ci_attach(struct ddb_port *port, u32 bitrate) +{ + switch (port->type) { + case DDB_CI_EXTERNAL_SONY: + cxd_cfg.bitrate = bitrate; + port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); + if (!port->en) + return -ENODEV; + dvb_ca_en50221_init(port->dvb[0].adap, + port->en, 0, 1); + break; + + case DDB_CI_EXTERNAL_XO2: + case DDB_CI_EXTERNAL_XO2_B: + ci_xo2_attach(port); + if (!port->en) + return -ENODEV; + dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); + break; + + case DDB_CI_INTERNAL: + ci_attach(port); + if (!port->en) + return -ENODEV; + dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); + break; + } + return 0; +} diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index 1e40c39..0f6a2e3 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -2467,334 +2467,6 @@ static void ddb_port_probe(struct ddb_port *port) /****************************************************************************/ /****************************************************************************/ -static int wait_ci_ready(struct ddb_ci *ci) -{ - u32 count = 10; - - ndelay(500); - do { - if (ddbreadl(ci->port->dev, - CI_CONTROL(ci->nr)) & CI_READY) - break; - usleep_range(1, 2); - if ((--count) == 0) - return -1; - } while (1); - return 0; -} - -static int read_attribute_mem(struct dvb_ca_en50221 *ca, - int slot, int address) -{ - struct ddb_ci *ci = ca->data; - u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); - - if (address > CI_BUFFER_SIZE) - return -1; - ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, - CI_DO_READ_ATTRIBUTES(ci->nr)); - wait_ci_ready(ci); - val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); - return val; -} - -static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, - int address, u8 value) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, - CI_DO_ATTRIBUTE_RW(ci->nr)); - wait_ci_ready(ci); - return 0; -} - -static int read_cam_control(struct dvb_ca_en50221 *ca, - int slot, u8 address) -{ - u32 count = 100; - struct ddb_ci *ci = ca->data; - u32 res; - - ddbwritel(ci->port->dev, CI_READ_CMD | address, - CI_DO_IO_RW(ci->nr)); - ndelay(500); - do { - res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); - if (res & CI_READY) - break; - usleep_range(1, 2); - if ((--count) == 0) - return -1; - } while (1); - return 0xff & res; -} - -static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, - u8 address, u8 value) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, - CI_DO_IO_RW(ci->nr)); - wait_ci_ready(ci); - return 0; -} - -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)); - msleep(100); - ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, - CI_CONTROL(ci->nr)); - ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, - CI_CONTROL(ci->nr)); - usleep_range(20, 25); - ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, - CI_CONTROL(ci->nr)); - return 0; -} - -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)); - msleep(300); - return 0; -} - -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)); - - ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, - CI_CONTROL(ci->nr)); - 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)); - int stat = 0; - - if (val & CI_CAM_DETECT) - stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; - if (val & CI_CAM_READY) - stat |= DVB_CA_EN50221_POLL_CAM_READY; - return stat; -} - -static struct dvb_ca_en50221 en_templ = { - .read_attribute_mem = read_attribute_mem, - .write_attribute_mem = write_attribute_mem, - .read_cam_control = read_cam_control, - .write_cam_control = write_cam_control, - .slot_reset = slot_reset, - .slot_shutdown = slot_shutdown, - .slot_ts_enable = slot_ts_enable, - .poll_slot_status = poll_slot_status, -}; - -static void ci_attach(struct ddb_port *port) -{ - struct ddb_ci *ci = 0; - - ci = kzalloc(sizeof(*ci), GFP_KERNEL); - if (!ci) - return; - memcpy(&ci->en, &en_templ, sizeof(en_templ)); - ci->en.data = ci; - port->en = &ci->en; - ci->port = port; - ci->nr = port->nr - 2; -} - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) -{ - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - ci->port->creg = (ci->port->creg & ~mask) | data; - return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); -} - -static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, - int slot, int address) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - int res; - u8 val; - - res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); - return res ? res : val; -} - -static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, - int address, u8 value) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - return i2c_write_reg16(i2c, adr, 0x8000 | address, value); -} - -static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, - int slot, u8 address) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - u8 val; - int res; - - res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); - return res ? res : val; -} - -static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, - u8 address, u8 value) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); -} - -static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - write_creg(ci, 0x01, 0x01); - write_creg(ci, 0x04, 0x04); - msleep(20); - write_creg(ci, 0x02, 0x02); - write_creg(ci, 0x00, 0x04); - write_creg(ci, 0x18, 0x18); - return 0; -} - -static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - /*i2c_write_reg(i2c, adr, 0x03, 0x60);*/ - /*i2c_write_reg(i2c, adr, 0x00, 0xc0);*/ - write_creg(ci, 0x10, 0xff); - write_creg(ci, 0x08, 0x08); - return 0; -} - -static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - write_creg(ci, 0x00, 0x10); - return 0; -} - -static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - u8 val = 0; - int stat = 0; - - i2c_read_reg(i2c, adr, 0x01, &val); - - if (val & 2) - stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; - if (val & 1) - stat |= DVB_CA_EN50221_POLL_CAM_READY; - return stat; -} - -static struct dvb_ca_en50221 en_xo2_templ = { - .read_attribute_mem = read_attribute_mem_xo2, - .write_attribute_mem = write_attribute_mem_xo2, - .read_cam_control = read_cam_control_xo2, - .write_cam_control = write_cam_control_xo2, - .slot_reset = slot_reset_xo2, - .slot_shutdown = slot_shutdown_xo2, - .slot_ts_enable = slot_ts_enable_xo2, - .poll_slot_status = poll_slot_status_xo2, -}; - -static void ci_xo2_attach(struct ddb_port *port) -{ - struct ddb_ci *ci = 0; - struct i2c_adapter *i2c; - - ci = kzalloc(sizeof(*ci), GFP_KERNEL); - if (!ci) - return; - memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); - ci->en.data = ci; - port->en = &ci->en; - ci->port = port; - ci->nr = port->nr - 2; - ci->port->creg = 0; - i2c = &ci->port->i2c->adap; - write_creg(ci, 0x10, 0xff); - write_creg(ci, 0x08, 0x08); -} - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -struct cxd2099_cfg cxd_cfg = { - .bitrate = 72000, - .adr = 0x40, - .polarity = 1, - .clock_mode = 1, - .max_i2c = 512, -}; - -static int ddb_ci_attach(struct ddb_port *port) -{ - switch (port->type) { - case DDB_CI_EXTERNAL_SONY: - cxd_cfg.bitrate = ci_bitrate; - port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, - port->en, 0, 1); - break; - - case DDB_CI_EXTERNAL_XO2: - case DDB_CI_EXTERNAL_XO2_B: - ci_xo2_attach(port); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); - break; - - case DDB_CI_INTERNAL: - ci_attach(port); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); - break; - } - return 0; -} - static int ddb_port_attach(struct ddb_port *port) { int ret = 0; @@ -2811,7 +2483,7 @@ static int ddb_port_attach(struct ddb_port *port) port->input[1]->redi = port->input[1]; break; case DDB_PORT_CI: - ret = ddb_ci_attach(port); + ret = ddb_ci_attach(port, ci_bitrate); if (ret < 0) break; case DDB_PORT_LOOP: diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index 16b61f3..cd62269 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -564,4 +564,6 @@ void ddb_class_destroy(void); int ddb_i2c_init(struct ddb *dev); void ddb_i2c_release(struct ddb *dev); +int ddb_ci_attach(struct ddb_port *port, u32 bitrate); + #endif