From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from imap.netup.ru ([77.72.80.14]:54635 "EHLO imap.netup.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751038AbdEaM2Z (ORCPT ); Wed, 31 May 2017 08:28:25 -0400 Received: from mail-oi0-f42.google.com (mail-oi0-f42.google.com [209.85.218.42]) by imap.netup.ru (Postfix) with ESMTPSA id 391ED8B3F99 for ; Wed, 31 May 2017 15:28:23 +0300 (MSK) Received: by mail-oi0-f42.google.com with SMTP id w10so13113066oif.0 for ; Wed, 31 May 2017 05:28:22 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <20170409193828.18458-18-d.scheller.oss@gmail.com> References: <20170409193828.18458-1-d.scheller.oss@gmail.com> <20170409193828.18458-18-d.scheller.oss@gmail.com> From: Abylay Ospan Date: Wed, 31 May 2017 08:28:00 -0400 Message-ID: Subject: Re: [PATCH 17/19] [media] ddbridge: add I2C functions, add XO2 module support To: Daniel Scheller Cc: Kozlov Sergey , Mauro Carvalho Chehab , linux-media , rjkm@metzlerbros.de Content-Type: text/plain; charset="UTF-8" Sender: linux-media-owner@vger.kernel.org List-ID: not related to cxd2841er. I'm skipping this ... same for rest of the patches (18/19, 19/19). 2017-04-09 15:38 GMT-04:00 Daniel Scheller : > From: Daniel Scheller > > Some Flex modules (mostly with anyof C/C2/T/T2 demods based on the Sony > CXD28xxER series) are equipped with an interface named XO2 (which > appears to be the Lattice MachXO2). Add functionality to detect such > links and initialise them, so any tuner module with such an interface can > be used. > > This also adds dummy detection for any possible connected module, telling > the user it isn't supported at this very moment. > > Also adds i2c_io(), i2c_write() and i2c_write_reg(), all required for the > XO2 handling functionality. > > Signed-off-by: Daniel Scheller > --- > drivers/media/pci/ddbridge/ddbridge-core.c | 147 +++++++++++++++++++++++++++++ > drivers/media/pci/ddbridge/ddbridge.h | 11 +++ > 2 files changed, 158 insertions(+) > > diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c > index 6b49fa9..ab88fcf 100644 > --- a/drivers/media/pci/ddbridge/ddbridge-core.c > +++ b/drivers/media/pci/ddbridge/ddbridge-core.c > @@ -43,6 +43,10 @@ > #include "stv0367_priv.h" > #include "tda18212.h" > > +static int xo2_speed = 2; > +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"); > + > DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > /* MSI had problems with lost interrupts, fixed but needs testing */ > @@ -50,6 +54,24 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > > /******************************************************************************/ > > +static int i2c_io(struct i2c_adapter *adapter, u8 adr, > + u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) > +{ > + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, > + .buf = wbuf, .len = wlen }, > + {.addr = adr, .flags = I2C_M_RD, > + .buf = rbuf, .len = rlen } }; > + return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; > +} > + > +static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) > +{ > + struct i2c_msg msg = {.addr = adr, .flags = 0, > + .buf = data, .len = len}; > + > + return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; > +} > + > static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) > { > struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, > @@ -83,6 +105,14 @@ static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, > return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; > } > > +static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, > + u8 reg, u8 val) > +{ > + u8 msg[2] = {reg, val}; > + > + return i2c_write(adap, adr, msg, 2); > +} > + > static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) > { > struct ddb *dev = i2c->dev; > @@ -1272,6 +1302,70 @@ static void ddb_ports_detach(struct ddb *dev) > /****************************************************************************/ > /****************************************************************************/ > > +static int init_xo2(struct ddb_port *port) > +{ > + struct i2c_adapter *i2c = &port->i2c->adap; > + u8 val, data[2]; > + int res; > + > + res = i2c_read_regs(i2c, 0x10, 0x04, data, 2); > + if (res < 0) > + return res; > + > + if (data[0] != 0x01) { > + pr_info("Port %d: invalid XO2\n", port->nr); > + return -1; > + } > + > + i2c_read_reg(i2c, 0x10, 0x08, &val); > + if (val != 0) { > + i2c_write_reg(i2c, 0x10, 0x08, 0x00); > + msleep(100); > + } > + /* Enable tuner power, disable pll, reset demods */ > + i2c_write_reg(i2c, 0x10, 0x08, 0x04); > + usleep_range(2000, 3000); > + /* Release demod resets */ > + i2c_write_reg(i2c, 0x10, 0x08, 0x07); > + > + /* speed: 0=55,1=75,2=90,3=104 MBit/s */ > + i2c_write_reg(i2c, 0x10, 0x09, > + ((xo2_speed >= 0 && xo2_speed <= 3) ? xo2_speed : 2)); > + > + i2c_write_reg(i2c, 0x10, 0x0a, 0x01); > + i2c_write_reg(i2c, 0x10, 0x0b, 0x01); > + > + usleep_range(2000, 3000); > + /* Start XO2 PLL */ > + i2c_write_reg(i2c, 0x10, 0x08, 0x87); > + > + return 0; > +} > + > +static int port_has_xo2(struct ddb_port *port, u8 *type, u8 *id) > +{ > + u8 probe[1] = { 0x00 }, data[4]; > + > + *type = DDB_XO2_TYPE_NONE; > + > + if (i2c_io(&port->i2c->adap, 0x10, probe, 1, data, 4)) > + return 0; > + if (data[0] == 'D' && data[1] == 'F') { > + *id = data[2]; > + *type = DDB_XO2_TYPE_DUOFLEX; > + return 1; > + } > + if (data[0] == 'C' && data[1] == 'I') { > + *id = data[2]; > + *type = DDB_XO2_TYPE_CI; > + return 1; > + } > + return 0; > +} > + > +/****************************************************************************/ > +/****************************************************************************/ > + > static int port_has_ci(struct ddb_port *port) > { > u8 val; > @@ -1322,6 +1416,7 @@ static void ddb_port_probe(struct ddb_port *port) > { > struct ddb *dev = port->dev; > char *modname = "NO MODULE"; > + u8 xo2_type, xo2_id; > > port->class = DDB_PORT_NONE; > > @@ -1329,6 +1424,58 @@ static void ddb_port_probe(struct ddb_port *port) > modname = "CI"; > port->class = DDB_PORT_CI; > ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); > + } else if (port_has_xo2(port, &xo2_type, &xo2_id)) { > + printk(KERN_INFO "Port %d (TAB %d): XO2 type: %d, id: %d\n", > + port->nr, port->nr+1, xo2_type, xo2_id); > + > + ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); > + > + switch (xo2_type) { > + case DDB_XO2_TYPE_DUOFLEX: > + init_xo2(port); > + switch (xo2_id >> 2) { > + case 0: > + modname = "DUAL DVB-S2 (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_DVBS_STV0910; > + break; > + case 1: > + modname = "DUAL DVB-C/T/T2 (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_DVBCT2_SONY; > + break; > + case 2: > + modname = "DUAL DVB-ISDBT (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_ISDBT_SONY; > + break; > + case 3: > + modname = "DUAL DVB-C/C2/T/T2 (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_DVBC2T2_SONY; > + break; > + case 4: > + modname = "DUAL ATSC (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_ATSC_ST; > + break; > + case 5: > + modname = "DUAL DVB-C/C2/T/T2/ISDBT (unsupported)"; > + port->class = DDB_PORT_NONE; > + port->type = DDB_TUNER_XO2_DVBC2T2I_SONY; > + break; > + default: > + modname = "Unknown XO2 DuoFlex module\n"; > + break; > + } > + break; > + case DDB_XO2_TYPE_CI: > + printk(KERN_INFO "DuoFlex CI modules not supported\n"); > + break; > + default: > + printk(KERN_INFO "Unknown XO2 DuoFlex module\n"); > + break; > + } > } else if (port_has_stv0900(port)) { > modname = "DUAL DVB-S2"; > port->class = DDB_PORT_TUNER; > diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h > index 734e18e..4e49faa 100644 > --- a/drivers/media/pci/ddbridge/ddbridge.h > +++ b/drivers/media/pci/ddbridge/ddbridge.h > @@ -48,6 +48,10 @@ > > #define DDB_LINK_TAG(_x) (_x << DDB_LINK_SHIFT) > > +#define DDB_XO2_TYPE_NONE 0 > +#define DDB_XO2_TYPE_DUOFLEX 1 > +#define DDB_XO2_TYPE_CI 2 > + > struct ddb_info { > int type; > #define DDB_NONE 0 > @@ -154,6 +158,13 @@ struct ddb_port { > #define DDB_TUNER_DVBS_ST_AA 2 > #define DDB_TUNER_DVBCT_TR 16 > #define DDB_TUNER_DVBCT_ST 17 > +#define DDB_TUNER_XO2_DVBS_STV0910 32 > +#define DDB_TUNER_XO2_DVBCT2_SONY 33 > +#define DDB_TUNER_XO2_ISDBT_SONY 34 > +#define DDB_TUNER_XO2_DVBC2T2_SONY 35 > +#define DDB_TUNER_XO2_ATSC_ST 36 > +#define DDB_TUNER_XO2_DVBC2T2I_SONY 37 > + > u32 adr; > > struct ddb_input *input[2]; > -- > 2.10.2 > -- Abylay Ospan, NetUP Inc. http://www.netup.tv