diff options
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lnbp21.c | 145 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lnbp21.h | 102 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/Kconfig | 3 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/av7110.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/budget-ci.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/budget.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-budget/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 28 |
10 files changed, 169 insertions, 127 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 6d90ff3..64cd636 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -216,4 +216,14 @@ config DVB_LGDT330X An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. + +comment "Miscellaneous devices" + depends on DVB_CORE + +config DVB_LNBP21 + tristate "LNBP21 SEC controller" + depends on DVB_CORE + help + An SEC control chip. + endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index d09b607..7238e6e 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o +obj-$(CONFIG_DVB_LNBP21) += lnbp21.o diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c new file mode 100644 index 0000000..c9152c1 --- /dev/null +++ b/drivers/media/dvb/frontends/lnbp21.c @@ -0,0 +1,145 @@ +/* + * lnbp21.h - driver for lnb supply and control ic lnbp21 + * + * Copyright (C) 2006 Oliver Endriss + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/string.h> +#include <linux/slab.h> + +#include "dvb_frontend.h" +#include "lnbp21.h" + +struct lnbp21 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + lnbp21->config |= LNBP21_EN; + break; + case SEC_VOLTAGE_18: + lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); + break; + default: + return -EINVAL; + }; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + if (arg) + lnbp21->config |= LNBP21_LLC; + else + lnbp21->config &= ~LNBP21_LLC; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void lnbp21_release(struct dvb_frontend *fe) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + + /* LNBP power off */ + lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops->release = lnbp21->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops->release) + fe->ops->release(fe); +} + +int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +{ + struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); + if (!lnbp21) + return -ENOMEM; + + /* default configuration */ + lnbp21->config = LNBP21_ISEL; + lnbp21->i2c = i2c; + fe->misc_priv = lnbp21; + + /* bits which should be forced to '1' */ + lnbp21->override_or = override_set; + + /* bits which should be forced to '0' */ + lnbp21->override_and = ~override_clear; + + /* detect if it is present or not */ + if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(lnbp21); + fe->misc_priv = NULL; + return -EIO; + } + + /* install release callback */ + lnbp21->release_chain = fe->ops->release; + fe->ops->release = lnbp21_release; + + /* override frontend ops */ + fe->ops->set_voltage = lnbp21_set_voltage; + fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + + return 0; +} +EXPORT_SYMBOL(lnbp21_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21"); +MODULE_AUTHOR("Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h index 0dcbe61..047a4ab 100644 --- a/drivers/media/dvb/frontends/lnbp21.h +++ b/drivers/media/dvb/frontends/lnbp21.h @@ -27,7 +27,7 @@ #ifndef _LNBP21_H #define _LNBP21_H -/* system register */ +/* system register bits */ #define LNBP21_OLF 0x01 #define LNBP21_OTF 0x02 #define LNBP21_EN 0x04 @@ -37,103 +37,9 @@ #define LNBP21_ISEL 0x40 #define LNBP21_PCL 0x80 -struct lnbp21 { - u8 config; - u8 override_or; - u8 override_and; - struct i2c_adapter *i2c; - void (*release_chain)(struct dvb_frontend* fe); -}; +#include <linux/dvb/frontend.h> -static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, - .buf = &lnbp21->config, - .len = sizeof(lnbp21->config) }; - - lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); - - switch(voltage) { - case SEC_VOLTAGE_OFF: - break; - case SEC_VOLTAGE_13: - lnbp21->config |= LNBP21_EN; - break; - case SEC_VOLTAGE_18: - lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); - break; - default: - return -EINVAL; - }; - - lnbp21->config |= lnbp21->override_or; - lnbp21->config &= lnbp21->override_and; - - return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; -} - -static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, - .buf = &lnbp21->config, - .len = sizeof(lnbp21->config) }; - - if (arg) - lnbp21->config |= LNBP21_LLC; - else - lnbp21->config &= ~LNBP21_LLC; - - lnbp21->config |= lnbp21->override_or; - lnbp21->config &= lnbp21->override_and; - - return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; -} - -static void lnbp21_exit(struct dvb_frontend *fe) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - - /* LNBP power off */ - lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); - - /* free data & call next release routine */ - fe->ops->release = lnbp21->release_chain; - kfree(fe->misc_priv); - fe->misc_priv = NULL; - if (fe->ops->release) - fe->ops->release(fe); -} - -static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) -{ - struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); - - if (!lnbp21) - return -ENOMEM; - - /* default configuration */ - lnbp21->config = LNBP21_ISEL; - - /* bits which should be forced to '1' */ - lnbp21->override_or = override_set; - - /* bits which should be forced to '0' */ - lnbp21->override_and = ~override_clear; - - /* install release callback */ - lnbp21->release_chain = fe->ops->release; - fe->ops->release = lnbp21_exit; - - /* override frontend ops */ - fe->ops->set_voltage = lnbp21_set_voltage; - fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - - lnbp21->i2c = i2c; - fe->misc_priv = lnbp21; - - return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); -} +/* override_set and override_clear control which system register bits (above) to always set & clear */ +extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); #endif diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index b5ac7df..987881f 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -10,6 +10,7 @@ config DVB_AV7110 select DVB_SP8870 select DVB_STV0297 select DVB_L64781 + select DVB_LNBP21 help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -67,6 +68,7 @@ config DVB_BUDGET select DVB_TDA8083 select DVB_TDA10021 select DVB_S5H1420 + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -84,6 +86,7 @@ config DVB_BUDGET_CI select DVB_STV0297 select DVB_STV0299 select DVB_TDA1004X + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 5f976d5..1a6d7a3 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2223,7 +2223,7 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops->tuner_ops.set_params = alps_bsbe1_tuner_set_params; av7110->fe->tuner_priv = &av7110->i2c_adap; - if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) { + if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) { printk("dvb-ttpci: LNBP21 not found!\n"); if (av7110->fe->ops->release) av7110->fe->ops->release(av7110->fe); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index ed610e5..145e12f 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1043,7 +1043,7 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; - if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { + if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); if (budget_ci->budget.dvb_frontend->ops->release) budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index a231975..d98395f 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -423,7 +423,7 @@ static void frontend_init(struct budget *budget) budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops->tuner_ops.set_params = s5h1420_tuner_set_params; - if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { + if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig index 914587d..d1004e8 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/dvb/ttusb-budget/Kconfig @@ -6,6 +6,7 @@ config DVB_TTUSB_BUDGET select DVB_VES1820 select DVB_TDA8083 select DVB_STV0299 + select DVB_LNBP21 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index cd19ba6..7158130 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -30,6 +30,7 @@ #include "tda1004x.h" #include "stv0299.h" #include "tda8083.h" +#include "lnbp21.h" #include <linux/dvb/frontend.h> #include <linux/dvb/dmx.h> @@ -486,31 +487,6 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe, } #endif -static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; - int ret; - u8 data[1]; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) }; - - switch(voltage) { - case SEC_VOLTAGE_OFF: - data[0] = 0x00; - break; - case SEC_VOLTAGE_13: - data[0] = 0x44; - break; - case SEC_VOLTAGE_18: - data[0] = 0x4c; - break; - default: - return -EINVAL; - }; - - ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1); - return (ret != 1) ? -EIO : 0; -} - static int ttusb_update_lnb(struct ttusb *ttusb) { u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1, @@ -1415,7 +1391,7 @@ static void frontend_init(struct ttusb* ttusb) if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1 alps_stv0299_config.inittab = alps_bsbe1_inittab; - ttusb->fe->ops->set_voltage = lnbp21_set_voltage; + lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0); } else { // ALPS BSRU6 ttusb->fe->ops->set_voltage = ttusb_set_voltage; } |