summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-01-17 18:10:47 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-01-24 11:24:59 -0500
commit593ae89a3f2ea69b0cffb8d8ca63549c6c02ec19 (patch)
tree9a9c5eeefc9adeadf692a2cdef9ce03be5d4ba30
parent94a93e5f85040114d6a77c085457b3943b6da889 (diff)
[media] mb86a20s: add block count measures (PER/UCB)
Add both per-layer and global block error count and block count, for PER and UCB measurements. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c190
1 files changed, 180 insertions, 10 deletions
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index 4f3e222a2bcf..c5c2c49ea99a 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -111,13 +111,21 @@ static struct regdata mb86a20s_init[] = {
111 { 0x50, 0xdf }, { 0x51, 0xf4 }, 111 { 0x50, 0xdf }, { 0x51, 0xf4 },
112 { 0x50, 0xe0 }, { 0x51, 0x01 }, 112 { 0x50, 0xe0 }, { 0x51, 0x01 },
113 { 0x50, 0xe1 }, { 0x51, 0xf4 }, 113 { 0x50, 0xe1 }, { 0x51, 0xf4 },
114 { 0x50, 0xb0 }, { 0x51, 0x07 }, 114
115 { 0x50, 0xb2 }, { 0x51, 0xff }, 115 /*
116 { 0x50, 0xb3 }, { 0x51, 0xff }, 116 * On this demod, when the block count reaches the count below,
117 { 0x50, 0xb4 }, { 0x51, 0xff }, 117 * it collects the block error count. The block counters are initialized
118 { 0x50, 0xb5 }, { 0x51, 0xff }, 118 * to 127 here. This warrants that all of them will be quickly
119 { 0x50, 0xb6 }, { 0x51, 0xff }, 119 * calculated when device gets locked. As TMCC is parsed, the values
120 { 0x50, 0xb7 }, { 0x51, 0xff }, 120 * will be adjusted later in the driver's code.
121 */
122 { 0x50, 0xb0 }, { 0x51, 0x07 }, /* Enable PER */
123 { 0x50, 0xb2 }, { 0x51, 0x00 },
124 { 0x50, 0xb3 }, { 0x51, 0x7f },
125 { 0x50, 0xb4 }, { 0x51, 0x00 },
126 { 0x50, 0xb5 }, { 0x51, 0x7f },
127 { 0x50, 0xb6 }, { 0x51, 0x00 },
128 { 0x50, 0xb7 }, { 0x51, 0x7f },
121 129
122 { 0x50, 0x50 }, { 0x51, 0x02 }, /* MER manual mode */ 130 { 0x50, 0x50 }, { 0x51, 0x02 }, /* MER manual mode */
123 { 0x50, 0x51 }, { 0x51, 0x04 }, /* MER symbol 4 */ 131 { 0x50, 0x51 }, { 0x51, 0x04 }, /* MER symbol 4 */
@@ -893,6 +901,123 @@ static int mb86a20s_get_ber_before_vterbi(struct dvb_frontend *fe,
893 return 0; 901 return 0;
894} 902}
895 903
904static int mb86a20s_get_blk_error(struct dvb_frontend *fe,
905 unsigned layer,
906 u32 *error, u32 *count)
907{
908 struct mb86a20s_state *state = fe->demodulator_priv;
909 int rc;
910 u32 collect_rate;
911 dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
912
913 if (layer >= 3)
914 return -EINVAL;
915
916 /* Check if the PER measures are already available */
917 rc = mb86a20s_writereg(state, 0x50, 0xb8);
918 if (rc < 0)
919 return rc;
920 rc = mb86a20s_readreg(state, 0x51);
921 if (rc < 0)
922 return rc;
923
924 /* Check if data is available for that layer */
925
926 if (!(rc & (1 << layer))) {
927 dev_dbg(&state->i2c->dev,
928 "%s: block counts for layer %c aren't available yet.\n",
929 __func__, 'A' + layer);
930 return -EBUSY;
931 }
932
933 /* Read Packet error Count */
934 rc = mb86a20s_writereg(state, 0x50, 0xb9 + layer * 2);
935 if (rc < 0)
936 return rc;
937 rc = mb86a20s_readreg(state, 0x51);
938 if (rc < 0)
939 return rc;
940 *error = rc << 8;
941 rc = mb86a20s_writereg(state, 0x50, 0xba + layer * 2);
942 if (rc < 0)
943 return rc;
944 rc = mb86a20s_readreg(state, 0x51);
945 if (rc < 0)
946 return rc;
947 *error |= rc;
948 dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
949 __func__, 'A' + layer, *error);
950
951 /* Read Bit Count */
952 rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2);
953 if (rc < 0)
954 return rc;
955 rc = mb86a20s_readreg(state, 0x51);
956 if (rc < 0)
957 return rc;
958 *count = rc << 8;
959 rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2);
960 if (rc < 0)
961 return rc;
962 rc = mb86a20s_readreg(state, 0x51);
963 if (rc < 0)
964 return rc;
965 *count |= rc;
966
967 dev_dbg(&state->i2c->dev,
968 "%s: block count for layer %c: %d.\n",
969 __func__, 'A' + layer, *count);
970
971 /*
972 * As we get TMCC data from the frontend, we can better estimate the
973 * BER bit counters, in order to do the BER measure during a longer
974 * time. Use those data, if available, to update the bit count
975 * measure.
976 */
977
978 if (!state->estimated_rate[layer])
979 goto reset_measurement;
980
981 collect_rate = state->estimated_rate[layer] / 204 / 8;
982
983 if (collect_rate < 32)
984 collect_rate = 32;
985 if (collect_rate > 65535)
986 collect_rate = 65535;
987
988 if (collect_rate != *count) {
989 dev_dbg(&state->i2c->dev,
990 "%s: updating PER counter on layer %c to %d.\n",
991 __func__, 'A' + layer, collect_rate);
992 rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2);
993 if (rc < 0)
994 return rc;
995 rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8);
996 if (rc < 0)
997 return rc;
998 rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2);
999 if (rc < 0)
1000 return rc;
1001 rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff);
1002 if (rc < 0)
1003 return rc;
1004 }
1005
1006reset_measurement:
1007 /* Reset counter to collect new data */
1008 rc = mb86a20s_writereg(state, 0x50, 0xb1);
1009 if (rc < 0)
1010 return rc;
1011 rc = mb86a20s_writereg(state, 0x51, (1 << layer));
1012 if (rc < 0)
1013 return rc;
1014 rc = mb86a20s_writereg(state, 0x51, 0x00);
1015 if (rc < 0)
1016 return rc;
1017
1018 return 0;
1019}
1020
896struct linear_segments { 1021struct linear_segments {
897 unsigned x, y; 1022 unsigned x, y;
898}; 1023};
@@ -1115,7 +1240,7 @@ static int mb86a20s_get_main_CNR(struct dvb_frontend *fe)
1115 return rc; 1240 return rc;
1116} 1241}
1117 1242
1118static int mb86a20s_get_per_layer_CNR(struct dvb_frontend *fe) 1243static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
1119{ 1244{
1120 struct mb86a20s_state *state = fe->demodulator_priv; 1245 struct mb86a20s_state *state = fe->demodulator_priv;
1121 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1246 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1258,14 +1383,16 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
1258 int rc = 0, i; 1383 int rc = 0, i;
1259 u32 bit_error = 0, bit_count = 0; 1384 u32 bit_error = 0, bit_count = 0;
1260 u32 t_pre_bit_error = 0, t_pre_bit_count = 0; 1385 u32 t_pre_bit_error = 0, t_pre_bit_count = 0;
1261 int active_layers = 0, ber_layers = 0; 1386 u32 block_error = 0, block_count = 0;
1387 u32 t_block_error = 0, t_block_count = 0;
1388 int active_layers = 0, ber_layers = 0, per_layers = 0;
1262 1389
1263 dev_dbg(&state->i2c->dev, "%s called.\n", __func__); 1390 dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1264 1391
1265 mb86a20s_get_main_CNR(fe); 1392 mb86a20s_get_main_CNR(fe);
1266 1393
1267 /* Get per-layer stats */ 1394 /* Get per-layer stats */
1268 mb86a20s_get_per_layer_CNR(fe); 1395 mb86a20s_get_blk_error_layer_CNR(fe);
1269 1396
1270 for (i = 0; i < 3; i++) { 1397 for (i = 0; i < 3; i++) {
1271 if (c->isdbt_layer_enabled & (1 << i)) { 1398 if (c->isdbt_layer_enabled & (1 << i)) {
@@ -1297,9 +1424,38 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
1297 if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) 1424 if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE)
1298 ber_layers++; 1425 ber_layers++;
1299 1426
1427 /* Handle Block errors for PER/UCB reports */
1428 rc = mb86a20s_get_blk_error(fe, i,
1429 &block_error,
1430 &block_count);
1431 if (rc >= 0) {
1432 c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER;
1433 c->block_error.stat[1 + i].uvalue += block_error;
1434 c->block_count.stat[1 + i].scale = FE_SCALE_COUNTER;
1435 c->block_count.stat[1 + i].uvalue += block_count;
1436 } else if (rc != -EBUSY) {
1437 /*
1438 * If an I/O error happened,
1439 * measures are now unavailable
1440 */
1441 c->block_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
1442 c->block_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
1443 dev_err(&state->i2c->dev,
1444 "%s: Can't get PER for layer %c (error %d).\n",
1445 __func__, 'A' + i, rc);
1446
1447 }
1448
1449 if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE)
1450 per_layers++;
1451
1300 /* Update total BER */ 1452 /* Update total BER */
1301 t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; 1453 t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue;
1302 t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; 1454 t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue;
1455
1456 /* Update total PER */
1457 t_block_error += c->block_error.stat[1 + i].uvalue;
1458 t_block_count += c->block_count.stat[1 + i].uvalue;
1303 } 1459 }
1304 } 1460 }
1305 1461
@@ -1321,6 +1477,20 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
1321 c->pre_bit_count.stat[0].uvalue = t_pre_bit_count; 1477 c->pre_bit_count.stat[0].uvalue = t_pre_bit_count;
1322 } 1478 }
1323 1479
1480 if (per_layers) {
1481 /*
1482 * At least one per-layer UCB measure was read. We can now
1483 * calculate the total UCB
1484 *
1485 * Total block Error/Count is calculated as the sum of the
1486 * block errors on all active layers.
1487 */
1488 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
1489 c->block_error.stat[0].uvalue = t_block_error;
1490 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1491 c->block_count.stat[0].uvalue = t_block_count;
1492 }
1493
1324 return rc; 1494 return rc;
1325} 1495}
1326 1496