/* * On this demod, when the bit count reaches the count below, * it collects the bit error count. The bit counters are initialized * to 65535 here. This warrants that all of them will be quickly * calculated when device gets locked. As TMCC is parsed, the values * will be adjusted later in the driver's code.
*/
{ 0x52, 0x01 }, /* Turn on BER before Viterbi */
{ 0x50, 0xa7 }, { 0x51, 0x00 },
{ 0x50, 0xa8 }, { 0x51, 0xff },
{ 0x50, 0xa9 }, { 0x51, 0xff },
{ 0x50, 0xaa }, { 0x51, 0x00 },
{ 0x50, 0xab }, { 0x51, 0xff },
{ 0x50, 0xac }, { 0x51, 0xff },
{ 0x50, 0xad }, { 0x51, 0x00 },
{ 0x50, 0xae }, { 0x51, 0xff },
{ 0x50, 0xaf }, { 0x51, 0xff },
/* * On this demod, post BER counts blocks. When the count reaches the * value below, it collects the block error count. The block counters * are initialized to 127 here. This warrants that all of them will be * quickly calculated when device gets locked. As TMCC is parsed, the * values will be adjusted later in the driver's code.
*/
{ 0x5e, 0x07 }, /* Turn on BER after Viterbi */
{ 0x50, 0xdc }, { 0x51, 0x00 },
{ 0x50, 0xdd }, { 0x51, 0x7f },
{ 0x50, 0xde }, { 0x51, 0x00 },
{ 0x50, 0xdf }, { 0x51, 0x7f },
{ 0x50, 0xe0 }, { 0x51, 0x00 },
{ 0x50, 0xe1 }, { 0x51, 0x7f },
/* * On this demod, when the block count reaches the count below, * it collects the block error count. The block counters are initialized * to 127 here. This warrants that all of them will be quickly * calculated when device gets locked. As TMCC is parsed, the values * will be adjusted later in the driver's code.
*/
{ 0x50, 0xb0 }, { 0x51, 0x07 }, /* Enable PER */
{ 0x50, 0xb2 }, { 0x51, 0x00 },
{ 0x50, 0xb3 }, { 0x51, 0x7f },
{ 0x50, 0xb4 }, { 0x51, 0x00 },
{ 0x50, 0xb5 }, { 0x51, 0x7f },
{ 0x50, 0xb6 }, { 0x51, 0x00 },
{ 0x50, 0xb7 }, { 0x51, 0x7f },
val = mb86a20s_readreg(state, 0x0a); if (val < 0) return val;
val &= 0xf; if (val >= 2)
*status |= FE_HAS_SIGNAL;
if (val >= 4)
*status |= FE_HAS_CARRIER;
if (val >= 5)
*status |= FE_HAS_VITERBI;
if (val >= 7)
*status |= FE_HAS_SYNC;
/* * Actually, on state S8, it starts receiving TS, but the TS * output is only on normal state after the transition to S9.
*/ if (val >= 9)
*status |= FE_HAS_LOCK;
/* * If modulation/fec/guard is not detected, the default is * to consider the lowest bit rate, to avoid taking too long time * to get BER.
*/ switch (c->layer[layer].modulation) { case DQPSK: case QPSK: default:
mod = 0; break; case QAM_16:
mod = 1; break; case QAM_64:
mod = 2; break;
}
switch (c->layer[layer].fec) { default: case FEC_1_2: case FEC_AUTO:
fec = 0; break; case FEC_2_3:
fec = 1; break; case FEC_3_4:
fec = 2; break; case FEC_5_6:
fec = 3; break; case FEC_7_8:
fec = 4; break;
}
switch (c->guard_interval) { default: case GUARD_INTERVAL_1_4:
guard = 0; break; case GUARD_INTERVAL_1_8:
guard = 1; break; case GUARD_INTERVAL_1_16:
guard = 2; break; case GUARD_INTERVAL_1_32:
guard = 3; break;
}
/* Check if the BER measures are already available */
rc = mb86a20s_readreg(state, 0x54); if (rc < 0) return rc;
/* Check if data is available for that layer */ if (!(rc & (1 << layer))) {
dev_dbg(&state->i2c->dev, "%s: preBER for layer %c is not available yet.\n",
__func__, 'A' + layer); return -EBUSY;
}
dev_dbg(&state->i2c->dev, "%s: bit count before Viterbi for layer %c: %d.\n",
__func__, 'A' + layer, *count);
/* * As we get TMCC data from the frontend, we can better estimate the * BER bit counters, in order to do the BER measure during a longer * time. Use those data, if available, to update the bit count * measure.
*/
/* Check if the BER measures are already available */
rc = mb86a20s_readreg(state, 0x60); if (rc < 0) return rc;
/* Check if data is available for that layer */ if (!(rc & (1 << layer))) {
dev_dbg(&state->i2c->dev, "%s: post BER for layer %c is not available yet.\n",
__func__, 'A' + layer); return -EBUSY;
}
dev_dbg(&state->i2c->dev, "%s: post bit count for layer %c: %d.\n",
__func__, 'A' + layer, *count);
/* * As we get TMCC data from the frontend, we can better estimate the * BER bit counters, in order to do the BER measure during a longer * time. Use those data, if available, to update the bit count * measure.
*/
if (!state->estimated_rate[layer]) goto reset_measurement;
collect_rate = state->estimated_rate[layer] / 204 / 8; if (collect_rate < 32)
collect_rate = 32; if (collect_rate > 65535)
collect_rate = 65535; if (collect_rate != counter) {
dev_dbg(&state->i2c->dev, "%s: updating postBER counter on layer %c to %d.\n",
__func__, 'A' + layer, collect_rate);
/* Turn off BER after Viterbi */
rc = mb86a20s_writereg(state, 0x5e, 0x00);
/* Check if the PER measures are already available */
rc = mb86a20s_writereg(state, 0x50, 0xb8); if (rc < 0) return rc;
rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc;
/* Check if data is available for that layer */
if (!(rc & (1 << layer))) {
dev_dbg(&state->i2c->dev, "%s: block counts for layer %c aren't available yet.\n",
__func__, 'A' + layer); return -EBUSY;
}
/* * As we get TMCC data from the frontend, we can better estimate the * BER bit counters, in order to do the BER measure during a longer * time. Use those data, if available, to update the bit count * measure.
*/
if (!state->estimated_rate[layer]) goto reset_measurement;
static u32 interpolate_value(u32 value, conststruct linear_segments *segments, unsigned len)
{
u64 tmp64;
u32 dx, dy; int i, ret;
if (value >= segments[0].x) return segments[0].y; if (value < segments[len-1].x) return segments[len-1].y;
for (i = 1; i < len - 1; i++) { /* If value is identical, no need to interpolate */ if (value == segments[i].x) return segments[i].y; if (value > segments[i].x) break;
}
/* Linear interpolation between the two (x,y) points */
dy = segments[i].y - segments[i - 1].y;
dx = segments[i - 1].x - segments[i].x;
tmp64 = value - segments[i].x;
tmp64 *= dy;
do_div(tmp64, dx);
ret = segments[i].y - tmp64;
/* Check if the measures are already available */
rc = mb86a20s_writereg(state, 0x50, 0x5b); if (rc < 0) return rc;
rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc;
/* Check if data is available */ if (!(rc & 0x01)) {
dev_dbg(&state->i2c->dev, "%s: MER measures aren't available yet.\n", __func__); return -EBUSY;
}
/* Read all layers */ for (layer = 0; layer < NUM_LAYERS; layer++) { if (!(c->isdbt_layer_enabled & (1 << layer))) {
c->cnr.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; continue;
}
rc = mb86a20s_writereg(state, 0x50, 0x52 + layer * 3); if (rc < 0) return rc;
rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc;
mer = rc << 16;
rc = mb86a20s_writereg(state, 0x50, 0x53 + layer * 3); if (rc < 0) return rc;
rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc;
mer |= rc << 8;
rc = mb86a20s_writereg(state, 0x50, 0x54 + layer * 3); if (rc < 0) return rc;
rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc;
mer |= rc;
switch (c->layer[layer].modulation) { case DQPSK: case QPSK:
segs = cnr_qpsk_table;
segs_len = ARRAY_SIZE(cnr_qpsk_table); break; case QAM_16:
segs = cnr_16qam_table;
segs_len = ARRAY_SIZE(cnr_16qam_table); break; default: case QAM_64:
segs = cnr_64qam_table;
segs_len = ARRAY_SIZE(cnr_64qam_table); break;
}
cnr = interpolate_value(mer, segs, segs_len);
/* Get per-layer stats */
mb86a20s_get_blk_error_layer_CNR(fe);
/* * At state 7, only CNR is available * For BER measures, state=9 is required * FIXME: we may get MER measures with state=8
*/ if (status_nr < 9) return 0;
for (layer = 0; layer < NUM_LAYERS; layer++) { if (c->isdbt_layer_enabled & (1 << layer)) { /* Handle BER before vterbi */
rc = mb86a20s_get_pre_ber(fe, layer,
&bit_error, &bit_count); if (rc >= 0) {
c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[1 + layer].uvalue += bit_error;
c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[1 + layer].uvalue += bit_count;
} elseif (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable
*/
c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev, "%s: Can't get BER for layer %c (error %d).\n",
__func__, 'A' + layer, rc);
} if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
pre_ber_layers++;
/* Handle BER post vterbi */
rc = mb86a20s_get_post_ber(fe, layer,
&bit_error, &bit_count); if (rc >= 0) {
c->post_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[1 + layer].uvalue += bit_error;
c->post_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[1 + layer].uvalue += bit_count;
} elseif (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable
*/
c->post_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev, "%s: Can't get BER for layer %c (error %d).\n",
__func__, 'A' + layer, rc);
} if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
post_ber_layers++;
/* Handle Block errors for PER/UCB reports */
rc = mb86a20s_get_blk_error(fe, layer,
&block_error,
&block_count); if (rc >= 0) {
c->block_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->block_error.stat[1 + layer].uvalue += block_error;
c->block_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->block_count.stat[1 + layer].uvalue += block_count;
} elseif (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable
*/
c->block_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev, "%s: Can't get PER for layer %c (error %d).\n",
__func__, 'A' + layer, rc);
} if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
per_layers++;
/* Update total PER */
t_block_error += c->block_error.stat[1 + layer].uvalue;
t_block_count += c->block_count.stat[1 + layer].uvalue;
}
}
/* * Start showing global count if at least one error count is * available.
*/ if (pre_ber_layers) { /* * At least one per-layer BER measure was read. We can now * calculate the total BER * * Total Bit Error/Count is calculated as the sum of the * bit errors on all active layers.
*/
c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[0].uvalue = t_pre_bit_error;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[0].uvalue = t_pre_bit_count;
} else {
c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
}
/* * Start showing global count if at least one error count is * available.
*/ if (post_ber_layers) { /* * At least one per-layer BER measure was read. We can now * calculate the total BER * * Total Bit Error/Count is calculated as the sum of the * bit errors on all active layers.
*/
c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[0].uvalue = t_post_bit_error;
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[0].uvalue = t_post_bit_count;
} else {
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
}
if (per_layers) { /* * At least one per-layer UCB measure was read. We can now * calculate the total UCB * * Total block Error/Count is calculated as the sum of the * block errors on all active layers.
*/
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue = t_block_error;
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue = t_block_count;
} else {
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
}
return rc;
}
/* * The functions below are called via DVB callbacks, so they need to * properly use the I2C gate control
*/
/* * Gate should already be opened, but it doesn't hurt to * double-check
*/ if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.set_params(fe);
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
/* * Make it more reliable: if, for some reason, the initial * device initialization doesn't happen, initialize it when * a SBTVD parameters are adjusted. * * Unfortunately, due to a hard to track bug at tda829x/tda18271, * the agc callback logic is not called during DVB attach time, * causing mb86a20s to not be initialized with Kworld SBTVD. * So, this hack is needed, in order to make Kworld SBTVD to work. * * It is also needed to change the IF after the initial init. * * HACK: Always init the frontend when set_frontend is called: * it was noticed that, on some devices, it fails to lock on a * different channel. So, it is better to reset everything, even * wasting some time, than to loose channel lock.
*/
mb86a20s_initfe(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
/* Get signal strength */
rc = mb86a20s_read_signal_strength(fe); if (rc < 0) {
dev_err(&state->i2c->dev, "%s: Can't reset VBER registers.\n", __func__);
mb86a20s_stats_not_ready(fe);
mb86a20s_reset_frontend_cache(fe);
rc = 0; /* Status is OK */ goto error;
}
if (status_nr >= 7) { /* Get TMCC info*/
rc = mb86a20s_get_frontend(fe); if (rc < 0) {
dev_err(&state->i2c->dev, "%s: Can't get FE TMCC data.\n", __func__);
rc = 0; /* Status is OK */ goto error;
}
/* Get statistics */
rc = mb86a20s_get_stats(fe, status_nr); if (rc < 0 && rc != -EBUSY) {
dev_err(&state->i2c->dev, "%s: Can't get FE statistics.\n", __func__);
rc = 0; goto error;
}
rc = 0; /* Don't return EBUSY to userspace */
} goto ok;
error:
mb86a20s_stats_not_ready(fe);
ok: if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.