diff options
author | Shengjiu Wang <b02247@freescale.com> | 2014-05-07 18:02:15 +0800 |
---|---|---|
committer | Shengjiu Wang <b02247@freescale.com> | 2014-05-07 18:35:16 +0800 |
commit | 84babc7fa0a56f6620f8b04a86baece620297dda (patch) | |
tree | 8208a064be324c37d2d53efddb90dd218f3719ba /sound | |
parent | 45a269edfe110f6f23b272eac2b0a20b18d584de (diff) |
ENGR00312217-1 ASoC: fsl: pop noise with wm8962
The reason of pop noise is that we change the sysclk in hw_free, which is
for another wm8962 issue. So in currently the pop noise can't be resolved
with no confliction. So for Android, because the samplerate is fixed. we can
use other workaround for this issue: change the sysclk in the set_bias().
Signed-off-by: Shengjiu Wang <b02247@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/fsl/Kconfig | 7 | ||||
-rw-r--r-- | sound/soc/fsl/imx-wm8962.c | 110 |
2 files changed, 117 insertions, 0 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 2b9f4bf0ae86..4a5063bf9882 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -215,6 +215,13 @@ config SND_SOC_IMX_WM8962 Say Y if you want to add support for SoC audio on an i.MX board with a wm8962 codec. +config SND_SOC_IMX_WM8962_ANDROID + tristate "SoC Audio support for i.MX boards with wm8962 in android" + depends on SND_SOC_IMX_WM8962=y + help + Say Y if you want to add support for SoC audio on an i.MX board with + a wm8962 codec in android. + config SND_SOC_IMX_SGTL5000 tristate "SoC Audio support for i.MX boards with sgtl5000" depends on OF && I2C diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 66cb2df64032..c8345704df6f 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -56,6 +56,11 @@ struct imx_priv { }; static struct imx_priv card_priv; +#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID +static int sample_rate = 44100; +static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE; +#endif + static struct snd_soc_jack imx_hp_jack; static struct snd_soc_jack_pin imx_hp_jack_pins[] = { { @@ -176,6 +181,107 @@ static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = { SND_SOC_DAPM_MIC("DMIC", NULL), }; +#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID +static int imx_hifi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct imx_priv *priv = &card_priv; + struct device *dev = &priv->pdev->dev; + u32 dai_format; + int ret = 0; + + sample_rate = params_rate(params); + sample_format = params_format(params); + + dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, dai_format); + if (ret) { + dev_err(dev, "failed to set codec dai fmt: %d\n", ret); + return ret; + } + + return 0; +} + +static struct snd_soc_ops imx_hifi_ops = { + .hw_params = imx_hifi_hw_params, +}; + +static int imx_wm8962_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct imx_priv *priv = &card_priv; + struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); + struct device *dev = &priv->pdev->dev; + unsigned int pll_out; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { + if (sample_format == SNDRV_PCM_FORMAT_S24_LE) + pll_out = sample_rate * 384; + else + pll_out = sample_rate * 256; + + ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, + WM8962_FLL_MCLK, data->clk_frequency, + pll_out); + if (ret < 0) { + dev_err(dev, "failed to start FLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + WM8962_SYSCLK_FLL, pll_out, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(dev, "failed to set SYSCLK: %d\n", ret); + return ret; + } + } + break; + + case SND_SOC_BIAS_STANDBY: + if (dapm->bias_level == SND_SOC_BIAS_PREPARE) { + ret = snd_soc_dai_set_sysclk(codec_dai, + WM8962_SYSCLK_MCLK, data->clk_frequency, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(dev, + "failed to switch away from FLL: %d\n", + ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, + 0, 0, 0); + if (ret < 0) { + dev_err(dev, "failed to stop FLL: %d\n", ret); + return ret; + } + } + break; + + default: + break; + } + + return 0; +} + +#else + static int imx_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -282,6 +388,7 @@ static struct snd_soc_ops imx_hifi_ops = { .hw_params = imx_hifi_hw_params, .hw_free = imx_hifi_hw_free, }; +#endif /* CONFIG_SND_SOC_IMX_WM8962_ANDROID */ static int imx_wm8962_gpio_init(struct snd_soc_card *card) { @@ -514,6 +621,9 @@ audmux_bypass: data->card.late_probe = imx_wm8962_late_probe; +#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID + data->card.set_bias_level = imx_wm8962_set_bias_level; +#endif platform_set_drvdata(pdev, &data->card); snd_soc_card_set_drvdata(&data->card, data); |