ASoC: Manage mode and rate bits correctly for CS4271 CODEC.
Alexander Sverdlin [Mon, 7 Mar 2011 17:29:45 +0000 (20:29 +0300)]
Manage mode and rate bits correctly, according to datasheet in CS4271 CODEC.
This is done to make capture work properly.

Signed-off-by: Alexander Sverdlin <subaparts@yandex.ru>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

sound/soc/codecs/cs4271.c

index 538e814..083aab9 100644 (file)
@@ -168,27 +168,6 @@ struct cs4271_private {
        int                             gpio_disable;
 };
 
-struct cs4271_clk_cfg {
-       unsigned int    ratio;          /* MCLK / sample rate */
-       u8              speed_mode;     /* codec speed mode: 1x, 2x, 4x */
-       u8              mclk_master;    /* ratio bit mask for Master mode */
-       u8              mclk_slave;     /* ratio bit mask for Slave mode */
-};
-
-static struct cs4271_clk_cfg cs4271_clk_tab[] = {
-       {64,   CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_1,  CS4271_MODE1_DIV_1},
-       {96,   CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
-       {128,  CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_1,  CS4271_MODE1_DIV_1},
-       {192,  CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
-       {256,  CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_1,  CS4271_MODE1_DIV_1},
-       {384,  CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
-       {512,  CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_2,  CS4271_MODE1_DIV_1},
-       {768,  CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3,  CS4271_MODE1_DIV_3},
-       {1024, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3,  CS4271_MODE1_DIV_3}
-};
-
-#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
-
 /*
  * @freq is the desired MCLK rate
  * MCLK rate should (c) be the sample rate, multiplied by one of the
@@ -297,6 +276,45 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
        return cs4271_set_deemph(codec);
 }
 
+struct cs4271_clk_cfg {
+       bool            master;         /* codec mode */
+       u8              speed_mode;     /* codec speed mode: 1x, 2x, 4x */
+       unsigned short  ratio;          /* MCLK / sample rate */
+       u8              ratio_mask;     /* ratio bit mask for Master mode */
+};
+
+static struct cs4271_clk_cfg cs4271_clk_tab[] = {
+       {1, CS4271_MODE1_MODE_1X, 256,  CS4271_MODE1_DIV_1},
+       {1, CS4271_MODE1_MODE_1X, 384,  CS4271_MODE1_DIV_15},
+       {1, CS4271_MODE1_MODE_1X, 512,  CS4271_MODE1_DIV_2},
+       {1, CS4271_MODE1_MODE_1X, 768,  CS4271_MODE1_DIV_3},
+       {1, CS4271_MODE1_MODE_2X, 128,  CS4271_MODE1_DIV_1},
+       {1, CS4271_MODE1_MODE_2X, 192,  CS4271_MODE1_DIV_15},
+       {1, CS4271_MODE1_MODE_2X, 256,  CS4271_MODE1_DIV_2},
+       {1, CS4271_MODE1_MODE_2X, 384,  CS4271_MODE1_DIV_3},
+       {1, CS4271_MODE1_MODE_4X, 64,   CS4271_MODE1_DIV_1},
+       {1, CS4271_MODE1_MODE_4X, 96,   CS4271_MODE1_DIV_15},
+       {1, CS4271_MODE1_MODE_4X, 128,  CS4271_MODE1_DIV_2},
+       {1, CS4271_MODE1_MODE_4X, 192,  CS4271_MODE1_DIV_3},
+       {0, CS4271_MODE1_MODE_1X, 256,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_1X, 384,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_1X, 512,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_1X, 768,  CS4271_MODE1_DIV_2},
+       {0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2},
+       {0, CS4271_MODE1_MODE_2X, 128,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_2X, 192,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_2X, 256,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_2X, 384,  CS4271_MODE1_DIV_2},
+       {0, CS4271_MODE1_MODE_2X, 512,  CS4271_MODE1_DIV_2},
+       {0, CS4271_MODE1_MODE_4X, 64,   CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_4X, 96,   CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_4X, 128,  CS4271_MODE1_DIV_1},
+       {0, CS4271_MODE1_MODE_4X, 192,  CS4271_MODE1_DIV_2},
+       {0, CS4271_MODE1_MODE_4X, 256,  CS4271_MODE1_DIV_2},
+};
+
+#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
+
 static int cs4271_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *params,
                            struct snd_soc_dai *dai)
@@ -308,23 +326,28 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
        unsigned int ratio, val;
 
        cs4271->rate = params_rate(params);
+
+       /* Configure DAC */
+       if (cs4271->rate < 50000)
+               val = CS4271_MODE1_MODE_1X;
+       else if (cs4271->rate < 100000)
+               val = CS4271_MODE1_MODE_2X;
+       else
+               val = CS4271_MODE1_MODE_4X;
+
        ratio = cs4271->mclk / cs4271->rate;
        for (i = 0; i < CS4171_NR_RATIOS; i++)
-               if (cs4271_clk_tab[i].ratio == ratio)
+               if ((cs4271_clk_tab[i].master == cs4271->master) &&
+                   (cs4271_clk_tab[i].speed_mode == val) &&
+                   (cs4271_clk_tab[i].ratio == ratio))
                        break;
 
-       if ((i == CS4171_NR_RATIOS) || ((ratio == 1024) && cs4271->master)) {
+       if (i == CS4171_NR_RATIOS) {
                dev_err(codec->dev, "Invalid sample rate\n");
                return -EINVAL;
        }
 
-       /* Configure DAC */
-       val = cs4271_clk_tab[i].speed_mode;
-
-       if (cs4271->master)
-               val |= cs4271_clk_tab[i].mclk_master;
-       else
-               val |= cs4271_clk_tab[i].mclk_slave;
+       val |= cs4271_clk_tab[i].ratio_mask;
 
        ret = snd_soc_update_bits(codec, CS4271_MODE1,
                CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);