diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-04 06:15:49 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-04 14:37:07 -0500 |
commit | 0e4bbedd638d6d13b0cfe2c95c75fc3736daec94 (patch) | |
tree | bdc113859e2503e298a1d066d6cc0c329507e8a5 /drivers/media/dvb-frontends | |
parent | 04fa725e7b1c22c583dd71a8cd85b8d997edfce3 (diff) |
[media] mb86a20s: Don't assume a 32.57142MHz clock
Now that some devices initialize register 0x2a with different
values, add the calculus formula, instead of hardcoding it.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.c | 26 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.h | 8 |
2 files changed, 30 insertions, 4 deletions
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 1859e9ddba6e..d04b52e3f4cc 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c | |||
@@ -70,7 +70,6 @@ static struct regdata mb86a20s_init1[] = { | |||
70 | { 0x70, 0xff }, | 70 | { 0x70, 0xff }, |
71 | { 0x08, 0x01 }, | 71 | { 0x08, 0x01 }, |
72 | { 0x50, 0xd1 }, { 0x51, 0x20 }, | 72 | { 0x50, 0xd1 }, { 0x51, 0x20 }, |
73 | { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, | ||
74 | }; | 73 | }; |
75 | 74 | ||
76 | static struct regdata mb86a20s_init2[] = { | 75 | static struct regdata mb86a20s_init2[] = { |
@@ -1776,6 +1775,7 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1776 | { | 1775 | { |
1777 | struct mb86a20s_state *state = fe->demodulator_priv; | 1776 | struct mb86a20s_state *state = fe->demodulator_priv; |
1778 | u64 pll; | 1777 | u64 pll; |
1778 | u32 fclk; | ||
1779 | int rc; | 1779 | int rc; |
1780 | u8 regD5 = 1, reg71, reg09 = 0x3a; | 1780 | u8 regD5 = 1, reg71, reg09 = 0x3a; |
1781 | 1781 | ||
@@ -1810,6 +1810,10 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1810 | goto err; | 1810 | goto err; |
1811 | } | 1811 | } |
1812 | 1812 | ||
1813 | fclk = state->config->fclk; | ||
1814 | if (!fclk) | ||
1815 | fclk = 32571428; | ||
1816 | |||
1813 | /* Adjust IF frequency to match tuner */ | 1817 | /* Adjust IF frequency to match tuner */ |
1814 | if (fe->ops.tuner_ops.get_if_frequency) | 1818 | if (fe->ops.tuner_ops.get_if_frequency) |
1815 | fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq); | 1819 | fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq); |
@@ -1817,6 +1821,24 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1817 | if (!state->if_freq) | 1821 | if (!state->if_freq) |
1818 | state->if_freq = 3300000; | 1822 | state->if_freq = 3300000; |
1819 | 1823 | ||
1824 | pll = (((u64)1) << 34) * state->if_freq; | ||
1825 | do_div(pll, 63 * fclk); | ||
1826 | pll = (1 << 25) - pll; | ||
1827 | rc = mb86a20s_writereg(state, 0x28, 0x2a); | ||
1828 | if (rc < 0) | ||
1829 | goto err; | ||
1830 | rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff); | ||
1831 | if (rc < 0) | ||
1832 | goto err; | ||
1833 | rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff); | ||
1834 | if (rc < 0) | ||
1835 | goto err; | ||
1836 | rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); | ||
1837 | if (rc < 0) | ||
1838 | goto err; | ||
1839 | dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n", | ||
1840 | __func__, fclk, state->if_freq, (long long)pll); | ||
1841 | |||
1820 | /* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */ | 1842 | /* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */ |
1821 | pll = state->if_freq * 1677721600L; | 1843 | pll = state->if_freq * 1677721600L; |
1822 | do_div(pll, 1628571429L); | 1844 | do_div(pll, 1628571429L); |
@@ -1832,7 +1854,7 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1832 | rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); | 1854 | rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); |
1833 | if (rc < 0) | 1855 | if (rc < 0) |
1834 | goto err; | 1856 | goto err; |
1835 | dev_dbg(&state->i2c->dev, "%s: IF=%d, PLL=0x%06llx\n", | 1857 | dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", |
1836 | __func__, state->if_freq, (long long)pll); | 1858 | __func__, state->if_freq, (long long)pll); |
1837 | 1859 | ||
1838 | if (!state->config->is_serial) { | 1860 | if (!state->config->is_serial) { |
diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h index bf22e77888b9..1a7dea2b237a 100644 --- a/drivers/media/dvb-frontends/mb86a20s.h +++ b/drivers/media/dvb-frontends/mb86a20s.h | |||
@@ -21,12 +21,16 @@ | |||
21 | /** | 21 | /** |
22 | * struct mb86a20s_config - Define the per-device attributes of the frontend | 22 | * struct mb86a20s_config - Define the per-device attributes of the frontend |
23 | * | 23 | * |
24 | * @fclk: Clock frequency. If zero, assumes the default | ||
25 | * (32.57142 Mhz) | ||
24 | * @demod_address: the demodulator's i2c address | 26 | * @demod_address: the demodulator's i2c address |
27 | * @is_serial: if true, TS is serial. Otherwise, TS is parallel | ||
25 | */ | 28 | */ |
26 | 29 | ||
27 | struct mb86a20s_config { | 30 | struct mb86a20s_config { |
28 | u8 demod_address; | 31 | u32 fclk; |
29 | bool is_serial; | 32 | u8 demod_address; |
33 | bool is_serial; | ||
30 | }; | 34 | }; |
31 | 35 | ||
32 | #if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ | 36 | #if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ |