summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorShengjiu Wang <b02247@freescale.com>2014-05-07 18:02:15 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:49:57 +0800
commit62f5b5f0caaed01166471a7e679f7ededb90fbd9 (patch)
tree00f574e236da98286652fa74af59209d1ce37171 /sound/soc
parent2237688f52e10f4939354bc74850a543036a1c05 (diff)
MLK-11479-10 ASoC: fsl: pop noise with wm8962
cherry-pick below patch from v3.14.y: 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> (cherry picked from commit 84babc7fa0a56f6620f8b04a86baece620297dda)
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/fsl/Kconfig7
-rw-r--r--sound/soc/fsl/imx-wm8962.c110
2 files changed, 117 insertions, 0 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 1d96da1e1e50..ea681cf2f929 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -301,6 +301,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_ES8328
tristate "SoC Audio support for i.MX boards with the ES8328 codec"
depends on OF && (I2C || SPI)
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 98b239e3070e..8f17a150cdb9 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)
{
@@ -513,6 +620,9 @@ static int imx_wm8962_probe(struct platform_device *pdev)
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);