The demodulator can get in a state in ATSC mode where just restarting the feed alone does not correct the corrupted stream. The demodulator reset in addition to the feed restart seems to correct the condition. The au8522 driver has been modified so that when set_frontend() is called with the same frequency and modulation mode, the demodulator will be reset. The au0282 drives uses this feature when it attempts to restart the feed. Signed-off-by: Tim Mester <tmester@xxxxxxxx> --- linux/drivers/media/dvb-frontends/au8522_dig.c | 38 +++++++++++++++++++++++++- linux/drivers/media/usb/au0828/au0828-dvb.c | 8 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb-frontends/au8522_dig.c b/linux/drivers/media/dvb-frontends/au8522_dig.c index a68974f..821cc70 100644 --- a/linux/drivers/media/dvb-frontends/au8522_dig.c +++ b/linux/drivers/media/dvb-frontends/au8522_dig.c @@ -469,6 +469,38 @@ static struct { { 0x8526, 0x01 }, }; +/* + * Reset the demodulator. Currently this only does something if + * configured in ATSC mode. This reset is needed in marginal signal + * levels when the feed (in MPEG-TS format) is correupted. + * + */ + +static int au8522_reset_demodulator(struct dvb_frontend *fe) +{ + struct au8522_state *state = fe->demodulator_priv; + + switch (state->current_modulation) { + case VSB_8: + dprintk("%s() VSB_8\n", __func__); + au8522_writereg(state, 0x80a4, 0); + au8522_writereg(state, 0x80a5, 0); + au8522_writereg(state, 0x80a4, 0xe8); + au8522_writereg(state, 0x80a5, 0x40); + break; + case QAM_64: + case QAM_256: + dprintk("%s() QAM 64/256\n", __func__); + break; + default: + dprintk("%s() Invalid modulation\n", __func__); + return -EINVAL; + } + + return 0; +} + + static int au8522_enable_modulation(struct dvb_frontend *fe, fe_modulation_t m) { @@ -522,8 +554,12 @@ static int au8522_set_frontend(struct dvb_frontend *fe) dprintk("%s(frequency=%d)\n", __func__, c->frequency); if ((state->current_frequency == c->frequency) && - (state->current_modulation == c->modulation)) + (state->current_modulation == c->modulation)) { + + au8522_reset_demodulator(fe); + msleep(100); return 0; + } if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) diff --git a/linux/drivers/media/usb/au0828/au0828-dvb.c b/linux/drivers/media/usb/au0828/au0828-dvb.c index 1673c88..483c587 100644 --- a/linux/drivers/media/usb/au0828/au0828-dvb.c +++ b/linux/drivers/media/usb/au0828/au0828-dvb.c @@ -330,6 +330,14 @@ static void au0828_restart_dvb_streaming(struct work_struct *work) stop_urb_transfer(dev); au0828_stop_transport(dev, 1); + /* + * In ATSC mode, we also need to reset the demodulator in lower signal + * level cases to help realign the data stream. + */ + + if (dvb->frontend->ops.set_frontend) + dvb->frontend->ops.set_frontend(dvb->frontend); + /* Start transport */ au0828_start_transport(dev); start_urb_transfer(dev); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html