diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-12-13 08:54:53 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-12-13 08:54:53 -0500 |
commit | afdcd431cebe3498db9aa963c780fdd5099917ec (patch) | |
tree | 16d9155e136f0df56689eead95cf44935aab2a0c /sound | |
parent | c29cb5eb8157a0049c882672a7f941261f23ea34 (diff) | |
parent | e20ab019e28dcf09c2727aa69e2a073ed66718b3 (diff) |
Merge tag 'asoc-v3.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v3.13
A few driver and error handling fixes plus a fix to ensure that we
mute streams when we should. The Atmel trigger addition is a fix to
ensure that we do the correct sequence of interactions with the
hardware.
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/atmel/atmel_ssc_dai.c | 30 | ||||
-rw-r--r-- | sound/soc/atmel/sam9x5_wm8731.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8962.c | 13 | ||||
-rw-r--r-- | sound/soc/fsl/imx-wm8962.c | 2 | ||||
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 38 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 5 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.c | 6 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.c | 10 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 6 |
9 files changed, 84 insertions, 28 deletions
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 8697cedccd21..1ead3c977a51 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, | |||
648 | 648 | ||
649 | dma_params = ssc_p->dma_params[dir]; | 649 | dma_params = ssc_p->dma_params[dir]; |
650 | 650 | ||
651 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | 651 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); |
652 | ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); | 652 | ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); |
653 | 653 | ||
654 | pr_debug("%s enabled SSC_SR=0x%08x\n", | 654 | pr_debug("%s enabled SSC_SR=0x%08x\n", |
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | |||
657 | return 0; | 657 | return 0; |
658 | } | 658 | } |
659 | 659 | ||
660 | static int atmel_ssc_trigger(struct snd_pcm_substream *substream, | ||
661 | int cmd, struct snd_soc_dai *dai) | ||
662 | { | ||
663 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; | ||
664 | struct atmel_pcm_dma_params *dma_params; | ||
665 | int dir; | ||
666 | |||
667 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
668 | dir = 0; | ||
669 | else | ||
670 | dir = 1; | ||
671 | |||
672 | dma_params = ssc_p->dma_params[dir]; | ||
673 | |||
674 | switch (cmd) { | ||
675 | case SNDRV_PCM_TRIGGER_START: | ||
676 | case SNDRV_PCM_TRIGGER_RESUME: | ||
677 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
678 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | ||
679 | break; | ||
680 | default: | ||
681 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); | ||
682 | break; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | } | ||
660 | 687 | ||
661 | #ifdef CONFIG_PM | 688 | #ifdef CONFIG_PM |
662 | static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) | 689 | 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 = { | |||
731 | .startup = atmel_ssc_startup, | 758 | .startup = atmel_ssc_startup, |
732 | .shutdown = atmel_ssc_shutdown, | 759 | .shutdown = atmel_ssc_shutdown, |
733 | .prepare = atmel_ssc_prepare, | 760 | .prepare = atmel_ssc_prepare, |
761 | .trigger = atmel_ssc_trigger, | ||
734 | .hw_params = atmel_ssc_hw_params, | 762 | .hw_params = atmel_ssc_hw_params, |
735 | .set_fmt = atmel_ssc_set_dai_fmt, | 763 | .set_fmt = atmel_ssc_set_dai_fmt, |
736 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, | 764 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, |
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 1b372283bd01..7d6a9055874b 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) | |||
109 | dai->stream_name = "WM8731 PCM"; | 109 | dai->stream_name = "WM8731 PCM"; |
110 | dai->codec_dai_name = "wm8731-hifi"; | 110 | dai->codec_dai_name = "wm8731-hifi"; |
111 | dai->init = sam9x5_wm8731_init; | 111 | dai->init = sam9x5_wm8731_init; |
112 | dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 112 | dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF |
113 | | SND_SOC_DAIFMT_CBM_CFM; | 113 | | SND_SOC_DAIFMT_CBM_CFM; |
114 | 114 | ||
115 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); | 115 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 543c5c2631b6..0f17ed3e29f4 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) | |||
2439 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | 2439 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, |
2440 | WM8962_SYSCLK_RATE_MASK, clocking4); | 2440 | WM8962_SYSCLK_RATE_MASK, clocking4); |
2441 | 2441 | ||
2442 | /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK. | ||
2443 | * So we here provisionally enable it and then disable it afterward | ||
2444 | * if current bias_level hasn't reached SND_SOC_BIAS_ON. | ||
2445 | */ | ||
2446 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | ||
2447 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
2448 | WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); | ||
2449 | |||
2442 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); | 2450 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); |
2451 | |||
2452 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | ||
2453 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
2454 | WM8962_SYSCLK_ENA_MASK, 0); | ||
2455 | |||
2443 | if (dspclk < 0) { | 2456 | if (dspclk < 0) { |
2444 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); | 2457 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); |
2445 | return; | 2458 | return; |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 61e48852b9e8..3fd76bc391de 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, | |||
130 | break; | 130 | break; |
131 | } | 131 | } |
132 | 132 | ||
133 | dapm->bias_level = level; | ||
134 | |||
135 | return 0; | 133 | return 0; |
136 | } | 134 | } |
137 | 135 | ||
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index cbc9c96ce1f4..41949af3baae 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | |||
305 | } | 305 | } |
306 | } | 306 | } |
307 | 307 | ||
308 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) | ||
309 | { | ||
310 | unsigned int i; | ||
311 | |||
312 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; | ||
313 | i++) { | ||
314 | if (!pcm->chan[i]) | ||
315 | continue; | ||
316 | dma_release_channel(pcm->chan[i]); | ||
317 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | |||
308 | /** | 322 | /** |
309 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device | 323 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device |
310 | * @dev: The parent device for the PCM device | 324 | * @dev: The parent device for the PCM device |
@@ -315,6 +329,7 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
315 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | 329 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
316 | { | 330 | { |
317 | struct dmaengine_pcm *pcm; | 331 | struct dmaengine_pcm *pcm; |
332 | int ret; | ||
318 | 333 | ||
319 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 334 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
320 | if (!pcm) | 335 | if (!pcm) |
@@ -326,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
326 | dmaengine_pcm_request_chan_of(pcm, dev); | 341 | dmaengine_pcm_request_chan_of(pcm, dev); |
327 | 342 | ||
328 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | 343 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
329 | return snd_soc_add_platform(dev, &pcm->platform, | 344 | ret = snd_soc_add_platform(dev, &pcm->platform, |
330 | &dmaengine_no_residue_pcm_platform); | 345 | &dmaengine_no_residue_pcm_platform); |
331 | else | 346 | else |
332 | return snd_soc_add_platform(dev, &pcm->platform, | 347 | ret = snd_soc_add_platform(dev, &pcm->platform, |
333 | &dmaengine_pcm_platform); | 348 | &dmaengine_pcm_platform); |
349 | if (ret) | ||
350 | goto err_free_dma; | ||
351 | |||
352 | return 0; | ||
353 | |||
354 | err_free_dma: | ||
355 | dmaengine_pcm_release_chan(pcm); | ||
356 | kfree(pcm); | ||
357 | return ret; | ||
334 | } | 358 | } |
335 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); | 359 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); |
336 | 360 | ||
@@ -345,7 +369,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
345 | { | 369 | { |
346 | struct snd_soc_platform *platform; | 370 | struct snd_soc_platform *platform; |
347 | struct dmaengine_pcm *pcm; | 371 | struct dmaengine_pcm *pcm; |
348 | unsigned int i; | ||
349 | 372 | ||
350 | platform = snd_soc_lookup_platform(dev); | 373 | platform = snd_soc_lookup_platform(dev); |
351 | if (!platform) | 374 | if (!platform) |
@@ -353,15 +376,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
353 | 376 | ||
354 | pcm = soc_platform_to_pcm(platform); | 377 | pcm = soc_platform_to_pcm(platform); |
355 | 378 | ||
356 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
357 | if (pcm->chan[i]) { | ||
358 | dma_release_channel(pcm->chan[i]); | ||
359 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | snd_soc_remove_platform(platform); | 379 | snd_soc_remove_platform(platform); |
380 | dmaengine_pcm_release_chan(pcm); | ||
365 | kfree(pcm); | 381 | kfree(pcm); |
366 | } | 382 | } |
367 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); | 383 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 11a90cd027fa..891b9a9bcbf8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -600,12 +600,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
600 | struct snd_soc_platform *platform = rtd->platform; | 600 | struct snd_soc_platform *platform = rtd->platform; |
601 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 601 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
602 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 602 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
603 | struct snd_soc_codec *codec = rtd->codec; | 603 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
604 | 604 | ||
605 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 605 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
606 | 606 | ||
607 | /* apply codec digital mute */ | 607 | /* apply codec digital mute */ |
608 | if (!codec->active) | 608 | if ((playback && codec_dai->playback_active == 1) || |
609 | (!playback && codec_dai->capture_active == 1)) | ||
609 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | 610 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); |
610 | 611 | ||
611 | /* free any machine hw params */ | 612 | /* free any machine hw params */ |
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 364bf6a907e1..8c819f811470 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, | |||
74 | unsigned int fmt) | 74 | unsigned int fmt) |
75 | { | 75 | { |
76 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 76 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
77 | unsigned int mask, val; | 77 | unsigned int mask = 0, val = 0; |
78 | 78 | ||
79 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 79 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
80 | case SND_SOC_DAIFMT_NB_NF: | 80 | case SND_SOC_DAIFMT_NB_NF: |
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | } | 84 | } |
85 | 85 | ||
86 | mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; | 86 | mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE; |
87 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 87 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
88 | case SND_SOC_DAIFMT_CBS_CFS: | 88 | case SND_SOC_DAIFMT_CBS_CFS: |
89 | val = TEGRA20_I2S_CTRL_MASTER_ENABLE; | 89 | val |= TEGRA20_I2S_CTRL_MASTER_ENABLE; |
90 | break; | 90 | break; |
91 | case SND_SOC_DAIFMT_CBM_CFM: | 91 | case SND_SOC_DAIFMT_CBM_CFM: |
92 | break; | 92 | break; |
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 08bc6931c7c7..8c7c1028e579 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, | |||
67 | { | 67 | { |
68 | struct device *dev = dai->dev; | 68 | struct device *dev = dai->dev; |
69 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); | 69 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); |
70 | unsigned int mask, val; | 70 | unsigned int mask = 0, val = 0; |
71 | int ret, spdifclock; | 71 | int ret, spdifclock; |
72 | 72 | ||
73 | mask = TEGRA20_SPDIF_CTRL_PACK | | 73 | mask |= TEGRA20_SPDIF_CTRL_PACK | |
74 | TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; | 74 | TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; |
75 | switch (params_format(params)) { | 75 | switch (params_format(params)) { |
76 | case SNDRV_PCM_FORMAT_S16_LE: | 76 | case SNDRV_PCM_FORMAT_S16_LE: |
77 | val = TEGRA20_SPDIF_CTRL_PACK | | 77 | val |= TEGRA20_SPDIF_CTRL_PACK | |
78 | TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; | 78 | TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; |
79 | break; | 79 | break; |
80 | default: | 80 | default: |
81 | return -EINVAL; | 81 | return -EINVAL; |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 231a785b3921..02247fee1cf7 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, | |||
118 | unsigned int fmt) | 118 | unsigned int fmt) |
119 | { | 119 | { |
120 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 120 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
121 | unsigned int mask, val; | 121 | unsigned int mask = 0, val = 0; |
122 | 122 | ||
123 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 123 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
124 | case SND_SOC_DAIFMT_NB_NF: | 124 | case SND_SOC_DAIFMT_NB_NF: |
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
127 | return -EINVAL; | 127 | return -EINVAL; |
128 | } | 128 | } |
129 | 129 | ||
130 | mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; | 130 | mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE; |
131 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 131 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
132 | case SND_SOC_DAIFMT_CBS_CFS: | 132 | case SND_SOC_DAIFMT_CBS_CFS: |
133 | val = TEGRA30_I2S_CTRL_MASTER_ENABLE; | 133 | val |= TEGRA30_I2S_CTRL_MASTER_ENABLE; |
134 | break; | 134 | break; |
135 | case SND_SOC_DAIFMT_CBM_CFM: | 135 | case SND_SOC_DAIFMT_CBM_CFM: |
136 | break; | 136 | break; |