From 3e51a4965b9b9ab4fc6a7ecacc85816c7ebeeccb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2020 11:01:23 +0200 Subject: media: vidtv: add basic support for DVBv5 stats The current stats code is broken on so many ways. It ends reporting 0 for signal strengh, and the work queue doesn't run. If it would run, the code would crash. Fix such issues and add the minimum stuff for DVBv5 stats. Right now, only strength and cnr and UCB are implemented. pre/post BER stats will always return zero. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vidtv/vidtv_demod.c | 195 ++++++++++++++++--------- drivers/media/test-drivers/vidtv/vidtv_tuner.c | 2 +- 2 files changed, 127 insertions(+), 70 deletions(-) (limited to 'drivers/media/test-drivers') diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c index 6199a4e06ff9..bfe63d7160f2 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_demod.c +++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c @@ -122,6 +122,74 @@ static const struct vidtv_demod_cnr_to_qual_s return NULL; /* not found */ } +static void vidtv_clean_stats(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + /* Fill the length of each status counter */ + + /* Signal is always available */ + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_DECIBEL; + c->strength.stat[0].svalue = 0; + + /* Usually available only after Viterbi lock */ + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->cnr.stat[0].svalue = 0; + c->cnr.len = 1; + + /* Those depends on full lock */ + c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_error.stat[0].uvalue = 0; + c->pre_bit_error.len = 1; + c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_count.stat[0].uvalue = 0; + c->pre_bit_count.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.stat[0].uvalue = 0; + c->post_bit_error.len = 1; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].uvalue = 0; + c->post_bit_count.len = 1; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.stat[0].uvalue = 0; + c->block_error.len = 1; + c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_count.stat[0].uvalue = 0; + c->block_count.len = 1; +} + +static void vidtv_demod_update_stats(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct vidtv_demod_state *state = fe->demodulator_priv; + u32 scale; + + if (state->status & FE_HAS_LOCK) { + scale = FE_SCALE_COUNTER; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + } else { + scale = FE_SCALE_NOT_AVAILABLE; + c->cnr.stat[0].scale = scale; + } + + c->pre_bit_error.stat[0].scale = scale; + c->pre_bit_count.stat[0].scale = scale; + c->post_bit_error.stat[0].scale = scale; + c->post_bit_count.stat[0].scale = scale; + c->block_error.stat[0].scale = scale; + c->block_count.stat[0].scale = scale; + + /* + * Add a 0.5% of randomness at the signal streangth and CNR, + * and make them different, as we want to have something closer + * to a real case scenario. + */ + c->strength.stat[0].svalue = state->tuner_cnr + prandom_u32_max(state->tuner_cnr / 50); + c->cnr.stat[0].svalue = state->tuner_cnr - prandom_u32_max(state->tuner_cnr / 50); + +} + static void vidtv_demod_poll_snr_handler(struct work_struct *work) { /* @@ -133,33 +201,34 @@ static void vidtv_demod_poll_snr_handler(struct work_struct *work) struct vidtv_demod_config *config; u16 snr = 0; - state = container_of(work, struct vidtv_demod_state, poll_snr.work); + state = container_of(work, struct vidtv_demod_state, poll_snr.work); config = &state->config; - if (!state->frontend.ops.tuner_ops.get_rf_strength) - return; - - state->frontend.ops.tuner_ops.get_rf_strength(&state->frontend, &snr); - + /* Simulate random lost of signal due to a bad-tuned channel */ cnr2qual = vidtv_match_cnr_s(&state->frontend); - if (!cnr2qual) - return; - if (snr < cnr2qual->cnr_ok) { - /* eventually lose the TS lock */ - if (prandom_u32_max(100) < config->drop_tslock_prob_on_low_snr) - state->status = 0; - } else { - /* recover if the signal improves */ - if (prandom_u32_max(100) < - config->recover_tslock_prob_on_good_snr) - state->status = FE_HAS_SIGNAL | - FE_HAS_CARRIER | - FE_HAS_VITERBI | - FE_HAS_SYNC | - FE_HAS_LOCK; + if (cnr2qual && state->tuner_cnr < cnr2qual->cnr_good && + state->frontend.ops.tuner_ops.get_rf_strength) { + state->frontend.ops.tuner_ops.get_rf_strength(&state->frontend, &snr); + + if (snr < cnr2qual->cnr_ok) { + /* eventually lose the TS lock */ + if (prandom_u32_max(100) < config->drop_tslock_prob_on_low_snr) + state->status = 0; + } else { + /* recover if the signal improves */ + if (prandom_u32_max(100) < + config->recover_tslock_prob_on_good_snr) + state->status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK; + } } + vidtv_demod_update_stats(&state->frontend); + schedule_delayed_work(&state->poll_snr, msecs_to_jiffies(POLL_THRD_TIME)); } @@ -174,28 +243,13 @@ static int vidtv_demod_read_status(struct dvb_frontend *fe, return 0; } -static int vidtv_demod_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - *ber = 0; - return 0; -} - static int vidtv_demod_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - *strength = 0; - return 0; -} + struct dtv_frontend_properties *c = &fe->dtv_property_cache; -static int vidtv_demod_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - *snr = 0; - return 0; -} + *strength = c->strength.stat[0].uvalue; -static int vidtv_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; return 0; } @@ -216,38 +270,42 @@ static int vidtv_demod_get_frontend(struct dvb_frontend *fe, static int vidtv_demod_set_frontend(struct dvb_frontend *fe) { - struct vidtv_demod_state *state = fe->demodulator_priv; const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL; - u32 tuner_status = 0; - - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe); - - /* store the CNR returned by the tuner */ - fe->ops.tuner_ops.get_rf_strength(fe, &state->tuner_cnr); - - fe->ops.tuner_ops.get_status(fe, &tuner_status); - state->status = (state->tuner_cnr > 0) ? FE_HAS_SIGNAL | - FE_HAS_CARRIER | - FE_HAS_VITERBI | - FE_HAS_SYNC | - FE_HAS_LOCK : - 0; - cnr2qual = vidtv_match_cnr_s(fe); - - /* signal isn't good: might lose the lock eventually */ - if (tuner_status == TUNER_STATUS_LOCKED && - state->tuner_cnr < cnr2qual->cnr_good) { - schedule_delayed_work(&state->poll_snr, - msecs_to_jiffies(POLL_THRD_TIME)); - - state->poll_snr_thread_running = true; - } + struct vidtv_demod_state *state = fe->demodulator_priv; + u32 tuner_status = 0; + int ret; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + if (!fe->ops.tuner_ops.set_params) + return 0; + + fe->ops.tuner_ops.set_params(fe); + + /* store the CNR returned by the tuner */ + ret = fe->ops.tuner_ops.get_rf_strength(fe, &state->tuner_cnr); + if (ret < 0) + return ret; + + fe->ops.tuner_ops.get_status(fe, &tuner_status); + state->status = (state->tuner_cnr > 0) ? FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK : + 0; + cnr2qual = vidtv_match_cnr_s(fe); + + vidtv_demod_update_stats(fe); + + if (state->tuner_cnr > 0) { + schedule_delayed_work(&state->poll_snr, + msecs_to_jiffies(POLL_THRD_TIME)); + + state->poll_snr_thread_running = true; } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return 0; } @@ -372,10 +430,7 @@ static const struct dvb_frontend_ops vidtv_demod_ops = { .get_frontend = vidtv_demod_get_frontend, .read_status = vidtv_demod_read_status, - .read_ber = vidtv_demod_read_ber, .read_signal_strength = vidtv_demod_read_signal_strength, - .read_snr = vidtv_demod_read_snr, - .read_ucblocks = vidtv_demod_read_ucblocks, /* For DVB-S/S2 */ .set_voltage = vidtv_demod_set_voltage, @@ -411,6 +466,8 @@ static int vidtv_demod_i2c_probe(struct i2c_client *client, state->frontend.demodulator_priv = state; i2c_set_clientdata(client, state); + vidtv_clean_stats(&state->frontend); + return 0; } diff --git a/drivers/media/test-drivers/vidtv/vidtv_tuner.c b/drivers/media/test-drivers/vidtv/vidtv_tuner.c index 13ce0a3ef43c..9bc49e099f65 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_tuner.c +++ b/drivers/media/test-drivers/vidtv/vidtv_tuner.c @@ -246,7 +246,7 @@ vidtv_tuner_get_signal_strength(struct dvb_frontend *fe, u16 *strength) * do a linear interpolation between 34dB and 10dB if we can't * match against the table */ - *strength = 34 - 24 * shift / 100; + *strength = 34000 - 24000 * shift / 100; return 0; } -- cgit v1.2.3