diff options
author | Manu Abraham <abraham.manu@gmail.com> | 2009-12-03 03:48:13 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-01-17 08:55:30 -0500 |
commit | 77557abef0de3f1f1e8f563db6df8710a9e930fe (patch) | |
tree | 65ffa61670376d2f0537d6993349ecfe41cc6b5d | |
parent | 417036844823313901d7f7d7b963f215cc3b0641 (diff) |
V4L/DVB (13717): [MB86A16] Statistics Updates
* Demodulator status check made reliable
* Code simplification for Viterbi Sync check, makes
acquisition more reliable
* Implement a BER monitor
* Implement a Signal strength monitor
* Implement a "simple" UCB monitor, no real UCB monitor
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb/frontends/mb86a16.c | 142 |
1 files changed, 117 insertions, 25 deletions
diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 4f8ef2e2ecd1..eddb35baaf00 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c | |||
@@ -36,7 +36,6 @@ struct mb86a16_state { | |||
36 | struct i2c_adapter *i2c_adap; | 36 | struct i2c_adapter *i2c_adap; |
37 | const struct mb86a16_config *config; | 37 | const struct mb86a16_config *config; |
38 | struct dvb_frontend frontend; | 38 | struct dvb_frontend frontend; |
39 | u8 signal; | ||
40 | 39 | ||
41 | // tuning parameters | 40 | // tuning parameters |
42 | int frequency; | 41 | int frequency; |
@@ -593,17 +592,39 @@ err: | |||
593 | 592 | ||
594 | static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) | 593 | static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) |
595 | { | 594 | { |
595 | u8 stat, stat2; | ||
596 | struct mb86a16_state *state = fe->demodulator_priv; | 596 | struct mb86a16_state *state = fe->demodulator_priv; |
597 | 597 | ||
598 | *status = 0; | 598 | *status = 0; |
599 | if (state->signal & 0x02) | 599 | |
600 | *status |= FE_HAS_VITERBI; | 600 | if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2) |
601 | if (state->signal & 0x01) | 601 | goto err; |
602 | if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2) | ||
603 | goto err; | ||
604 | if ((stat > 25) && (stat2 > 25)) | ||
605 | *status |= FE_HAS_SIGNAL; | ||
606 | if ((stat > 45) && (stat2 > 45)) | ||
607 | *status |= FE_HAS_CARRIER; | ||
608 | |||
609 | if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2) | ||
610 | goto err; | ||
611 | |||
612 | if (stat & 0x01) | ||
602 | *status |= FE_HAS_SYNC; | 613 | *status |= FE_HAS_SYNC; |
603 | if (state->signal & 0x03) | 614 | if (stat & 0x01) |
615 | *status |= FE_HAS_VITERBI; | ||
616 | |||
617 | if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2) | ||
618 | goto err; | ||
619 | |||
620 | if ((stat & 0x0f) && (*status & FE_HAS_VITERBI)) | ||
604 | *status |= FE_HAS_LOCK; | 621 | *status |= FE_HAS_LOCK; |
605 | 622 | ||
606 | return 0; | 623 | return 0; |
624 | |||
625 | err: | ||
626 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
627 | return -EREMOTEIO; | ||
607 | } | 628 | } |
608 | 629 | ||
609 | static int sync_chk(struct mb86a16_state *state, | 630 | static int sync_chk(struct mb86a16_state *state, |
@@ -1439,10 +1460,6 @@ static int mb86a16_set_fe(struct mb86a16_state *state) | |||
1439 | msleep_interruptible(wait_t); | 1460 | msleep_interruptible(wait_t); |
1440 | sync = sync_chk(state, &VIRM); | 1461 | sync = sync_chk(state, &VIRM); |
1441 | dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); | 1462 | dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); |
1442 | if (mb86a16_read(state, 0x0d, &state->signal) != 2) { | ||
1443 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1444 | return -EREMOTEIO; | ||
1445 | } | ||
1446 | if (VIRM) { | 1463 | if (VIRM) { |
1447 | if (VIRM == 4) { // 5/6 | 1464 | if (VIRM == 4) { // 5/6 |
1448 | if (SIG1 > 110) | 1465 | if (SIG1 > 110) |
@@ -1459,22 +1476,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) | |||
1459 | iq_vt_set(state, 1); | 1476 | iq_vt_set(state, 1); |
1460 | FEC_srst(state); | 1477 | FEC_srst(state); |
1461 | } | 1478 | } |
1462 | if (SIG1 > 110) | ||
1463 | wait_t = ( 786432 + state->srate / 2) / state->srate; | ||
1464 | else | ||
1465 | wait_t = (1572864 + state->srate / 2) / state->srate; | ||
1466 | |||
1467 | msleep_interruptible(wait_t); | ||
1468 | SEQ_set(state, 1); | ||
1469 | } else { // 1/2, 2/3, 3/4, 7/8 | ||
1470 | if (SIG1 > 110) | ||
1471 | wait_t = ( 786432 + state->srate / 2) / state->srate; | ||
1472 | else | ||
1473 | wait_t = (1572864 + state->srate / 2) / state->srate; | ||
1474 | |||
1475 | msleep_interruptible(wait_t); | ||
1476 | SEQ_set(state, 1); | ||
1477 | } | 1479 | } |
1480 | // 1/2, 2/3, 3/4, 7/8 | ||
1481 | if (SIG1 > 110) | ||
1482 | wait_t = ( 786432 + state->srate / 2) / state->srate; | ||
1483 | else | ||
1484 | wait_t = (1572864 + state->srate / 2) / state->srate; | ||
1485 | msleep_interruptible(wait_t); | ||
1486 | SEQ_set(state, 1); | ||
1478 | } else { | 1487 | } else { |
1479 | dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); | 1488 | dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); |
1480 | SEQ_set(state, 1); | 1489 | SEQ_set(state, 1); |
@@ -1648,12 +1657,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe) | |||
1648 | 1657 | ||
1649 | static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) | 1658 | static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) |
1650 | { | 1659 | { |
1660 | u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst; | ||
1661 | u32 timer; | ||
1662 | |||
1663 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1664 | |||
1665 | *ber = 0; | ||
1666 | if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2) | ||
1667 | goto err; | ||
1668 | if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2) | ||
1669 | goto err; | ||
1670 | if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2) | ||
1671 | goto err; | ||
1672 | if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2) | ||
1673 | goto err; | ||
1674 | if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2) | ||
1675 | goto err; | ||
1676 | /* BER monitor invalid when BER_EN = 0 */ | ||
1677 | if (ber_mon & 0x04) { | ||
1678 | /* coarse, fast calculation */ | ||
1679 | *ber = ber_tab & 0x1f; | ||
1680 | dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber); | ||
1681 | if (ber_mon & 0x01) { | ||
1682 | /* | ||
1683 | * BER_SEL = 1, The monitored BER is the estimated | ||
1684 | * value with a Reed-Solomon decoder error amount at | ||
1685 | * the deinterleaver output. | ||
1686 | * monitored BER is expressed as a 20 bit output in total | ||
1687 | */ | ||
1688 | ber_rst = ber_mon >> 3; | ||
1689 | *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; | ||
1690 | if (ber_rst == 0) | ||
1691 | timer = 12500000; | ||
1692 | if (ber_rst == 1) | ||
1693 | timer = 25000000; | ||
1694 | if (ber_rst == 2) | ||
1695 | timer = 50000000; | ||
1696 | if (ber_rst == 3) | ||
1697 | timer = 100000000; | ||
1698 | |||
1699 | *ber /= timer; | ||
1700 | dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); | ||
1701 | } else { | ||
1702 | /* | ||
1703 | * BER_SEL = 0, The monitored BER is the estimated | ||
1704 | * value with a Viterbi decoder error amount at the | ||
1705 | * QPSK demodulator output. | ||
1706 | * monitored BER is expressed as a 24 bit output in total | ||
1707 | */ | ||
1708 | ber_tim = ber_mon >> 1; | ||
1709 | *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; | ||
1710 | if (ber_tim == 0) | ||
1711 | timer = 16; | ||
1712 | if (ber_tim == 1) | ||
1713 | timer = 24; | ||
1714 | |||
1715 | *ber /= 2 ^ timer; | ||
1716 | dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); | ||
1717 | } | ||
1718 | } | ||
1651 | return 0; | 1719 | return 0; |
1720 | err: | ||
1721 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1722 | return -EREMOTEIO; | ||
1652 | } | 1723 | } |
1653 | 1724 | ||
1654 | static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | 1725 | static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
1655 | { | 1726 | { |
1727 | u8 agcm = 0; | ||
1728 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1729 | |||
1656 | *strength = 0; | 1730 | *strength = 0; |
1731 | if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) { | ||
1732 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1733 | return -EREMOTEIO; | ||
1734 | } | ||
1735 | |||
1736 | *strength = ((0xff - agcm) * 100) / 256; | ||
1737 | dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength); | ||
1738 | *strength = (0xffff - 0xff) + agcm; | ||
1657 | 1739 | ||
1658 | return 0; | 1740 | return 0; |
1659 | } | 1741 | } |
@@ -1708,12 +1790,22 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
1708 | } | 1790 | } |
1709 | q_level = (*snr * 100) / (high_tide - low_tide); | 1791 | q_level = (*snr * 100) / (high_tide - low_tide); |
1710 | dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); | 1792 | dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); |
1793 | *snr = (0xffff - 0xff) + *snr; | ||
1711 | 1794 | ||
1712 | return 0; | 1795 | return 0; |
1713 | } | 1796 | } |
1714 | 1797 | ||
1715 | static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | 1798 | static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
1716 | { | 1799 | { |
1800 | u8 dist; | ||
1801 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1802 | |||
1803 | if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) { | ||
1804 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1805 | return -EREMOTEIO; | ||
1806 | } | ||
1807 | *ucblocks = dist; | ||
1808 | |||
1717 | return 0; | 1809 | return 0; |
1718 | } | 1810 | } |
1719 | 1811 | ||
@@ -1723,7 +1815,7 @@ static struct dvb_frontend_ops mb86a16_ops = { | |||
1723 | .type = FE_QPSK, | 1815 | .type = FE_QPSK, |
1724 | .frequency_min = 950000, | 1816 | .frequency_min = 950000, |
1725 | .frequency_max = 2150000, | 1817 | .frequency_max = 2150000, |
1726 | .frequency_stepsize = 125, | 1818 | .frequency_stepsize = 3000, |
1727 | .frequency_tolerance = 0, | 1819 | .frequency_tolerance = 0, |
1728 | .symbol_rate_min = 1000000, | 1820 | .symbol_rate_min = 1000000, |
1729 | .symbol_rate_max = 45000000, | 1821 | .symbol_rate_max = 45000000, |