aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2016-07-01 10:03:15 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-07-16 05:53:46 -0400
commit4216be14be19ef3ca0c0afdb2f5c1a352e688a61 (patch)
tree9acb20dd1d69395b566e21f66ea376905ef68c35
parenteca2d34b9d2ce70165a50510659838e28ca22742 (diff)
[media] cxd2841er: fix BER report via DVBv5 stats API
What userspace expects is to receive both bit_error and bit_count counters. So, instead of doing the division at the Kernel, return the counters for userspace to handle it the way it wants. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/dvb-frontends/cxd2841er.c137
1 files changed, 66 insertions, 71 deletions
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index 721fb074da7c..94de6ba3d0e2 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -1330,11 +1330,10 @@ static int cxd2841er_read_packet_errors_i(
1330 return 0; 1330 return 0;
1331} 1331}
1332 1332
1333static int cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv, u32 *ber) 1333static int cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv,
1334 u32 *bit_error, u32 *bit_count)
1334{ 1335{
1335 u8 data[11]; 1336 u8 data[11];
1336 u32 bit_error, bit_count;
1337 u32 temp_q, temp_r;
1338 1337
1339 /* Set SLV-T Bank : 0xA0 */ 1338 /* Set SLV-T Bank : 0xA0 */
1340 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0); 1339 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0);
@@ -1350,28 +1349,18 @@ static int cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv, u32 *ber)
1350 */ 1349 */
1351 cxd2841er_read_regs(priv, I2C_SLVT, 0x35, data, 11); 1350 cxd2841er_read_regs(priv, I2C_SLVT, 0x35, data, 11);
1352 if (data[0] & 0x01) { 1351 if (data[0] & 0x01) {
1353 bit_error = ((u32)(data[1] & 0x3F) << 16) | 1352 *bit_error = ((u32)(data[1] & 0x3F) << 16) |
1354 ((u32)(data[2] & 0xFF) << 8) | 1353 ((u32)(data[2] & 0xFF) << 8) |
1355 (u32)(data[3] & 0xFF); 1354 (u32)(data[3] & 0xFF);
1356 bit_count = ((u32)(data[8] & 0x3F) << 16) | 1355 *bit_count = ((u32)(data[8] & 0x3F) << 16) |
1357 ((u32)(data[9] & 0xFF) << 8) | 1356 ((u32)(data[9] & 0xFF) << 8) |
1358 (u32)(data[10] & 0xFF); 1357 (u32)(data[10] & 0xFF);
1359 /* 1358 if ((*bit_count == 0) || (*bit_error > *bit_count)) {
1360 * BER = bitError / bitCount
1361 * = (bitError * 10^7) / bitCount
1362 * = ((bitError * 625 * 125 * 128) / bitCount
1363 */
1364 if ((bit_count == 0) || (bit_error > bit_count)) {
1365 dev_dbg(&priv->i2c->dev, 1359 dev_dbg(&priv->i2c->dev,
1366 "%s(): invalid bit_error %d, bit_count %d\n", 1360 "%s(): invalid bit_error %d, bit_count %d\n",
1367 __func__, bit_error, bit_count); 1361 __func__, *bit_error, *bit_count);
1368 return -EINVAL; 1362 return -EINVAL;
1369 } 1363 }
1370 temp_q = div_u64_rem(10000000ULL * bit_error,
1371 bit_count, &temp_r);
1372 if (bit_count != 1 && temp_r >= bit_count / 2)
1373 temp_q++;
1374 *ber = temp_q;
1375 return 0; 1364 return 0;
1376 } 1365 }
1377 dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__); 1366 dev_dbg(&priv->i2c->dev, "%s(): no data available\n", __func__);
@@ -1379,11 +1368,11 @@ static int cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv, u32 *ber)
1379} 1368}
1380 1369
1381 1370
1382static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv, u32 *ber) 1371static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv,
1372 u32 *bit_error, u32 *bit_count)
1383{ 1373{
1384 u8 data[5]; 1374 u8 data[5];
1385 u32 bit_error, period; 1375 u32 period;
1386 u32 temp_q, temp_r;
1387 1376
1388 /* Set SLV-T Bank : 0xB2 */ 1377 /* Set SLV-T Bank : 0xB2 */
1389 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xb2); 1378 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xb2);
@@ -1398,10 +1387,10 @@ static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv, u32 *ber)
1398 cxd2841er_read_regs(priv, I2C_SLVT, 0x30, data, 5); 1387 cxd2841er_read_regs(priv, I2C_SLVT, 0x30, data, 5);
1399 if (data[0] & 0x01) { 1388 if (data[0] & 0x01) {
1400 /* Bit error count */ 1389 /* Bit error count */
1401 bit_error = ((u32)(data[1] & 0x0F) << 24) | 1390 *bit_error = ((u32)(data[1] & 0x0F) << 24) |
1402 ((u32)(data[2] & 0xFF) << 16) | 1391 ((u32)(data[2] & 0xFF) << 16) |
1403 ((u32)(data[3] & 0xFF) << 8) | 1392 ((u32)(data[3] & 0xFF) << 8) |
1404 (u32)(data[4] & 0xFF); 1393 (u32)(data[4] & 0xFF);
1405 1394
1406 /* Set SLV-T Bank : 0xA0 */ 1395 /* Set SLV-T Bank : 0xA0 */
1407 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0); 1396 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0xa0);
@@ -1413,24 +1402,14 @@ static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv, u32 *ber)
1413 "%s(): period is 0\n", __func__); 1402 "%s(): period is 0\n", __func__);
1414 return -EINVAL; 1403 return -EINVAL;
1415 } 1404 }
1416 if (bit_error > (period * 64800)) { 1405 if (*bit_error > (period * 64800)) {
1417 dev_dbg(&priv->i2c->dev, 1406 dev_dbg(&priv->i2c->dev,
1418 "%s(): invalid bit_err 0x%x period 0x%x\n", 1407 "%s(): invalid bit_err 0x%x period 0x%x\n",
1419 __func__, bit_error, period); 1408 __func__, *bit_error, period);
1420 return -EINVAL; 1409 return -EINVAL;
1421 } 1410 }
1422 /* 1411 *bit_count = period * 64800;
1423 * BER = bitError / (period * 64800) 1412
1424 * = (bitError * 10^7) / (period * 64800)
1425 * = (bitError * 10^5) / (period * 648)
1426 * = (bitError * 12500) / (period * 81)
1427 * = (bitError * 10) * 1250 / (period * 81)
1428 */
1429 temp_q = div_u64_rem(12500ULL * bit_error,
1430 period * 81, &temp_r);
1431 if (temp_r >= period * 40)
1432 temp_q++;
1433 *ber = temp_q;
1434 return 0; 1413 return 0;
1435 } else { 1414 } else {
1436 dev_dbg(&priv->i2c->dev, 1415 dev_dbg(&priv->i2c->dev,
@@ -1439,13 +1418,12 @@ static int cxd2841er_mon_read_ber_s2(struct cxd2841er_priv *priv, u32 *ber)
1439 return -EINVAL; 1418 return -EINVAL;
1440} 1419}
1441 1420
1442static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv, u32 *ber) 1421static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv,
1422 u32 *bit_error, u32 *bit_count)
1443{ 1423{
1444 u8 data[4]; 1424 u8 data[4];
1445 u32 div, q, r; 1425 u32 period_exp, n_ldpc;
1446 u32 bit_err, period_exp, n_ldpc;
1447 1426
1448 *ber = 0;
1449 if (priv->state != STATE_ACTIVE_TC) { 1427 if (priv->state != STATE_ACTIVE_TC) {
1450 dev_dbg(&priv->i2c->dev, 1428 dev_dbg(&priv->i2c->dev,
1451 "%s(): invalid state %d\n", __func__, priv->state); 1429 "%s(): invalid state %d\n", __func__, priv->state);
@@ -1456,40 +1434,44 @@ static int cxd2841er_read_ber_t2(struct cxd2841er_priv *priv, u32 *ber)
1456 if (!(data[0] & 0x10)) { 1434 if (!(data[0] & 0x10)) {
1457 dev_dbg(&priv->i2c->dev, 1435 dev_dbg(&priv->i2c->dev,
1458 "%s(): no valid BER data\n", __func__); 1436 "%s(): no valid BER data\n", __func__);
1459 return 0; 1437 return -EINVAL;
1460 } 1438 }
1461 bit_err = ((u32)(data[0] & 0x0f) << 24) | 1439 *bit_error = ((u32)(data[0] & 0x0f) << 24) |
1462 ((u32)data[1] << 16) | 1440 ((u32)data[1] << 16) |
1463 ((u32)data[2] << 8) | 1441 ((u32)data[2] << 8) |
1464 (u32)data[3]; 1442 (u32)data[3];
1465 cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data); 1443 cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data);
1466 period_exp = data[0] & 0x0f; 1444 period_exp = data[0] & 0x0f;
1467 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x22); 1445 cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x22);
1468 cxd2841er_read_reg(priv, I2C_SLVT, 0x5e, data); 1446 cxd2841er_read_reg(priv, I2C_SLVT, 0x5e, data);
1469 n_ldpc = ((data[0] & 0x03) == 0 ? 16200 : 64800); 1447 n_ldpc = ((data[0] & 0x03) == 0 ? 16200 : 64800);
1470 if (bit_err > ((1U << period_exp) * n_ldpc)) { 1448 if (*bit_error > ((1U << period_exp) * n_ldpc)) {
1471 dev_dbg(&priv->i2c->dev, 1449 dev_dbg(&priv->i2c->dev,
1472 "%s(): invalid BER value\n", __func__); 1450 "%s(): invalid BER value\n", __func__);
1473 return -EINVAL; 1451 return -EINVAL;
1474 } 1452 }
1453
1454 /*
1455 * FIXME: the right thing would be to return bit_error untouched,
1456 * but, as we don't know the scale returned by the counters, let's
1457 * at least preserver BER = bit_error/bit_count.
1458 */
1475 if (period_exp >= 4) { 1459 if (period_exp >= 4) {
1476 div = (1U << (period_exp - 4)) * (n_ldpc / 200); 1460 *bit_count = (1U << (period_exp - 4)) * (n_ldpc / 200);
1477 q = div_u64_rem(3125ULL * bit_err, div, &r); 1461 *bit_error *= 3125ULL;
1478 } else { 1462 } else {
1479 div = (1U << period_exp) * (n_ldpc / 200); 1463 *bit_count = (1U << period_exp) * (n_ldpc / 200);
1480 q = div_u64_rem(50000ULL * bit_err, div, &r); 1464 *bit_error *= 50000ULL;;
1481 } 1465 }
1482 *ber = (r >= div / 2) ? q + 1 : q;
1483 return 0; 1466 return 0;
1484} 1467}
1485 1468
1486static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv, u32 *ber) 1469static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv,
1470 u32 *bit_error, u32 *bit_count)
1487{ 1471{
1488 u8 data[2]; 1472 u8 data[2];
1489 u32 div, q, r; 1473 u32 period;
1490 u32 bit_err, period;
1491 1474
1492 *ber = 0;
1493 if (priv->state != STATE_ACTIVE_TC) { 1475 if (priv->state != STATE_ACTIVE_TC) {
1494 dev_dbg(&priv->i2c->dev, 1476 dev_dbg(&priv->i2c->dev,
1495 "%s(): invalid state %d\n", __func__, priv->state); 1477 "%s(): invalid state %d\n", __func__, priv->state);
@@ -1503,12 +1485,17 @@ static int cxd2841er_read_ber_t(struct cxd2841er_priv *priv, u32 *ber)
1503 return 0; 1485 return 0;
1504 } 1486 }
1505 cxd2841er_read_regs(priv, I2C_SLVT, 0x22, data, sizeof(data)); 1487 cxd2841er_read_regs(priv, I2C_SLVT, 0x22, data, sizeof(data));
1506 bit_err = ((u32)data[0] << 8) | (u32)data[1]; 1488 *bit_error = ((u32)data[0] << 8) | (u32)data[1];
1507 cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data); 1489 cxd2841er_read_reg(priv, I2C_SLVT, 0x6f, data);
1508 period = ((data[0] & 0x07) == 0) ? 256 : (4096 << (data[0] & 0x07)); 1490 period = ((data[0] & 0x07) == 0) ? 256 : (4096 << (data[0] & 0x07));
1509 div = period / 128; 1491
1510 q = div_u64_rem(78125ULL * bit_err, div, &r); 1492 /*
1511 *ber = (r >= div / 2) ? q + 1 : q; 1493 * FIXME: the right thing would be to return bit_error untouched,
1494 * but, as we don't know the scale returned by the counters, let's
1495 * at least preserver BER = bit_error/bit_count.
1496 */
1497 *bit_count = period / 128;
1498 *bit_error *= 78125ULL;
1512 return 0; 1499 return 0;
1513} 1500}
1514 1501
@@ -1722,32 +1709,36 @@ static void cxd2841er_read_ber(struct dvb_frontend *fe)
1722{ 1709{
1723 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1710 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1724 struct cxd2841er_priv *priv = fe->demodulator_priv; 1711 struct cxd2841er_priv *priv = fe->demodulator_priv;
1725 u32 ber = 0, ret; 1712 u32 ret, bit_error = 0, bit_count = 0;
1726 1713
1727 dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 1714 dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
1728 switch (p->delivery_system) { 1715 switch (p->delivery_system) {
1729 case SYS_DVBS: 1716 case SYS_DVBS:
1730 ret = cxd2841er_mon_read_ber_s(priv, &ber); 1717 ret = cxd2841er_mon_read_ber_s(priv, &bit_error, &bit_count);
1731 break; 1718 break;
1732 case SYS_DVBS2: 1719 case SYS_DVBS2:
1733 ret = cxd2841er_mon_read_ber_s2(priv, &ber); 1720 ret = cxd2841er_mon_read_ber_s2(priv, &bit_error, &bit_count);
1734 break; 1721 break;
1735 case SYS_DVBT: 1722 case SYS_DVBT:
1736 ret = cxd2841er_read_ber_t(priv, &ber); 1723 ret = cxd2841er_read_ber_t(priv, &bit_error, &bit_count);
1737 break; 1724 break;
1738 case SYS_DVBT2: 1725 case SYS_DVBT2:
1739 ret = cxd2841er_read_ber_t2(priv, &ber); 1726 ret = cxd2841er_read_ber_t2(priv, &bit_error, &bit_count);
1740 break; 1727 break;
1741 default: 1728 default:
1742 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1729 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1730 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1743 return; 1731 return;
1744 } 1732 }
1745 1733
1746 if (!ret) { 1734 if (!ret) {
1747 p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 1735 p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1748 p->post_bit_error.stat[0].uvalue = ber; 1736 p->post_bit_error.stat[0].uvalue = bit_error;
1737 p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1738 p->post_bit_count.stat[0].uvalue = bit_count;
1749 } else { 1739 } else {
1750 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1740 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1741 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1751 } 1742 }
1752} 1743}
1753 1744
@@ -2988,6 +2979,7 @@ static int cxd2841er_get_frontend(struct dvb_frontend *fe,
2988 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2979 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2989 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2980 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2990 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2981 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2982 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2991 } 2983 }
2992 return 0; 2984 return 0;
2993} 2985}
@@ -3052,6 +3044,7 @@ done:
3052 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3044 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3053 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3045 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3054 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3046 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3047 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3055 3048
3056 return ret; 3049 return ret;
3057} 3050}
@@ -3426,6 +3419,8 @@ static void cxd2841er_init_stats(struct dvb_frontend *fe)
3426 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3419 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3427 p->post_bit_error.len = 1; 3420 p->post_bit_error.len = 1;
3428 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3421 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3422 p->post_bit_count.len = 1;
3423 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3429} 3424}
3430 3425
3431 3426