aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-06 10:44:07 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-08 06:08:44 -0500
commitda18396f949ecaa45007d3aeb1b81bd6da092811 (patch)
treeb55566ec8ecc2ecd42a1caec23310e41b24ebfb9 /sound
parente38b9b7478d57701fbcbaafdde169aa1a88d0eca (diff)
ASoC: core: Allow digital mute for capture
Help avoid noise from the power up of the capture path propagating through into the start of the recording (especially noise caused by the ramp of microphone biases) by keeping the capture muted until after we've finished powering things up with DAPM in the same manner we do for playback. This allows us to take advantage of soft mute support in the hardware more effectively and is more consistent. The core code using the existing digital mute operation is updated to take advantage of this. Some additional cases in the soc-pcm code and suspend will need separate handling but these are less practically relevant than the main runtime stream start/stop case. Rather than refactor the digital mute function in every single driver a new operation is added for drivers taking advantage of this functionality, the old operation should be phased out over time. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by Vinod Koul <vinod.koul@intel.com> Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-compress.c19
-rw-r--r--sound/soc/soc-core.c12
-rw-r--r--sound/soc/soc-dapm.c6
-rw-r--r--sound/soc/soc-pcm.c7
4 files changed, 26 insertions, 18 deletions
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 35726cbf1f02..b5b3db71e253 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -116,12 +116,13 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
116 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 116 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
117 cpu_dai->playback_active--; 117 cpu_dai->playback_active--;
118 codec_dai->playback_active--; 118 codec_dai->playback_active--;
119 snd_soc_dai_digital_mute(codec_dai, 1);
120 } else { 119 } else {
121 cpu_dai->capture_active--; 120 cpu_dai->capture_active--;
122 codec_dai->capture_active--; 121 codec_dai->capture_active--;
123 } 122 }
124 123
124 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
125
125 cpu_dai->active--; 126 cpu_dai->active--;
126 codec_dai->active--; 127 codec_dai->active--;
127 codec->active--; 128 codec->active--;
@@ -178,15 +179,13 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
178 goto out; 179 goto out;
179 } 180 }
180 181
181 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 182 switch (cmd) {
182 switch (cmd) { 183 case SNDRV_PCM_TRIGGER_START:
183 case SNDRV_PCM_TRIGGER_START: 184 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
184 snd_soc_dai_digital_mute(codec_dai, 0); 185 break;
185 break; 186 case SNDRV_PCM_TRIGGER_STOP:
186 case SNDRV_PCM_TRIGGER_STOP: 187 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
187 snd_soc_dai_digital_mute(codec_dai, 1); 188 break;
188 break;
189 }
190 } 189 }
191 190
192out: 191out:
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2370063b5824..4eac22797893 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3540,12 +3540,20 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
3540 * snd_soc_dai_digital_mute - configure DAI system or master clock. 3540 * snd_soc_dai_digital_mute - configure DAI system or master clock.
3541 * @dai: DAI 3541 * @dai: DAI
3542 * @mute: mute enable 3542 * @mute: mute enable
3543 * @direction: stream to mute
3543 * 3544 *
3544 * Mutes the DAI DAC. 3545 * Mutes the DAI DAC.
3545 */ 3546 */
3546int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 3547int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
3548 int direction)
3547{ 3549{
3548 if (dai->driver && dai->driver->ops->digital_mute) 3550 if (!dai->driver)
3551 return -ENOTSUPP;
3552
3553 if (dai->driver->ops->mute_stream)
3554 return dai->driver->ops->mute_stream(dai, mute, direction);
3555 else if (direction == SNDRV_PCM_STREAM_PLAYBACK &&
3556 dai->driver->ops->digital_mute)
3549 return dai->driver->ops->digital_mute(dai, mute); 3557 return dai->driver->ops->digital_mute(dai, mute);
3550 else 3558 else
3551 return -ENOTSUPP; 3559 return -ENOTSUPP;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1e36bc81e5af..4d664f3df805 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -3247,14 +3247,16 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
3247 break; 3247 break;
3248 3248
3249 case SND_SOC_DAPM_POST_PMU: 3249 case SND_SOC_DAPM_POST_PMU:
3250 ret = snd_soc_dai_digital_mute(sink, 0); 3250 ret = snd_soc_dai_digital_mute(sink, 0,
3251 SNDRV_PCM_STREAM_PLAYBACK);
3251 if (ret != 0 && ret != -ENOTSUPP) 3252 if (ret != 0 && ret != -ENOTSUPP)
3252 dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret); 3253 dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
3253 ret = 0; 3254 ret = 0;
3254 break; 3255 break;
3255 3256
3256 case SND_SOC_DAPM_PRE_PMD: 3257 case SND_SOC_DAPM_PRE_PMD:
3257 ret = snd_soc_dai_digital_mute(sink, 1); 3258 ret = snd_soc_dai_digital_mute(sink, 1,
3259 SNDRV_PCM_STREAM_PLAYBACK);
3258 if (ret != 0 && ret != -ENOTSUPP) 3260 if (ret != 0 && ret != -ENOTSUPP)
3259 dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret); 3261 dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
3260 ret = 0; 3262 ret = 0;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index cf191e6aebbe..d675b4ae0df6 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -383,8 +383,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
383 /* Muting the DAC suppresses artifacts caused during digital 383 /* Muting the DAC suppresses artifacts caused during digital
384 * shutdown, for example from stopping clocks. 384 * shutdown, for example from stopping clocks.
385 */ 385 */
386 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 386 snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
387 snd_soc_dai_digital_mute(codec_dai, 1);
388 387
389 if (cpu_dai->driver->ops->shutdown) 388 if (cpu_dai->driver->ops->shutdown)
390 cpu_dai->driver->ops->shutdown(substream, cpu_dai); 389 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
@@ -488,7 +487,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
488 snd_soc_dapm_stream_event(rtd, substream->stream, 487 snd_soc_dapm_stream_event(rtd, substream->stream,
489 SND_SOC_DAPM_STREAM_START); 488 SND_SOC_DAPM_STREAM_START);
490 489
491 snd_soc_dai_digital_mute(codec_dai, 0); 490 snd_soc_dai_digital_mute(codec_dai, 0, substream->stream);
492 491
493out: 492out:
494 mutex_unlock(&rtd->pcm_mutex); 493 mutex_unlock(&rtd->pcm_mutex);
@@ -586,7 +585,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
586 585
587 /* apply codec digital mute */ 586 /* apply codec digital mute */
588 if (!codec->active) 587 if (!codec->active)
589 snd_soc_dai_digital_mute(codec_dai, 1); 588 snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
590 589
591 /* free any machine hw params */ 590 /* free any machine hw params */
592 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) 591 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)