From a8f1f100ad994725a8295f6997524c57c72e06f5 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 4 Dec 2013 10:37:03 +0800 Subject: ASoC: atmel_ssc_dai: add dai trigger ops According to the SSC specifiation, it should be enabled after DMA is enabled. So, add trigger operation to make sure the right sequence. Signed-off-by: Bo Shen Tested-by: Richard Genoud Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_ssc_dai.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 8697cedccd2..1ead3c977a5 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, dma_params = ssc_p->dma_params[dir]; - ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); + ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); pr_debug("%s enabled SSC_SR=0x%08x\n", @@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, return 0; } +static int atmel_ssc_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; + struct atmel_pcm_dma_params *dma_params; + int dir; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dir = 0; + else + dir = 1; + + dma_params = ssc_p->dma_params[dir]; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); + break; + default: + ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); + break; + } + + return 0; +} #ifdef CONFIG_PM static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) @@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { .startup = atmel_ssc_startup, .shutdown = atmel_ssc_shutdown, .prepare = atmel_ssc_prepare, + .trigger = atmel_ssc_trigger, .hw_params = atmel_ssc_hw_params, .set_fmt = atmel_ssc_set_dai_fmt, .set_clkdiv = atmel_ssc_set_dai_clkdiv, -- cgit v1.2.3-70-g09d2 From bc567a93502275755492141524935269dcf0ea1b Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 4 Dec 2013 10:37:04 +0800 Subject: ASoC: sam9x5_wm8731: change to work in DSP A mode Change sam9x5 with wm8731 work in DSP A mode, this will fix the left/right channel swap issue. Signed-off-by: Bo Shen Tested-by: Richard Genoud Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 1b372283bd0..7d6a9055874 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -109,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) dai->stream_name = "WM8731 PCM"; dai->codec_dai_name = "wm8731-hifi"; dai->init = sam9x5_wm8731_init; - dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; ret = snd_soc_of_parse_card_name(card, "atmel,model"); -- cgit v1.2.3-70-g09d2 From 75704ecfbb4124139b78b71dd603f05d61abe689 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 4 Dec 2013 17:22:16 +0800 Subject: ASoC: wm8962: Enable SYSCLK provisonally before fetching generated DSPCLK_DIV DSPCLK_DIV can be only generated correctly after enabling SYSCLK. But if the current bias_level hasn't reached SND_SOC_BIAS_ON, DAPM won't enable SYSCLK, which would cause the calculation result from DSPCLK_DIV invalid since bit DSPCLK_DIV will be finally turned to its true value after DAPM enables SYSCLK while the driver won't calculate it again for the current instance. In this circumstance, a playback which needs non-zero DSPCLK_DIV would be distorted due to unexpected clock frequency resulted from an invalid DSPCLK_DIV value. So this patch provisionally enables the SYSCLK to get a valid DSPCLK_DIV for calculation and then disables it afterward. Signed-off-by: Nicolin Chen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 543c5c2631b..0f17ed3e29f 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8962_CLOCKING_4, WM8962_SYSCLK_RATE_MASK, clocking4); + /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK. + * So we here provisionally enable it and then disable it afterward + * if current bias_level hasn't reached SND_SOC_BIAS_ON. + */ + if (codec->dapm.bias_level != SND_SOC_BIAS_ON) + snd_soc_update_bits(codec, WM8962_CLOCKING2, + WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); + dspclk = snd_soc_read(codec, WM8962_CLOCKING1); + + if (codec->dapm.bias_level != SND_SOC_BIAS_ON) + snd_soc_update_bits(codec, WM8962_CLOCKING2, + WM8962_SYSCLK_ENA_MASK, 0); + if (dspclk < 0) { dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); return; -- cgit v1.2.3-70-g09d2 From 241bf43321a10815225f477bba96a42285a2da73 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Dec 2013 13:34:50 -0700 Subject: ASoC: tegra: fix uninitialized variables in set_fmt In tegra*_i2s_set_fmt(), in the (fmt == SND_SOC_DAIFMT_CBM_CFM) case, "val" is never assigned to, but left uninitialized. The other case does initialized it. Fix this by initializing val at the start of the function, and only ever ORing into it. Update the handling of "mask" so it works the same way for consistency. Update tegra20_spdif.c to use the same code-style for consistency, even though it doesn't happen to suffer from the same problem at present. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Signed-off-by: Mark Brown Fixes: 0f163546a772 ("ASoC: tegra: use regmap more directly") Cc: --- sound/soc/tegra/tegra20_i2s.c | 6 +++--- sound/soc/tegra/tegra20_spdif.c | 10 +++++----- sound/soc/tegra/tegra30_i2s.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 364bf6a907e..8c819f81147 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); - unsigned int mask, val; + unsigned int mask = 0, val = 0; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; + mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - val = TEGRA20_I2S_CTRL_MASTER_ENABLE; + val |= TEGRA20_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 08bc6931c7c..8c7c1028e57 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); - unsigned int mask, val; + unsigned int mask = 0, val = 0; int ret, spdifclock; - mask = TEGRA20_SPDIF_CTRL_PACK | - TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; + mask |= TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - val = TEGRA20_SPDIF_CTRL_PACK | - TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; + val |= TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; break; default: return -EINVAL; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 231a785b392..02247fee1cf 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); - unsigned int mask, val; + unsigned int mask = 0, val = 0; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; + mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - val = TEGRA30_I2S_CTRL_MASTER_ENABLE; + val |= TEGRA30_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; -- cgit v1.2.3-70-g09d2 From 5dfc03f141993c101c626c84d639019e98a4f39c Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Fri, 6 Dec 2013 23:38:28 +0800 Subject: ASoC: fsl: imx-wm8962: Don't update bias_level in machine driver If we update it here, the set_bias_level() of Codec driver won't be normally called and we will then miss some essential procedures in set_bias_level() of the Codec driver. Thus drop it. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/imx-wm8962.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 72064e99568..72718e19a3c 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card, break; } - dapm->bias_level = level; - return 0; } -- cgit v1.2.3-70-g09d2