diff options
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9013.c | 52 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9013.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9013_priv.h | 8 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/au8522_decoder.c | 26 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib3000mb.c | 9 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib3000mb_priv.h | 4 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib3000mc.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/ds3000.c | 5 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgdt3305.c | 267 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgdt3305.h | 10 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.c | 50 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/mb86a16.c | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/stv6110x.c | 5 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda10048.c | 43 |
15 files changed, 298 insertions, 187 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index cd7f9b7cbffa..51d578a758a7 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -584,6 +584,7 @@ config DVB_LGS8GL5 config DVB_LGS8GXX tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" depends on DVB_CORE && I2C + select FW_LOADER default m if DVB_FE_CUSTOMISE help A DMB-TH tuner module. Say Y when you want to support this frontend. diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 12e018b4107d..dac917f7bb7f 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -1,5 +1,5 @@ /* - * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * Afatech AF9013 demodulator driver * * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> * @@ -761,6 +761,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe, state->frequency = params->frequency; + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, params); + /* program CFOE coefficients */ ret = af9013_set_coeff(state, params->u.ofdm.bandwidth); if (ret) @@ -791,10 +795,6 @@ static int af9013_set_frontend(struct dvb_frontend *fe, if (ret) goto error; - /* program tuner */ - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe, params); - /* program TPS and bandwidth, check if auto mode needed */ ret = af9013_set_ofdm_params(state, ¶ms->u.ofdm, &auto_mode); if (ret) @@ -1184,45 +1184,49 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) u8 tmp; *status = 0; - /* TPS lock */ - ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp); - if (ret) - goto error; - if (tmp) - *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; - /* MPEG2 lock */ ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp); if (ret) goto error; if (tmp) - *status |= FE_HAS_SYNC | FE_HAS_LOCK; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_LOCK; - if (!(*status & FE_HAS_SIGNAL)) { - /* AGC lock */ - ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); + if (!*status) { + /* TPS lock */ + ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp); if (ret) goto error; if (tmp) - *status |= FE_HAS_SIGNAL; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI; } - if (!(*status & FE_HAS_CARRIER)) { + if (!*status) { /* CFO lock */ ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); if (ret) goto error; if (tmp) - *status |= FE_HAS_CARRIER; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; } - if (!(*status & FE_HAS_CARRIER)) { + if (!*status) { /* SFOE lock */ ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); if (ret) goto error; if (tmp) - *status |= FE_HAS_CARRIER; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; + } + + if (!*status) { + /* AGC lock */ + ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_SIGNAL; } ret = af9013_update_statistics(fe); @@ -1574,7 +1578,7 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config, { int ret; struct af9013_state *state = NULL; - u8 buf[3], i; + u8 buf[4], i; /* allocate memory for the internal state */ state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL); @@ -1607,12 +1611,12 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config, } /* firmware version */ - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { ret = af9013_read_reg(state, 0x5103 + i, &buf[i]); if (ret) goto error; } - info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]); + info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]); /* settings for mp2if */ if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) { diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h index e90fa92b1c1d..72c71bb5d117 100644 --- a/drivers/media/dvb/frontends/af9013.h +++ b/drivers/media/dvb/frontends/af9013.h @@ -1,5 +1,5 @@ /* - * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * Afatech AF9013 demodulator driver * * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> * diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h index 163e251d0b73..0fd42b7e248e 100644 --- a/drivers/media/dvb/frontends/af9013_priv.h +++ b/drivers/media/dvb/frontends/af9013_priv.h @@ -1,5 +1,5 @@ /* - * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * Afatech AF9013 demodulator driver * * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> * @@ -132,6 +132,8 @@ static struct regdesc ofsm_init[] = { { 0xd740, 2, 1, 0x00 }, { 0xd740, 3, 1, 0x01 }, { 0xd3c1, 4, 1, 0x01 }, + { 0x9124, 0, 8, 0x58 }, + { 0x9125, 0, 2, 0x02 }, { 0xd3a2, 0, 8, 0x00 }, { 0xd3a3, 0, 8, 0x04 }, { 0xd305, 0, 8, 0x32 }, @@ -143,7 +145,7 @@ static struct regdesc ofsm_init[] = { { 0x911b, 0, 1, 0x01 }, { 0x9bce, 0, 4, 0x02 }, { 0x9116, 0, 1, 0x01 }, - { 0x9bd1, 0, 1, 0x01 }, + { 0x9122, 0, 8, 0xd0 }, { 0xd2e0, 0, 8, 0xd0 }, { 0xd2e9, 0, 4, 0x0d }, { 0xd38c, 0, 8, 0xfc }, @@ -165,7 +167,6 @@ static struct regdesc ofsm_init[] = { { 0xd081, 4, 4, 0x09 }, { 0xd098, 4, 4, 0x0f }, { 0xd098, 0, 4, 0x03 }, - { 0xdbc0, 3, 1, 0x01 }, { 0xdbc0, 4, 1, 0x01 }, { 0xdbc7, 0, 8, 0x08 }, { 0xdbc8, 4, 4, 0x00 }, @@ -179,6 +180,7 @@ static struct regdesc ofsm_init[] = { { 0xd0f0, 0, 7, 0x1a }, { 0xd0f1, 4, 1, 0x01 }, { 0xd0f2, 0, 8, 0x0c }, + { 0xd101, 5, 3, 0x06 }, { 0xd103, 0, 4, 0x08 }, { 0xd0f8, 0, 7, 0x20 }, { 0xd111, 5, 1, 0x00 }, diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 68dba3a4b4da..29cdbfe36852 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -567,30 +567,6 @@ static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* ----------------------------------------------------------------------- */ -static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - default: - return -EINVAL; - } - return 0; -} - -static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - /* Not yet implemented */ - break; - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - #ifdef CONFIG_VIDEO_ADV_DEBUG static int au8522_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -772,8 +748,6 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = { static const struct v4l2_subdev_video_ops au8522_video_ops = { .s_routing = au8522_s_video_routing, - .g_fmt = au8522_g_fmt, - .s_fmt = au8522_s_fmt, .s_stream = au8522_s_stream, }; diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c index ad4c8cfd8090..e80c59796368 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb/frontends/dib3000mb.c @@ -38,11 +38,10 @@ #define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator" #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" -#ifdef CONFIG_DVB_DIBCOM_DEBUG static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able))."); -#endif + #define deb_info(args...) dprintk(0x01,args) #define deb_i2c(args...) dprintk(0x02,args) #define deb_srch(args...) dprintk(0x04,args) @@ -51,12 +50,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a #define deb_setf(args...) dprintk(0x04,args) #define deb_getf(args...) dprintk(0x08,args) -#ifdef CONFIG_DVB_DIBCOM_DEBUG -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able))."); -#endif - static int dib3000_read_reg(struct dib3000_state *state, u16 reg) { u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h index 1a12747fdc91..16c526591f36 100644 --- a/drivers/media/dvb/frontends/dib3000mb_priv.h +++ b/drivers/media/dvb/frontends/dib3000mb_priv.h @@ -37,12 +37,8 @@ /* debug */ -#ifdef CONFIG_DVB_DIBCOM_DEBUG #define dprintk(level,args...) \ do { if ((debug & level)) { printk(args); } } while (0) -#else -#define dprintk(args...) do { } while (0) -#endif /* mask for enabling a specific pid for the pid_filter */ #define DIB3000_ACTIVATE_PID_FILTERING (0x2000) diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index afad252abf41..088e7fadbe3d 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c @@ -822,7 +822,7 @@ int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defa dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL); if (dmcst == NULL) - return -ENODEV; + return -ENOMEM; dmcst->i2c_adap = i2c; diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c index 78001e8bcdb7..fc61d9230db8 100644 --- a/drivers/media/dvb/frontends/ds3000.c +++ b/drivers/media/dvb/frontends/ds3000.c @@ -969,15 +969,12 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL); + state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL); if (state == NULL) { printk(KERN_ERR "Unable to kmalloc\n"); goto error2; } - /* setup the state */ - memset(state, 0, sizeof(struct ds3000_state)); - state->config = config; state->i2c = i2c; state->prevUCBS2 = 0; diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c index d69c775f8645..3272881cb112 100644 --- a/drivers/media/dvb/frontends/lgdt3305.c +++ b/drivers/media/dvb/frontends/lgdt3305.c @@ -1,7 +1,9 @@ /* - * Support for LGDT3305 - VSB/QAM + * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM * - * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org> + * Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org> + * + * LGDT3304 support by Jarod Wilson <jarod@redhat.com> * * 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 @@ -65,6 +67,8 @@ struct lgdt3305_state { /* ------------------------------------------------------------------------ */ +/* FIXME: verify & document the LGDT3304 registers */ + #define LGDT3305_GEN_CTRL_1 0x0000 #define LGDT3305_GEN_CTRL_2 0x0001 #define LGDT3305_GEN_CTRL_3 0x0002 @@ -358,7 +362,12 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state, case QAM_256: agcdelay = 0x046b; rfbw = 0x8889; - ifbw = 0x8888; + /* FIXME: investigate optimal ifbw & rfbw values for the + * DT3304 and re-write this switch..case block */ + if (state->cfg->demod_chip == LGDT3304) + ifbw = 0x6666; + else /* (state->cfg->demod_chip == LGDT3305) */ + ifbw = 0x8888; break; default: return -EINVAL; @@ -410,8 +419,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state, lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen); /* control agc function */ - lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); - lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); + switch (state->cfg->demod_chip) { + case LGDT3304: + lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1); + lgdt3305_set_reg_bit(state, 0x030e, 2, acqen); + break; + case LGDT3305: + lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); + lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); + break; + default: + return -EINVAL; + } return lgdt3305_rfagc_loop(state, param); } @@ -577,61 +596,79 @@ static int lgdt3305_init(struct dvb_frontend *fe) struct lgdt3305_state *state = fe->demodulator_priv; int ret; + static struct lgdt3305_reg lgdt3304_init_data[] = { + { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, }, + { .reg = 0x000d, .val = 0x02, }, + { .reg = 0x000e, .val = 0x02, }, + { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, }, + { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, }, + { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, }, + { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, }, + { .reg = 0x0112, .val = 0x17, }, + { .reg = 0x0113, .val = 0x15, }, + { .reg = 0x0114, .val = 0x18, }, + { .reg = 0x0115, .val = 0xff, }, + { .reg = 0x0116, .val = 0x3c, }, + { .reg = 0x0214, .val = 0x67, }, + { .reg = 0x0424, .val = 0x8d, }, + { .reg = 0x0427, .val = 0x12, }, + { .reg = 0x0428, .val = 0x4f, }, + { .reg = LGDT3305_IFBW_1, .val = 0x80, }, + { .reg = LGDT3305_IFBW_2, .val = 0x00, }, + { .reg = 0x030a, .val = 0x08, }, + { .reg = 0x030b, .val = 0x9b, }, + { .reg = 0x030d, .val = 0x00, }, + { .reg = 0x030e, .val = 0x1c, }, + { .reg = 0x0314, .val = 0xe1, }, + { .reg = 0x000d, .val = 0x82, }, + { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, }, + { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, }, + }; + static struct lgdt3305_reg lgdt3305_init_data[] = { - { .reg = LGDT3305_GEN_CTRL_1, - .val = 0x03, }, - { .reg = LGDT3305_GEN_CTRL_2, - .val = 0xb0, }, - { .reg = LGDT3305_GEN_CTRL_3, - .val = 0x01, }, - { .reg = LGDT3305_GEN_CONTROL, - .val = 0x6f, }, - { .reg = LGDT3305_GEN_CTRL_4, - .val = 0x03, }, - { .reg = LGDT3305_DGTL_AGC_REF_1, - .val = 0x32, }, - { .reg = LGDT3305_DGTL_AGC_REF_2, - .val = 0xc4, }, - { .reg = LGDT3305_CR_CTR_FREQ_1, - .val = 0x00, }, - { .reg = LGDT3305_CR_CTR_FREQ_2, - .val = 0x00, }, - { .reg = LGDT3305_CR_CTR_FREQ_3, - .val = 0x00, }, - { .reg = LGDT3305_CR_CTR_FREQ_4, - .val = 0x00, }, - { .reg = LGDT3305_CR_CTRL_7, - .val = 0x79, }, - { .reg = LGDT3305_AGC_POWER_REF_1, - .val = 0x32, }, - { .reg = LGDT3305_AGC_POWER_REF_2, - .val = 0xc4, }, - { .reg = LGDT3305_AGC_DELAY_PT_1, - .val = 0x0d, }, - { .reg = LGDT3305_AGC_DELAY_PT_2, - .val = 0x30, }, - { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, - .val = 0x80, }, - { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, - .val = 0x00, }, - { .reg = LGDT3305_IFBW_1, - .val = 0x80, }, - { .reg = LGDT3305_IFBW_2, - .val = 0x00, }, - { .reg = LGDT3305_AGC_CTRL_1, - .val = 0x30, }, - { .reg = LGDT3305_AGC_CTRL_4, - .val = 0x61, }, - { .reg = LGDT3305_FEC_BLOCK_CTRL, - .val = 0xff, }, - { .reg = LGDT3305_TP_CTRL_1, - .val = 0x1b, }, + { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, }, + { .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, }, + { .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, }, + { .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, }, + { .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, }, + { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, }, + { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, }, + { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, }, + { .reg = LGDT3305_CR_CTRL_7, .val = 0x79, }, + { .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, }, + { .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, }, + { .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, }, + { .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, }, + { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, }, + { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, }, + { .reg = LGDT3305_IFBW_1, .val = 0x80, }, + { .reg = LGDT3305_IFBW_2, .val = 0x00, }, + { .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, }, + { .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, }, + { .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, }, + { .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, }, }; lg_dbg("\n"); - ret = lgdt3305_write_regs(state, lgdt3305_init_data, - ARRAY_SIZE(lgdt3305_init_data)); + switch (state->cfg->demod_chip) { + case LGDT3304: + ret = lgdt3305_write_regs(state, lgdt3304_init_data, + ARRAY_SIZE(lgdt3304_init_data)); + break; + case LGDT3305: + ret = lgdt3305_write_regs(state, lgdt3305_init_data, + ARRAY_SIZE(lgdt3305_init_data)); + break; + default: + ret = -EINVAL; + } if (lg_fail(ret)) goto fail; @@ -640,6 +677,76 @@ fail: return ret; } +static int lgdt3304_set_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + int ret; + + lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation); + + if (fe->ops.tuner_ops.set_params) { + ret = fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + if (lg_fail(ret)) + goto fail; + state->current_frequency = param->frequency; + } + + ret = lgdt3305_set_modulation(state, param); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_passband_digital_agc(state, param); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_agc_setup(state, param); + if (lg_fail(ret)) + goto fail; + + /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */ + switch (param->u.vsb.modulation) { + case VSB_8: + lgdt3305_write_reg(state, 0x030d, 0x00); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba); + break; + case QAM_64: + case QAM_256: + lgdt3305_write_reg(state, 0x030d, 0x14); + ret = lgdt3305_set_if(state, param); + if (lg_fail(ret)) + goto fail; + break; + default: + return -EINVAL; + } + + + ret = lgdt3305_spectral_inversion(state, param, + state->cfg->spectral_inversion + ? 1 : 0); + if (lg_fail(ret)) + goto fail; + + state->current_modulation = param->u.vsb.modulation; + + ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode); + if (lg_fail(ret)) + goto fail; + + /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */ + ret = lgdt3305_mpeg_mode_polarity(state, + state->cfg->tpclk_edge, + state->cfg->tpvalid_polarity); +fail: + return ret; +} + static int lgdt3305_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { @@ -848,6 +955,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status) switch (state->current_modulation) { case QAM_256: case QAM_64: + /* signal bit is unreliable on the DT3304 in QAM mode */ + if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock)) + *status |= FE_HAS_SIGNAL; + ret = lgdt3305_read_fec_lock_status(state, &fec_lock); if (lg_fail(ret)) goto fail; @@ -993,6 +1104,7 @@ static void lgdt3305_release(struct dvb_frontend *fe) kfree(state); } +static struct dvb_frontend_ops lgdt3304_ops; static struct dvb_frontend_ops lgdt3305_ops; struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, @@ -1013,11 +1125,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, state->cfg = config; state->i2c_adap = i2c_adap; - memcpy(&state->frontend.ops, &lgdt3305_ops, - sizeof(struct dvb_frontend_ops)); + switch (config->demod_chip) { + case LGDT3304: + memcpy(&state->frontend.ops, &lgdt3304_ops, + sizeof(struct dvb_frontend_ops)); + break; + case LGDT3305: + memcpy(&state->frontend.ops, &lgdt3305_ops, + sizeof(struct dvb_frontend_ops)); + break; + default: + goto fail; + } state->frontend.demodulator_priv = state; - /* verify that we're talking to a lg dt3305 */ + /* verify that we're talking to a lg dt3304/5 */ ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val); if ((lg_fail(ret)) | (val == 0)) goto fail; @@ -1036,12 +1158,35 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, return &state->frontend; fail: - lg_warn("unable to detect LGDT3305 hardware\n"); + lg_warn("unable to detect %s hardware\n", + config->demod_chip ? "LGDT3304" : "LGDT3305"); kfree(state); return NULL; } EXPORT_SYMBOL(lgdt3305_attach); +static struct dvb_frontend_ops lgdt3304_ops = { + .info = { + .name = "LG Electronics LGDT3304 VSB/QAM Frontend", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_stepsize = 62500, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl, + .init = lgdt3305_init, + .set_frontend = lgdt3304_set_parameters, + .get_frontend = lgdt3305_get_frontend, + .get_tune_settings = lgdt3305_get_tune_settings, + .read_status = lgdt3305_read_status, + .read_ber = lgdt3305_read_ber, + .read_signal_strength = lgdt3305_read_signal_strength, + .read_snr = lgdt3305_read_snr, + .read_ucblocks = lgdt3305_read_ucblocks, + .release = lgdt3305_release, +}; + static struct dvb_frontend_ops lgdt3305_ops = { .info = { .name = "LG Electronics LGDT3305 VSB/QAM Frontend", @@ -1065,10 +1210,10 @@ static struct dvb_frontend_ops lgdt3305_ops = { .release = lgdt3305_release, }; -MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); +MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver"); MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.1"); +MODULE_VERSION("0.2"); /* * Local variables: diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h index 9cb11c9cae53..02172eca4d47 100644 --- a/drivers/media/dvb/frontends/lgdt3305.h +++ b/drivers/media/dvb/frontends/lgdt3305.h @@ -1,7 +1,7 @@ /* - * Support for LGDT3305 - VSB/QAM + * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM * - * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org> + * Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org> * * 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 @@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity { LGDT3305_TP_VALID_HIGH = 1, }; +enum lgdt_demod_chip_type { + LGDT3305 = 0, + LGDT3304 = 1, +}; + struct lgdt3305_config { u8 i2c_addr; @@ -65,6 +70,7 @@ struct lgdt3305_config { enum lgdt3305_mpeg_mode mpeg_mode; enum lgdt3305_tp_clock_edge tpclk_edge; enum lgdt3305_tp_valid_polarity tpvalid_polarity; + enum lgdt_demod_chip_type demod_chip; }; #if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \ diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index dee53960e7e8..5ea28ae2ba8f 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c @@ -24,6 +24,7 @@ */ #include <asm/div64.h> +#include <linux/firmware.h> #include "dvb_frontend.h" @@ -46,42 +47,6 @@ module_param(fake_signal_str, int, 0644); MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." "Signal strength calculation is slow.(default:on)."); -static const u8 lgs8g75_initdat[] = { - 0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5, - 0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50, - 0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5, - 0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01, - 0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90, - 0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23, - 0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90, - 0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D, - 0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60, - 0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12, - 0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD, - 0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60, - 0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12, - 0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B, - 0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60, - 0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74, - 0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74, - 0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2, - 0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09, - 0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00, - 0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90, - 0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08, - 0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, - 0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80, - 0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80, - 0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22 -}; - /* LGS8GXX internal helper functions */ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) @@ -627,9 +592,14 @@ static int lgs8913_init(struct lgs8gxx_state *priv) static int lgs8g75_init_data(struct lgs8gxx_state *priv) { - const u8 *p = lgs8g75_initdat; + const struct firmware *fw; + int rc; int i; + rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev); + if (rc) + return rc; + lgs8gxx_write_reg(priv, 0xC6, 0x40); lgs8gxx_write_reg(priv, 0x3D, 0x04); @@ -640,16 +610,16 @@ static int lgs8g75_init_data(struct lgs8gxx_state *priv) lgs8gxx_write_reg(priv, 0x3B, 0x00); lgs8gxx_write_reg(priv, 0x38, 0x00); - for (i = 0; i < sizeof(lgs8g75_initdat); i++) { + for (i = 0; i < fw->size; i++) { lgs8gxx_write_reg(priv, 0x38, 0x00); lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff)); lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8)); - lgs8gxx_write_reg(priv, 0x3C, *p); - p++; + lgs8gxx_write_reg(priv, 0x3C, fw->data[i]); } lgs8gxx_write_reg(priv, 0x38, 0x00); + release_firmware(fw); return 0; } diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 599d1aa519a3..33b63235b86e 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1833,7 +1833,6 @@ static struct dvb_frontend_ops mb86a16_ops = { .get_frontend_algo = mb86a16_frontend_algo, .search = mb86a16_search, - .read_status = mb86a16_read_status, .init = mb86a16_init, .sleep = mb86a16_sleep, .read_status = mb86a16_read_status, diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index 42591ce1aaad..f36cab12bdc7 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c @@ -303,7 +303,10 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) static int stv6110x_sleep(struct dvb_frontend *fe) { - return stv6110x_set_mode(fe, TUNER_SLEEP); + if (fe->tuner_priv) + return stv6110x_set_mode(fe, TUNER_SLEEP); + + return 0; } static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 4e2a7c8b2f62..93f6a75c238e 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb/frontends/tda10048.c @@ -25,6 +25,7 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/math64.h> #include <asm/div64.h> #include "dvb_frontend.h" #include "dvb_math.h" @@ -49,8 +50,8 @@ #define TDA10048_CONF_C4_1 0x1E #define TDA10048_CONF_C4_2 0x1F #define TDA10048_CODE_IN_RAM 0x20 -#define TDA10048_CHANNEL_INFO_1_R 0x22 -#define TDA10048_CHANNEL_INFO_2_R 0x23 +#define TDA10048_CHANNEL_INFO1_R 0x22 +#define TDA10048_CHANNEL_INFO2_R 0x23 #define TDA10048_CHANNEL_INFO1 0x24 #define TDA10048_CHANNEL_INFO2 0x25 #define TDA10048_TIME_ERROR_R 0x26 @@ -63,8 +64,8 @@ #define TDA10048_IT_STAT 0x32 #define TDA10048_DSP_AD_LSB 0x3C #define TDA10048_DSP_AD_MSB 0x3D -#define TDA10048_DSP_REF_LSB 0x3E -#define TDA10048_DSP_REF_MSB 0x3F +#define TDA10048_DSP_REG_LSB 0x3E +#define TDA10048_DSP_REG_MSB 0x3F #define TDA10048_CONF_TRISTATE1 0x44 #define TDA10048_CONF_TRISTATE2 0x45 #define TDA10048_CONF_POLARITY 0x46 @@ -112,7 +113,7 @@ #define TDA10048_FREE_REG_1 0xB2 #define TDA10048_FREE_REG_2 0xB3 #define TDA10048_CONF_C3_1 0xC0 -#define TDA10048_CYBER_CTRL 0xC2 +#define TDA10048_CVBER_CTRL 0xC2 #define TDA10048_CBER_NMAX_LSB 0xC4 #define TDA10048_CBER_NMAX_MSB 0xC5 #define TDA10048_CBER_LSB 0xC6 @@ -120,7 +121,7 @@ #define TDA10048_VBER_LSB 0xC8 #define TDA10048_VBER_MID 0xC9 #define TDA10048_VBER_MSB 0xCA -#define TDA10048_CYBER_LUT 0xCC +#define TDA10048_CVBER_LUT 0xCC #define TDA10048_UNCOR_CTRL 0xCD #define TDA10048_UNCOR_CPT_LSB 0xCE #define TDA10048_UNCOR_CPT_MSB 0xCF @@ -183,7 +184,7 @@ static struct init_tab { { TDA10048_AGC_IF_MAX, 0xff }, { TDA10048_AGC_THRESHOLD_MSB, 0x00 }, { TDA10048_AGC_THRESHOLD_LSB, 0x70 }, - { TDA10048_CYBER_CTRL, 0x38 }, + { TDA10048_CVBER_CTRL, 0x38 }, { TDA10048_AGC_GAINS, 0x12 }, { TDA10048_CONF_XO, 0x00 }, { TDA10048_CONF_TS1, 0x07 }, @@ -688,7 +689,7 @@ static int tda10048_get_tps(struct tda10048_state *state, p->guard_interval = GUARD_INTERVAL_1_4; break; } - switch (val & 0x02) { + switch (val & 0x03) { case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; @@ -765,6 +766,8 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, /* Enable demod TPS auto detection and begin acquisition */ tda10048_writereg(state, TDA10048_AUTO, 0x57); + /* trigger cber and vber acquisition */ + tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B); return 0; } @@ -830,12 +833,27 @@ static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status) static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber) { struct tda10048_state *state = fe->demodulator_priv; + static u32 cber_current; + u32 cber_nmax; + u64 cber_tmp; dprintk(1, "%s()\n", __func__); - /* TODO: A reset may be required here */ - *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 | - tda10048_readreg(state, TDA10048_CBER_LSB); + /* update cber on interrupt */ + if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) { + cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 | + tda10048_readreg(state, TDA10048_CBER_LSB); + cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 | + tda10048_readreg(state, TDA10048_CBER_NMAX_LSB); + cber_tmp *= 100000000; + cber_tmp *= 2; + cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1); + cber_current = (u32)cber_tmp; + /* retrigger cber acquisition */ + tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39); + } + /* actual cber is (*ber)/1e8 */ + *ber = cber_current; return 0; } @@ -1015,6 +1033,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 | tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB); + /* clear the uncorrected TS packets counter when saturated */ + if (*ucblocks == 0xFFFF) + tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80); return 0; } |