aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-01-20 09:48:55 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-20 09:48:55 -0500
commit7552f34a790069a008bd3e2ab4c0954b30c2f63b (patch)
treed51ab23d4d59248c969c25bb2fc14f45158ff5ae
parent258753361534a40ad7180c742da813fc659e427b (diff)
parentac6d7c48e3a5e82e876114b9ca0b489e96997743 (diff)
Merge tag 'asoc-v3.14-3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Last updates for the merge window A couple more fixes plus some extensions to DPCM for use with compressed audio from Liam which arrived just after my previous pull request.
-rw-r--r--include/sound/soc-dpcm.h22
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-compress.c301
-rw-r--r--sound/soc/soc-dapm.c11
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c9
-rw-r--r--sound/soc/soc-pcm.c29
6 files changed, 347 insertions, 26 deletions
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 047d657c331c..2883a7a6f9f3 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -11,6 +11,7 @@
11#ifndef __LINUX_SND_SOC_DPCM_H 11#ifndef __LINUX_SND_SOC_DPCM_H
12#define __LINUX_SND_SOC_DPCM_H 12#define __LINUX_SND_SOC_DPCM_H
13 13
14#include <linux/slab.h>
14#include <linux/list.h> 15#include <linux/list.h>
15#include <sound/pcm.h> 16#include <sound/pcm.h>
16 17
@@ -135,4 +136,25 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
135int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); 136int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
136int soc_dpcm_runtime_update(struct snd_soc_card *); 137int soc_dpcm_runtime_update(struct snd_soc_card *);
137 138
139int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
140 int stream, struct snd_soc_dapm_widget_list **list_);
141int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
142 int stream, struct snd_soc_dapm_widget_list **list, int new);
143int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
144int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream);
145void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
146void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
147int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
148int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
149int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
150int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
151int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
152 int event);
153
154static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
155{
156 kfree(*list);
157}
158
159
138#endif 160#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 03ce45bf8ade..9a001472b96a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1042,6 +1042,7 @@ struct snd_soc_pcm_runtime {
1042 1042
1043 /* Dynamic PCM BE runtime data */ 1043 /* Dynamic PCM BE runtime data */
1044 struct snd_soc_dpcm_runtime dpcm[2]; 1044 struct snd_soc_dpcm_runtime dpcm[2];
1045 int fe_compr;
1045 1046
1046 long pmdown_time; 1047 long pmdown_time;
1047 unsigned char pop_wait:1; 1048 unsigned char pop_wait:1;
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 53c9ecdd119f..5e9690c85d8f 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -24,6 +24,7 @@
24#include <sound/compress_driver.h> 24#include <sound/compress_driver.h>
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/initval.h> 26#include <sound/initval.h>
27#include <sound/soc-dpcm.h>
27 28
28static int soc_compr_open(struct snd_compr_stream *cstream) 29static int soc_compr_open(struct snd_compr_stream *cstream)
29{ 30{
@@ -75,6 +76,98 @@ out:
75 return ret; 76 return ret;
76} 77}
77 78
79static int soc_compr_open_fe(struct snd_compr_stream *cstream)
80{
81 struct snd_soc_pcm_runtime *fe = cstream->private_data;
82 struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
83 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;
87 struct snd_soc_dapm_widget_list *list;
88 int stream;
89 int ret = 0;
90
91 if (cstream->direction == SND_COMPRESS_PLAYBACK)
92 stream = SNDRV_PCM_STREAM_PLAYBACK;
93 else
94 stream = SNDRV_PCM_STREAM_CAPTURE;
95
96 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
97
98 if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
99 ret = platform->driver->compr_ops->open(cstream);
100 if (ret < 0) {
101 pr_err("compress asoc: can't open platform %s\n", platform->name);
102 goto out;
103 }
104 }
105
106 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
107 ret = fe->dai_link->compr_ops->startup(cstream);
108 if (ret < 0) {
109 pr_err("compress asoc: %s startup failed\n", fe->dai_link->name);
110 goto machine_err;
111 }
112 }
113
114 fe->dpcm[stream].runtime = fe_substream->runtime;
115
116 if (dpcm_path_get(fe, stream, &list) <= 0) {
117 dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
118 fe->dai_link->name, stream ? "capture" : "playback");
119 }
120
121 /* calculate valid and active FE <-> BE dpcms */
122 dpcm_process_paths(fe, stream, &list, 1);
123
124 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
125
126 ret = dpcm_be_dai_startup(fe, stream);
127 if (ret < 0) {
128 /* clean up all links */
129 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
130 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
131
132 dpcm_be_disconnect(fe, stream);
133 fe->dpcm[stream].runtime = NULL;
134 goto fe_err;
135 }
136
137 dpcm_clear_pending_state(fe, stream);
138 dpcm_path_put(&list);
139
140 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
141 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
142
143 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
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
155 mutex_unlock(&fe->card->mutex);
156
157 return 0;
158
159fe_err:
160 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
161 fe->dai_link->compr_ops->shutdown(cstream);
162machine_err:
163 if (platform->driver->compr_ops && platform->driver->compr_ops->free)
164 platform->driver->compr_ops->free(cstream);
165out:
166 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
167 mutex_unlock(&fe->card->mutex);
168 return ret;
169}
170
78/* 171/*
79 * Power down the audio subsystem pmdown_time msecs after close is called. 172 * Power down the audio subsystem pmdown_time msecs after close is called.
80 * This is to ensure there are no pops or clicks in between any music tracks 173 * This is to ensure there are no pops or clicks in between any music tracks
@@ -164,6 +257,65 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
164 return 0; 257 return 0;
165} 258}
166 259
260static int soc_compr_free_fe(struct snd_compr_stream *cstream)
261{
262 struct snd_soc_pcm_runtime *fe = cstream->private_data;
263 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;
267 int stream, ret;
268
269 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
270
271 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
272 stream = SNDRV_PCM_STREAM_PLAYBACK;
273 cpu_dai->playback_active--;
274 codec_dai->playback_active--;
275 } else {
276 stream = SNDRV_PCM_STREAM_CAPTURE;
277 cpu_dai->capture_active--;