[media] mb86a20s: Don't assume a 32.57142MHz clock
authorMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 4 Mar 2013 11:15:49 +0000 (08:15 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 4 Mar 2013 19:37:07 +0000 (16:37 -0300)
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>
drivers/media/dvb-frontends/mb86a20s.c
drivers/media/dvb-frontends/mb86a20s.h

index 1859e9ddba6e76964fab262e28e902974a0189a9..d04b52e3f4cc7ee8a2b4a1344c2b313773475d00 100644 (file)
@@ -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) {
index bf22e77888b93ea8065477246369ea800aa118fa..1a7dea2b237a5e0ea5798517b1a64958e3f0fb14 100644 (file)
 /**
  * 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) \