ASoC: sun8i-codec: Don't hardcode BCLK / LRCK ratio
authorVasily Khoruzhick <anarsoul@gmail.com>
Wed, 17 Oct 2018 07:38:06 +0000 (00:38 -0700)
committerMark Brown <broonie@kernel.org>
Wed, 17 Oct 2018 10:10:58 +0000 (11:10 +0100)
BCLK / LRCK ratio should be sample size * channels, but it was
hardcoded to 32 (0x1 is 32 as per A33 and A64 datasheets).

Calculate it basing on sample size and number of channels.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sunxi/sun8i-codec.c

index fb37dd927e3385b1e7ac807866bcaf6577df9731..522a72fde78da9b89f40551577de40fee351f59f 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/log2.h>
 
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -52,7 +53,6 @@
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV               13
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV               9
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV               6
-#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16            (1 << 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ               4
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16            (1 << 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT               2
@@ -300,12 +300,23 @@ static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec,
        return best_val;
 }
 
+static int sun8i_codec_get_lrck_div(unsigned int channels,
+                                   unsigned int word_size)
+{
+       unsigned int div = word_size * channels;
+
+       if (div < 16 || div > 256)
+               return -EINVAL;
+
+       return ilog2(div) - 4;
+}
+
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
        struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component);
-       int sample_rate;
+       int sample_rate, lrck_div;
        u8 bclk_div;
 
        /*
@@ -321,9 +332,14 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
                           SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
                           bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
 
+       lrck_div = sun8i_codec_get_lrck_div(params_channels(params),
+                                           params_physical_width(params));
+       if (lrck_div < 0)
+               return lrck_div;
+
        regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
                           SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
-                          SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16);
+                          lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
 
        sample_rate = sun8i_codec_get_hw_rate(params);
        if (sample_rate < 0)