diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
| commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
| tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/dvb/ddbridge | |
| parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) | |
Diffstat (limited to 'drivers/media/dvb/ddbridge')
| -rw-r--r-- | drivers/media/dvb/ddbridge/Kconfig | 18 | ||||
| -rw-r--r-- | drivers/media/dvb/ddbridge/Makefile | 14 | ||||
| -rw-r--r-- | drivers/media/dvb/ddbridge/ddbridge-core.c | 1719 | ||||
| -rw-r--r-- | drivers/media/dvb/ddbridge/ddbridge-regs.h | 151 | ||||
| -rw-r--r-- | drivers/media/dvb/ddbridge/ddbridge.h | 187 |
5 files changed, 2089 insertions, 0 deletions
diff --git a/drivers/media/dvb/ddbridge/Kconfig b/drivers/media/dvb/ddbridge/Kconfig new file mode 100644 index 00000000000..d099e1a12c8 --- /dev/null +++ b/drivers/media/dvb/ddbridge/Kconfig | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | config DVB_DDBRIDGE | ||
| 2 | tristate "Digital Devices bridge support" | ||
| 3 | depends on DVB_CORE && PCI && I2C | ||
| 4 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | ||
| 5 | select DVB_STV6110x if !DVB_FE_CUSTOMISE | ||
| 6 | select DVB_STV090x if !DVB_FE_CUSTOMISE | ||
| 7 | select DVB_DRXK if !DVB_FE_CUSTOMISE | ||
| 8 | select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE | ||
| 9 | ---help--- | ||
| 10 | Support for cards with the Digital Devices PCI express bridge: | ||
| 11 | - Octopus PCIe Bridge | ||
| 12 | - Octopus mini PCIe Bridge | ||
| 13 | - Octopus LE | ||
| 14 | - DuoFlex S2 Octopus | ||
| 15 | - DuoFlex CT Octopus | ||
| 16 | - cineS2(v6) | ||
| 17 | |||
| 18 | Say Y if you own such a card and want to use it. | ||
diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/dvb/ddbridge/Makefile new file mode 100644 index 00000000000..de4fe193c3e --- /dev/null +++ b/drivers/media/dvb/ddbridge/Makefile | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the ddbridge device driver | ||
| 3 | # | ||
| 4 | |||
| 5 | ddbridge-objs := ddbridge-core.o | ||
| 6 | |||
| 7 | obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o | ||
| 8 | |||
| 9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ | ||
| 10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ | ||
| 11 | EXTRA_CFLAGS += -Idrivers/media/common/tuners/ | ||
| 12 | |||
| 13 | # For the staging CI driver cxd2099 | ||
| 14 | EXTRA_CFLAGS += -Idrivers/staging/cxd2099/ | ||
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c new file mode 100644 index 00000000000..573d540f213 --- /dev/null +++ b/drivers/media/dvb/ddbridge/ddbridge-core.c | |||
| @@ -0,0 +1,1719 @@ | |||
| 1 | /* | ||
| 2 | * ddbridge.c: Digital Devices PCIe bridge driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010-2011 Digital Devices GmbH | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 only, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301, USA | ||
| 21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/poll.h> | ||
| 30 | #include <linux/io.h> | ||
| 31 | #include <linux/pci.h> | ||
| 32 | #include <linux/pci_ids.h> | ||
| 33 | #include <linux/timer.h> | ||
| 34 | #include <linux/version.h> | ||
| 35 | #include <linux/i2c.h> | ||
| 36 | #include <linux/swab.h> | ||
| 37 | #include <linux/vmalloc.h> | ||
| 38 | #include "ddbridge.h" | ||
| 39 | |||
| 40 | #include "ddbridge-regs.h" | ||
| 41 | |||
| 42 | #include "tda18271c2dd.h" | ||
| 43 | #include "stv6110x.h" | ||
| 44 | #include "stv090x.h" | ||
| 45 | #include "lnbh24.h" | ||
| 46 | #include "drxk.h" | ||
| 47 | |||
| 48 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 49 | |||
| 50 | /* MSI had problems with lost interrupts, fixed but needs testing */ | ||
| 51 | #undef CONFIG_PCI_MSI | ||
| 52 | |||
| 53 | /******************************************************************************/ | ||
| 54 | |||
| 55 | static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) | ||
| 56 | { | ||
| 57 | struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, | ||
| 58 | .buf = val, .len = 1 } }; | ||
| 59 | return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) | ||
| 63 | { | ||
| 64 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, | ||
| 65 | .buf = ®, .len = 1 }, | ||
| 66 | {.addr = adr, .flags = I2C_M_RD, | ||
| 67 | .buf = val, .len = 1 } }; | ||
| 68 | return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, | ||
| 72 | u16 reg, u8 *val) | ||
| 73 | { | ||
| 74 | u8 msg[2] = {reg>>8, reg&0xff}; | ||
| 75 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, | ||
| 76 | .buf = msg, .len = 2}, | ||
| 77 | {.addr = adr, .flags = I2C_M_RD, | ||
| 78 | .buf = val, .len = 1} }; | ||
| 79 | return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) | ||
| 83 | { | ||
| 84 | struct ddb *dev = i2c->dev; | ||
| 85 | int stat; | ||
| 86 | u32 val; | ||
| 87 | |||
| 88 | i2c->done = 0; | ||
| 89 | ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); | ||
| 90 | stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); | ||
| 91 | if (stat <= 0) { | ||
| 92 | printk(KERN_ERR "I2C timeout\n"); | ||
| 93 | { /* MSI debugging*/ | ||
| 94 | u32 istat = ddbreadl(INTERRUPT_STATUS); | ||
| 95 | printk(KERN_ERR "IRS %08x\n", istat); | ||
| 96 | ddbwritel(istat, INTERRUPT_ACK); | ||
| 97 | } | ||
| 98 | return -EIO; | ||
| 99 | } | ||
| 100 | val = ddbreadl(i2c->regs+I2C_COMMAND); | ||
| 101 | if (val & 0x70000) | ||
| 102 | return -EIO; | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, | ||
| 107 | struct i2c_msg msg[], int num) | ||
| 108 | { | ||
| 109 | struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); | ||
| 110 | struct ddb *dev = i2c->dev; | ||
| 111 | u8 addr = 0; | ||
| 112 | |||
| 113 | if (num) | ||
| 114 | addr = msg[0].addr; | ||
| 115 | |||
| 116 | if (num == 2 && msg[1].flags & I2C_M_RD && | ||
| 117 | !(msg[0].flags & I2C_M_RD)) { | ||
| 118 | memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, | ||
| 119 | msg[0].buf, msg[0].len); | ||
| 120 | ddbwritel(msg[0].len|(msg[1].len << 16), | ||
| 121 | i2c->regs+I2C_TASKLENGTH); | ||
| 122 | if (!ddb_i2c_cmd(i2c, addr, 1)) { | ||
| 123 | memcpy_fromio(msg[1].buf, | ||
| 124 | dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, | ||
| 125 | msg[1].len); | ||
| 126 | return num; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | ||
| 131 | ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); | ||
| 132 | ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); | ||
| 133 | if (!ddb_i2c_cmd(i2c, addr, 2)) | ||
| 134 | return num; | ||
| 135 | } | ||
| 136 | if (num == 1 && (msg[0].flags & I2C_M_RD)) { | ||
| 137 | ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); | ||
| 138 | if (!ddb_i2c_cmd(i2c, addr, 3)) { | ||
| 139 | ddbcpyfrom(msg[0].buf, | ||
| 140 | I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); | ||
| 141 | return num; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | return -EIO; | ||
| 145 | } | ||
| 146 | |||
| 147 | |||
| 148 | static u32 ddb_i2c_functionality(struct i2c_adapter *adap) | ||
| 149 | { | ||
| 150 | return I2C_FUNC_SMBUS_EMUL; | ||
| 151 | } | ||
| 152 | |||
| 153 | struct i2c_algorithm ddb_i2c_algo = { | ||
| 154 | .master_xfer = ddb_i2c_master_xfer, | ||
| 155 | .functionality = ddb_i2c_functionality, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static void ddb_i2c_release(struct ddb *dev) | ||
| 159 | { | ||
| 160 | int i; | ||
| 161 | struct ddb_i2c *i2c; | ||
