diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-core.c | 33 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 11 |
2 files changed, 44 insertions, 0 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b38e0ee622df..1a4e97773c71 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -662,6 +662,8 @@ int snd_soc_suspend(struct device *dev) codec->cache_sync = 1; if (codec->using_regmap) regcache_mark_dirty(codec->control_data); + /* deactivate pins to sleep state */ + pinctrl_pm_select_sleep_state(codec->dev); break; default: dev_dbg(codec->dev, @@ -679,6 +681,9 @@ int snd_soc_suspend(struct device *dev) if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) cpu_dai->driver->suspend(cpu_dai); + + /* deactivate pins to sleep state */ + pinctrl_pm_select_sleep_state(cpu_dai->dev); } if (card->suspend_post) @@ -807,6 +812,16 @@ int snd_soc_resume(struct device *dev) if (list_empty(&card->codec_dev_list)) return 0; + /* activate pins from sleep state */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; + if (cpu_dai->active) + pinctrl_pm_select_default_state(cpu_dai->dev); + if (codec_dai->active) + pinctrl_pm_select_default_state(codec_dai->dev); + } + /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume @@ -1930,6 +1945,14 @@ int snd_soc_poweroff(struct device *dev) snd_soc_dapm_shutdown(card); + /* deactivate pins to sleep state */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; + pinctrl_pm_select_sleep_state(codec_dai->dev); + pinctrl_pm_select_sleep_state(cpu_dai->dev); + } + return 0; } EXPORT_SYMBOL_GPL(snd_soc_poweroff); @@ -3752,6 +3775,16 @@ int snd_soc_register_card(struct snd_soc_card *card) if (ret != 0) soc_cleanup_card_debugfs(card); + /* deactivate pins to sleep state */ + for (i = 0; i < card->num_rtd; i++) { + struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; + struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; + if (!codec_dai->active) + pinctrl_pm_select_sleep_state(codec_dai->dev); + if (!cpu_dai->active) + pinctrl_pm_select_sleep_state(cpu_dai->dev); + } + return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_card); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 591f0f3074c5..42782c01e413 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/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/workqueue.h> @@ -183,6 +184,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; int ret = 0; + pinctrl_pm_select_default_state(cpu_dai->dev); + pinctrl_pm_select_default_state(codec_dai->dev); pm_runtime_get_sync(cpu_dai->dev); pm_runtime_get_sync(codec_dai->dev); pm_runtime_get_sync(platform->dev); @@ -317,6 +320,10 @@ out: pm_runtime_put(platform->dev); pm_runtime_put(codec_dai->dev); pm_runtime_put(cpu_dai->dev); + if (!codec_dai->active) + pinctrl_pm_select_sleep_state(codec_dai->dev); + if (!cpu_dai->active) + pinctrl_pm_select_sleep_state(cpu_dai->dev); return ret; } @@ -426,6 +433,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) pm_runtime_put(platform->dev); pm_runtime_put(codec_dai->dev); pm_runtime_put(cpu_dai->dev); + if (!codec_dai->active) + pinctrl_pm_select_sleep_state(codec_dai->dev); + if (!cpu_dai->active) + pinctrl_pm_select_sleep_state(cpu_dai->dev); return 0; } |