From: Michael Krufky Date: Sun, 19 Nov 2006 22:45:26 +0000 (-0300) Subject: V4L/DVB (4846): Create new lgh06xf atsc tuner module X-Git-Tag: v2.6.20-rc1~145^2~5^2~80 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76db93d03f1e9a9a3371f787ae30780cdf10400c;p=linux-2.6 V4L/DVB (4846): Create new lgh06xf atsc tuner module This patch creates a new atsc tuner module for the LG TDVS-H06xF ATSC tuners, called lgh06xf. The purpose of this change is to reduce some duplicated code, and to allow the lgh06xf tuner code to take advantage of dvb_attach(). As a side effect, the dependency of dvb-bt8xx on dvb-pll has been removed, since the lgh06xf module itself will use dvb-pll, while remaining optional for the dvb-bt8xx driver through the use of DVB_FE_CUSTOMISE Acked-by: Andrew de Quincey Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index a0dcd59da7..7987595893 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index b8ba878634..c2b35e3662 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -14,7 +14,7 @@ #include "stv0297.h" #include "mt312.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "dvb-pll.h" /* lnb control */ @@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir return request_firmware(fw, name, fc->dev); } -static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) -{ - struct flexcop_device *fc = fe->dvb->priv; - return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); -} - static struct lgdt330x_config air2pc_atsc_hd5000_config = { .demod_address = 0x59, .demod_chip = LGDT3303, @@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) /* try the air atsc 3nd generation (lgdt3303) */ if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; - fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index ae2ff5dc23..dd66b60fbc 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -1,13 +1,13 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 - select DVB_PLL select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_SP887X if !DVB_FE_CUSTOMISE select DVB_NXT6000 if !DVB_FE_CUSTOMISE select DVB_CX24110 if !DVB_FE_CUSTOMISE select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select FW_LOADER help diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 14e69a736e..80a85cb497 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -34,7 +34,6 @@ #include "dvb_frontend.h" #include "dvb-bt8xx.h" #include "bt878.h" -#include "dvb-pll.h" static int debug; @@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = { .demod_init = digitv_alps_tded4_demod_init, }; -static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) -{ - struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; - return lg_h06xf_pll_set(fe, card->i2c_adapter, params); -} - static struct lgdt330x_config tdvs_tua6034_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, @@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) lgdt330x_reset(card); card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) { - card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; + dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); dprintk ("dvb_bt8xx: lgdt330x detected\n"); } break; diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 4745a9017a..e75f4173c0 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,7 +37,7 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "zl10353.h" struct dvb_bt8xx_card { diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index dfd53d5e79..bfe5691dde 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -98,6 +98,7 @@ config DVB_USB_CXUSB depends on DVB_USB select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 4e2eef86ec..ae039b9cb7 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -27,7 +27,7 @@ #include "cx22702.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "mt352.h" #include "mt352_priv.h" #include "zl10353.h" @@ -324,13 +324,6 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) return 0; } -static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *fep) -{ - struct dvb_usb_adapter *adap = fe->dvb->priv; - return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep); -} - static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, @@ -398,7 +391,7 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { - adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; + dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); return 0; } diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7279e587e1..af314bb1dc 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -297,6 +297,14 @@ config DVB_TUNER_MT2060 help A driver for the silicon IF tuner MT2060 from Microtune. +config DVB_TUNER_LGH06XF + tristate "LG TDVS-H06xF ATSC tuner" + depends on DVB_CORE && I2C + select DVB_PLL + default m if DVB_FE_CUSTOMISE + help + A driver for the LG TDVS-H06xF ATSC tuner family. + comment "Miscellaneous devices" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 593152ecf7..3fa6e5d32a 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o +obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h deleted file mode 100644 index 754d51d111..0000000000 --- a/drivers/media/dvb/frontends/lg_h06xf.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _LG_H06XF_H_ -#define _LG_H06XF_H_ -#include "dvb-pll.h" - -static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, - struct dvb_frontend_parameters* params) -{ - u8 buf[4]; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, - .buf = buf, .len = sizeof(buf) }; - int err; - - dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lg_h06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - /* Set the Auxiliary Byte. */ - buf[0] = buf[2]; - buf[0] &= ~0x20; - buf[0] |= 0x18; - buf[1] = 0x50; - msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lg_h06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} -#endif diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c new file mode 100644 index 0000000000..badbea8ad8 --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.c @@ -0,0 +1,139 @@ +/* + * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dvb-pll.h" +#include "lgh06xf.h" + +#define LG_H06XF_PLL_I2C_ADDR 0x61 + +struct lgh06xf_priv { + struct i2c_adapter *i2c; + u32 frequency; +}; + +static int lgh06xf_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int lgh06xf_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct lgh06xf_priv *priv = fe->tuner_priv; + u8 buf[4]; + struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + u32 div; + int i; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + printk(KERN_WARNING "lgh06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + printk(KERN_WARNING "lgh06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + // calculate the frequency we set it to + for (i = 0; i < dvb_pll_lg_tdvs_h06xf.count; i++) { + if (params->frequency > dvb_pll_lg_tdvs_h06xf.entries[i].limit) + continue; + break; + } + div = (params->frequency + dvb_pll_lg_tdvs_h06xf.entries[i].offset) / + dvb_pll_lg_tdvs_h06xf.entries[i].stepsize; + priv->frequency = (div * dvb_pll_lg_tdvs_h06xf.entries[i].stepsize) - + dvb_pll_lg_tdvs_h06xf.entries[i].offset; + + return 0; +} + +static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct lgh06xf_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static struct dvb_tuner_ops lgh06xf_tuner_ops = { + .release = lgh06xf_release, + .set_params = lgh06xf_set_params, + .get_frequency = lgh06xf_get_frequency, +}; + +struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c) +{ + struct lgh06xf_priv *priv = NULL; + + priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c = i2c; + + memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name, + sizeof(fe->ops.tuner_ops.info.name)); + + fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min; + fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max; + + fe->tuner_priv = priv; + return fe; +} + +EXPORT_SYMBOL(lgh06xf_attach); + +MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support"); +MODULE_AUTHOR("Michael Krufky"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h new file mode 100644 index 0000000000..41c41fc59b --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.h @@ -0,0 +1,35 @@ +/* + * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LGH06XF_H_ +#define _LGH06XF_H_ +#include "dvb_frontend.h" + +#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE)) +extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, + struct i2c_adapter *i2c); +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_TUNER_LGH06XF */ + +#endif /* _LGH06XF_H_ */ diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0f9d969636..b2a66ba625 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -53,6 +53,7 @@ config VIDEO_CX88_DVB select DVB_OR51132 if !DVB_FE_CUSTOMISE select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8150c09cd2..0266a3616c 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -42,7 +42,7 @@ #include "cx22702.h" #include "or51132.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" @@ -392,18 +392,6 @@ static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, return 0; } -static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx88_core *core = dev->core; - - /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); - - return lg_h06xf_pll_set(fe, &core->i2c_adap, params); -} - static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; @@ -719,7 +707,8 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_5_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + dvb_attach(lgh06xf_attach, dev->dvb.frontend, + &dev->core->i2c_adap); } } break; @@ -737,7 +726,8 @@ static int dvb_register(struct cx8802_dev *dev) &pchdtv_hd5500, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + dvb_attach(lgh06xf_attach, dev->dvb.frontend, + &dev->core->i2c_adap); } } break;