diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-02-28 14:45:39 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-04 14:32:33 -0500 |
commit | 768e6dadd748ecceee852def1f7f71aac4cd35a1 (patch) | |
tree | 31950f5638a41a5a9e8af06c7ae13b5f17c6476e /drivers/media/dvb-frontends/mb86a20s.c | |
parent | d56e326f7b7f409f0390517b0a29d65b4d60c14c (diff) |
[media] mb86a20s: adjust IF based on what's set on the tuner
Instead of hardcoding a fixed IF frequency of 3.3 MHz, use
the IF frequency provided by the tuner driver.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-frontends/mb86a20s.c')
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.c | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 44bfb884ba11..daeee814e491 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c | |||
@@ -31,6 +31,8 @@ struct mb86a20s_state { | |||
31 | 31 | ||
32 | struct dvb_frontend frontend; | 32 | struct dvb_frontend frontend; |
33 | 33 | ||
34 | u32 if_freq; | ||
35 | |||
34 | u32 estimated_rate[3]; | 36 | u32 estimated_rate[3]; |
35 | 37 | ||
36 | bool need_init; | 38 | bool need_init; |
@@ -47,7 +49,7 @@ struct regdata { | |||
47 | * Initialization sequence: Use whatevere default values that PV SBTVD | 49 | * Initialization sequence: Use whatevere default values that PV SBTVD |
48 | * does on its initialisation, obtained via USB snoop | 50 | * does on its initialisation, obtained via USB snoop |
49 | */ | 51 | */ |
50 | static struct regdata mb86a20s_init[] = { | 52 | static struct regdata mb86a20s_init1[] = { |
51 | { 0x70, 0x0f }, | 53 | { 0x70, 0x0f }, |
52 | { 0x70, 0xff }, | 54 | { 0x70, 0xff }, |
53 | { 0x08, 0x01 }, | 55 | { 0x08, 0x01 }, |
@@ -56,7 +58,9 @@ static struct regdata mb86a20s_init[] = { | |||
56 | { 0x39, 0x01 }, | 58 | { 0x39, 0x01 }, |
57 | { 0x71, 0x00 }, | 59 | { 0x71, 0x00 }, |
58 | { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, | 60 | { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, |
59 | { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 }, | 61 | }; |
62 | |||
63 | static struct regdata mb86a20s_init2[] = { | ||
60 | { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 }, | 64 | { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 }, |
61 | { 0x3b, 0x21 }, | 65 | { 0x3b, 0x21 }, |
62 | { 0x3c, 0x3a }, | 66 | { 0x3c, 0x3a }, |
@@ -1737,6 +1741,7 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) | |||
1737 | static int mb86a20s_initfe(struct dvb_frontend *fe) | 1741 | static int mb86a20s_initfe(struct dvb_frontend *fe) |
1738 | { | 1742 | { |
1739 | struct mb86a20s_state *state = fe->demodulator_priv; | 1743 | struct mb86a20s_state *state = fe->demodulator_priv; |
1744 | u64 pll; | ||
1740 | int rc; | 1745 | int rc; |
1741 | u8 regD5 = 1; | 1746 | u8 regD5 = 1; |
1742 | 1747 | ||
@@ -1746,10 +1751,35 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1746 | fe->ops.i2c_gate_ctrl(fe, 0); | 1751 | fe->ops.i2c_gate_ctrl(fe, 0); |
1747 | 1752 | ||
1748 | /* Initialize the frontend */ | 1753 | /* Initialize the frontend */ |
1749 | rc = mb86a20s_writeregdata(state, mb86a20s_init); | 1754 | rc = mb86a20s_writeregdata(state, mb86a20s_init1); |
1750 | if (rc < 0) | 1755 | if (rc < 0) |
1751 | goto err; | 1756 | goto err; |
1752 | 1757 | ||
1758 | /* Adjust IF frequency to match tuner */ | ||
1759 | if (fe->ops.tuner_ops.get_if_frequency) | ||
1760 | fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq); | ||
1761 | |||
1762 | if (!state->if_freq) | ||
1763 | state->if_freq = 3300000; | ||
1764 | |||
1765 | /* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */ | ||
1766 | pll = state->if_freq * 1677721600L; | ||
1767 | do_div(pll, 1628571429L); | ||
1768 | rc = mb86a20s_writereg(state, 0x28, 0x20); | ||
1769 | if (rc < 0) | ||
1770 | goto err; | ||
1771 | rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff); | ||
1772 | if (rc < 0) | ||
1773 | goto err; | ||
1774 | rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff); | ||
1775 | if (rc < 0) | ||
1776 | goto err; | ||
1777 | rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); | ||
1778 | if (rc < 0) | ||
1779 | goto err; | ||
1780 | dev_dbg(&state->i2c->dev, "%s: IF=%d, PLL=0x%06llx\n", | ||
1781 | __func__, state->if_freq, (long long)pll); | ||
1782 | |||
1753 | if (!state->config->is_serial) { | 1783 | if (!state->config->is_serial) { |
1754 | regD5 &= ~1; | 1784 | regD5 &= ~1; |
1755 | 1785 | ||
@@ -1761,6 +1791,11 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1761 | goto err; | 1791 | goto err; |
1762 | } | 1792 | } |
1763 | 1793 | ||
1794 | rc = mb86a20s_writeregdata(state, mb86a20s_init2); | ||
1795 | if (rc < 0) | ||
1796 | goto err; | ||
1797 | |||
1798 | |||
1764 | err: | 1799 | err: |
1765 | if (fe->ops.i2c_gate_ctrl) | 1800 | if (fe->ops.i2c_gate_ctrl) |
1766 | fe->ops.i2c_gate_ctrl(fe, 1); | 1801 | fe->ops.i2c_gate_ctrl(fe, 1); |
@@ -1779,7 +1814,7 @@ err: | |||
1779 | static int mb86a20s_set_frontend(struct dvb_frontend *fe) | 1814 | static int mb86a20s_set_frontend(struct dvb_frontend *fe) |
1780 | { | 1815 | { |
1781 | struct mb86a20s_state *state = fe->demodulator_priv; | 1816 | struct mb86a20s_state *state = fe->demodulator_priv; |
1782 | int rc; | 1817 | int rc, if_freq; |
1783 | #if 0 | 1818 | #if 0 |
1784 | /* | 1819 | /* |
1785 | * FIXME: Properly implement the set frontend properties | 1820 | * FIXME: Properly implement the set frontend properties |
@@ -1796,6 +1831,18 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe) | |||
1796 | fe->ops.i2c_gate_ctrl(fe, 1); | 1831 | fe->ops.i2c_gate_ctrl(fe, 1); |
1797 | fe->ops.tuner_ops.set_params(fe); | 1832 | fe->ops.tuner_ops.set_params(fe); |
1798 | 1833 | ||
1834 | if (fe->ops.tuner_ops.get_if_frequency) { | ||
1835 | fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); | ||
1836 | |||
1837 | /* | ||
1838 | * If the IF frequency changed, re-initialize the | ||
1839 | * frontend. This is needed by some drivers like tda18271, | ||
1840 | * that only sets the IF after receiving a set_params() call | ||
1841 | */ | ||
1842 | if (if_freq != state->if_freq) | ||
1843 | state->need_init = true; | ||
1844 | } | ||
1845 | |||
1799 | /* | 1846 | /* |
1800 | * Make it more reliable: if, for some reason, the initial | 1847 | * Make it more reliable: if, for some reason, the initial |
1801 | * device initialization doesn't happen, initialize it when | 1848 | * device initialization doesn't happen, initialize it when |
@@ -1805,6 +1852,8 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe) | |||
1805 | * the agc callback logic is not called during DVB attach time, | 1852 | * the agc callback logic is not called during DVB attach time, |
1806 | * causing mb86a20s to not be initialized with Kworld SBTVD. | 1853 | * causing mb86a20s to not be initialized with Kworld SBTVD. |
1807 | * So, this hack is needed, in order to make Kworld SBTVD to work. | 1854 | * So, this hack is needed, in order to make Kworld SBTVD to work. |
1855 | * | ||
1856 | * It is also needed to change the IF after the initial init. | ||
1808 | */ | 1857 | */ |
1809 | if (state->need_init) | 1858 | if (state->need_init) |
1810 | mb86a20s_initfe(fe); | 1859 | mb86a20s_initfe(fe); |