diff options
Diffstat (limited to 'drivers/media/dvb-frontends/dib7000p.c')
| -rw-r--r-- | drivers/media/dvb-frontends/dib7000p.c | 433 |
1 files changed, 401 insertions, 32 deletions
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index effb87f773b0..661760d60232 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 12 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
| 13 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
| 14 | #include <asm/div64.h> | ||
| 14 | 15 | ||
| 15 | #include "dvb_math.h" | 16 | #include "dvb_math.h" |
| 16 | #include "dvb_frontend.h" | 17 | #include "dvb_frontend.h" |
| @@ -72,6 +73,12 @@ struct dib7000p_state { | |||
| 72 | struct mutex i2c_buffer_lock; | 73 | struct mutex i2c_buffer_lock; |
| 73 | 74 | ||
| 74 | u8 input_mode_mpeg; | 75 | u8 input_mode_mpeg; |
| 76 | |||
| 77 | /* for DVBv5 stats */ | ||
| 78 | s64 old_ucb; | ||
| 79 | unsigned long per_jiffies_stats; | ||
| 80 | unsigned long ber_jiffies_stats; | ||
| 81 | unsigned long get_stats_time; | ||
| 75 | }; | 82 | }; |
| 76 | 83 | ||
| 77 | enum dib7000p_power_mode { | 84 | enum dib7000p_power_mode { |
| @@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state) | |||
| 401 | return 0; | 408 | return 0; |
| 402 | } | 409 | } |
| 403 | 410 | ||
| 404 | int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value) | 411 | static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value) |
| 405 | { | 412 | { |
| 406 | struct dib7000p_state *state = demod->demodulator_priv; | 413 | struct dib7000p_state *state = demod->demodulator_priv; |
| 407 | if (value > 4095) | 414 | if (value > 4095) |
| @@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value) | |||
| 409 | state->wbd_ref = value; | 416 | state->wbd_ref = value; |
| 410 | return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value); | 417 | return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value); |
| 411 | } | 418 | } |
| 412 | EXPORT_SYMBOL(dib7000p_set_wbd_ref); | ||
| 413 | 419 | ||
| 414 | int dib7000p_get_agc_values(struct dvb_frontend *fe, | 420 | static int dib7000p_get_agc_values(struct dvb_frontend *fe, |
| 415 | u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd) | 421 | u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd) |
| 416 | { | 422 | { |
| 417 | struct dib7000p_state *state = fe->demodulator_priv; | 423 | struct dib7000p_state *state = fe->demodulator_priv; |
| @@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe, | |||
| 427 | 433 | ||
| 428 | return 0; | 434 | return 0; |
| 429 | } | 435 | } |
| 430 | EXPORT_SYMBOL(dib7000p_get_agc_values); | ||
| 431 | 436 | ||
| 432 | int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v) | 437 | static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v) |
| 433 | { | 438 | { |
| 434 | struct dib7000p_state *state = fe->demodulator_priv; | 439 | struct dib7000p_state *state = fe->demodulator_priv; |
| 435 | return dib7000p_write_word(state, 108, v); | 440 | return dib7000p_write_word(state, 108, v); |
| 436 | } | 441 | } |
| 437 | EXPORT_SYMBOL(dib7000p_set_agc1_min); | ||
| 438 | 442 | ||
| 439 | static void dib7000p_reset_pll(struct dib7000p_state *state) | 443 | static void dib7000p_reset_pll(struct dib7000p_state *state) |
| 440 | { | 444 | { |
| @@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state) | |||
| 478 | return internal; | 482 | return internal; |
| 479 | } | 483 | } |
| 480 | 484 | ||
| 481 | int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw) | 485 | static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw) |
| 482 | { | 486 | { |
| 483 | struct dib7000p_state *state = fe->demodulator_priv; | 487 | struct dib7000p_state *state = fe->demodulator_priv; |
| 484 | u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856); | 488 | u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856); |
| @@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config | |||
| 513 | } | 517 | } |
| 514 | return -EIO; | 518 | return -EIO; |
| 515 | } | 519 | } |
| 516 | EXPORT_SYMBOL(dib7000p_update_pll); | ||
| 517 | 520 | ||
| 518 | static int dib7000p_reset_gpio(struct dib7000p_state *st) | 521 | static int dib7000p_reset_gpio(struct dib7000p_state *st) |
| 519 | { | 522 | { |
| @@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val) | |||
| 546 | return 0; | 549 | return 0; |
| 547 | } | 550 | } |
| 548 | 551 | ||
| 549 | int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val) | 552 | static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val) |
| 550 | { | 553 | { |
| 551 | struct dib7000p_state *state = demod->demodulator_priv; | 554 | struct dib7000p_state *state = demod->demodulator_priv; |
| 552 | return dib7000p_cfg_gpio(state, num, dir, val); | 555 | return dib7000p_cfg_gpio(state, num, dir, val); |
| 553 | } | 556 | } |
| 554 | EXPORT_SYMBOL(dib7000p_set_gpio); | ||
| 555 | 557 | ||
| 556 | static u16 dib7000p_defaults[] = { | 558 | static u16 dib7000p_defaults[] = { |
| 557 | // auto search configuration | 559 | // auto search configuration |
| @@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = { | |||
| 636 | 0, | 638 | 0, |
| 637 | }; | 639 | }; |
| 638 | 640 | ||
| 641 | static void dib7000p_reset_stats(struct dvb_frontend *fe); | ||
| 642 | |||
| 639 | static int dib7000p_demod_reset(struct dib7000p_state *state) | 643 | static int dib7000p_demod_reset(struct dib7000p_state *state) |
| 640 | { | 644 | { |
| 641 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | 645 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); |
| @@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state) | |||
| 934 | 938 | ||
| 935 | } | 939 | } |
| 936 | 940 | ||
| 937 | u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf) | 941 | static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf) |
| 938 | { | 942 | { |
| 939 | struct dib7000p_state *state = fe->demodulator_priv; | 943 | struct dib7000p_state *state = fe->demodulator_priv; |
| 940 | switch (op) { | 944 | switch (op) { |
| @@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf) | |||
| 950 | dib7000p_set_bandwidth(state, state->current_bandwidth); | 954 | dib7000p_set_bandwidth(state, state->current_bandwidth); |
| 951 | return state->timf; | 955 | return state->timf; |
| 952 | } | 956 | } |
| 953 | EXPORT_SYMBOL(dib7000p_ctrl_timf); | ||
| 954 | 957 | ||
| 955 | static void dib7000p_set_channel(struct dib7000p_state *state, | 958 | static void dib7000p_set_channel(struct dib7000p_state *state, |
| 956 | struct dtv_frontend_properties *ch, u8 seq) | 959 | struct dtv_frontend_properties *ch, u8 seq) |
| @@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_frontend *demod) | |||
| 1360 | dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); | 1363 | dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); |
| 1361 | 1364 | ||
| 1362 | dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); | 1365 | dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); |
| 1366 | |||
| 1367 | dib7000p_reset_stats(demod); | ||
| 1368 | |||
| 1363 | return 0; | 1369 | return 0; |
| 1364 | } | 1370 | } |
| 1365 | 1371 | ||
| @@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe) | |||
| 1552 | return ret; | 1558 | return ret; |
| 1553 | } | 1559 | } |
| 1554 | 1560 | ||
| 1561 | static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat); | ||
| 1562 | |||
| 1555 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat) | 1563 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat) |
| 1556 | { | 1564 | { |
| 1557 | struct dib7000p_state *state = fe->demodulator_priv; | 1565 | struct dib7000p_state *state = fe->demodulator_priv; |
| @@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat) | |||
| 1570 | if ((lock & 0x0038) == 0x38) | 1578 | if ((lock & 0x0038) == 0x38) |
| 1571 | *stat |= FE_HAS_LOCK; | 1579 | *stat |= FE_HAS_LOCK; |
| 1572 | 1580 | ||
| 1581 | dib7000p_get_stats(fe, *stat); | ||
| 1582 | |||
| 1573 | return 0; | 1583 | return 0; |
| 1574 | } | 1584 | } |
| 1575 | 1585 | ||
| @@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength | |||
| 1595 | return 0; | 1605 | return 0; |
| 1596 | } | 1606 | } |
| 1597 | 1607 | ||
| 1598 | static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr) | 1608 | static u32 dib7000p_get_snr(struct dvb_frontend *fe) |
| 1599 | { | 1609 | { |
| 1600 | struct dib7000p_state *state = fe->demodulator_priv; | 1610 | struct dib7000p_state *state = fe->demodulator_priv; |
| 1601 | u16 val; | 1611 | u16 val; |
| @@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr) | |||
| 1625 | else | 1635 | else |
| 1626 | result -= intlog10(2) * 10 * noise_exp - 100; | 1636 | result -= intlog10(2) * 10 * noise_exp - 100; |
| 1627 | 1637 | ||
| 1638 | return result; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 1642 | { | ||
| 1643 | u32 result; | ||
| 1644 | |||
| 1645 | result = dib7000p_get_snr(fe); | ||
| 1646 | |||
| 1628 | *snr = result / ((1 << 24) / 10); | 1647 | *snr = result / ((1 << 24) / 10); |
| 1629 | return 0; | 1648 | return 0; |
| 1630 | } | 1649 | } |
| 1631 | 1650 | ||
| 1651 | static void dib7000p_reset_stats(struct dvb_frontend *demod) | ||
| 1652 | { | ||
| 1653 | struct dib7000p_state *state = demod->demodulator_priv; | ||
| 1654 | struct dtv_frontend_properties *c = &demod->dtv_property_cache; | ||
| 1655 | u32 ucb; | ||
| 1656 | |||
| 1657 | memset(&c->strength, 0, sizeof(c->strength)); | ||
| 1658 | memset(&c->cnr, 0, sizeof(c->cnr)); | ||
| 1659 | memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); | ||
| 1660 | memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); | ||
| 1661 | memset(&c->block_error, 0, sizeof(c->block_error)); | ||
| 1662 | |||
| 1663 | c->strength.len = 1; | ||
| 1664 | c->cnr.len = 1; | ||
| 1665 | c->block_error.len = 1; | ||
| 1666 | c->block_count.len = 1; | ||
| 1667 | c->post_bit_error.len = 1; | ||
| 1668 | c->post_bit_count.len = 1; | ||
| 1669 | |||
| 1670 | c->strength.stat[0].scale = FE_SCALE_DECIBEL; | ||
| 1671 | c->strength.stat[0].uvalue = 0; | ||
| 1672 | |||
| 1673 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1674 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1675 | c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1676 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1677 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1678 | |||
| 1679 | dib7000p_read_unc_blocks(demod, &ucb); | ||
| 1680 | |||
| 1681 | state->old_ucb = ucb; | ||
| 1682 | state->ber_jiffies_stats = 0; | ||
| 1683 | state->per_jiffies_stats = 0; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | struct linear_segments { | ||
| 1687 | unsigned x; | ||
| 1688 | signed y; | ||
| 1689 | }; | ||
| 1690 | |||
| 1691 | /* | ||
| 1692 | * Table to estimate signal strength in dBm. | ||
| 1693 | * This table should be empirically determinated by measuring the signal | ||
| 1694 | * strength generated by a RF generator directly connected into | ||
| 1695 | * a device. | ||
| 1696 | * This table was determinated by measuring the signal strength generated | ||
| 1697 | * by a DTA-2111 RF generator directly connected into a dib7000p device | ||
| 1698 | * (a Hauppauge Nova-TD stick), using a good quality 3 meters length | ||
| 1699 | * RC6 cable and good RC6 connectors, connected directly to antenna 1. | ||
| 1700 | * As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator | ||
| 1701 | * were used, for the lower power values. | ||
| 1702 | * The real value can actually be on other devices, or even at the | ||
| 1703 | * second antena input, depending on several factors, like if LNA | ||
| 1704 | * is enabled or not, if diversity is enabled, type of connectors, etc. | ||
| 1705 | * Yet, it is better to use this measure in dB than a random non-linear | ||
| 1706 | * percentage value, especially for antenna adjustments. | ||
| 1707 | * On my tests, the precision of the measure using this table is about | ||
| 1708 | * 0.5 dB, with sounds reasonable enough to adjust antennas. | ||
| 1709 | */ | ||
| 1710 | #define DB_OFFSET 131000 | ||
| 1711 | |||
| 1712 | static struct linear_segments strength_to_db_table[] = { | ||
| 1713 | { 63630, DB_OFFSET - 20500}, | ||
| 1714 | { 62273, DB_OFFSET - 21000}, | ||
| 1715 | { 60162, DB_OFFSET - 22000}, | ||
| 1716 | { 58730, DB_OFFSET - 23000}, | ||
| 1717 | { 58294, DB_OFFSET - 24000}, | ||
| 1718 | { 57778, DB_OFFSET - 25000}, | ||
| 1719 | { 57320, DB_OFFSET - 26000}, | ||
| 1720 | { 56779, DB_OFFSET - 27000}, | ||
| 1721 | { 56293, DB_OFFSET - 28000}, | ||
| 1722 | { 55724, DB_OFFSET - 29000}, | ||
| 1723 | { 55145, DB_OFFSET - 30000}, | ||
| 1724 | { 54680, DB_OFFSET - 31000}, | ||
| 1725 | { 54293, DB_OFFSET - 32000}, | ||
| 1726 | { 53813, DB_OFFSET - 33000}, | ||
| 1727 | { 53427, DB_OFFSET - 34000}, | ||
| 1728 | { 52981, DB_OFFSET - 35000}, | ||
| 1729 | |||
| 1730 | { 52636, DB_OFFSET - 36000}, | ||
| 1731 | { 52014, DB_OFFSET - 37000}, | ||
| 1732 | { 51674, DB_OFFSET - 38000}, | ||
| 1733 | { 50692, DB_OFFSET - 39000}, | ||
| 1734 | { 49824, DB_OFFSET - 40000}, | ||
| 1735 | { 49052, DB_OFFSET - 41000}, | ||
| 1736 | { 48436, DB_OFFSET - 42000}, | ||
| 1737 | { 47836, DB_OFFSET - 43000}, | ||
| 1738 | { 47368, DB_OFFSET - 44000}, | ||
| 1739 | { 46468, DB_OFFSET - 45000}, | ||
| 1740 | { 45597, DB_OFFSET - 46000}, | ||
| 1741 | { 44586, DB_OFFSET - 47000}, | ||
| 1742 | { 43667, DB_OFFSET - 48000}, | ||
| 1743 | { 42673, DB_OFFSET - 49000}, | ||
| 1744 | { 41816, DB_OFFSET - 50000}, | ||
| 1745 | { 40876, DB_OFFSET - 51000}, | ||
| 1746 | { 0, 0}, | ||
| 1747 | }; | ||
| 1748 | |||
| 1749 | static u32 interpolate_value(u32 value, struct linear_segments *segments, | ||
| 1750 | unsigned len) | ||
| 1751 | { | ||
| 1752 | u64 tmp64; | ||
| 1753 | u32 dx; | ||
| 1754 | s32 dy; | ||
| 1755 | int i, ret; | ||
| 1756 | |||
| 1757 | if (value >= segments[0].x) | ||
| 1758 | return segments[0].y; | ||
| 1759 | if (value < segments[len-1].x) | ||
| 1760 | return segments[len-1].y; | ||
| 1761 | |||
| 1762 | for (i = 1; i < len - 1; i++) { | ||
| 1763 | /* If value is identical, no need to interpolate */ | ||
| 1764 | if (value == segments[i].x) | ||
| 1765 | return segments[i].y; | ||
| 1766 | if (value > segments[i].x) | ||
| 1767 | break; | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | /* Linear interpolation between the two (x,y) points */ | ||
| 1771 | dy = segments[i - 1].y - segments[i].y; | ||
| 1772 | dx = segments[i - 1].x - segments[i].x; | ||
| 1773 | |||
| 1774 | tmp64 = value - segments[i].x; | ||
| 1775 | tmp64 *= dy; | ||
| 1776 | do_div(tmp64, dx); | ||
| 1777 | ret = segments[i].y + tmp64; | ||
| 1778 | |||
| 1779 | return ret; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | /* FIXME: may require changes - this one was borrowed from dib8000 */ | ||
| 1783 | static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer) | ||
| 1784 | { | ||
| 1785 | struct dtv_frontend_properties *c = &demod->dtv_property_cache; | ||
| 1786 | u64 time_us, tmp64; | ||
| 1787 | u32 tmp, denom; | ||
| 1788 | int guard, rate_num, rate_denum = 1, bits_per_symbol; | ||
| 1789 | int interleaving = 0, fft_div; | ||
| 1790 | |||
| 1791 | switch (c->guard_interval) { | ||
| 1792 | case GUARD_INTERVAL_1_4: | ||
| 1793 | guard = 4; | ||
| 1794 | break; | ||
| 1795 | case GUARD_INTERVAL_1_8: | ||
| 1796 | guard = 8; | ||
| 1797 | break; | ||
| 1798 | case GUARD_INTERVAL_1_16: | ||
| 1799 | guard = 16; | ||
| 1800 | break; | ||
| 1801 | default: | ||
| 1802 | case GUARD_INTERVAL_1_32: | ||
| 1803 | guard = 32; | ||
| 1804 | break; | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | switch (c->transmission_mode) { | ||
| 1808 | case TRANSMISSION_MODE_2K: | ||
| 1809 | fft_div = 4; | ||
| 1810 | break; | ||
| 1811 | case TRANSMISSION_MODE_4K: | ||
| 1812 | fft_div = 2; | ||
| 1813 | break; | ||
| 1814 | default: | ||
| 1815 | case TRANSMISSION_MODE_8K: | ||
| 1816 | fft_div = 1; | ||
| 1817 | break; | ||
| 1818 | } | ||
| 1819 | |||
| 1820 | switch (c->modulation) { | ||
| 1821 | case DQPSK: | ||
| 1822 | case QPSK: | ||
| 1823 | bits_per_symbol = 2; | ||
| 1824 | break; | ||
| 1825 | case QAM_16: | ||
| 1826 | bits_per_symbol = 4; | ||
| 1827 | break; | ||
| 1828 | default: | ||
| 1829 | case QAM_64: | ||
| 1830 | bits_per_symbol = 6; | ||
| 1831 | break; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) { | ||
| 1835 | case FEC_1_2: | ||
| 1836 | rate_num = 1; | ||
| 1837 | rate_denum = 2; | ||
| 1838 | break; | ||
| 1839 | case FEC_2_3: | ||
| 1840 | rate_num = 2; | ||
| 1841 | rate_denum = 3; | ||
| 1842 | break; | ||
| 1843 | case FEC_3_4: | ||
| 1844 | rate_num = 3; | ||
| 1845 | rate_denum = 4; | ||
| 1846 | break; | ||
| 1847 | case FEC_5_6: | ||
| 1848 | rate_num = 5; | ||
| 1849 | rate_denum = 6; | ||
| 1850 | break; | ||
| 1851 | default: | ||
| 1852 | case FEC_7_8: | ||
| 1853 | rate_num = 7; | ||
| 1854 | rate_denum = 8; | ||
| 1855 | break; | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | interleaving = interleaving; | ||
| 1859 | |||
| 1860 | denom = bits_per_symbol * rate_num * fft_div * 384; | ||
| 1861 | |||
| 1862 | /* If calculus gets wrong, wait for 1s for the next stats */ | ||
| 1863 | if (!denom) | ||
| 1864 | return 0; | ||
| 1865 | |||
| 1866 | /* Estimate the period for the total bit rate */ | ||
| 1867 | time_us = rate_denum * (1008 * 1562500L); | ||
| 1868 | tmp64 = time_us; | ||
| 1869 | do_div(tmp64, guard); | ||
| 1870 | time_us = time_us + tmp64; | ||
| 1871 | time_us += denom / 2; | ||
| 1872 | do_div(time_us, denom); | ||
| 1873 | |||
| 1874 | tmp = 1008 * 96 * interleaving; | ||
| 1875 | time_us += tmp + tmp / guard; | ||
| 1876 | |||
| 1877 | return time_us; | ||
| 1878 | } | ||
| 1879 | |||
| 1880 | static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat) | ||
| 1881 | { | ||
| 1882 | struct dib7000p_state *state = demod->demodulator_priv; | ||
| 1883 | struct dtv_frontend_properties *c = &demod->dtv_property_cache; | ||
| 1884 | int i; | ||
| 1885 | int show_per_stats = 0; | ||
| 1886 | u32 time_us = 0, val, snr; | ||
| 1887 | u64 blocks, ucb; | ||
| 1888 | s32 db; | ||
| 1889 | u16 strength; | ||
| 1890 | |||
| 1891 | /* Get Signal strength */ | ||
| 1892 | dib7000p_read_signal_strength(demod, &strength); | ||
| 1893 | val = strength; | ||
| 1894 | db = interpolate_value(val, | ||
| 1895 | strength_to_db_table, | ||
| 1896 | ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET; | ||
| 1897 | c->strength.stat[0].svalue = db; | ||
| 1898 | |||
| 1899 | /* UCB/BER/CNR measures require lock */ | ||
| 1900 | if (!(stat & FE_HAS_LOCK)) { | ||
| 1901 | c->cnr.len = 1; | ||
| 1902 | c->block_count.len = 1; | ||
| 1903 | c->block_error.len = 1; | ||
| 1904 | c->post_bit_error.len = 1; | ||
| 1905 | c->post_bit_count.len = 1; | ||
| 1906 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1907 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1908 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1909 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1910 | c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||
| 1911 | return 0; | ||
| 1912 | } | ||
| 1913 | |||
| 1914 | /* Check if time for stats was elapsed */ | ||
| 1915 | if (time_after(jiffies, state->per_jiffies_stats)) { | ||
| 1916 | state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000); | ||
| 1917 | |||
| 1918 | /* Get SNR */ | ||
| 1919 | snr = dib7000p_get_snr(demod); | ||
| 1920 | if (snr) | ||
| 1921 | snr = (1000L * snr) >> 24; | ||
| 1922 | else | ||
| 1923 | snr = 0; | ||
| 1924 | c->cnr.stat[0].svalue = snr; | ||
| 1925 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; | ||
| 1926 | |||
| 1927 | /* Get UCB measures */ | ||
| 1928 | dib7000p_read_unc_blocks(demod, &val); | ||
| 1929 | ucb = val - state->old_ucb; | ||
| 1930 | if (val < state->old_ucb) | ||
| 1931 | ucb += 0x100000000LL; | ||
| 1932 | |||
| 1933 | c->block_error.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1934 | c->block_error.stat[0].uvalue = ucb; | ||
| 1935 | |||
| 1936 | /* Estimate the number of packets based on bitrate */ | ||
| 1937 | if (!time_us) | ||
| 1938 | time_us = dib7000p_get_time_us(demod, -1); | ||
| 1939 | |||
| 1940 | if (time_us) { | ||
| 1941 | blocks = 1250000ULL * 1000000ULL; | ||
| 1942 | do_div(blocks, time_us * 8 * 204); | ||
| 1943 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1944 | c->block_count.stat[0].uvalue += blocks; | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | show_per_stats = 1; | ||
| 1948 | } | ||
| 1949 | |||
| 1950 | /* Get post-BER measures */ | ||
| 1951 | if (time_after(jiffies, state->ber_jiffies_stats)) { | ||
| 1952 | time_us = dib7000p_get_time_us(demod, -1); | ||
| 1953 | state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000); | ||
| 1954 | |||
| 1955 | dprintk("Next all layers stats available in %u us.", time_us); | ||
| 1956 | |||
| 1957 | dib7000p_read_ber(demod, &val); | ||
| 1958 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1959 | c->post_bit_error.stat[0].uvalue += val; | ||
| 1960 | |||
| 1961 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1962 | c->post_bit_count.stat[0].uvalue += 100000000; | ||
| 1963 | } | ||
| 1964 | |||
| 1965 | /* Get PER measures */ | ||
| 1966 | if (show_per_stats) { | ||
| 1967 | dib7000p_read_unc_blocks(demod, &val); | ||
| 1968 | |||
| 1969 | c->block_error.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1970 | c->block_error.stat[0].uvalue += val; | ||
| 1971 | |||
| 1972 | time_us = dib7000p_get_time_us(demod, i); | ||
| 1973 | if (time_us) { | ||
| 1974 | blocks = 1250000ULL * 1000000ULL; | ||
| 1975 | do_div(blocks, time_us * 8 * 204); | ||
| 1976 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | ||
| 1977 | c->block_count.stat[0].uvalue += blocks; | ||
| 1978 | } | ||
| 1979 | } | ||
| 1980 | return 0; | ||
| 1981 | } | ||
| 1982 | |||
| 1632 | static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) | 1983 | static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) |
| 1633 | { | 1984 | { |
| 1634 | tune->min_delay_ms = 1000; | 1985 | tune->min_delay_ms = 1000; |
| @@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_frontend *demod) | |||
| 1643 | kfree(st); | 1994 | kfree(st); |
| 1644 | } | 1995 | } |
| 1645 | 1996 | ||
| 1646 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) | 1997 | static int dib7000pc_detection(struct i2c_adapter *i2c_adap) |
| 1647 | { | 1998 | { |
| 1648 | u8 *tx, *rx; | 1999 | u8 *tx, *rx; |
| 1649 | struct i2c_msg msg[2] = { | 2000 | struct i2c_msg msg[2] = { |
| @@ -1688,16 +2039,14 @@ rx_memory_error: | |||
| 1688 | kfree(tx); | 2039 | kfree(tx); |
| 1689 | return ret; | 2040 | return ret; |
| 1690 | } | 2041 | } |
| 1691 | EXPORT_SYMBOL(dib7000pc_detection); | ||
| 1692 | 2042 | ||
| 1693 | struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | 2043 | static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) |
| 1694 | { | 2044 | { |
| 1695 | struct dib7000p_state *st = demod->demodulator_priv; | 2045 | struct dib7000p_state *st = demod->demodulator_priv; |
| 1696 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | 2046 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); |
| 1697 | } | 2047 | } |
| 1698 | EXPORT_SYMBOL(dib7000p_get_i2c_master); | ||
| 1699 | 2048 | ||
| 1700 | int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | 2049 | static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) |
| 1701 | { | 2050 | { |
| 1702 | struct dib7000p_state *state = fe->demodulator_priv; | 2051 | struct dib7000p_state *state = fe->demodulator_priv; |
| 1703 | u16 val = dib7000p_read_word(state, 235) & 0xffef; | 2052 | u16 val = dib7000p_read_word(state, 235) & 0xffef; |
| @@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | |||
| 1705 | dprintk("PID filter enabled %d", onoff); | 2054 | dprintk("PID filter enabled %d", onoff); |
| 1706 | return dib7000p_write_word(state, 235, val); | 2055 | return dib7000p_write_word(state, 235, val); |
| 1707 | } | 2056 | } |
| 1708 | EXPORT_SYMBOL(dib7000p_pid_filter_ctrl); | ||
| 1709 | 2057 | ||
| 1710 | int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | 2058 | static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) |
| 1711 | { | 2059 | { |
| 1712 | struct dib7000p_state *state = fe->demodulator_priv; | 2060 | struct dib7000p_state *state = fe->demodulator_priv; |
| 1713 | dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff); | 2061 | dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff); |
| 1714 | return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0); | 2062 | return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0); |
| 1715 | } | 2063 | } |
| 1716 | EXPORT_SYMBOL(dib7000p_pid_filter); | ||
| 1717 | 2064 | ||
| 1718 | int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) | 2065 | static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) |
| 1719 | { | 2066 | { |
| 1720 | struct dib7000p_state *dpst; | 2067 | struct dib7000p_state *dpst; |
| 1721 | int k = 0; | 2068 | int k = 0; |
| @@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau | |||
| 1774 | kfree(dpst); | 2121 | kfree(dpst); |
| 1775 | return 0; | 2122 | return 0; |
| 1776 | } | 2123 | } |
| 1777 | EXPORT_SYMBOL(dib7000p_i2c_enumeration); | ||
| 1778 | 2124 | ||
| 1779 | static const s32 lut_1000ln_mant[] = { | 2125 | static const s32 lut_1000ln_mant[] = { |
| 1780 | 6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600 | 2126 | 6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600 |
| @@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = { | |||
| 2032 | .functionality = dib7000p_i2c_func, | 2378 | .functionality = dib7000p_i2c_func, |
| 2033 | }; | 2379 | }; |
| 2034 | 2380 | ||
| 2035 | struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe) | 2381 | static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe) |
| 2036 | { | 2382 | { |
| 2037 | struct dib7000p_state *st = fe->demodulator_priv; | 2383 | struct dib7000p_state *st = fe->demodulator_priv; |
| 2038 | return &st->dib7090_tuner_adap; | 2384 | return &st->dib7090_tuner_adap; |
| 2039 | } | 2385 | } |
| 2040 | EXPORT_SYMBOL(dib7090_get_i2c_tuner); | ||
| 2041 | 2386 | ||
| 2042 | static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive) | 2387 | static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive) |
| 2043 | { | 2388 | { |
| @@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode) | |||
| 2329 | return ret; | 2674 | return ret; |
| 2330 | } | 2675 | } |
| 2331 | 2676 | ||
| 2332 | int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff) | 2677 | static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff) |
| 2333 | { | 2678 | { |
| 2334 | struct dib7000p_state *state = fe->demodulator_priv; | 2679 | struct dib7000p_state *state = fe->demodulator_priv; |
| 2335 | u16 en_cur_state; | 2680 | u16 en_cur_state; |
| @@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff) | |||
| 2352 | 2697 | ||
| 2353 | return 0; | 2698 | return 0; |
| 2354 | } | 2699 | } |
| 2355 | EXPORT_SYMBOL(dib7090_tuner_sleep); | ||
| 2356 | 2700 | ||
| 2357 | int dib7090_get_adc_power(struct dvb_frontend *fe) | 2701 | static int dib7090_get_adc_power(struct dvb_frontend *fe) |
| 2358 | { | 2702 | { |
| 2359 | return dib7000p_get_adc_power(fe); | 2703 | return dib7000p_get_adc_power(fe); |
| 2360 | } | 2704 | } |
| 2361 | EXPORT_SYMBOL(dib7090_get_adc_power); | ||
| 2362 | 2705 | ||
| 2363 | int dib7090_slave_reset(struct dvb_frontend *fe) | 2706 | static int dib7090_slave_reset(struct dvb_frontend *fe) |
| 2364 | { | 2707 | { |
| 2365 | struct dib7000p_state *state = fe->demodulator_priv; | 2708 | struct dib7000p_state *state = fe->demodulator_priv; |
| 2366 | u16 reg; | 2709 | u16 reg; |
| @@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe) | |||
| 2371 | dib7000p_write_word(state, 1032, 0xffff); | 2714 | dib7000p_write_word(state, 1032, 0xffff); |
| 2372 | return 0; | 2715 | return 0; |
| 2373 | } | 2716 | } |
| 2374 | EXPORT_SYMBOL(dib7090_slave_reset); | ||
| 2375 | 2717 | ||
| 2376 | static struct dvb_frontend_ops dib7000p_ops; | 2718 | static struct dvb_frontend_ops dib7000p_ops; |
| 2377 | struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) | 2719 | static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) |
| 2378 | { | 2720 | { |
| 2379 | struct dvb_frontend *demod; | 2721 | struct dvb_frontend *demod; |
| 2380 | struct dib7000p_state *st; | 2722 | struct dib7000p_state *st; |
| @@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, | |||
| 2423 | 2765 | ||
| 2424 | dib7000p_demod_reset(st); | 2766 | dib7000p_demod_reset(st); |
| 2425 | 2767 | ||
| 2768 | dib7000p_reset_stats(demod); | ||
| 2769 | |||
| 2426 | if (st->version == SOC7090) { | 2770 | if (st->version == SOC7090) { |
| 2427 | dib7090_set_output_mode(demod, st->cfg.output_mode); | 2771 | dib7090_set_output_mode(demod, st->cfg.output_mode); |
| 2428 | dib7090_set_diversity_in(demod, 0); | 2772 | dib7090_set_diversity_in(demod, 0); |
| @@ -2434,6 +2778,31 @@ error: | |||
| 2434 | kfree(st); | 2778 | kfree(st); |
| 2435 | return NULL; | 2779 | return NULL; |
| 2436 | } | 2780 | } |
| 2781 | |||
| 2782 | void *dib7000p_attach(struct dib7000p_ops *ops) | ||
| 2783 | { | ||
| 2784 | if (!ops) | ||
| 2785 | return NULL; | ||
| 2786 | |||
| 2787 | ops->slave_reset = dib7090_slave_reset; | ||
| 2788 | ops->get_adc_power = dib7090_get_adc_power; | ||
| 2789 | ops->dib7000pc_detection = dib7000pc_detection; | ||
| 2790 | ops->get_i2c_tuner = dib7090_get_i2c_tuner; | ||
| 2791 | ops->tuner_sleep = dib7090_tuner_sleep; | ||
| 2792 | ops->init = dib7000p_init; | ||
| 2793 | ops->set_agc1_min = dib7000p_set_agc1_min; | ||
| 2794 | ops->set_gpio = dib7000p_set_gpio; | ||
| 2795 | ops->i2c_enumeration = dib7000p_i2c_enumeration; | ||
| 2796 | ops->pid_filter = dib7000p_pid_filter; | ||
| 2797 | ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl; | ||
| 2798 | ops->get_i2c_master = dib7000p_get_i2c_master; | ||
| 2799 | ops->update_pll = dib7000p_update_pll; | ||
| 2800 | ops->ctrl_timf = dib7000p_ctrl_timf; | ||
| 2801 | ops->get_agc_values = dib7000p_get_agc_values; | ||
| 2802 | ops->set_wbd_ref = dib7000p_set_wbd_ref; | ||
| 2803 | |||
| 2804 | return ops; | ||
| 2805 | } | ||
| 2437 | EXPORT_SYMBOL(dib7000p_attach); | 2806 | EXPORT_SYMBOL(dib7000p_attach); |
| 2438 | 2807 | ||
| 2439 | static struct dvb_frontend_ops dib7000p_ops = { | 2808 | static struct dvb_frontend_ops dib7000p_ops = { |
