[alsa-devel] [RFC PATCH 19/34] ASoC: sun8i-codec: Support mono DAI configurations

Samuel Holland
2020-02-17T06:55:11Z

Calculate the correct clock rate for a mono configuration.

The AIFs have a bit that must be set for mono input/output.
Set the bit when the number of channels is 1.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun8i-codec.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index f8cde149a92b..2df899daec67 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -47,6 +47,7 @@
#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
+#define SUN8I_AIF1CLK_CTRL_AIF1_MONO_PCM 1
#define SUN8I_AIF1_ADCDAT_CTRL 0x044
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15
#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14
@@ -280,10 +281,11 @@ static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {

static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec,
unsigned int rate,
+ unsigned int channels,
unsigned int word_size)
{
unsigned long clk_rate = clk_get_rate(scodec->clk_module);
- unsigned int div = clk_rate / rate / word_size / 2;
+ unsigned int div = clk_rate / rate / word_size / channels;
unsigned int best_val = 0, best_diff = ~0;
int i;

@@ -316,8 +318,10 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component);
+ unsigned int channels = params_channels(params);
int sample_rate, lrck_div;
u8 bclk_div;
+ u32 value;

/*
* The CPU DAI handles only a sample of 16 bits. Configure the
@@ -327,12 +331,13 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16);

- bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
+ bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params),
+ channels, 16);
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
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),
+ lrck_div = sun8i_codec_get_lrck_div(channels,
params_physical_width(params));
if (lrck_div < 0)
return lrck_div;
@@ -341,6 +346,11 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);

+ value = channels == 1;
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ BIT(SUN8I_AIF1CLK_CTRL_AIF1_MONO_PCM),
+ value << SUN8I_AIF1CLK_CTRL_AIF1_MONO_PCM);
+
sample_rate = sun8i_codec_get_hw_rate(params);
if (sample_rate < 0)
return sample_rate;