From: Maik Broemme <mbroemme@parallels.com>
To: Linux Media Mailing List <linux-media@vger.kernel.org>
Subject: [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file
Date: Sun, 3 Nov 2013 01:40:15 +0100 [thread overview]
Message-ID: <20131103004014.GL7956@parallels.com> (raw)
In-Reply-To: <20131103002235.GD7956@parallels.com>
Moved i2c interfaces from ddbridge-core.c into separate file.
Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
drivers/media/pci/ddbridge/ddbridge-i2c.c | 239 ++++++++++++++++++++++++++++++
1 file changed, 239 insertions(+)
create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
new file mode 100644
index 0000000..5e9788c
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
@@ -0,0 +1,239 @@
+/*
+ * ddbridge-i2c.c: Digital Devices bridge i2c driver
+ *
+ * Copyright (C) 2010-2013 Digital Devices GmbH
+ * Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include "ddbridge.h"
+#include "ddbridge-regs.h"
+
+static int i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
+{
+ struct ddb *dev = i2c->dev;
+ int stat;
+ u32 val;
+ u32 istat;
+
+ // i2c->done = 0;
+ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+
+ // TODO: fix timeout issue.
+ // stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
+ stat = wait_for_completion_timeout(&i2c->completion, HZ);
+ if (stat <= 0) {
+ printk(KERN_ERR "DDBridge I2C timeout, card %d, port %d\n",
+ dev->nr, i2c->nr);
+ istat = ddbreadl(dev, INTERRUPT_STATUS);
+ printk(KERN_ERR "DDBridge IRS %08x\n", istat);
+ ddbwritel(dev, istat, INTERRUPT_ACK);
+ return -EIO;
+ }
+ val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
+ if (val & 0x70000)
+ return -EIO;
+ return 0;
+}
+
+static int i2c_master_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg msg[], int num)
+{
+ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
+ struct ddb *dev = i2c->dev;
+ u8 addr = 0;
+
+ if (num)
+ addr = msg[0].addr;
+ if (num == 2 && msg[1].flags & I2C_M_RD &&
+ !(msg[0].flags & I2C_M_RD)) {
+ memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
+ msg[0].buf, msg[0].len);
+ ddbwritel(dev, msg[0].len|(msg[1].len << 16),
+ i2c->regs + I2C_TASKLENGTH);
+ if (!i2c_cmd(i2c, addr, 1)) {
+ memcpy_fromio(msg[1].buf,
+ dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
+ msg[1].len);
+ return num;
+ }
+ }
+ if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+ ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf,
+ msg[0].buf, msg[0].len);
+ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
+ if (!i2c_cmd(i2c, addr, 2)) {
+ return num;
+ }
+ }
+ if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+ if (!i2c_cmd(i2c, addr, 3)) {
+ ddbcpyfrom(dev, msg[0].buf,
+ I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
+ return num;
+ }
+ }
+ return -EIO;
+}
+
+static u32 i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static void i2c_handler(unsigned long priv)
+{
+ struct ddb_i2c *i2c = (struct ddb_i2c *) priv;
+
+ complete(&i2c->completion);
+}
+
+static struct i2c_algorithm i2c_algo = {
+ .master_xfer = i2c_master_xfer,
+ .functionality = i2c_functionality,
+};
+
+int ddb_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;
+}
+
+int ddb_i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = 1 } };
+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+int ddb_i2c_read_regs(struct i2c_adapter *adapter,
+ u8 adr, u8 reg, u8 *val, u8 len)
+{
+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+ .buf = ®, .len = 1 },
+ {.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = len } };
+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_regs16(struct i2c_adapter *adapter,
+ u8 adr, u16 reg, u8 *val, u8 len)
+{
+ u8 reg16[2] = { reg >> 8, reg };
+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+ .buf = reg16, .len = 2 },
+ {.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = len } };
+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
+{
+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+ .buf = ®, .len = 1},
+ {.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = 1 } };
+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+ u16 reg, u8 *val)
+{
+ u8 msg[2] = {reg >> 8, reg & 0xff};
+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+ .buf = msg, .len = 2},
+ {.addr = adr, .flags = I2C_M_RD,
+ .buf = val, .len = 1 } };
+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
+ u16 reg, u8 val)
+{
+ u8 msg[3] = {reg >> 8, reg & 0xff, val};
+
+ return ddb_i2c_write(adap, adr, msg, 3);
+}
+
+int ddb_i2c_write_reg(struct i2c_adapter *adap, u8 adr,
+ u8 reg, u8 val)
+{
+ u8 msg[2] = {reg, val};
+
+ return ddb_i2c_write(adap, adr, msg, 2);
+}
+
+void ddb_i2c_release(struct ddb *dev)
+{
+ int i;
+ struct ddb_i2c *i2c;
+ struct i2c_adapter *adap;
+
+ for (i = 0; i < dev->info->i2c_num; i++) {
+ i2c = &dev->i2c[i];
+ adap = &i2c->adap;
+ i2c_del_adapter(adap);
+ }
+}
+
+int ddb_i2c_init(struct ddb *dev)
+{
+ int i, j, stat = 0;
+ struct ddb_i2c *i2c;
+ struct i2c_adapter *adap;
+
+ for (i = 0; i < dev->info->i2c_num; i++) {
+ i2c = &dev->i2c[i];
+ dev->handler[i] = i2c_handler;
+ dev->handler_data[i] = (unsigned long) i2c;
+ i2c->dev = dev;
+ i2c->nr = i;
+ i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
+ i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
+ i2c->regs = 0x80 + i * 0x20;
+ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
+ ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf,
+ i2c->regs + I2C_TASKADDRESS);
+ // init_waitqueue_head(&i2c->wq);
+ init_completion(&i2c->completion);
+
+ adap = &i2c->adap;
+ i2c_set_adapdata(adap, i2c);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+ adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
+#else
+#ifdef I2C_CLASS_TV_ANALOG
+ adap->class = I2C_CLASS_TV_ANALOG;
+#endif
+#endif
+ strcpy(adap->name, "ddbridge");
+ adap->algo = &i2c_algo;
+ adap->algo_data = (void *)i2c;
+ adap->dev.parent = dev->dev;
+ stat = i2c_add_adapter(adap);
+ if (stat)
+ break;
+ }
+ if (stat)
+ for (j = 0; j < i; j++) {
+ i2c = &dev->i2c[j];
+ adap = &i2c->adap;
+ i2c_del_adapter(adap);
+ }
+ return stat;
+}
--
1.8.4.2
next prev parent reply other threads:[~2013-11-03 0:40 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-03 0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
2013-11-03 0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
2013-11-03 9:23 ` Mauro Carvalho Chehab
2013-11-03 10:47 ` Ralph Metzler
2013-11-03 11:22 ` Mauro Carvalho Chehab
2013-11-03 12:20 ` Maik Broemme
2013-11-03 0:25 ` [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner Maik Broemme
2013-11-03 9:27 ` Mauro Carvalho Chehab
2013-11-03 12:17 ` Maik Broemme
2013-11-04 12:13 ` Mauro Carvalho Chehab
2013-11-03 0:28 ` [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator Maik Broemme
2013-11-03 9:29 ` Mauro Carvalho Chehab
2013-11-03 0:31 ` [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner Maik Broemme
2013-11-03 9:56 ` Mauro Carvalho Chehab
2013-11-03 17:00 ` Antti Palosaari
2013-11-04 12:12 ` Mauro Carvalho Chehab
2013-11-04 12:49 ` Maik Broemme
2013-11-04 13:04 ` Antti Palosaari
2013-11-03 0:32 ` [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2 Maik Broemme
2013-11-03 10:11 ` Mauro Carvalho Chehab
2013-11-03 0:33 ` [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants Maik Broemme
2013-11-03 10:16 ` Mauro Carvalho Chehab
2013-11-03 0:35 ` [PATCH 07/12] ddbridge: Updated ddbridge registers Maik Broemme
2013-11-03 10:17 ` Mauro Carvalho Chehab
2013-11-03 0:40 ` Maik Broemme [this message]
2013-11-03 10:23 ` [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file Mauro Carvalho Chehab
2013-11-03 0:41 ` [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card Maik Broemme
2013-11-03 10:44 ` Mauro Carvalho Chehab
2013-11-03 0:44 ` [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10 Maik Broemme
2013-11-03 10:49 ` Mauro Carvalho Chehab
2013-11-03 0:45 ` [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes Maik Broemme
2013-11-03 10:50 ` Mauro Carvalho Chehab
2013-11-03 0:46 ` [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge Maik Broemme
2013-11-03 10:51 ` Mauro Carvalho Chehab
2013-11-03 10:58 ` [PATCH 00/12] DDBridge 0.9.10 driver updates Mauro Carvalho Chehab
2013-11-03 12:46 ` Maik Broemme
2013-11-03 13:11 ` Ralph Metzler
2013-11-03 13:19 ` Maik Broemme
2013-11-04 12:19 ` Mauro Carvalho Chehab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131103004014.GL7956@parallels.com \
--to=mbroemme@parallels.com \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox