diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-24 08:25:16 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-24 11:28:14 -0500 |
commit | d9b6f08a7f756d2d5105f5aaf23c326f41a0683b (patch) | |
tree | bf38863daa8cbf1e3728ec5d34924f0a04dd3627 | |
parent | 313cf4efa40ef739199bd68a76f89f8a5224a541 (diff) |
[media] mb86a20s: add a logic for post-BER measurement
The logic here is similar to the preBER.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.c | 220 |
1 files changed, 196 insertions, 24 deletions
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 7d4e9119632d..ed39ee13a5ad 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c | |||
@@ -104,13 +104,20 @@ static struct regdata mb86a20s_init[] = { | |||
104 | { 0x50, 0xae }, { 0x51, 0xff }, | 104 | { 0x50, 0xae }, { 0x51, 0xff }, |
105 | { 0x50, 0xaf }, { 0x51, 0xff }, | 105 | { 0x50, 0xaf }, { 0x51, 0xff }, |
106 | 106 | ||
107 | { 0x5e, 0x00 }, /* Turn off BER after Viterbi */ | 107 | /* |
108 | { 0x50, 0xdc }, { 0x51, 0x01 }, | 108 | * On this demod, post BER counts blocks. When the count reaches the |
109 | { 0x50, 0xdd }, { 0x51, 0xf4 }, | 109 | * value below, it collects the block error count. The block counters |
110 | { 0x50, 0xde }, { 0x51, 0x01 }, | 110 | * are initialized to 127 here. This warrants that all of them will be |
111 | { 0x50, 0xdf }, { 0x51, 0xf4 }, | 111 | * quickly calculated when device gets locked. As TMCC is parsed, the |
112 | { 0x50, 0xe0 }, { 0x51, 0x01 }, | 112 | * values will be adjusted later in the driver's code. |
113 | { 0x50, 0xe1 }, { 0x51, 0xf4 }, | 113 | */ |
114 | { 0x5e, 0x07 }, /* Turn on BER after Viterbi */ | ||
115 | { 0x50, 0xdc }, { 0x51, 0x00 }, | ||
116 | { 0x50, 0xdd }, { 0x51, 0x7f }, | ||
117 | { 0x50, 0xde }, { 0x51, 0x00 }, | ||
118 | { 0x50, 0xdf }, { 0x51, 0x7f }, | ||
119 | { 0x50, 0xe0 }, { 0x51, 0x00 }, | ||
120 | { 0x50, 0xe1 }, { 0x51, 0x7f }, | ||
114 | 121 | ||
115 | /* | 122 | /* |
116 | * On this demod, when the block count reaches the count below, | 123 | * On this demod, when the block count reaches the count below, |
@@ -187,12 +194,13 @@ static struct regdata mb86a20s_reset_reception[] = { | |||
187 | { 0x08, 0x00 }, | 194 | { 0x08, 0x00 }, |
188 | }; | 195 | }; |
189 | 196 | ||
190 | static struct regdata mb86a20s_vber_reset[] = { | 197 | static struct regdata mb86a20s_per_ber_reset[] = { |
191 | { 0x53, 0x00 }, /* VBER Counter reset */ | 198 | { 0x53, 0x00 }, /* pre BER Counter reset */ |
192 | { 0x53, 0x07 }, | 199 | { 0x53, 0x07 }, |
193 | }; | ||
194 | 200 | ||
195 | static struct regdata mb86a20s_per_reset[] = { | 201 | { 0x5f, 0x00 }, /* post BER Counter reset */ |
202 | { 0x5f, 0x07 }, | ||
203 | |||
196 | { 0x50, 0xb1 }, /* PER Counter reset */ | 204 | { 0x50, 0xb1 }, /* PER Counter reset */ |
197 | { 0x51, 0x07 }, | 205 | { 0x51, 0x07 }, |
198 | { 0x51, 0x00 }, | 206 | { 0x51, 0x00 }, |
@@ -731,6 +739,8 @@ static int mb86a20s_reset_counters(struct dvb_frontend *fe) | |||
731 | memset(&c->cnr, 0, sizeof(c->cnr)); | 739 | memset(&c->cnr, 0, sizeof(c->cnr)); |
732 | memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error)); | 740 | memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error)); |
733 | memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count)); | 741 | memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count)); |
742 | memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); | ||
743 | memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); | ||
734 | memset(&c->block_error, 0, sizeof(c->block_error)); | 744 | memset(&c->block_error, 0, sizeof(c->block_error)); |
735 | memset(&c->block_count, 0, sizeof(c->block_count)); | 745 | memset(&c->block_count, 0, sizeof(c->block_count)); |
736 | 746 | ||
@@ -739,13 +749,8 @@ static int mb86a20s_reset_counters(struct dvb_frontend *fe) | |||
739 | 749 | ||
740 | /* Clear status for most stats */ | 750 | /* Clear status for most stats */ |
741 | 751 | ||
742 | /* BER counter reset */ | 752 | /* BER/PER counter reset */ |
743 | rc = mb86a20s_writeregdata(state, mb86a20s_vber_reset); | 753 | rc = mb86a20s_writeregdata(state, mb86a20s_per_ber_reset); |
744 | if (rc < 0) | ||
745 | goto err; | ||
746 | |||
747 | /* MER, PER counter reset */ | ||
748 | rc = mb86a20s_writeregdata(state, mb86a20s_per_reset); | ||
749 | if (rc < 0) | 754 | if (rc < 0) |
750 | goto err; | 755 | goto err; |
751 | 756 | ||
@@ -915,7 +920,124 @@ static int mb86a20s_get_pre_ber(struct dvb_frontend *fe, | |||
915 | rc = mb86a20s_writereg(state, 0x53, val | (1 << layer)); | 920 | rc = mb86a20s_writereg(state, 0x53, val | (1 << layer)); |
916 | } | 921 | } |
917 | 922 | ||
923 | return rc; | ||
924 | } | ||
925 | |||
926 | static int mb86a20s_get_post_ber(struct dvb_frontend *fe, | ||
927 | unsigned layer, | ||
928 | u32 *error, u32 *count) | ||
929 | { | ||
930 | struct mb86a20s_state *state = fe->demodulator_priv; | ||
931 | u32 counter, collect_rate; | ||
932 | int rc, val; | ||
933 | |||
934 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | ||
935 | |||
936 | if (layer >= 3) | ||
937 | return -EINVAL; | ||
938 | |||
939 | /* Check if the BER measures are already available */ | ||
940 | rc = mb86a20s_readreg(state, 0x60); | ||
941 | if (rc < 0) | ||
942 | return rc; | ||
943 | |||
944 | /* Check if data is available for that layer */ | ||
945 | if (!(rc & (1 << layer))) { | ||
946 | dev_dbg(&state->i2c->dev, | ||
947 | "%s: post BER for layer %c is not available yet.\n", | ||
948 | __func__, 'A' + layer); | ||
949 | return -EBUSY; | ||
950 | } | ||
918 | 951 | ||
952 | /* Read Bit Error Count */ | ||
953 | rc = mb86a20s_readreg(state, 0x64 + layer * 3); | ||
954 | if (rc < 0) | ||
955 | return rc; | ||
956 | *error = rc << 16; | ||
957 | rc = mb86a20s_readreg(state, 0x65 + layer * 3); | ||
958 | if (rc < 0) | ||
959 | return rc; | ||
960 | *error |= rc << 8; | ||
961 | rc = mb86a20s_readreg(state, 0x66 + layer * 3); | ||
962 | if (rc < 0) | ||
963 | return rc; | ||
964 | *error |= rc; | ||
965 | |||
966 | dev_dbg(&state->i2c->dev, | ||
967 | "%s: post bit error for layer %c: %d.\n", | ||
968 | __func__, 'A' + layer, *error); | ||
969 | |||
970 | /* Read Bit Count */ | ||
971 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); | ||
972 | if (rc < 0) | ||
973 | return rc; | ||
974 | rc = mb86a20s_readreg(state, 0x51); | ||
975 | if (rc < 0) | ||
976 | return rc; | ||
977 | counter = rc << 8; | ||
978 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); | ||
979 | if (rc < 0) | ||
980 | return rc; | ||
981 | rc = mb86a20s_readreg(state, 0x51); | ||
982 | if (rc < 0) | ||
983 | return rc; | ||
984 | counter |= rc; | ||
985 | *count = counter * 204 * 8; | ||
986 | |||
987 | dev_dbg(&state->i2c->dev, | ||
988 | "%s: post bit count for layer %c: %d.\n", | ||
989 | __func__, 'A' + layer, *count); | ||
990 | |||
991 | /* | ||
992 | * As we get TMCC data from the frontend, we can better estimate the | ||
993 | * BER bit counters, in order to do the BER measure during a longer | ||
994 | * time. Use those data, if available, to update the bit count | ||
995 | * measure. | ||
996 | */ | ||
997 | |||
998 | if (!state->estimated_rate[layer]) | ||
999 | goto reset_measurement; | ||
1000 | |||
1001 | collect_rate = state->estimated_rate[layer] / 204 / 8; | ||
1002 | if (collect_rate < 32) | ||
1003 | collect_rate = 32; | ||
1004 | if (collect_rate > 65535) | ||
1005 | collect_rate = 65535; | ||
1006 | if (collect_rate != counter) { | ||
1007 | dev_dbg(&state->i2c->dev, | ||
1008 | "%s: updating postBER counter on layer %c to %d.\n", | ||
1009 | __func__, 'A' + layer, collect_rate); | ||
1010 | |||
1011 | /* Turn off BER after Viterbi */ | ||
1012 | rc = mb86a20s_writereg(state, 0x5e, 0x00); | ||
1013 | |||
1014 | /* Update counter for this layer */ | ||
1015 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); | ||
1016 | if (rc < 0) | ||
1017 | return rc; | ||
1018 | rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8); | ||
1019 | if (rc < 0) | ||
1020 | return rc; | ||
1021 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); | ||
1022 | if (rc < 0) | ||
1023 | return rc; | ||
1024 | rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff); | ||
1025 | if (rc < 0) | ||
1026 | return rc; | ||
1027 | |||
1028 | /* Turn on BER after Viterbi */ | ||
1029 | rc = mb86a20s_writereg(state, 0x5e, 0x07); | ||
1030 | |||
1031 | /* Reset all preBER counters */ | ||
1032 | rc = mb86a20s_writereg(state, 0x5f, 0x00); | ||
1033 | if (rc < 0) | ||
1034 | return rc; | ||
1035 | rc = mb86a20s_writereg(state, 0x5f, 0x07); | ||
1036 | |||
1037 | return rc; | ||
1038 | } | ||
1039 | |||
1040 | reset_measurement: | ||
919 | /* Reset counter to collect new data */ | 1041 | /* Reset counter to collect new data */ |
920 | rc = mb86a20s_readreg(state, 0x5f); | 1042 | rc = mb86a20s_readreg(state, 0x5f); |
921 | if (rc < 0) | 1043 | if (rc < 0) |
@@ -924,7 +1046,7 @@ static int mb86a20s_get_pre_ber(struct dvb_frontend *fe, | |||
924 | rc = mb86a20s_writereg(state, 0x5f, val & ~(1 << layer)); | 1046 | rc = mb86a20s_writereg(state, 0x5f, val & ~(1 << layer)); |
925 | if (rc < 0) | 1047 | if (rc < 0) |
926 | return rc; | 1048 | return rc; |
927 | rc = mb86a20s_writereg(state, 0x5f, val); | 1049 | rc = mb86a20s_writereg(state, 0x5f, val | (1 << layer)); |
928 | 1050 | ||
929 | return rc; | 1051 | return rc; |
930 | } | 1052 | } |
@@ -1417,6 +1539,8 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) | |||
1417 | c->cnr.len = 4; | 1539 | c->cnr.len = 4; |
1418 | c->pre_bit_error.len = 4; | 1540 | c->pre_bit_error.len = 4; |
1419 | c->pre_bit_count.len = 4; | 1541 | c->pre_bit_count.len = 4; |
1542 | c->post_bit_error.len = 4; | ||
1543 | c->post_bit_count.len = 4; | ||
1420 | c->block_error.len = 4; | 1544 | c->block_error.len = 4; |
1421 | c->block_count.len = 4; | 1545 | c->block_count.len = 4; |
1422 | 1546 | ||
@@ -1429,6 +1553,8 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) | |||
1429 | c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1553 | c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1430 | c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1554 | c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1431 | c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1555 | c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1556 | c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||
1557 | c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||
1432 | c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1558 | c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1433 | c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1559 | c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1434 | } | 1560 | } |
@@ -1441,9 +1567,11 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1441 | int rc = 0, i; | 1567 | int rc = 0, i; |
1442 | u32 bit_error = 0, bit_count = 0; | 1568 | u32 bit_error = 0, bit_count = 0; |
1443 | u32 t_pre_bit_error = 0, t_pre_bit_count = 0; | 1569 | u32 t_pre_bit_error = 0, t_pre_bit_count = 0; |
1570 | u32 t_post_bit_error = 0, t_post_bit_count = 0; | ||
1444 | u32 block_error = 0, block_count = 0; | 1571 | u32 block_error = 0, block_count = 0; |
1445 | u32 t_block_error = 0, t_block_count = 0; | 1572 | u32 t_block_error = 0, t_block_count = 0; |
1446 | int active_layers = 0, ber_layers = 0, per_layers = 0; | 1573 | int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; |
1574 | int per_layers = 0; | ||
1447 | 1575 | ||
1448 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1576 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1449 | 1577 | ||
@@ -1457,7 +1585,6 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1457 | /* Layer is active and has rc segments */ | 1585 | /* Layer is active and has rc segments */ |
1458 | active_layers++; | 1586 | active_layers++; |
1459 | 1587 | ||
1460 | /* Read per-layer BER */ | ||
1461 | /* Handle BER before vterbi */ | 1588 | /* Handle BER before vterbi */ |
1462 | rc = mb86a20s_get_pre_ber(fe, i, | 1589 | rc = mb86a20s_get_pre_ber(fe, i, |
1463 | &bit_error, &bit_count); | 1590 | &bit_error, &bit_count); |
@@ -1479,7 +1606,30 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1479 | } | 1606 | } |
1480 | 1607 | ||
1481 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | 1608 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) |
1482 | ber_layers++; | 1609 | pre_ber_layers++; |
1610 | |||
1611 | /* Handle BER post vterbi */ | ||
1612 | rc = mb86a20s_get_post_ber(fe, i, | ||
1613 | &bit_error, &bit_count); | ||
1614 | if (rc >= 0) { | ||
1615 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; | ||
1616 | c->post_bit_error.stat[1 + i].uvalue += bit_error; | ||
1617 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; | ||
1618 | c->post_bit_count.stat[1 + i].uvalue += bit_count; | ||
1619 | } else if (rc != -EBUSY) { | ||
1620 | /* | ||
1621 | * If an I/O error happened, | ||
1622 | * measures are now unavailable | ||
1623 | */ | ||
1624 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | ||
1625 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | ||
1626 | dev_err(&state->i2c->dev, | ||
1627 | "%s: Can't get BER for layer %c (error %d).\n", | ||
1628 | __func__, 'A' + i, rc); | ||
1629 | } | ||
1630 | |||
1631 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | ||
1632 | post_ber_layers++; | ||
1483 | 1633 | ||
1484 | /* Handle Block errors for PER/UCB reports */ | 1634 | /* Handle Block errors for PER/UCB reports */ |
1485 | rc = mb86a20s_get_blk_error(fe, i, | 1635 | rc = mb86a20s_get_blk_error(fe, i, |
@@ -1506,10 +1656,14 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1506 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | 1656 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) |
1507 | per_layers++; | 1657 | per_layers++; |
1508 | 1658 | ||
1509 | /* Update total BER */ | 1659 | /* Update total preBER */ |
1510 | t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; | 1660 | t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; |
1511 | t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; | 1661 | t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; |
1512 | 1662 | ||
1663 | /* Update total postBER */ | ||
1664 | t_post_bit_error += c->post_bit_error.stat[1 + i].uvalue; | ||
1665 | t_post_bit_count += c->post_bit_count.stat[1 + i].uvalue; | ||
1666 | |||
1513 | /* Update total PER */ | 1667 | /* Update total PER */ |
1514 | t_block_error += c->block_error.stat[1 + i].uvalue; | 1668 | t_block_error += c->block_error.stat[1 + i].uvalue; |
1515 | t_block_count += c->block_count.stat[1 + i].uvalue; | 1669 | t_block_count += c->block_count.stat[1 + i].uvalue; |
@@ -1520,7 +1674,7 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1520 | * Start showing global count if at least one error count is | 1674 | * Start showing global count if at least one error count is |
1521 | * available. | 1675 | * available. |
1522 | */ | 1676 | */ |
1523 | if (ber_layers) { | 1677 | if (pre_ber_layers) { |
1524 | /* | 1678 | /* |
1525 | * At least one per-layer BER measure was read. We can now | 1679 | * At least one per-layer BER measure was read. We can now |
1526 | * calculate the total BER | 1680 | * calculate the total BER |
@@ -1534,6 +1688,24 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1534 | c->pre_bit_count.stat[0].uvalue = t_pre_bit_count; | 1688 | c->pre_bit_count.stat[0].uvalue = t_pre_bit_count; |
1535 | } | 1689 | } |
1536 | 1690 | ||
1691 | /* | ||
1692 | * Start showing global count if at least one error count is | ||
1693 | * available. | ||
1694 | */ | ||
1695 | if (post_ber_layers) { | ||
1696 | /* | ||
1697 | * At least one per-layer BER measure was read. We can now | ||
1698 | * calculate the total BER | ||
1699 | * | ||
1700 | * Total Bit Error/Count is calculated as the sum of the | ||
1701 | * bit errors on all active layers. | ||
1702 | */ | ||
1703 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||
1704 | c->post_bit_error.stat[0].uvalue = t_post_bit_error; | ||
1705 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | ||
1706 | c->post_bit_count.stat[0].uvalue = t_post_bit_count; | ||
1707 | } | ||
1708 | |||
1537 | if (per_layers) { | 1709 | if (per_layers) { |
1538 | /* | 1710 | /* |
1539 | * At least one per-layer UCB measure was read. We can now | 1711 | * At least one per-layer UCB measure was read. We can now |