diff options
author | Mark Brown <broonie@linaro.org> | 2014-03-06 04:07:39 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-03-06 04:07:39 -0500 |
commit | 6af5263ceaffc9d4403592dc81cd3b197702dc69 (patch) | |
tree | 4c144be49e1ade130571d0169e259e9966177962 | |
parent | 234c0b8fb0db790aaebec07d1d190e789d8ec7b9 (diff) | |
parent | 3d59400fe47e7e8bfb024cd1651433bef42e268e (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.h | 1 | ||||
-rw-r--r-- | include/sound/soc.h | 22 | ||||
-rw-r--r-- | sound/soc/codecs/adav80x.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic23.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/uda1380.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wl1273.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8711.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8753.c | 4 | ||||
-rw-r--r-- | sound/soc/soc-compress.c | 65 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 22 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 109 |
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, | |||
427 | struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | 427 | struct 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 | ||
430 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); | ||
431 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); | ||
432 | void 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 */ |
431 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 435 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
432 | int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); | 436 | int 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 | ||
1212 | static inline bool snd_soc_component_is_active( | ||
1213 | struct snd_soc_component *component) | ||
1214 | { | ||
1215 | return component->active != 0; | ||
1216 | } | ||
1217 | |||
1218 | static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) | ||
1219 | { | ||
1220 | return snd_soc_component_is_active(&codec->component); | ||
1221 | } | ||
1222 | |||
1205 | int snd_soc_util_init(void); | 1223 | int snd_soc_util_init(void); |
1206 | void snd_soc_util_exit(void); | 1224 | void 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 | */ |
3874 | static int snd_soc_register_dai(struct device *dev, | 3875 | static 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 | */ |
3953 | static int snd_soc_register_dais(struct device *dev, | 3957 | static 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 | */ | ||
47 | void 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 | */ | ||
78 | void 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 | */ | ||
108 | bool 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 | ||
380 | dynamic: | 460 | dynamic: |
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, |