From beafee85e0651cf3824c532354059fba79f12d0c Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 3 May 2018 16:42:42 +0800 Subject: [PATCH] ASoC: rockchip: multicodecs: fix the excessive mclk_fs Usually, the MCLK should be 256 times that of LRCLK, the excessive mclk (@FS 16KHz and mclk 12.288MHz) may cause frequency aliasing. Change-Id: I2665c44dfcdfb51cc4708427782eb68b897c52c4 Signed-off-by: Xing Zheng --- sound/soc/rockchip/rockchip_multicodecs.c | 66 +++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/sound/soc/rockchip/rockchip_multicodecs.c b/sound/soc/rockchip/rockchip_multicodecs.c index f57daa415267..8a6de82fc888 100644 --- a/sound/soc/rockchip/rockchip_multicodecs.c +++ b/sound/soc/rockchip/rockchip_multicodecs.c @@ -30,50 +30,38 @@ #define DRV_NAME "rk-multicodecs" #define MAX_CODECS 2 +#define DEFAULT_MCLK_FS 256 + +struct multicodecs_data { + unsigned int mclk_fs; +}; static int rk_multicodecs_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int mclk; + struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(rtd->card); + unsigned int mclk; + int ret; - switch (params_rate(params)) { - case 8000: - case 16000: - case 24000: - case 32000: - case 48000: - case 64000: - case 96000: - mclk = 12288000; - break; - case 11025: - case 22050: - case 44100: - case 88200: - mclk = 11289600; - break; - case 176400: - mclk = 11289600 * 2; - break; - case 192000: - mclk = 12288000 * 2; - break; - default: - return -EINVAL; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, - SND_SOC_CLOCK_OUT); + mclk = params_rate(params) * mc_data->mclk_fs; + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) { - dev_err(cpu_dai->dev, "Can't set cpu clock %d\n", ret); - return ret; + pr_err("Set codec_dai sysclk failed: %d\n", ret); + goto out; } - return 0; + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, SND_SOC_CLOCK_OUT); + if (ret && ret != -ENOTSUPP) { + pr_err("Set cpu_dai sysclk failed: %d\n", ret); + goto out; + } + +out: + return ret; } static struct snd_soc_ops rk_ops = { @@ -101,13 +89,19 @@ static int rk_multicodecs_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct snd_soc_dai_link *link = card->dai_link; struct snd_soc_dai_link_component *codecs; + struct multicodecs_data *mc_data; struct of_phandle_args args; struct device_node *node; + u32 val; int count; int ret = 0, i = 0, idx = 0; card->dev = &pdev->dev; + mc_data = devm_kzalloc(&pdev->dev, sizeof(*mc_data), GFP_KERNEL); + if (!mc_data) + return -ENOMEM; + count = of_count_phandle_with_args(np, "rockchip,codec", NULL); if (count < 0 || count > MAX_CODECS) return -EINVAL; @@ -154,6 +148,12 @@ static int rk_multicodecs_probe(struct platform_device *pdev) link->platform_of_node = link->cpu_of_node; + mc_data->mclk_fs = DEFAULT_MCLK_FS; + if (!of_property_read_u32(np, "rockchip,mclk-fs", &val)) + mc_data->mclk_fs = val; + + snd_soc_card_set_drvdata(card, mc_data); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret == -EPROBE_DEFER) return -EPROBE_DEFER;