The patch number 13390 was added via Jean-Francois Moine <moin...@free.fr> to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: Linux Media Mailing List <linux-me...@vger.kernel.org> ------ merge: v4l-dvb --- linux/drivers/media/common/tuners/mxl5005s.c | 5 linux/drivers/media/common/tuners/mxl5005s.h | 4 linux/drivers/media/dvb/frontends/s5h1409.c | 149 +++++++++++++++- linux/drivers/media/dvb/frontends/s5h1409.h | 7 linux/drivers/media/video/cx18/cx18-dvb.c | 4 linux/drivers/media/video/em28xx/em28xx-cards.c | 3 linux/drivers/media/video/em28xx/em28xx-reg.h | 1 7 files changed, 163 insertions(+), 10 deletions(-) diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/common/tuners/mxl5005s.c --- a/linux/drivers/media/common/tuners/mxl5005s.c Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/common/tuners/mxl5005s.c Sun Nov 15 10:06:08 2009 +0100 @@ -2791,7 +2791,10 @@ /* add for 2.6.5 Special setting for QAM */ if (state->Mod_Type == MXL_QAM) { - if (state->RF_IN < 680000000) + if (state->config->qam_gain != 0) + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, + state->config->qam_gain); + else if (state->RF_IN < 680000000) status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); else status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/common/tuners/mxl5005s.h --- a/linux/drivers/media/common/tuners/mxl5005s.h Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/common/tuners/mxl5005s.h Sun Nov 15 10:06:08 2009 +0100 @@ -108,6 +108,10 @@ #define MXL_LOW_IF 1 u8 if_mode; + /* Some boards need to override the built-in logic for determining + the gain when in QAM mode (the HVR-1600 is one such case) */ + u8 qam_gain; + /* Stuff I don't know what to do with */ u8 AgcMasterByte; }; diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/dvb/frontends/s5h1409.c --- a/linux/drivers/media/dvb/frontends/s5h1409.c Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/dvb/frontends/s5h1409.c Sun Nov 15 10:06:08 2009 +0100 @@ -44,7 +44,15 @@ int if_freq; u32 is_qam_locked; - u32 qam_state; + + /* QAM tuning state goes through the following state transitions */ +#define QAM_STATE_UNTUNED 0 +#define QAM_STATE_TUNING_STARTED 1 +#define QAM_STATE_INTERLEAVE_SET 2 +#define QAM_STATE_QAM_OPTIMIZED_L1 3 +#define QAM_STATE_QAM_OPTIMIZED_L2 4 +#define QAM_STATE_QAM_OPTIMIZED_L3 5 + u8 qam_state; }; static int debug; @@ -347,7 +355,7 @@ s5h1409_writereg(state, 0xf5, 0); s5h1409_writereg(state, 0xf5, 1); state->is_qam_locked = 0; - state->qam_state = 0; + state->qam_state = QAM_STATE_UNTUNED; return 0; } @@ -474,6 +482,59 @@ struct s5h1409_state *state = fe->demodulator_priv; u16 reg; + if (state->qam_state < QAM_STATE_INTERLEAVE_SET) { + /* We should not perform amhum optimization until + the interleave mode has been configured */ + return; + } + + if (state->qam_state == QAM_STATE_QAM_OPTIMIZED_L3) { + /* We've already reached the maximum optimization level, so + dont bother banging on the status registers */ + return; + } + + /* QAM EQ lock check */ + reg = s5h1409_readreg(state, 0xf0); + + if ((reg >> 13) & 0x1) { + reg &= 0xff; + + s5h1409_writereg(state, 0x96, 0x000c); + if (reg < 0x68) { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L3) { + dprintk("%s() setting QAM state to OPT_L3\n", + __func__); + s5h1409_writereg(state, 0x93, 0x3130); + s5h1409_writereg(state, 0x9e, 0x2836); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L3; + } + } else { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L2) { + dprintk("%s() setting QAM state to OPT_L2\n", + __func__); + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L2; + } + } + + } else { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L1) { + dprintk("%s() setting QAM state to OPT_L1\n", __func__); + s5h1409_writereg(state, 0x96, 0x0008); + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L1; + } + } +} + +static void s5h1409_set_qam_amhum_mode_legacy(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg; + if (state->is_qam_locked) return; @@ -506,6 +567,44 @@ struct s5h1409_state *state = fe->demodulator_priv; u16 reg, reg1, reg2; + if (state->qam_state >= QAM_STATE_INTERLEAVE_SET) { + /* We've done the optimization already */ + return; + } + + reg = s5h1409_readreg(state, 0xf1); + + /* Master lock */ + if ((reg >> 15) & 0x1) { + if (state->qam_state == QAM_STATE_UNTUNED || + state->qam_state == QAM_STATE_TUNING_STARTED) { + dprintk("%s() setting QAM state to INTERLEAVE_SET\n", + __func__); + reg1 = s5h1409_readreg(state, 0xb2); + reg2 = s5h1409_readreg(state, 0xad); + + s5h1409_writereg(state, 0x96, 0x0020); + s5h1409_writereg(state, 0xad, + (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff))); + state->qam_state = QAM_STATE_INTERLEAVE_SET; + } + } else { + if (state->qam_state == QAM_STATE_UNTUNED) { + dprintk("%s() setting QAM state to TUNING_STARTED\n", + __func__); + s5h1409_writereg(state, 0x96, 0x08); + s5h1409_writereg(state, 0xab, + s5h1409_readreg(state, 0xab) | 0x1001); + state->qam_state = QAM_STATE_TUNING_STARTED; + } + } +} + +static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg, reg1, reg2; + reg = s5h1409_readreg(state, 0xf1); /* Master lock */ @@ -553,16 +652,24 @@ fe->ops.i2c_gate_ctrl(fe, 0); } - /* Optimize the demod for QAM */ - if (p->u.vsb.modulation != VSB_8) { - s5h1409_set_qam_amhum_mode(fe); - s5h1409_set_qam_interleave_mode(fe); - } - /* Issue a reset to the demod so it knows to resync against the newly tuned frequency */ s5h1409_softreset(fe); + /* Optimize the demod for QAM */ + if (state->current_modulation != VSB_8) { + /* This almost certainly applies to all boards, but for now + only do it for the HVR-1600. Once the other boards are + tested, the "legacy" versions can just go away */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + s5h1409_set_qam_interleave_mode(fe); + s5h1409_set_qam_amhum_mode(fe); + } else { + s5h1409_set_qam_amhum_mode_legacy(fe); + s5h1409_set_qam_interleave_mode_legacy(fe); + } + } + return 0; } @@ -614,6 +721,21 @@ /* The datasheet says that after initialisation, VSB is default */ state->current_modulation = VSB_8; + /* Optimize for the HVR-1600 if appropriate. Note that some of these + may get folded into the generic case after testing with other + devices */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + /* VSB AGC REF */ + s5h1409_writereg(state, 0x09, 0x0050); + + /* Unknown but Windows driver does it... */ + s5h1409_writereg(state, 0x21, 0x0001); + s5h1409_writereg(state, 0x50, 0x030e); + + /* QAM AGC REF */ + s5h1409_writereg(state, 0x82, 0x0800); + } + if (state->config->output_mode == S5H1409_SERIAL_OUTPUT) s5h1409_writereg(state, 0xab, s5h1409_readreg(state, 0xab) | 0x100); /* Serial */ @@ -641,6 +763,17 @@ *status = 0; + /* Optimize the demod for QAM */ + if (state->current_modulation != VSB_8) { + /* This almost certainly applies to all boards, but for now + only do it for the HVR-1600. Once the other boards are + tested, the "legacy" versions can just go away */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + s5h1409_set_qam_interleave_mode(fe); + s5h1409_set_qam_amhum_mode(fe); + } + } + /* Get the demodulator status */ reg = s5h1409_readreg(state, 0xf1); if (reg & 0x1000) diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/dvb/frontends/s5h1409.h --- a/linux/drivers/media/dvb/frontends/s5h1409.h Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/dvb/frontends/s5h1409.h Sun Nov 15 10:06:08 2009 +0100 @@ -57,6 +57,13 @@ #define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2 #define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3 u16 mpeg_timing; + + /* HVR-1600 optimizations (to better work with MXL5005s) + Note: some of these are likely to be folded into the generic driver + after being regression tested with other boards */ +#define S5H1409_HVR1600_NOOPTIMIZE 0 +#define S5H1409_HVR1600_OPTIMIZE 1 + u8 hvr1600_opt; }; #if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \ diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/video/cx18/cx18-dvb.c --- a/linux/drivers/media/video/cx18/cx18-dvb.c Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/video/cx18/cx18-dvb.c Sun Nov 15 10:06:08 2009 +0100 @@ -61,6 +61,7 @@ .top = MXL5005S_TOP_25P2, .mod_mode = MXL_DIGITAL_MODE, .if_mode = MXL_ZERO_IF, + .qam_gain = 0x02, .AgcMasterByte = 0x00, }; @@ -71,7 +72,8 @@ .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, + .hvr1600_opt = S5H1409_HVR1600_OPTIMIZE }; /* diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/video/em28xx/em28xx-cards.c --- a/linux/drivers/media/video/em28xx/em28xx-cards.c Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c Sun Nov 15 10:06:08 2009 +0100 @@ -2648,6 +2648,9 @@ dev->chip_id = retval; switch (dev->chip_id) { + case CHIP_ID_EM2800: + em28xx_info("chip ID is em2800\n"); + break; case CHIP_ID_EM2710: em28xx_info("chip ID is em2710\n"); break; diff -r 3fd924da7091 -r 29c41565ce54 linux/drivers/media/video/em28xx/em28xx-reg.h --- a/linux/drivers/media/video/em28xx/em28xx-reg.h Sun Nov 08 08:41:28 2009 +0100 +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h Sun Nov 15 10:06:08 2009 +0100 @@ -192,6 +192,7 @@ /* FIXME: Need to be populated with the other chip ID's */ enum em28xx_chip_id { + CHIP_ID_EM2800 = 7, CHIP_ID_EM2710 = 17, CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ CHIP_ID_EM2840 = 20, --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/29c41565ce54a6e86d38c3de6c3a4d21708dd729 _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits