aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-03-06 04:07:39 -0500
committerMark Brown <broonie@linaro.org>2014-03-06 04:07:39 -0500
commit6af5263ceaffc9d4403592dc81cd3b197702dc69 (patch)
tree4c144be49e1ade130571d0169e259e9966177962
parent234c0b8fb0db790aaebec07d1d190e789d8ec7b9 (diff)
parent3d59400fe47e7e8bfb024cd1651433bef42e268e (diff)
Merge branch 'topic/pcm' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-enum
Conflicts: include/sound/soc.h
-rw-r--r--include/sound/soc-dai.h1
-rw-r--r--include/sound/soc.h22
-rw-r--r--sound/soc/codecs/adav80x.c4
-rw-r--r--sound/soc/codecs/tlv320aic23.c2
-rw-r--r--sound/soc/codecs/tlv320dac33.c2
-rw-r--r--sound/soc/codecs/uda1380.c2
-rw-r--r--sound/soc/codecs/wl1273.c2
-rw-r--r--sound/soc/codecs/wm8711.c2
-rw-r--r--sound/soc/codecs/wm8753.c4
-rw-r--r--sound/soc/soc-compress.c65
-rw-r--r--sound/soc/soc-core.c22
-rw-r--r--sound/soc/soc-pcm.c109
12 files changed, 143 insertions, 94 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 71f27c403194..8763e539c487 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -270,6 +270,7 @@ struct snd_soc_dai {
270 /* parent platform/codec */ 270 /* parent platform/codec */
271 struct snd_soc_platform *platform; 271 struct snd_soc_platform *platform;
272 struct snd_soc_codec *codec; 272 struct snd_soc_codec *codec;
273 struct snd_soc_component *component;
273 274
274 struct snd_soc_card *card; 275 struct snd_soc_card *card;
275 276
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 08cb677b464b..5710f9e4b43f 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -427,6 +427,10 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
427struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, 427struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
428 const char *dai_link); 428 const char *dai_link);
429 429
430bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
431void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
432void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
433
430/* Utility functions to get clock rates from various things */ 434/* Utility functions to get clock rates from various things */
431int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); 435int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
432int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); 436int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -666,6 +670,11 @@ struct snd_soc_component {
666 const char *name; 670 const char *name;
667 int id; 671 int id;
668 struct device *dev; 672 struct device *dev;
673
674 unsigned int active;
675
676 unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
677
669 struct list_head list; 678 struct list_head list;
670 679
671 struct snd_soc_dai_driver *dai_drv; 680 struct snd_soc_dai_driver *dai_drv;
@@ -693,7 +702,6 @@ struct snd_soc_codec {
693 702
694 /* runtime */ 703 /* runtime */
695 struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ 704 struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
696 unsigned int active;
697 unsigned int cache_bypass:1; /* Suppress access to the cache */ 705 unsigned int cache_bypass:1; /* Suppress access to the cache */
698 unsigned int suspended:1; /* Codec is in suspend PM state */ 706 unsigned int suspended:1; /* Codec is in suspend PM state */
699 unsigned int probed:1; /* Codec has been probed */ 707 unsigned int probed:1; /* Codec has been probed */
@@ -719,7 +727,6 @@ struct snd_soc_codec {
719 727
720 /* dapm */ 728 /* dapm */
721 struct snd_soc_dapm_context dapm; 729 struct snd_soc_dapm_context dapm;
722 unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
723 730
724#ifdef CONFIG_DEBUG_FS 731#ifdef CONFIG_DEBUG_FS
725 struct dentry *debugfs_codec_root; 732 struct dentry *debugfs_codec_root;
@@ -1202,6 +1209,17 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
1202 return e->values[item]; 1209 return e->values[item];
1203} 1210}
1204 1211
1212static inline bool snd_soc_component_is_active(
1213 struct snd_soc_component *component)
1214{
1215 return component->active != 0;
1216}
1217
1218static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
1219{
1220 return snd_soc_component_is_active(&codec->component);
1221}
1222
1205int snd_soc_util_init(void); 1223int snd_soc_util_init(void);
1206void snd_soc_util_exit(void); 1224void snd_soc_util_exit(void);
1207 1225
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index ab790d5fe53d..f0f18ea680ac 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -727,7 +727,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
727 struct snd_soc_codec *codec = dai->codec; 727 struct snd_soc_codec *codec = dai->codec;
728 struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 728 struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
729 729
730 if (!codec->active || !adav80x->rate) 730 if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
731 return 0; 731 return 0;
732 732
733 return snd_pcm_hw_constraint_minmax(substream->runtime, 733 return snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -740,7 +740,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
740 struct snd_soc_codec *codec = dai->codec; 740 struct snd_soc_codec *codec = dai->codec;
741 struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); 741 struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
742 742
743 if (!codec->active) 743 if (!snd_soc_codec_is_active(codec))
744 adav80x->rate = 0; 744 adav80x->rate = 0;
745} 745}
746 746
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 5d430cc56f51..458a6aed203e 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
400 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); 400 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
401 401
402 /* deactivate */ 402 /* deactivate */
403 if (!codec->active) { 403 if (!snd_soc_codec_is_active(codec)) {
404 udelay(50); 404 udelay(50);
405 snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); 405 snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
406 } 406 }
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 4f358393d6d6..35b2d244e42e 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -461,7 +461,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
461 if (dac33->fifo_mode == ucontrol->value.integer.value[0]) 461 if (dac33->fifo_mode == ucontrol->value.integer.value[0])
462 return 0; 462 return 0;
463 /* Do not allow changes while stream is running*/ 463 /* Do not allow changes while stream is running*/
464 if (codec->active) 464 if (snd_soc_codec_is_active(codec))
465 return -EPERM; 465 return -EPERM;
466 466
467 if (ucontrol->value.integer.value[0] < 0 || 467 if (ucontrol->value.integer.value[0] < 0 ||
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 726df6d43c2b..8e3940dcff20 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
108 /* the interpolator & decimator regs must only be written when the 108 /* the interpolator & decimator regs must only be written when the
109 * codec DAI is active. 109 * codec DAI is active.
110 */ 110 */
111 if (!codec->active && (reg >= UDA1380_MVOL)) 111 if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL))
112 return 0; 112 return 0;
113 pr_debug("uda1380: hw write %x val %x\n", reg, value); 113 pr_debug("uda1380: hw write %x val %x\n", reg, value);
114 if (codec->hw_write(codec->control_data, data, 3) == 3) { 114 if (codec->hw_write(codec->control_data, data, 3) == 3) {
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index b7ab2ef567c8..47e96ff30064 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
197 return 0; 197 return 0;
198 198
199 /* Do not allow changes while stream is running */ 199 /* Do not allow changes while stream is running */
200 if (codec->active) 200 if (snd_soc_codec_is_active(codec))
201 return -EPERM; 201 return -EPERM;
202 202
203 if (ucontrol->value.integer.value[0] < 0 || 203 if (ucontrol->value.integer.value[0] < 0 ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index d99f948c513c..6efcc40a7cb3 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream,
201 struct snd_soc_codec *codec = dai->codec; 201 struct snd_soc_codec *codec = dai->codec;
202 202
203 /* deactivate */ 203 /* deactivate */
204 if (!codec->active) { 204 if (!snd_soc_codec_is_active(codec)) {
205 udelay(50); 205 udelay(50);
206 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 206 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
207 } 207 }
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index be85da93a268..5cf4bebc5d89 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
251 if (wm8753->dai_func == ucontrol->value.integer.value[0]) 251 if (wm8753->dai_func == ucontrol->value.integer.value[0])
252 return 0; 252 return 0;
253 253
254 if (codec->active) 254 if (snd_soc_codec_is_active(codec))
255 return -EBUSY; 255 return -EBUSY;
256 256
257 ioctl = snd_soc_read(codec, WM8753_IOCTL); 257 ioctl = snd_soc_read(codec, WM8753_IOCTL);
@@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
1314 /* the digital mute covers the HiFi and Voice DAC's on the WM8753. 1314 /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
1315 * make sure we check if they are not both active when we mute */ 1315 * make sure we check if they are not both active when we mute */
1316 if (mute && wm8753->dai_func == 1) { 1316 if (mute && wm8753->dai_func == 1) {
1317 if (!codec->active) 1317 if (!snd_soc_codec_is_active(codec))
1318 snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); 1318 snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
1319 } else { 1319 } else {
1320 if (mute) 1320 if (mute)
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 5e9690c85d8f..91083e6a6b38 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
30{ 30{
31 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 31 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
32 struct snd_soc_platform *platform = rtd->platform; 32 struct snd_soc_platform *platform = rtd->platform;
33 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
34 struct snd_soc_dai *codec_dai = rtd->codec_dai;
35 int ret = 0; 33 int ret = 0;
36 34
37 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 35 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
52 } 50 }
53 } 51 }
54 52
55 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 53 snd_soc_runtime_activate(rtd, cstream->direction);
56 cpu_dai->playback_active++;
57 codec_dai->playback_active++;
58 } else {
59 cpu_dai->capture_active++;
60 codec_dai->capture_active++;
61 }
62
63 cpu_dai->active++;
64 codec_dai->active++;
65 rtd->codec->active++;
66 54
67 mutex_unlock(&rtd->pcm_mutex); 55 mutex_unlock(&rtd->pcm_mutex);
68 56
@@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
81 struct snd_soc_pcm_runtime *fe = cstream->private_data; 69 struct snd_soc_pcm_runtime *fe = cstream->private_data;
82 struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; 70 struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
83 struct snd_soc_platform *platform = fe->platform; 71 struct snd_soc_platform *platform = fe->platform;
84 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
85 struct snd_soc_dai *codec_dai = fe->codec_dai;
86 struct snd_soc_dpcm *dpcm; 72 struct snd_soc_dpcm *dpcm;
87 struct snd_soc_dapm_widget_list *list; 73 struct snd_soc_dapm_widget_list *list;
88 int stream; 74 int stream;
@@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
140 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; 126 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
141 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 127 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
142 128
143 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 129 snd_soc_runtime_activate(fe, stream);
144 cpu_dai->playback_active++;
145 codec_dai->playback_active++;
146 } else {
147 cpu_dai->capture_active++;
148 codec_dai->capture_active++;
149 }
150
151 cpu_dai->active++;
152 codec_dai->active++;
153 fe->codec->active++;
154 130
155 mutex_unlock(&fe->card->mutex); 131 mutex_unlock(&fe->card->mutex);
156 132
@@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
202 struct snd_soc_platform *platform = rtd->platform; 178 struct snd_soc_platform *platform = rtd->platform;
203 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 179 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
204 struct snd_soc_dai *codec_dai = rtd->codec_dai; 180 struct snd_soc_dai *codec_dai = rtd->codec_dai;
205 struct snd_soc_codec *codec = rtd->codec; 181 int stream;
206 182
207 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 183 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
208 184
209 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 185 if (cstream->direction == SND_COMPRESS_PLAYBACK)
210 cpu_dai->playback_active--; 186 stream = SNDRV_PCM_STREAM_PLAYBACK;
211 codec_dai->playback_active--; 187 else
212 } else { 188 stream = SNDRV_PCM_STREAM_CAPTURE;
213 cpu_dai->capture_active--;
214 codec_dai->capture_active--;
215 }
216 189
217 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 190 snd_soc_runtime_deactivate(rtd, stream);
218 191
219 cpu_dai->active--; 192 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
220 codec_dai->active--;
221 codec->active--;
222 193
223 if (!cpu_dai->active) 194 if (!cpu_dai->active)
224 cpu_dai->rate = 0; 195 cpu_dai->rate = 0;
@@ -235,8 +206,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
235 cpu_dai->runtime = NULL; 206 cpu_dai->runtime = NULL;
236 207
237 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 208 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
238 if (!rtd->pmdown_time || codec->ignore_pmdown_time || 209 if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
239 rtd->dai_link->ignore_pmdown_time) {
240 snd_soc_dapm_stream_event(rtd, 210 snd_soc_dapm_stream_event(rtd,
241 SNDRV_PCM_STREAM_PLAYBACK, 211 SNDRV_PCM_STREAM_PLAYBACK,
242 SND_SOC_DAPM_STREAM_STOP); 212 SND_SOC_DAPM_STREAM_STOP);
@@ -261,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
261{ 231{
262 struct snd_soc_pcm_runtime *fe = cstream->private_data; 232 struct snd_soc_pcm_runtime *fe = cstream->private_data;
263 struct snd_soc_platform *platform = fe->platform; 233 struct snd_soc_platform *platform = fe->platform;
264 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
265 struct snd_soc_dai *codec_dai = fe->codec_dai;
266 struct snd_soc_dpcm *dpcm; 234 struct snd_soc_dpcm *dpcm;
267 int stream, ret; 235 int stream, ret;
268 236
269 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 237 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
270 238
271 if (cstream->direction == SND_COMPRESS_PLAYBACK) { 239 if (cstream->direction == SND_COMPRESS_PLAYBACK)
272 stream = SNDRV_PCM_STREAM_PLAYBACK; 240 stream = SNDRV_PCM_STREAM_PLAYBACK;
273 cpu_dai->playback_active--; 241 else
274 codec_dai->playback_active--;
275 } else {
276 stream = SNDRV_PCM_STREAM_CAPTURE; 242 stream = SNDRV_PCM_STREAM_CAPTURE;
277 cpu_dai->capture_active--;
278 codec_dai->capture_active--;
279 }
280 243
281 cpu_dai->active--; 244 snd_soc_runtime_deactivate(fe, stream);
282 codec_dai->active--;
283 fe->codec->active--;
284 245
285 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 246 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
286 247
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2ddc7a4939d2..1fa7dda2e2bf 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3869,11 +3869,13 @@ static inline char *fmt_multiple_name(struct device *dev,
3869/** 3869/**
3870 * snd_soc_register_dai - Register a DAI with the ASoC core 3870 * snd_soc_register_dai - Register a DAI with the ASoC core
3871 * 3871 *
3872 * @dai: DAI to register 3872 * @component: The component the DAIs are registered for
3873 * @dai_drv: DAI driver to use for the DAIs
3873 */ 3874 */
3874static int snd_soc_register_dai(struct device *dev, 3875static int snd_soc_register_dai(struct snd_soc_component *component,
3875 struct snd_soc_dai_driver *dai_drv) 3876 struct snd_soc_dai_driver *dai_drv)
3876{ 3877{
3878 struct device *dev = component->dev;
3877 struct snd_soc_codec *codec; 3879 struct snd_soc_codec *codec;
3878 struct snd_soc_dai *dai; 3880 struct snd_soc_dai *dai;
3879 3881
@@ -3890,6 +3892,7 @@ static int snd_soc_register_dai(struct device *dev,
3890 return -ENOMEM; 3892 return -ENOMEM;
3891 } 3893 }
3892 3894
3895 dai->component = component;
3893 dai->dev = dev; 3896 dai->dev = dev;
3894 dai->driver = dai_drv; 3897 dai->driver = dai_drv;
3895 dai->dapm.dev = dev; 3898 dai->dapm.dev = dev;
@@ -3947,12 +3950,14 @@ found:
3947/** 3950/**
3948 * snd_soc_register_dais - Register multiple DAIs with the ASoC core 3951 * snd_soc_register_dais - Register multiple DAIs with the ASoC core
3949 * 3952 *
3950 * @dai: Array of DAIs to register 3953 * @component: The component the DAIs are registered for
3954 * @dai_drv: DAI driver to use for the DAIs
3951 * @count: Number of DAIs 3955 * @count: Number of DAIs
3952 */ 3956 */
3953static int snd_soc_register_dais(struct device *dev, 3957static int snd_soc_register_dais(struct snd_soc_component *component,
3954 struct snd_soc_dai_driver *dai_drv, size_t count) 3958 struct snd_soc_dai_driver *dai_drv, size_t count)
3955{ 3959{
3960 struct device *dev = component->dev;
3956 struct snd_soc_codec *codec; 3961 struct snd_soc_codec *codec;
3957 struct snd_soc_dai *dai; 3962 struct snd_soc_dai *dai;
3958 int i, ret = 0; 3963 int i, ret = 0;
@@ -3975,6 +3980,7 @@ static int snd_soc_register_dais(struct device *dev,
3975 goto err; 3980 goto err;
3976 } 3981 }
3977 3982
3983 dai->component = component;
3978 dai->dev = dev; 3984 dai->dev = dev;
3979 dai->driver = &dai_drv[i]; 3985 dai->driver = &dai_drv[i];
3980 if (dai->driver->id) 3986 if (dai->driver->id)
@@ -4071,9 +4077,9 @@ __snd_soc_register_component(struct device *dev,
4071 * since it had been used snd_soc_register_dais(), 4077 * since it had been used snd_soc_register_dais(),
4072 */ 4078 */
4073 if ((1 == num_dai) && allow_single_dai) 4079 if ((1 == num_dai) && allow_single_dai)
4074 ret = snd_soc_register_dai(dev, dai_drv); 4080 ret = snd_soc_register_dai(cmpnt, dai_drv);
4075 else 4081 else
4076 ret = snd_soc_register_dais(dev, dai_drv, num_dai); 4082 ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai);
4077 if (ret < 0) { 4083 if (ret < 0) {
4078 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); 4084 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
4079 goto error_component_name; 4085 goto error_component_name;
@@ -4106,6 +4112,8 @@ int snd_soc_register_component(struct device *dev,
4106 return -ENOMEM; 4112 return -ENOMEM;
4107 } 4113 }
4108 4114
4115 cmpnt->ignore_pmdown_time = true;
4116
4109 return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, 4117 return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
4110 dai_drv, num_dai, true); 4118 dai_drv, num_dai, true);
4111} 4119}
@@ -4304,7 +4312,7 @@ int snd_soc_register_codec(struct device *dev,
4304 codec->volatile_register = codec_drv->volatile_register; 4312 codec->volatile_register = codec_drv->volatile_register;
4305 codec->readable_register = codec_drv->readable_register; 4313 codec->readable_register = codec_drv->readable_register;
4306 codec->writable_register = codec_drv->writable_register; 4314 codec->writable_register = codec_drv->writable_register;
4307 codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; 4315 codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
4308 codec->dapm.bias_level = SND_SOC_BIAS_OFF; 4316 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
4309 codec->dapm.dev = dev; 4317 codec->dapm.dev = dev;
4310 codec->dapm.codec = codec; 4318 codec->dapm.codec = codec;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 47e1ce771e65..2cedf09f6d96 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -35,6 +35,86 @@
35#define DPCM_MAX_BE_USERS 8 35#define DPCM_MAX_BE_USERS 8
36 36
37/** 37/**
38 * snd_soc_runtime_activate() - Increment active count for PCM runtime components
39 * @rtd: ASoC PCM runtime that is activated
40 * @stream: Direction of the PCM stream
41 *
42 * Increments the active count for all the DAIs and components attached to a PCM
43 * runtime. Should typically be called when a stream is opened.
44 *
45 * Must be called with the rtd->pcm_mutex being held
46 */
47void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
48{
49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
50 struct snd_soc_dai *codec_dai = rtd->codec_dai;
51
52 lockdep_assert_held(&rtd->pcm_mutex);
53
54 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
55 cpu_dai->playback_active++;
56 codec_dai->playback_active++;
57 } else {
58 cpu_dai->capture_active++;
59 codec_dai->capture_active++;
60 }
61
62 cpu_dai->active++;
63 codec_dai->active++;
64 cpu_dai->component->active++;
65 codec_dai->component->active++;
66}
67
68/**
69 * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components
70 * @rtd: ASoC PCM runtime that is deactivated
71 * @stream: Direction of the PCM stream
72 *
73 * Decrements the active count for all the DAIs and components attached to a PCM
74 * runtime. Should typically be called when a stream is closed.
75 *
76 * Must be called with the rtd->pcm_mutex being held
77 */
78void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
79{
80 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82
83 lockdep_assert_held(&rtd->pcm_mutex);
84
85 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
86 cpu_dai->playback_active--;
87 codec_dai->playback_active--;
88 } else {
89 cpu_dai->capture_active--;
90 codec_dai->capture_active--;
91 }
92
93 cpu_dai->active--;
94 codec_dai->active--;
95 cpu_dai->component->active--;
96 codec_dai->component->active--;
97}
98
99/**
100 * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
101 * @rtd: The ASoC PCM runtime that should be checked.
102 *
103 * This function checks whether the power down delay should be ignored for a
104 * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has
105 * been configured to ignore the delay, or if none of the components benefits
106 * from having the delay.
107 */
108bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
109{
110 if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
111 return true;
112
113 return rtd->cpu_dai->component->ignore_pmdown_time &&
114 rtd->codec_dai->component->ignore_pmdown_time;
115}
116
117/**
38 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters 118 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
39 * @substream: the pcm substream 119 * @substream: the pcm substream
40 * @hw: the hardware parameters 120 * @hw: the hardware parameters
@@ -378,16 +458,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
378 runtime->hw.rate_max); 458 runtime->hw.rate_max);
379 459
380dynamic: 460dynamic:
381 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 461
382 cpu_dai->playback_active++; 462 snd_soc_runtime_activate(rtd, substream->stream);
383 codec_dai->playback_active++; 463
384 } else {
385 cpu_dai->capture_active++;
386 codec_dai->capture_active++;
387 }
388 cpu_dai->active++;
389 codec_dai->active++;
390 rtd->codec->active++;
391 mutex_unlock(&rtd->pcm_mutex); 464 mutex_unlock(&rtd->pcm_mutex);
392 return 0; 465 return 0;
393 466
@@ -459,21 +532,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
459 struct snd_soc_platform *platform = rtd->platform; 532 struct snd_soc_platform *platform = rtd->platform;
460 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 533 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
461 struct snd_soc_dai *codec_dai = rtd->codec_dai; 534 struct snd_soc_dai *codec_dai = rtd->codec_dai;
462 struct snd_soc_codec *codec = rtd->codec;
463 535
464 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 536 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
465 537
466 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 538 snd_soc_runtime_deactivate(rtd, substream->stream);
467 cpu_dai->playback_active--;
468 codec_dai->playback_active--;
469 } else {
470 cpu_dai->capture_active--;
471 codec_dai->capture_active--;
472 }
473
474 cpu_dai->active--;
475 codec_dai->active--;
476 codec->active--;
477 539
478 /* clear the corresponding DAIs rate when inactive */ 540 /* clear the corresponding DAIs rate when inactive */
479 if (!cpu_dai->active) 541 if (!cpu_dai->active)
@@ -496,8 +558,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
496 cpu_dai->runtime = NULL; 558 cpu_dai->runtime = NULL;
497 559
498 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 560 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
499 if (!rtd->pmdown_time || codec->ignore_pmdown_time || 561 if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
500 rtd->dai_link->ignore_pmdown_time) {
501 /* powered down playback stream now */ 562 /* powered down playback stream now */
502 snd_soc_dapm_stream_event(rtd, 563 snd_soc_dapm_stream_event(rtd,
503 SNDRV_PCM_STREAM_PLAYBACK, 564 SNDRV_PCM_STREAM_PLAYBACK,