From c2e591fcb7aa5300cf6967edb29960628cf1831d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Oct 2008 13:44:38 -0300 Subject: V4L/DVB (9366): Move S921 driver to the proper place and allow it to compile Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 96b93e21a84b..8da1e81668e7 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -369,6 +369,17 @@ config DVB_S5H1411 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. +comment "ISDB-T (terrestrial) frontends" + depends on DVB_CORE + +config DVB_S921 + tristate "Sharp S921 tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module. + Say Y when you want to support this frontend. + comment "Digital terrestrial only tuners/PLL" depends on DVB_CORE -- cgit v1.2.3 From f71f11ed46df2f29daf928eb5fd8c6c2d1455f36 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Oct 2008 15:06:17 -0300 Subject: V4L/DVB (9367): Move lgdt3304 driver to the proper place and allow it to compile Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 2 + drivers/media/dvb/frontends/lgdt3304.c | 378 ++++++++++++++++++++++++++ drivers/media/dvb/frontends/lgdt3304.h | 45 +++ drivers/media/video/empia/lgdt3304/Makefile | 7 - drivers/media/video/empia/lgdt3304/lgdt3304.c | 378 -------------------------- drivers/media/video/empia/lgdt3304/lgdt3304.h | 45 --- 7 files changed, 433 insertions(+), 430 deletions(-) create mode 100644 drivers/media/dvb/frontends/lgdt3304.c create mode 100644 drivers/media/dvb/frontends/lgdt3304.h delete mode 100644 drivers/media/video/empia/lgdt3304/Makefile delete mode 100644 drivers/media/video/empia/lgdt3304/lgdt3304.c delete mode 100644 drivers/media/video/empia/lgdt3304/lgdt3304.h (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 8da1e81668e7..69eb1f8eb4a9 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -345,6 +345,14 @@ config DVB_LGDT330X An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. +config DVB_LGDT3304 + tristate "LG Electronics LGDT3304" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want + to support this frontend. + config DVB_S5H1409 tristate "Samsung S5H1409 based" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 11a5407ecdb7..651c9e889a66 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o obj-$(CONFIG_DVB_BCM3510) += bcm3510.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o +obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_ISL6405) += isl6405.o @@ -58,3 +59,4 @@ obj-$(CONFIG_DVB_SI21XX) += si21xx.o obj-$(CONFIG_DVB_STV0288) += stv0288.o obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_S921) += s921.o + diff --git a/drivers/media/dvb/frontends/lgdt3304.c b/drivers/media/dvb/frontends/lgdt3304.c new file mode 100644 index 000000000000..469ace5692c6 --- /dev/null +++ b/drivers/media/dvb/frontends/lgdt3304.c @@ -0,0 +1,378 @@ +/* + * Driver for LG ATSC lgdt3304 driver + * + * Copyright (C) 2008 Markus Rechberger + * + */ + +#include +#include +#include +#include "dvb_frontend.h" +#include "lgdt3304.h" + +static unsigned int debug = 0; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)"); + +#define dprintk(fmt, args...) if (debug) do {\ + printk("lgdt3304 debug: " fmt, ##args); } while (0) + +struct lgdt3304_state +{ + struct dvb_frontend frontend; + fe_modulation_t current_modulation; + __u32 snr; + __u32 current_frequency; + __u8 addr; + struct i2c_adapter *i2c; +}; + +static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len) +{ + struct lgdt3304_state *state = fe->demodulator_priv; + struct i2c_msg i2cmsgs = { + .addr = state->addr, + .flags = 0, + .len = 3, + .buf = buf + }; + int i; + int err; + + for (i=0; ii2c, &i2cmsgs, 1))<0) { + printk("%s i2c_transfer error %d\n", __FUNCTION__, err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + i2cmsgs.buf += 3; + } + return 0; +} + +static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg) +{ + struct lgdt3304_state *state = fe->demodulator_priv; + struct i2c_msg i2cmsgs[2]; + int ret; + __u8 buf; + + __u8 regbuf[2] = { reg>>8, reg&0xff }; + + i2cmsgs[0].addr = state->addr; + i2cmsgs[0].flags = 0; + i2cmsgs[0].len = 2; + i2cmsgs[0].buf = regbuf; + + i2cmsgs[1].addr = state->addr; + i2cmsgs[1].flags = I2C_M_RD; + i2cmsgs[1].len = 1; + i2cmsgs[1].buf = &buf; + + if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) { + printk("%s i2c_transfer error %d\n", __FUNCTION__, ret); + return ret; + } + + return buf; +} + +static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val) +{ + struct lgdt3304_state *state = fe->demodulator_priv; + char buffer[3] = { reg>>8, reg&0xff, val }; + int ret; + + struct i2c_msg i2cmsgs = { + .addr = state->addr, + .flags = 0, + .len = 3, + .buf=buffer + }; + ret = i2c_transfer(state->i2c, &i2cmsgs, 1); + if (ret != 1) { + printk("%s i2c_transfer error %d\n", __FUNCTION__, ret); + return ret; + } + + return 0; +} + + +static int lgdt3304_soft_Reset(struct dvb_frontend *fe) +{ + lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a); + lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b); + mdelay(200); + return 0; +} + +static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { + int err = 0; + + static __u8 lgdt3304_vsb8_data[] = { + /* 16bit , 8bit */ + /* regs , val */ + 0x00, 0x00, 0x02, + 0x00, 0x00, 0x13, + 0x00, 0x0d, 0x02, + 0x00, 0x0e, 0x02, + 0x00, 0x12, 0x32, + 0x00, 0x13, 0xc4, + 0x01, 0x12, 0x17, + 0x01, 0x13, 0x15, + 0x01, 0x14, 0x18, + 0x01, 0x15, 0xff, + 0x01, 0x16, 0x2c, + 0x02, 0x14, 0x67, + 0x02, 0x24, 0x8d, + 0x04, 0x27, 0x12, + 0x04, 0x28, 0x4f, + 0x03, 0x08, 0x80, + 0x03, 0x09, 0x00, + 0x03, 0x0d, 0x00, + 0x03, 0x0e, 0x1c, + 0x03, 0x14, 0xe1, + 0x05, 0x0e, 0x5b, + }; + + /* not yet tested .. */ + static __u8 lgdt3304_qam64_data[] = { + /* 16bit , 8bit */ + /* regs , val */ + 0x00, 0x00, 0x18, + 0x00, 0x0d, 0x02, + //0x00, 0x0e, 0x02, + 0x00, 0x12, 0x2a, + 0x00, 0x13, 0x00, + 0x03, 0x14, 0xe3, + 0x03, 0x0e, 0x1c, + 0x03, 0x08, 0x66, + 0x03, 0x09, 0x66, + 0x03, 0x0a, 0x08, + 0x03, 0x0b, 0x9b, + 0x05, 0x0e, 0x5b, + }; + + + /* tested with KWorld a340 */ + static __u8 lgdt3304_qam256_data[] = { + /* 16bit , 8bit */ + /* regs , val */ + 0x00, 0x00, 0x01, //0x19, + 0x00, 0x12, 0x2a, + 0x00, 0x13, 0x80, + 0x00, 0x0d, 0x02, + 0x03, 0x14, 0xe3, + + 0x03, 0x0e, 0x1c, + 0x03, 0x08, 0x66, + 0x03, 0x09, 0x66, + 0x03, 0x0a, 0x08, + 0x03, 0x0b, 0x9b, + + 0x03, 0x0d, 0x14, + //0x05, 0x0e, 0x5b, + 0x01, 0x06, 0x4a, + 0x01, 0x07, 0x3d, + 0x01, 0x08, 0x70, + 0x01, 0x09, 0xa3, + + 0x05, 0x04, 0xfd, + + 0x00, 0x0d, 0x82, + + 0x05, 0x0e, 0x5b, + + 0x05, 0x0e, 0x5b, + + 0x00, 0x02, 0x9a, + + 0x00, 0x02, 0x9b, + + 0x00, 0x00, 0x01, + 0x00, 0x12, 0x2a, + 0x00, 0x13, 0x80, + 0x00, 0x0d, 0x02, + 0x03, 0x14, 0xe3, + + 0x03, 0x0e, 0x1c, + 0x03, 0x08, 0x66, + 0x03, 0x09, 0x66, + 0x03, 0x0a, 0x08, + 0x03, 0x0b, 0x9b, + + 0x03, 0x0d, 0x14, + 0x01, 0x06, 0x4a, + 0x01, 0x07, 0x3d, + 0x01, 0x08, 0x70, + 0x01, 0x09, 0xa3, + + 0x05, 0x04, 0xfd, + + 0x00, 0x0d, 0x82, + + 0x05, 0x0e, 0x5b, + }; + + struct lgdt3304_state *state = fe->demodulator_priv; + if (state->current_modulation != param->u.vsb.modulation) { + switch(param->u.vsb.modulation) { + case VSB_8: + err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data, + sizeof(lgdt3304_vsb8_data)); + break; + case QAM_64: + err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data, + sizeof(lgdt3304_qam64_data)); + break; + case QAM_256: + err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data, + sizeof(lgdt3304_qam256_data)); + break; + default: + break; + } + + if (err) { + printk("%s error setting modulation\n", __FUNCTION__); + } else { + state->current_modulation = param->u.vsb.modulation; + } + } + state->current_frequency = param->frequency; + + lgdt3304_soft_Reset(fe); + + + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, param); + + return 0; +} + +static int lgdt3304_init(struct dvb_frontend *fe) { + return 0; +} + +static int lgdt3304_sleep(struct dvb_frontend *fe) { + return 0; +} + + +static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct lgdt3304_state *state = fe->demodulator_priv; + int r011d; + int qam_lck; + + *status = 0; + dprintk("lgdt read status\n"); + + r011d = lgdt3304_i2c_read_reg(fe, 0x011d); + + dprintk("%02x\n", r011d); + + switch(state->current_modulation) { + case VSB_8: + if (r011d & 0x80) { + dprintk("VSB Locked\n"); + *status |= FE_HAS_CARRIER; + *status |= FE_HAS_LOCK; + *status |= FE_HAS_SYNC; + *status |= FE_HAS_SIGNAL; + } + break; + case QAM_64: + case QAM_256: + qam_lck = r011d & 0x7; + switch(qam_lck) { + case 0x0: dprintk("Unlock\n"); + break; + case 0x4: dprintk("1st Lock in acquisition state\n"); + break; + case 0x6: dprintk("2nd Lock in acquisition state\n"); + break; + case 0x7: dprintk("Final Lock in good reception state\n"); + *status |= FE_HAS_CARRIER; + *status |= FE_HAS_LOCK; + *status |= FE_HAS_SYNC; + *status |= FE_HAS_SIGNAL; + break; + } + break; + default: + printk("%s unhandled modulation\n", __FUNCTION__); + } + + + return 0; +} + +static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber) +{ + dprintk("read ber\n"); + return 0; +} + +static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr) +{ + dprintk("read snr\n"); + return 0; +} + +static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks) +{ + dprintk("read ucblocks\n"); + return 0; +} + +static void lgdt3304_release(struct dvb_frontend *fe) +{ + struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops demod_lgdt3304={ + .info = { + .name = "LG 3304", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_stepsize = 62500, + .symbol_rate_min = 5056941, + .symbol_rate_max = 10762000, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + .init = lgdt3304_init, + .sleep = lgdt3304_sleep, + .set_frontend = lgdt3304_set_parameters, + .read_snr = lgdt3304_read_snr, + .read_ber = lgdt3304_read_ber, + .read_status = lgdt3304_read_status, + .read_ucblocks = lgdt3304_read_ucblocks, + .release = lgdt3304_release, +}; + +struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, + struct i2c_adapter *i2c) +{ + + struct lgdt3304_state *state; + state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); + memset(state, 0x0, sizeof(struct lgdt3304_state)); + state->addr = config->i2c_address; + state->i2c = i2c; + + memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; +} + +EXPORT_SYMBOL_GPL(lgdt3304_attach); +MODULE_AUTHOR("Markus Rechberger "); +MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/lgdt3304.h b/drivers/media/dvb/frontends/lgdt3304.h new file mode 100644 index 000000000000..fc409fe59acb --- /dev/null +++ b/drivers/media/dvb/frontends/lgdt3304.h @@ -0,0 +1,45 @@ +/* + * Driver for DVB-T lgdt3304 demodulator + * + * Copyright (C) 2008 Markus Rechberger + * + * 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 LGDT3304_H +#define LGDT3304_H + +#include + +struct lgdt3304_config +{ + /* demodulator's I2C address */ + u8 i2c_address; +}; + +#if defined(CONFIG_DVB_LGDT3304) || (defined(CONFIG_DVB_LGDT3304_MODULE) && defined(MODULE)) +extern struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_LGDT */ + +#endif /* LGDT3304_H */ diff --git a/drivers/media/video/empia/lgdt3304/Makefile b/drivers/media/video/empia/lgdt3304/Makefile deleted file mode 100644 index 4d261a7627a6..000000000000 --- a/drivers/media/video/empia/lgdt3304/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -lgdt3304-demod-objs := lgdt3304.o - -obj-m += lgdt3304-demod.o - -EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -EXTRA_CFLAGS += -DCONFIG_DVB_LGDT3304 diff --git a/drivers/media/video/empia/lgdt3304/lgdt3304.c b/drivers/media/video/empia/lgdt3304/lgdt3304.c deleted file mode 100644 index 2af09bef0d6c..000000000000 --- a/drivers/media/video/empia/lgdt3304/lgdt3304.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Driver for LG ATSC lgdt3304 driver - * - * Copyright (C) 2008 Markus Rechberger - * - */ - -#include -#include -#include -#include "dvb_frontend.h" -#include "lgdt3304.h" - -static unsigned int debug = 0; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)"); - -#define dprintk(fmt, args...) if (debug) do {\ - printk("lgdt3304 debug: " fmt, ##args); } while (0) - -struct lgdt3304_state -{ - struct dvb_frontend frontend; - fe_modulation_t current_modulation; - __u32 snr; - __u32 current_frequency; - __u8 addr; - struct i2c_adapter *i2c; -}; - -static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len) -{ - struct lgdt3304_state *state = fe->demodulator_priv; - struct i2c_msg i2cmsgs = { - .addr = state->addr, - .flags = 0, - .len = 3, - .buf = buf - }; - int i; - int err; - - for (i=0; ii2c, &i2cmsgs, 1))<0) { - printk("%s i2c_transfer error %d\n", __FUNCTION__, err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - i2cmsgs.buf += 3; - } - return 0; -} - -static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg) -{ - struct lgdt3304_state *state = fe->demodulator_priv; - struct i2c_msg i2cmsgs[2]; - int ret; - __u8 buf; - - __u8 regbuf[2] = { reg>>8, reg&0xff }; - - i2cmsgs[0].addr = state->addr; - i2cmsgs[0].flags = 0; - i2cmsgs[0].len = 2; - i2cmsgs[0].buf = regbuf; - - i2cmsgs[1].addr = state->addr; - i2cmsgs[1].flags = I2C_M_RD; - i2cmsgs[1].len = 1; - i2cmsgs[1].buf = &buf; - - if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) { - printk("%s i2c_transfer error %d\n", __FUNCTION__, ret); - return ret; - } - - return buf; -} - -static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val) -{ - struct lgdt3304_state *state = fe->demodulator_priv; - char buffer[3] = { reg>>8, reg&0xff, val }; - int ret; - - struct i2c_msg i2cmsgs = { - .addr = state->addr, - .flags = 0, - .len = 3, - .buf=buffer - }; - ret = i2c_transfer(state->i2c, &i2cmsgs, 1); - if (ret != 1) { - printk("%s i2c_transfer error %d\n", __FUNCTION__, ret); - return ret; - } - - return 0; -} - - -static int lgdt3304_soft_Reset(struct dvb_frontend *fe) -{ - lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a); - lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b); - mdelay(200); - return 0; -} - -static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { - int err = 0; - - static __u8 lgdt3304_vsb8_data[] = { - /* 16bit , 8bit */ - /* regs , val */ - 0x00, 0x00, 0x02, - 0x00, 0x00, 0x13, - 0x00, 0x0d, 0x02, - 0x00, 0x0e, 0x02, - 0x00, 0x12, 0x32, - 0x00, 0x13, 0xc4, - 0x01, 0x12, 0x17, - 0x01, 0x13, 0x15, - 0x01, 0x14, 0x18, - 0x01, 0x15, 0xff, - 0x01, 0x16, 0x2c, - 0x02, 0x14, 0x67, - 0x02, 0x24, 0x8d, - 0x04, 0x27, 0x12, - 0x04, 0x28, 0x4f, - 0x03, 0x08, 0x80, - 0x03, 0x09, 0x00, - 0x03, 0x0d, 0x00, - 0x03, 0x0e, 0x1c, - 0x03, 0x14, 0xe1, - 0x05, 0x0e, 0x5b, - }; - - /* not yet tested .. */ - static __u8 lgdt3304_qam64_data[] = { - /* 16bit , 8bit */ - /* regs , val */ - 0x00, 0x00, 0x18, - 0x00, 0x0d, 0x02, - //0x00, 0x0e, 0x02, - 0x00, 0x12, 0x2a, - 0x00, 0x13, 0x00, - 0x03, 0x14, 0xe3, - 0x03, 0x0e, 0x1c, - 0x03, 0x08, 0x66, - 0x03, 0x09, 0x66, - 0x03, 0x0a, 0x08, - 0x03, 0x0b, 0x9b, - 0x05, 0x0e, 0x5b, - }; - - - /* tested with KWorld a340 */ - static __u8 lgdt3304_qam256_data[] = { - /* 16bit , 8bit */ - /* regs , val */ - 0x00, 0x00, 0x01, //0x19, - 0x00, 0x12, 0x2a, - 0x00, 0x13, 0x80, - 0x00, 0x0d, 0x02, - 0x03, 0x14, 0xe3, - - 0x03, 0x0e, 0x1c, - 0x03, 0x08, 0x66, - 0x03, 0x09, 0x66, - 0x03, 0x0a, 0x08, - 0x03, 0x0b, 0x9b, - - 0x03, 0x0d, 0x14, - //0x05, 0x0e, 0x5b, - 0x01, 0x06, 0x4a, - 0x01, 0x07, 0x3d, - 0x01, 0x08, 0x70, - 0x01, 0x09, 0xa3, - - 0x05, 0x04, 0xfd, - - 0x00, 0x0d, 0x82, - - 0x05, 0x0e, 0x5b, - - 0x05, 0x0e, 0x5b, - - 0x00, 0x02, 0x9a, - - 0x00, 0x02, 0x9b, - - 0x00, 0x00, 0x01, - 0x00, 0x12, 0x2a, - 0x00, 0x13, 0x80, - 0x00, 0x0d, 0x02, - 0x03, 0x14, 0xe3, - - 0x03, 0x0e, 0x1c, - 0x03, 0x08, 0x66, - 0x03, 0x09, 0x66, - 0x03, 0x0a, 0x08, - 0x03, 0x0b, 0x9b, - - 0x03, 0x0d, 0x14, - 0x01, 0x06, 0x4a, - 0x01, 0x07, 0x3d, - 0x01, 0x08, 0x70, - 0x01, 0x09, 0xa3, - - 0x05, 0x04, 0xfd, - - 0x00, 0x0d, 0x82, - - 0x05, 0x0e, 0x5b, - }; - - struct lgdt3304_state *state = fe->demodulator_priv; - if (state->current_modulation != param->u.vsb.modulation) { - switch(param->u.vsb.modulation) { - case VSB_8: - err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data, - sizeof(lgdt3304_vsb8_data)); - break; - case QAM_64: - err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data, - sizeof(lgdt3304_qam64_data)); - break; - case QAM_256: - err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data, - sizeof(lgdt3304_qam256_data)); - break; - default: - break; - } - - if (err) { - printk("%s error setting modulation\n", __FUNCTION__); - } else { - state->current_modulation = param->u.vsb.modulation; - } - } - state->current_frequency = param->frequency; - - lgdt3304_soft_Reset(fe); - - - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe, param); - - return 0; -} - -static int lgdt3304_init(struct dvb_frontend *fe) { - return 0; -} - -static int lgdt3304_sleep(struct dvb_frontend *fe) { - return 0; -} - - -static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status) -{ - struct lgdt3304_state *state = fe->demodulator_priv; - int r011d; - int qam_lck; - - *status = 0; - dprintk("lgdt read status\n"); - - r011d = lgdt3304_i2c_read_reg(fe, 0x011d); - - dprintk("%02x\n", r011d); - - switch(state->current_modulation) { - case VSB_8: - if (r011d & 0x80) { - dprintk("VSB Locked\n"); - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_LOCK; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_SIGNAL; - } - break; - case QAM_64: - case QAM_256: - qam_lck = r011d & 0x7; - switch(qam_lck) { - case 0x0: dprintk("Unlock\n"); - break; - case 0x4: dprintk("1st Lock in acquisition state\n"); - break; - case 0x6: dprintk("2nd Lock in acquisition state\n"); - break; - case 0x7: dprintk("Final Lock in good reception state\n"); - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_LOCK; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_SIGNAL; - break; - } - break; - default: - printk("%s unhandled modulation\n", __FUNCTION__); - } - - - return 0; -} - -static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber) -{ - dprintk("read ber\n"); - return 0; -} - -static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr) -{ - dprintk("read snr\n"); - return 0; -} - -static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks) -{ - dprintk("read ucblocks\n"); - return 0; -} - -static void lgdt3304_release(struct dvb_frontend *fe) -{ - struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops demod_lgdt3304={ - .info = { - .name = "LG 3304", - .type = FE_ATSC, - .frequency_min = 54000000, - .frequency_max = 858000000, - .frequency_stepsize = 62500, - .symbol_rate_min = 5056941, - .symbol_rate_max = 10762000, - .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB - }, - .init = lgdt3304_init, - .sleep = lgdt3304_sleep, - .set_frontend = lgdt3304_set_parameters, - .read_snr = lgdt3304_read_snr, - .read_ber = lgdt3304_read_ber, - .read_status = lgdt3304_read_status, - .read_ucblocks = lgdt3304_read_ucblocks, - .release = lgdt3304_release, -}; - -struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, - struct i2c_adapter *i2c) -{ - - struct lgdt3304_state *state; - state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); - memset(state, 0x0, sizeof(struct lgdt3304_state)); - state->addr = config->i2c_address; - state->i2c = i2c; - - memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; - return &state->frontend; -} - -EXPORT_SYMBOL_GPL(lgdt3304_attach); -MODULE_AUTHOR("Markus Rechberger "); -MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/empia/lgdt3304/lgdt3304.h b/drivers/media/video/empia/lgdt3304/lgdt3304.h deleted file mode 100644 index fc409fe59acb..000000000000 --- a/drivers/media/video/empia/lgdt3304/lgdt3304.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Driver for DVB-T lgdt3304 demodulator - * - * Copyright (C) 2008 Markus Rechberger - * - * 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 LGDT3304_H -#define LGDT3304_H - -#include - -struct lgdt3304_config -{ - /* demodulator's I2C address */ - u8 i2c_address; -}; - -#if defined(CONFIG_DVB_LGDT3304) || (defined(CONFIG_DVB_LGDT3304_MODULE) && defined(MODULE)) -extern struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, - struct i2c_adapter *i2c); -#else -static inline struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, - struct i2c_adapter *i2c) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} -#endif /* CONFIG_DVB_LGDT */ - -#endif /* LGDT3304_H */ -- cgit v1.2.3 From e50e8e3338788359d63f0a1ea2e038dd48415754 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 3 Jul 2007 09:53:42 -0300 Subject: V4L/DVB (9376): Add STB0899 to build Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 10 ++++++++++ drivers/media/dvb/frontends/Makefile | 2 ++ 2 files changed, 12 insertions(+) (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 69eb1f8eb4a9..35eb5f888b42 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -12,6 +12,16 @@ config DVB_FE_CUSTOMISE If unsure say N. +comment "Multistandard (satellite) frontends" + depends on DVB_CORE + +config DVB_STB0899 + tristate "STB0899 based" + depends on DVB_CORE + help + A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want + to support this demodulator based frontends + comment "DVB-S (satellite) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 651c9e889a66..f0a31c56ca47 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -6,9 +6,11 @@ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ s921-objs := s921_module.o s921_core.o +stb0899-objs = stb0899_drv.o stb0899_algo.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o +obj-$(CONFIG_DVB_STB0899) += stb0899.o obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_CX24110) += cx24110.o -- cgit v1.2.3 From 040dcc3e5194d0170727adc5df213cfe9d994302 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 24 Feb 2007 08:31:40 -0300 Subject: V4L/DVB (9378): Add STB6100 Support Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 +++++++ drivers/media/dvb/frontends/Makefile | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 35eb5f888b42..88e461e41558 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -22,6 +22,13 @@ config DVB_STB0899 A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want to support this demodulator based frontends +config DVB_STB6100 + tristate "STB6100 based tuners" + depends on DVB_CORE + help + A Silicon tuner from ST used in conjunction with the STB0899 + demodulator. Say Y when you want to support this tuner. + comment "DVB-S (satellite) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index f0a31c56ca47..ad89dbf760cd 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -11,6 +11,7 @@ stb0899-objs = stb0899_drv.o stb0899_algo.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_STB0899) += stb0899.o +obj-$(CONFIG_DVB_STB6100) += stb6100.o obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_CX24110) += cx24110.o -- cgit v1.2.3 From 654dbad45d83ef1a1d234940705d775dc813a501 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Oct 2008 17:56:07 -0300 Subject: V4L/DVB (9393): Add TDA8261 to build Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 +++++++ drivers/media/dvb/frontends/Makefile | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 88e461e41558..941bc8febee7 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -95,6 +95,13 @@ config DVB_TDA10086 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_TDA8261 + tristate "Philips TDA8261 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_VES1X93 tristate "VLSI VES1893 or VES1993 based" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index ad89dbf760cd..7a19c0c7b7a0 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_DVB_ISL6405) += isl6405.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o +obj-$(CONFIG_DVB_TDA8261) += tda8261.o obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o obj-$(CONFIG_DVB_S5H1409) += s5h1409.o -- cgit v1.2.3 From 6199ceef8bd28b79e0792423ca79cce8b224cd50 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 8 Oct 2007 18:51:54 -0300 Subject: V4L/DVB (9418): DVB_ATTACH for STB0899, STB6100, TDA8261 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 941bc8febee7..2470d88e901a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -17,14 +17,16 @@ comment "Multistandard (satellite) frontends" config DVB_STB0899 tristate "STB0899 based" - depends on DVB_CORE + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE help A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want to support this demodulator based frontends config DVB_STB6100 tristate "STB6100 based tuners" - depends on DVB_CORE + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE help A Silicon tuner from ST used in conjunction with the STB0899 demodulator. Say Y when you want to support this tuner. -- cgit v1.2.3 From 4c48ae8e8a490f16abbd874602135bcd83c84f26 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 23 Nov 2008 16:26:54 -0300 Subject: V4L/DVB (9811): Add support for the CX24113 DVB-S tuner driver This commit adds support for the CX24113 DVB-S tuner driver and thus support for the Technisat Skystar2 revision 2.8. The driver was created with the help of Technisat. Thank you very much. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 1 + drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/cx24113.c | 608 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/cx24113.h | 11 +- 5 files changed, 626 insertions(+), 3 deletions(-) create mode 100644 drivers/media/dvb/frontends/cx24113.c (limited to 'drivers/media/dvb/frontends/Kconfig') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index b34301d56cd2..a8c6249c4099 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -14,6 +14,7 @@ config DVB_B2C2_FLEXCOP select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select DVB_TUNER_CX24113 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/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 2470d88e901a..00269560793a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -118,6 +118,14 @@ config DVB_TUNER_ITD1000 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_TUNER_CX24113 + tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + config DVB_TDA826X tristate "Philips TDA826X silicon tuner" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 7a19c0c7b7a0..af7bdf0ad4c7 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o obj-$(CONFIG_DVB_AU8522) += au8522.o obj-$(CONFIG_DVB_TDA10048) += tda10048.o +obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb/frontends/cx24113.c new file mode 100644 index 000000000000..e2e5df9de1ec --- /dev/null +++ b/drivers/media/dvb/frontends/cx24113.c @@ -0,0 +1,608 @@ +/* + * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * + * Copyright (C) 2007-8 Patrick Boettcher + * + * Developed for BBTI / Technisat + * + * 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 +#include +#include +#include + +#include "dvb_frontend.h" +#include "cx24113.h" + +static int debug; + +#define info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0) +#define err(args...) do { printk(KERN_ERR "CX24113: " args); } while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "CX24113: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct cx24113_state { + struct i2c_adapter *i2c; + const struct cx24113_config *config; + +#define REV_CX24113 0x23 + u8 rev; + u8 ver; + + u8 icp_mode:1; + +#define ICP_LEVEL1 0 +#define ICP_LEVEL2 1 +#define ICP_LEVEL3 2 +#define ICP_LEVEL4 3 + u8 icp_man:2; + u8 icp_auto_low:2; + u8 icp_auto_mlow:2; + u8 icp_auto_mhi:2; + u8 icp_auto_hi:2; + u8 icp_dig; + +#define LNA_MIN_GAIN 0 +#define LNA_MID_GAIN 1 +#define LNA_MAX_GAIN 2 + u8 lna_gain:2; + + u8 acp_on:1; + + u8 vco_mode:2; + u8 vco_shift:1; +#define VCOBANDSEL_6 0x80 +#define VCOBANDSEL_5 0x01 +#define VCOBANDSEL_4 0x02 +#define VCOBANDSEL_3 0x04 +#define VCOBANDSEL_2 0x08 +#define VCOBANDSEL_1 0x10 + u8 vco_band; + +#define VCODIV4 4 +#define VCODIV2 2 + u8 vcodiv; + + u8 bs_delay:4; + u16 bs_freqcnt:13; + u16 bs_rdiv; + u8 prescaler_mode:1; + + u8 rfvga_bias_ctrl; + + s16 tuner_gain_thres; + u8 gain_level; + + u32 frequency; + + u8 refdiv; + + u8 Fwindow_enabled; +}; + +static int cx24113_writereg(struct cx24113_state *state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->i2c_addr, + .flags = 0, .buf = buf, .len = 2 }; + int err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, err, reg, data); + return err; + } + + return 0; +} + +static int cx24113_readreg(struct cx24113_state *state, u8 reg) +{ + int ret; + u8 b; + struct i2c_msg msg[] = { + { .addr = state->config->i2c_addr, + .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->config->i2c_addr, + .flags = I2C_M_RD, .buf = &b, .len = 1 } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk(KERN_DEBUG "%s: reg=0x%x (error=%d)\n", + __func__, reg, ret); + return ret; + } + + return b; +} + +static void cx24113_set_parameters(struct cx24113_state *state) +{ + u8 r; + + r = cx24113_readreg(state, 0x10) & 0x82; + r |= state->icp_mode; + r |= state->icp_man << 4; + r |= state->icp_dig << 2; + r |= state->prescaler_mode << 5; + cx24113_writereg(state, 0x10, r); + + r = (state->icp_auto_low << 0) | (state->icp_auto_mlow << 2) + | (state->icp_auto_mhi << 4) | (state->icp_auto_hi << 6); + cx24113_writereg(state, 0x11, r); + + if (state->rev == REV_CX24113) { + r = cx24113_readreg(state, 0x20) & 0xec; + r |= state->lna_gain; + r |= state->rfvga_bias_ctrl << 4; + cx24113_writereg(state, 0x20, r); + } + + r = cx24113_readreg(state, 0x12) & 0x03; + r |= state->acp_on << 2; + r |= state->bs_delay << 4; + cx24113_writereg(state, 0x12, r); + + r = cx24113_readreg(state, 0x18) & 0x40; + r |= state->vco_shift; + if (state->vco_band == VCOBANDSEL_6) + r |= (1 << 7); + else + r |= (state->vco_band << 1); + cx24113_writereg(state, 0x18, r); + + r = cx24113_readreg(state, 0x14) & 0x20; + r |= (state->vco_mode << 6) | ((state->bs_freqcnt >> 8) & 0x1f); + cx24113_writereg(state, 0x14, r); + cx24113_writereg(state, 0x15, (state->bs_freqcnt & 0xff)); + + cx24113_writereg(state, 0x16, (state->bs_rdiv >> 4) & 0xff); + r = (cx24113_readreg(state, 0x17) & 0x0f) | + ((state->bs_rdiv & 0x0f) << 4); + cx24113_writereg(state, 0x17, r); +} + +#define VGA_0 0x00 +#define VGA_1 0x04 +#define VGA_2 0x02 +#define VGA_3 0x06 +#define VGA_4 0x01 +#define VGA_5 0x05 +#define VGA_6 0x03 +#define VGA_7 0x07 + +#define RFVGA_0 0x00 +#define RFVGA_1 0x01 +#define RFVGA_2 0x02 +#define RFVGA_3 0x03 + +static int cx24113_set_gain_settings(struct cx24113_state *state, + s16 power_estimation) +{ + u8 ampout = cx24113_readreg(state, 0x1d) & 0xf0, + vga = cx24113_readreg(state, 0x1f) & 0x3f, + rfvga = cx24113_readreg(state, 0x20) & 0xf3; + u8 gain_level = power_estimation >= state->tuner_gain_thres; + + dprintk("power estimation: %d, thres: %d, gain_level: %d/%d\n", + power_estimation, state->tuner_gain_thres, + state->gain_level, gain_level); + + if (gain_level == state->gain_level) + return 0; /* nothing to be done */ + + ampout |= 0xf; + + if (gain_level) { + rfvga |= RFVGA_0 << 2; + vga |= (VGA_7 << 3) | VGA_7; + } else { + rfvga |= RFVGA_2 << 2; + vga |= (VGA_6 << 3) | VGA_2; + } + state->gain_level = gain_level; + + cx24113_writereg(state, 0x1d, ampout); + cx24113_writereg(state, 0x1f, vga); + cx24113_writereg(state, 0x20, rfvga); + + return 1; /* did something */ +} + +static int cx24113_set_Fref(struct cx24113_state *state, u8 high) +{ + u8 xtal = cx24113_readreg(state, 0x02); + if (state->rev == 0x43 && state->vcodiv == VCODIV4) + high = 1; + + xtal &= ~0x2; + if (high) + xtal |= high << 1; + return cx24113_writereg(state, 0x02, xtal); +} + +static int cx24113_enable(struct cx24113_state *state, u8 enable) +{ + u8 r21 = (cx24113_readreg(state, 0x21) & 0xc0) | enable; + if (state->rev == REV_CX24113) + r21 |= (1 << 1); + return cx24113_writereg(state, 0x21, r21); +} + +static int cx24113_set_bandwidth(struct cx24113_state *state, u32 bandwidth_khz) +{ + u8 r; + + if (bandwidth_khz <= 19000) + r = 0x03 << 6; + else if (bandwidth_khz <= 25000) + r = 0x02 << 6; + else + r = 0x01 << 6; + + dprintk("bandwidth to be set: %d\n", bandwidth_khz); + bandwidth_khz *= 10; + bandwidth_khz -= 10000; + bandwidth_khz /= 1000; + bandwidth_khz += 5; + bandwidth_khz /= 10; + + dprintk("bandwidth: %d %d\n", r >> 6, bandwidth_khz); + + r |= bandwidth_khz & 0x3f; + + return cx24113_writereg(state, 0x1e, r); +} + +static int cx24113_set_clk_inversion(struct cx24113_state *state, u8 on) +{ + u8 r = (cx24113_readreg(state, 0x10) & 0x7f) | ((on & 0x1) << 7); + return cx24113_writereg(state, 0x10, r); +} + +static int cx24113_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct cx24113_state *state = fe->tuner_priv; + u8 r = (cx24113_readreg(state, 0x10) & 0x02) >> 1; + if (r) + *status |= TUNER_STATUS_LOCKED; + dprintk("PLL locked: %d\n", r); + return 0; +} + +static u8 cx24113_set_ref_div(struct cx24113_state *state, u8 refdiv) +{ + if (state->rev == 0x43 && state->vcodiv == VCODIV4) + refdiv = 2; + return state->refdiv = refdiv; +} + +static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) +{ + s32 N; + s64 F; + u8 R, r; + u8 vcodiv; + u8 factor; + s32 freq_hz = state->frequency * 1000; + + if (state->config->xtal_khz < 20000) + factor = 1; + else + factor = 2; + + if (state->rev == REV_CX24113) { + if (state->frequency >= 1100000) + vcodiv = VCODIV2; + else + vcodiv = VCODIV4; + } else { + if (state->frequency >= 1165000) + vcodiv = VCODIV2; + else + vcodiv = VCODIV4; + } + state->vcodiv = vcodiv; + + dprintk("calculating N/F for %dHz with vcodiv %d\n", freq_hz, vcodiv); + R = 0; + do { + R = cx24113_set_ref_div(state, R + 1); + + /* calculate tuner PLL settings: */ + N = (freq_hz / 100 * vcodiv) * R; + N /= (state->config->xtal_khz) * factor * 2; + N += 5; /* For round up. */ + N /= 10; + N -= 32; + } while (N < 6 && R < 3); + + if (N < 6) { + err("strange frequency: N < 6\n"); + return; + } + F = freq_hz; + F *= (u64) (R * vcodiv * 262144); + dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); + do_div(F, state->config->xtal_khz*1000 * factor * 2); + dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); + F -= (N + 32) * 262144; + + dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); + + if (state->Fwindow_enabled) { + if (F > (262144 / 2 - 1638)) + F = 262144 / 2 - 1638; + if (F < (-262144 / 2 + 1638)) + F = -262144 / 2 + 1638; + if ((F < 3277 && F > 0) || (F > -3277 && F < 0)) { + F = 0; + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r | (1 << 6)); + } + } + dprintk("4 N: %d, F: %lld, R: %d\n", N, F, R); + + *n = (u16) N; + *f = (s32) F; +} + + +static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r) +{ + u8 reg; + cx24113_writereg(state, 0x19, (n >> 1) & 0xff); + + reg = ((n & 0x1) << 7) | ((f >> 11) & 0x7f); + cx24113_writereg(state, 0x1a, reg); + + cx24113_writereg(state, 0x1b, (f >> 3) & 0xff); + + reg = cx24113_readreg(state, 0x1c) & 0x1f; + cx24113_writereg(state, 0x1c, reg | ((f & 0x7) << 5)); + + cx24113_set_Fref(state, r - 1); +} + +static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency) +{ + u8 r = 1; /* or 2 */ + u16 n = 6; + s32 f = 0; + + r = cx24113_readreg(state, 0x14); + cx24113_writereg(state, 0x14, r & 0x3f); + + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r & 0xbf); + + state->frequency = frequency; + + dprintk("tuning to frequency: %d\n", frequency); + + cx24113_calc_pll_nf(state, &n, &f); + cx24113_set_nfr(state, n, f, state->refdiv); + + r = cx24113_readreg(state, 0x18) & 0xbf; + if (state->vcodiv != VCODIV2) + r |= 1 << 6; + cx24113_writereg(state, 0x18, r); + + /* The need for this sleep is not clear. But helps in some cases */ + msleep(5); + + r = cx24113_readreg(state, 0x1c) & 0xef; + cx24113_writereg(state, 0x1c, r | (1 << 4)); + return 0; +} + +static int cx24113_init(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + int ret; + + state->tuner_gain_thres = -50; + state->gain_level = 255; /* to force a gain-setting initialization */ + state->icp_mode = 0; + + if (state->config->xtal_khz < 11000) { + state->icp_auto_hi = ICP_LEVEL4; + state->icp_auto_mhi = ICP_LEVEL4; + state->icp_auto_mlow = ICP_LEVEL3; + state->icp_auto_low = ICP_LEVEL3; + } else { + state->icp_auto_hi = ICP_LEVEL4; + state->icp_auto_mhi = ICP_LEVEL4; + state->icp_auto_mlow = ICP_LEVEL3; + state->icp_auto_low = ICP_LEVEL2; + } + + state->icp_dig = ICP_LEVEL3; + state->icp_man = ICP_LEVEL1; + state->acp_on = 1; + state->vco_mode = 0; + state->vco_shift = 0; + state->vco_band = VCOBANDSEL_1; + state->bs_delay = 8; + state->bs_freqcnt = 0x0fff; + state->bs_rdiv = 0x0fff; + state->prescaler_mode = 0; + state->lna_gain = LNA_MAX_GAIN; + state->rfvga_bias_ctrl = 1; + state->Fwindow_enabled = 1; + + cx24113_set_Fref(state, 0); + cx24113_enable(state, 0x3d); + cx24113_set_parameters(state); + + cx24113_set_gain_settings(state, -30); + + cx24113_set_bandwidth(state, 18025); + cx24113_set_clk_inversion(state, 1); + + if (state->config->xtal_khz >= 40000) + ret = cx24113_writereg(state, 0x02, + (cx24113_readreg(state, 0x02) & 0xfb) | (1 << 2)); + else + ret = cx24113_writereg(state, 0x02, + (cx24113_readreg(state, 0x02) & 0xfb) | (0 << 2)); + + return ret; +} + +static int cx24113_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct cx24113_state *state = fe->tuner_priv; + /* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */ + u32 roll_off = 675; + u32 bw; + + bw = ((p->u.qpsk.symbol_rate/100) * roll_off) / 1000; + bw += (10000000/100) + 5; + bw /= 10; + bw += 1000; + cx24113_set_bandwidth(state, bw); + + cx24113_set_frequency(state, p->frequency); + msleep(5); + return cx24113_get_status(fe, &bw); +} + +static s8 cx24113_agc_table[2][10] = { + {-54, -41, -35, -30, -25, -21, -16, -10, -6, -2}, + {-39, -35, -30, -25, -19, -15, -11, -5, 1, 9}, +}; + +void cx24113_agc_callback(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + s16 s, i; + if (!fe->ops.read_signal_strength) + return; + + do { + /* this only works with the current CX24123 implementation */ + fe->ops.read_signal_strength(fe, (u16 *) &s); + s >>= 8; + dprintk("signal strength: %d\n", s); + for (i = 0; i < sizeof(cx24113_agc_table[0]); i++) + if (cx24113_agc_table[state->gain_level][i] > s) + break; + s = -25 - i*5; + } while (cx24113_set_gain_settings(state, s)); +} +EXPORT_SYMBOL(cx24113_agc_callback); + +static int cx24113_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct cx24113_state *state = fe->tuner_priv; + *frequency = state->frequency; + return 0; +} + +static int cx24113_release(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + dprintk("\n"); + fe->tuner_priv = NULL; + kfree(state); + return 0; +} + +static const struct dvb_tuner_ops cx24113_tuner_ops = { + .info = { + .name = "Conexant CX24113", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 125, + }, + + .release = cx24113_release, + + .init = cx24113_init, + .sleep = NULL, + + .set_params = cx24113_set_params, + .get_frequency = cx24113_get_frequency, + .get_bandwidth = NULL, + .get_status = cx24113_get_status, +}; + +struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, + const struct cx24113_config *config, struct i2c_adapter *i2c) +{ + /* allocate memory for the internal state */ + struct cx24113_state *state = + kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); + if (state == NULL) { + err("Unable to kmalloc\n"); + goto error; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + info("trying to detect myself\n"); + + /* making a dummy read, because of some expected troubles + * after power on */ + cx24113_readreg(state, 0x00); + + switch (state->rev = cx24113_readreg(state, 0x00)) { + case 0x43: + info("unknown device\n"); + break; + case REV_CX24113: + info("CX24113\n"); + break; + default: + err("unsupported revision: %x\n", state->rev); + goto error; + } + state->ver = cx24113_readreg(state, 0x01); + info("version: %x\n", state->ver); + + /* create dvb_frontend */ + memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops, + sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = state; + return fe; + +error: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(cx24113_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24113/CX24128hardware"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h index 5ab3dd11076b..5de0f7ffd8d2 100644 --- a/drivers/media/dvb/frontends/cx24113.h +++ b/drivers/media/dvb/frontends/cx24113.h @@ -16,7 +16,7 @@ * * 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.= + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CX24113_H @@ -30,9 +30,13 @@ struct cx24113_config { u32 xtal_khz; }; -/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \ - * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */ +#if defined(CONFIG_DVB_TUNER_CX24113) || \ + (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) +extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *, + const struct cx24113_config *config, struct i2c_adapter *i2c); +extern void cx24113_agc_callback(struct dvb_frontend *fe); +#else static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, const struct cx24113_config *config, struct i2c_adapter *i2c) { @@ -44,5 +48,6 @@ static inline void cx24113_agc_callback(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); } +#endif #endif /* CX24113_H */ -- cgit v1.2.3