From 85bc9b510aae310ac5530ae364b1145b5cc0ce68 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 1 Aug 2011 00:52:11 -0300 Subject: [PATCH] [media] a8293: Allegro A8293 SEC driver Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 5 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/a8293.c | 184 +++++++++++++++++++++++++++ drivers/media/dvb/frontends/a8293.h | 41 ++++++ 4 files changed, 231 insertions(+) create mode 100644 drivers/media/dvb/frontends/a8293.c create mode 100644 drivers/media/dvb/frontends/a8293.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 17082df7da39..8e1a18337246 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -621,6 +621,11 @@ config DVB_ISL6423 help A SEC controller chip from Intersil +config DVB_A8293 + tristate "Allegro A8293" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + config DVB_LGS8GL5 tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 18d045d78bdb..08040cf1fd69 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -92,4 +92,5 @@ obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o obj-$(CONFIG_DVB_DRXK) += drxk.o obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o +obj-$(CONFIG_DVB_A8293) += a8293.o diff --git a/drivers/media/dvb/frontends/a8293.c b/drivers/media/dvb/frontends/a8293.c new file mode 100644 index 000000000000..bb56497e940a --- /dev/null +++ b/drivers/media/dvb/frontends/a8293.c @@ -0,0 +1,184 @@ +/* + * Allegro A8293 SEC driver + * + * Copyright (C) 2011 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "dvb_frontend.h" +#include "a8293.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +#define LOG_PREFIX "a8293" + +#undef dbg +#define dbg(f, arg...) \ + if (debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + + +struct a8293_priv { + struct i2c_adapter *i2c; + const struct a8293_config *cfg; + u8 reg[2]; +}; + +static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd) +{ + int ret; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg->i2c_addr, + .len = len, + .buf = val, + } + }; + + if (rd) + msg[0].flags = I2C_M_RD; + else + msg[0].flags = 0; + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + warn("i2c failed=%d rd=%d", ret, rd); + ret = -EREMOTEIO; + } + + return ret; +} + +static int a8293_wr(struct a8293_priv *priv, u8 *val, int len) +{ + return a8293_i2c(priv, val, len, 0); +} + +static int a8293_rd(struct a8293_priv *priv, u8 *val, int len) +{ + return a8293_i2c(priv, val, len, 1); +} + +static int a8293_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t fe_sec_voltage) +{ + struct a8293_priv *priv = fe->sec_priv; + int ret; + + dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage); + + switch (fe_sec_voltage) { + case SEC_VOLTAGE_OFF: + /* ENB=0 */ + priv->reg[0] = 0x10; + break; + case SEC_VOLTAGE_13: + /* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/ + priv->reg[0] = 0x31; + break; + case SEC_VOLTAGE_18: + /* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/ + priv->reg[0] = 0x38; + break; + default: + ret = -EINVAL; + goto err; + }; + + ret = a8293_wr(priv, &priv->reg[0], 1); + if (ret) + goto err; + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + +static void a8293_release_sec(struct dvb_frontend *fe) +{ + dbg("%s:", __func__); + + a8293_set_voltage(fe, SEC_VOLTAGE_OFF); + + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *a8293_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct a8293_config *cfg) +{ + int ret; + struct a8293_priv *priv = NULL; + u8 buf[2]; + + /* allocate memory for the internal priv */ + priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL); + if (priv == NULL) { + ret = -ENOMEM; + goto err; + } + + /* setup the priv */ + priv->i2c = i2c; + priv->cfg = cfg; + fe->sec_priv = priv; + + /* check if the SEC is there */ + ret = a8293_rd(priv, buf, 2); + if (ret) + goto err; + + /* ENB=0 */ + priv->reg[0] = 0x10; + ret = a8293_wr(priv, &priv->reg[1], 1); + if (ret) + goto err; + + /* TMODE=0, TGATE=1 */ + priv->reg[1] = 0x82; + ret = a8293_wr(priv, &priv->reg[1], 1); + if (ret) + goto err; + + info("Allegro A8293 SEC attached."); + + fe->ops.release_sec = a8293_release_sec; + + /* override frontend ops */ + fe->ops.set_voltage = a8293_set_voltage; + + return fe; +err: + dbg("%s: failed=%d", __func__, ret); + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(a8293_attach); + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("Allegro A8293 SEC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/a8293.h b/drivers/media/dvb/frontends/a8293.h new file mode 100644 index 000000000000..ed29e5504f76 --- /dev/null +++ b/drivers/media/dvb/frontends/a8293.h @@ -0,0 +1,41 @@ +/* + * Allegro A8293 SEC driver + * + * Copyright (C) 2011 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#ifndef A8293_H +#define A8293_H + +struct a8293_config { + u8 i2c_addr; +}; + +#if defined(CONFIG_DVB_A8293) || \ + (defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE)) +extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct a8293_config *cfg); +#else +static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct a8293_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* A8293_H */ -- 2.34.1