aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb-frontends
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-03-04 08:15:49 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-04 16:37:07 -0300
commit0e4bbedd638d6d13b0cfe2c95c75fc3736daec94 (patch)
treebdc113859e2503e298a1d066d6cc0c329507e8a5 /drivers/media/dvb-frontends
parent[media] mb86a20s: Implement set_frontend cache logic (diff)
downloadlinux-dev-0e4bbedd638d6d13b0cfe2c95c75fc3736daec94.tar.xz
linux-dev-0e4bbedd638d6d13b0cfe2c95c75fc3736daec94.zip
[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.c26
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.h8
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[] = {
{ 0x70, 0xff },
{ 0x08, 0x01 },
{ 0x50, 0xd1 }, { 0x51, 0x20 },
- { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
};
static struct regdata mb86a20s_init2[] = {
@@ -1776,6 +1775,7 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
u64 pll;
+ u32 fclk;
int rc;
u8 regD5 = 1, reg71, reg09 = 0x3a;
@@ -1810,6 +1810,10 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
goto err;
}
+ fclk = state->config->fclk;
+ if (!fclk)
+ fclk = 32571428;
+
/* Adjust IF frequency to match tuner */
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq);
@@ -1817,6 +1821,24 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
if (!state->if_freq)
state->if_freq = 3300000;
+ pll = (((u64)1) << 34) * state->if_freq;
+ do_div(pll, 63 * fclk);
+ pll = (1 << 25) - pll;
+ rc = mb86a20s_writereg(state, 0x28, 0x2a);
+ if (rc < 0)
+ goto err;
+ rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
+ if (rc < 0)
+ goto err;
+ rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
+ if (rc < 0)
+ goto err;
+ rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
+ if (rc < 0)
+ goto err;
+ dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n",
+ __func__, fclk, state->if_freq, (long long)pll);
+
/* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */
pll = state->if_freq * 1677721600L;
do_div(pll, 1628571429L);
@@ -1832,7 +1854,7 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
if (rc < 0)
goto err;
- dev_dbg(&state->i2c->dev, "%s: IF=%d, PLL=0x%06llx\n",
+ dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
__func__, state->if_freq, (long long)pll);
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 @@
/**
* struct mb86a20s_config - Define the per-device attributes of the frontend
*
+ * @fclk: Clock frequency. If zero, assumes the default
+ * (32.57142 Mhz)
* @demod_address: the demodulator's i2c address
+ * @is_serial: if true, TS is serial. Otherwise, TS is parallel
*/
struct mb86a20s_config {
- u8 demod_address;
- bool is_serial;
+ u32 fclk;
+ u8 demod_address;
+ bool is_serial;
};
#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \