diff options
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r-- | sound/soc/soc-pcm.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ee15337353fa..cdc860a5ff37 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <sound/core.h> @@ -77,6 +78,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; int ret = 0; + pm_runtime_get_sync(cpu_dai->dev); + pm_runtime_get_sync(codec_dai->dev); + pm_runtime_get_sync(platform->dev); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); /* startup the audio subsystem */ @@ -233,6 +238,11 @@ platform_err: cpu_dai->driver->ops->shutdown(substream, cpu_dai); out: mutex_unlock(&rtd->pcm_mutex); + + pm_runtime_put(platform->dev); + pm_runtime_put(codec_dai->dev); + pm_runtime_put(cpu_dai->dev); + return ret; } @@ -319,7 +329,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) cpu_dai->runtime = NULL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (unlikely(codec->ignore_pmdown_time)) { + if (codec->ignore_pmdown_time || + rtd->dai_link->ignore_pmdown_time) { /* powered down playback stream now */ snd_soc_dapm_stream_event(rtd, codec_dai->driver->playback.stream_name, @@ -338,6 +349,11 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) } mutex_unlock(&rtd->pcm_mutex); + + pm_runtime_put(platform->dev); + pm_runtime_put(codec_dai->dev); + pm_runtime_put(cpu_dai->dev); + return 0; } @@ -582,17 +598,6 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) return offset; } -/* ASoC PCM operations */ -static struct snd_pcm_ops soc_pcm_ops = { - .open = soc_pcm_open, - .close = soc_pcm_close, - .hw_params = soc_pcm_hw_params, - .hw_free = soc_pcm_hw_free, - .prepare = soc_pcm_prepare, - .trigger = soc_pcm_trigger, - .pointer = soc_pcm_pointer, -}; - /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { @@ -600,10 +605,19 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_pcm_ops *soc_pcm_ops = &rtd->ops; struct snd_pcm *pcm; char new_name[64]; int ret = 0, playback = 0, capture = 0; + soc_pcm_ops->open = soc_pcm_open; + soc_pcm_ops->close = soc_pcm_close; + soc_pcm_ops->hw_params = soc_pcm_hw_params; + soc_pcm_ops->hw_free = soc_pcm_hw_free; + soc_pcm_ops->prepare = soc_pcm_prepare; + soc_pcm_ops->trigger = soc_pcm_trigger; + soc_pcm_ops->pointer = soc_pcm_pointer; + /* check client and interface hw capabilities */ snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, codec_dai->name, num); @@ -627,20 +641,20 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->pcm = pcm; pcm->private_data = rtd; if (platform->driver->ops) { - soc_pcm_ops.mmap = platform->driver->ops->mmap; - soc_pcm_ops.pointer = platform->driver->ops->pointer; - soc_pcm_ops.ioctl = platform->driver->ops->ioctl; - soc_pcm_ops.copy = platform->driver->ops->copy; - soc_pcm_ops.silence = platform->driver->ops->silence; - soc_pcm_ops.ack = platform->driver->ops->ack; - soc_pcm_ops.page = platform->driver->ops->page; + soc_pcm_ops->mmap = platform->driver->ops->mmap; + soc_pcm_ops->pointer = platform->driver->ops->pointer; + soc_pcm_ops->ioctl = platform->driver->ops->ioctl; + soc_pcm_ops->copy = platform->driver->ops->copy; + soc_pcm_ops->silence = platform->driver->ops->silence; + soc_pcm_ops->ack = platform->driver->ops->ack; + soc_pcm_ops->page = platform->driver->ops->page; } if (playback) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, soc_pcm_ops); if (capture) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, soc_pcm_ops); if (platform->driver->pcm_new) { ret = platform->driver->pcm_new(rtd); |