[alsa-devel] [PATCH v1 0/5] Support more sample rates, let the rates normal work
That's seem the moment rockchip-codec driver other than 44100 and 48000 do not work. Says the (max98090, rt5640).
---- As the chromeos reported issue:(https://chromium.googlesource.com/chromiumos/third_party/kernel/+/v3.14)
For detail: In that bug we want to add 32000 to sound/soc/rockchip/rockchip_max98090.c rk_aif1_hw_params. However that does not work.
Previously, in https://chromium-review.googlesource.com/#/c/268398/ , rate 8000, 1600, 96000 were added. However, those rates do not work. I got the same audio as 48000 when I run
aplay -D hw:0,0 /usr/local/autotest/cros/audio/fix_440_16_half.raw --rate 8000 -f S16_LE -c2 aplay -D hw:0,0 /usr/local/autotest/cros/audio/fix_440_16_half.raw --rate 16000 -f S16_LE -c2 aplay -D hw:0,0 /usr/local/autotest/cros/audio/fix_440_16_half.raw --rate 96000 -f S16_LE -c2
They all sound identical to aplay -D hw:0,0 /usr/local/autotest/cros/audio/fix_440_16_half.raw --rate 48000 -f S16_LE -c2
Also, recording using aplay -D hw:0,0 /usr/local/test.raw --rate 96000 -f S16_LE -c2 and examine the output we see it was recording using 48000.
Okay, let's add this series patchs to fix this issue.
arecord -D hw:0 -f S16_LE -c 2 --rate 96000 -d 5 foobar.wav and aplay -D hw:0 foobar.wav Tested on veyron devices.
Changes in v1: - change the subject and commit. - remove the print message dev_dbg(). - Fix a subject missspell.
Caesar Wang (5): ASoC: rockchip: i2s: Support to set the divider clock API ASoC: rockchip-max98090: Allow more sample rates ASoC: rockchip-rt5645: Allow more sample rates ASoC: rockchip-max98090: Add the divider clock for cpu ASoC: rockchip-rt5645: Add the divider clock for cpu
sound/soc/rockchip/rockchip_i2s.c | 27 +++++++++++++++++++++++++ sound/soc/rockchip/rockchip_max98090.c | 37 ++++++++++++++++++++++++++++++++++ sound/soc/rockchip/rockchip_rt5645.c | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+)
In order to support more sample rates, add the divider clock api.
As the input source clock to the module is MCLK_I2S, and by the divider of the module, the clock generator generates SCLK and LRCK to transmitter and receiver.
Signed-off-by: Caesar Wang wxt@rock-chips.com ---
Changes in v1: - change the subject and commit. - remove the print message dev_dbg().
sound/soc/rockchip/rockchip_i2s.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index b936102..23c867f 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -286,6 +286,32 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, return ret; }
+static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, + int div_id, int div) +{ + struct rk_i2s_dev *i2s = to_info(cpu_dai); + unsigned int val = 0; + + switch (div_id) { + case ROCKCHIP_DIV_BCLK: + val |= I2S_CKR_TSD(div); + val |= I2S_CKR_RSD(div); + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK, + val); + break; + case ROCKCHIP_DIV_MCLK: + val |= I2S_CKR_MDIV(div); + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_MDIV_MASK, val); + break; + default: + return -EINVAL; + } + + return 0; +} + static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { @@ -311,6 +337,7 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { .hw_params = rockchip_i2s_hw_params, + .set_clkdiv = rockchip_i2s_set_clkdiv, .set_sysclk = rockchip_i2s_set_sysclk, .set_fmt = rockchip_i2s_set_fmt, .trigger = rockchip_i2s_trigger,
On Tue, Nov 03, 2015 at 09:33:54AM +0800, Caesar Wang wrote:
In order to support more sample rates, add the divider clock api.
As the input source clock to the module is MCLK_I2S, and by the divider of the module, the clock generator generates SCLK and LRCK to transmitter and receiver.
Same thing as your other very similar patch: why does this feature require set_clkdiv()?
The MAX98090 audio codec support sample rates from 8 to 96 kHz as the dai claim.
Signed-off-by: Caesar Wang wxt@rock-chips.com ---
Changes in v1: None
sound/soc/rockchip/rockchip_max98090.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 26567b1..a6ff221 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -80,11 +80,16 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: case 16000: + case 24000: + case 32000: case 48000: case 96000: mclk = 12288000; break; + case 11025: + case 22050: case 44100: + case 88200: mclk = 11289600; break; default:
The RT5645 audio codec support sample rates from 8 to 96 kHz as the dai claim.
Signed-off-by: Caesar Wang wxt@rock-chips.com ---
Changes in v1: None
sound/soc/rockchip/rockchip_rt5645.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index 68c62e4..edff07f 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -79,11 +79,16 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: case 16000: + case 24000: + case 32000: case 48000: case 96000: mclk = 12288000; break; + case 11025: + case 22050: case 44100: + case 88200: mclk = 11289600; break; default:
Add to set the cpu/codec DAI configure, let's divider the Transmit/Receive clocks for cpu.
In master mode, The SCLK and LRCK are configured as output, this patch should can set each divider to arrange the clock distribution.
Signed-off-by: Caesar Wang wxt@rock-chips.com ---
Changes in v1: None
sound/soc/rockchip/rockchip_max98090.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index a6ff221..e1cdd40 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -75,8 +75,25 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; + int dai_fmt = rtd->card->dai_link->dai_fmt; int mclk;
+ /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); + if (ret < 0) { + dev_err(codec_dai->dev, + "failed to set the format for codec side\n"); + return ret; + } + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); + if (ret < 0) { + dev_err(codec_dai->dev, + "failed to set the format for cpu side\n"); + return ret; + } + switch (params_rate(params)) { case 8000: case 16000: @@ -110,6 +127,21 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, return ret; }
+ /* The codec is master mode, that's not needed set clkdiv for cpu */ + if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) + return ret; + + /* the LRCK clock for cpu */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, + (mclk / 4) / params_rate(params)); + if (ret < 0) + return ret; + + /* the SCLK clock for cpu */ + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 4); + if (ret < 0) + return ret; + return ret; }
Add to set the cpu/codec DAI configure, let's divider the Transmit/Receive clock for cpu.
In master mode, The SCLK and LRCK are configured as output, this patch should can set each divider to arrange the clock distribution.
Signed-off-by: Caesar Wang wxt@rock-chips.com
---
Changes in v1: - Fix a subject missspell.
sound/soc/rockchip/rockchip_rt5645.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index edff07f..4c1a693 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -74,8 +74,25 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; + int dai_fmt = rtd->card->dai_link->dai_fmt; int mclk;
+ /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); + if (ret < 0) { + dev_err(codec_dai->dev, + "failed to set the format for codec side\n"); + return ret; + } + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); + if (ret < 0) { + dev_err(codec_dai->dev, + "failed to set the format for cpu side\n"); + return ret; + } + switch (params_rate(params)) { case 8000: case 16000: @@ -109,6 +126,21 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, return ret; }
+ /* The codec is master mode, that's not needed set clkdiv for cpu */ + if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) + return ret; + + /* the LRCK clock for cpu */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, + (mclk / 4) / params_rate(params)); + if (ret < 0) + return ret; + + /* the SCLK clock for cpu */ + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 4); + if (ret < 0) + return ret; + return ret; }
participants (2)
-
Caesar Wang
-
Mark Brown