forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/soc-pcm.c
....@@ -19,127 +19,216 @@
1919 #include <linux/workqueue.h>
2020 #include <linux/export.h>
2121 #include <linux/debugfs.h>
22
-#include <linux/dma-mapping.h>
2322 #include <sound/core.h>
2423 #include <sound/pcm.h>
2524 #include <sound/pcm_params.h>
2625 #include <sound/soc.h>
2726 #include <sound/soc-dpcm.h>
27
+#include <sound/soc-link.h>
2828 #include <sound/initval.h>
29
+#include <trace/hooks/sound.h>
2930
3031 #define DPCM_MAX_BE_USERS 8
3132
32
-/*
33
- * ASoC no host IO hardware.
34
- * TODO: fine tune these values for all host less transfers.
35
- */
36
-static const struct snd_pcm_hardware no_host_hardware = {
37
- .info = SNDRV_PCM_INFO_MMAP |
38
- SNDRV_PCM_INFO_MMAP_VALID |
39
- SNDRV_PCM_INFO_INTERLEAVED |
40
- SNDRV_PCM_INFO_PAUSE |
41
- SNDRV_PCM_INFO_RESUME,
42
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
43
- SNDRV_PCM_FMTBIT_S32_LE,
44
- .period_bytes_min = PAGE_SIZE >> 2,
45
- .period_bytes_max = PAGE_SIZE >> 1,
46
- .periods_min = 2,
47
- .periods_max = 4,
48
- /*
49
- * Increase the max buffer bytes as PAGE_SIZE bytes is
50
- * not enough to encompass all the scenarios sent by
51
- * userspapce.
52
- */
53
- .buffer_bytes_max = PAGE_SIZE * 4,
33
+#ifdef CONFIG_DEBUG_FS
34
+static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
35
+{
36
+ switch (state) {
37
+ case SND_SOC_DPCM_STATE_NEW:
38
+ return "new";
39
+ case SND_SOC_DPCM_STATE_OPEN:
40
+ return "open";
41
+ case SND_SOC_DPCM_STATE_HW_PARAMS:
42
+ return "hw_params";
43
+ case SND_SOC_DPCM_STATE_PREPARE:
44
+ return "prepare";
45
+ case SND_SOC_DPCM_STATE_START:
46
+ return "start";
47
+ case SND_SOC_DPCM_STATE_STOP:
48
+ return "stop";
49
+ case SND_SOC_DPCM_STATE_SUSPEND:
50
+ return "suspend";
51
+ case SND_SOC_DPCM_STATE_PAUSED:
52
+ return "paused";
53
+ case SND_SOC_DPCM_STATE_HW_FREE:
54
+ return "hw_free";
55
+ case SND_SOC_DPCM_STATE_CLOSE:
56
+ return "close";
57
+ }
58
+
59
+ return "unknown";
60
+}
61
+
62
+static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
63
+ int stream, char *buf, size_t size)
64
+{
65
+ struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
66
+ struct snd_soc_dpcm *dpcm;
67
+ ssize_t offset = 0;
68
+ unsigned long flags;
69
+
70
+ /* FE state */
71
+ offset += scnprintf(buf + offset, size - offset,
72
+ "[%s - %s]\n", fe->dai_link->name,
73
+ stream ? "Capture" : "Playback");
74
+
75
+ offset += scnprintf(buf + offset, size - offset, "State: %s\n",
76
+ dpcm_state_string(fe->dpcm[stream].state));
77
+
78
+ if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
79
+ (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
80
+ offset += scnprintf(buf + offset, size - offset,
81
+ "Hardware Params: "
82
+ "Format = %s, Channels = %d, Rate = %d\n",
83
+ snd_pcm_format_name(params_format(params)),
84
+ params_channels(params),
85
+ params_rate(params));
86
+
87
+ /* BEs state */
88
+ offset += scnprintf(buf + offset, size - offset, "Backends:\n");
89
+
90
+ if (list_empty(&fe->dpcm[stream].be_clients)) {
91
+ offset += scnprintf(buf + offset, size - offset,
92
+ " No active DSP links\n");
93
+ goto out;
94
+ }
95
+
96
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
97
+ for_each_dpcm_be(fe, stream, dpcm) {
98
+ struct snd_soc_pcm_runtime *be = dpcm->be;
99
+ params = &dpcm->hw_params;
100
+
101
+ offset += scnprintf(buf + offset, size - offset,
102
+ "- %s\n", be->dai_link->name);
103
+
104
+ offset += scnprintf(buf + offset, size - offset,
105
+ " State: %s\n",
106
+ dpcm_state_string(be->dpcm[stream].state));
107
+
108
+ if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
109
+ (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
110
+ offset += scnprintf(buf + offset, size - offset,
111
+ " Hardware Params: "
112
+ "Format = %s, Channels = %d, Rate = %d\n",
113
+ snd_pcm_format_name(params_format(params)),
114
+ params_channels(params),
115
+ params_rate(params));
116
+ }
117
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
118
+out:
119
+ return offset;
120
+}
121
+
122
+static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
123
+ size_t count, loff_t *ppos)
124
+{
125
+ struct snd_soc_pcm_runtime *fe = file->private_data;
126
+ ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
127
+ int stream;
128
+ char *buf;
129
+
130
+ if (fe->num_cpus > 1) {
131
+ dev_err(fe->dev,
132
+ "%s doesn't support Multi CPU yet\n", __func__);
133
+ return -EINVAL;
134
+ }
135
+
136
+ buf = kmalloc(out_count, GFP_KERNEL);
137
+ if (!buf)
138
+ return -ENOMEM;
139
+
140
+ for_each_pcm_streams(stream)
141
+ if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream))
142
+ offset += dpcm_show_state(fe, stream,
143
+ buf + offset,
144
+ out_count - offset);
145
+
146
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
147
+
148
+ kfree(buf);
149
+ return ret;
150
+}
151
+
152
+static const struct file_operations dpcm_state_fops = {
153
+ .open = simple_open,
154
+ .read = dpcm_state_read_file,
155
+ .llseek = default_llseek,
54156 };
55157
56
-/*
57
- * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
58
- *
59
- * Returns true if the DAI supports the indicated stream type.
60
- */
61
-static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream)
158
+void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
62159 {
63
- struct snd_soc_pcm_stream *codec_stream;
160
+ if (!rtd->dai_link)
161
+ return;
64162
65
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
66
- codec_stream = &dai->driver->playback;
67
- else
68
- codec_stream = &dai->driver->capture;
163
+ if (!rtd->dai_link->dynamic)
164
+ return;
69165
70
- /* If the codec specifies any channels at all, it supports the stream */
71
- return codec_stream->channels_min;
166
+ if (!rtd->card->debugfs_card_root)
167
+ return;
168
+
169
+ rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
170
+ rtd->card->debugfs_card_root);
171
+
172
+ debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
173
+ rtd, &dpcm_state_fops);
72174 }
73175
176
+static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream)
177
+{
178
+ char *name;
179
+
180
+ name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name,
181
+ stream ? "capture" : "playback");
182
+ if (name) {
183
+ dpcm->debugfs_state = debugfs_create_dir(
184
+ name, dpcm->fe->debugfs_dpcm_root);
185
+ debugfs_create_u32("state", 0644, dpcm->debugfs_state,
186
+ &dpcm->state);
187
+ kfree(name);
188
+ }
189
+}
190
+
191
+static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
192
+{
193
+ debugfs_remove_recursive(dpcm->debugfs_state);
194
+}
195
+
196
+#else
197
+static inline void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm,
198
+ int stream)
199
+{
200
+}
201
+
202
+static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
203
+{
204
+}
205
+#endif
206
+
74207 /**
75
- * snd_soc_runtime_activate() - Increment active count for PCM runtime components
208
+ * snd_soc_runtime_action() - Increment/Decrement active count for
209
+ * PCM runtime components
76210 * @rtd: ASoC PCM runtime that is activated
77211 * @stream: Direction of the PCM stream
212
+ * @action: Activate stream if 1. Deactivate if -1.
78213 *
79
- * Increments the active count for all the DAIs and components attached to a PCM
80
- * runtime. Should typically be called when a stream is opened.
214
+ * Increments/Decrements the active count for all the DAIs and components
215
+ * attached to a PCM runtime.
216
+ * Should typically be called when a stream is opened.
81217 *
82
- * Must be called with the rtd->pcm_mutex being held
218
+ * Must be called with the rtd->card->pcm_mutex being held
83219 */
84
-void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
220
+void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
221
+ int stream, int action)
85222 {
86
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
223
+ struct snd_soc_dai *dai;
87224 int i;
88225
89
- lockdep_assert_held(&rtd->pcm_mutex);
226
+ lockdep_assert_held(&rtd->card->pcm_mutex);
90227
91
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
92
- cpu_dai->playback_active++;
93
- for (i = 0; i < rtd->num_codecs; i++)
94
- rtd->codec_dais[i]->playback_active++;
95
- } else {
96
- cpu_dai->capture_active++;
97
- for (i = 0; i < rtd->num_codecs; i++)
98
- rtd->codec_dais[i]->capture_active++;
99
- }
100
-
101
- cpu_dai->active++;
102
- cpu_dai->component->active++;
103
- for (i = 0; i < rtd->num_codecs; i++) {
104
- rtd->codec_dais[i]->active++;
105
- rtd->codec_dais[i]->component->active++;
106
- }
228
+ for_each_rtd_dais(rtd, i, dai)
229
+ snd_soc_dai_action(dai, stream, action);
107230 }
108
-
109
-/**
110
- * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components
111
- * @rtd: ASoC PCM runtime that is deactivated
112
- * @stream: Direction of the PCM stream
113
- *
114
- * Decrements the active count for all the DAIs and components attached to a PCM
115
- * runtime. Should typically be called when a stream is closed.
116
- *
117
- * Must be called with the rtd->pcm_mutex being held
118
- */
119
-void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
120
-{
121
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
122
- int i;
123
-
124
- lockdep_assert_held(&rtd->pcm_mutex);
125
-
126
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
127
- cpu_dai->playback_active--;
128
- for (i = 0; i < rtd->num_codecs; i++)
129
- rtd->codec_dais[i]->playback_active--;
130
- } else {
131
- cpu_dai->capture_active--;
132
- for (i = 0; i < rtd->num_codecs; i++)
133
- rtd->codec_dais[i]->capture_active--;
134
- }
135
-
136
- cpu_dai->active--;
137
- cpu_dai->component->active--;
138
- for (i = 0; i < rtd->num_codecs; i++) {
139
- rtd->codec_dais[i]->component->active--;
140
- rtd->codec_dais[i]->active--;
141
- }
142
-}
231
+EXPORT_SYMBOL_GPL(snd_soc_runtime_action);
143232
144233 /**
145234 * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
....@@ -152,18 +241,15 @@
152241 */
153242 bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
154243 {
155
- struct snd_soc_rtdcom_list *rtdcom;
156244 struct snd_soc_component *component;
157245 bool ignore = true;
246
+ int i;
158247
159248 if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
160249 return true;
161250
162
- for_each_rtdcom(rtd, rtdcom) {
163
- component = rtdcom->component;
164
-
251
+ for_each_rtd_components(rtd, i, component)
165252 ignore &= !component->driver->use_pmdown_time;
166
- }
167253
168254 return ignore;
169255 }
....@@ -179,8 +265,6 @@
179265 const struct snd_pcm_hardware *hw)
180266 {
181267 struct snd_pcm_runtime *runtime = substream->runtime;
182
- if (!runtime)
183
- return 0;
184268 runtime->hw.info = hw->info;
185269 runtime->hw.formats = hw->formats;
186270 runtime->hw.period_bytes_min = hw->period_bytes_min;
....@@ -199,7 +283,7 @@
199283 {
200284 struct snd_soc_dpcm *dpcm;
201285
202
- list_for_each_entry(dpcm, &fe->dpcm[dir].be_clients, list_be) {
286
+ for_each_dpcm_be(fe, dir, dpcm) {
203287
204288 struct snd_soc_pcm_runtime *be = dpcm->be;
205289
....@@ -221,7 +305,7 @@
221305 static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
222306 struct snd_soc_dai *soc_dai)
223307 {
224
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
308
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
225309 int ret;
226310
227311 if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
....@@ -278,8 +362,9 @@
278362 static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
279363 struct snd_pcm_hw_params *params)
280364 {
281
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
282
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
365
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
366
+ struct snd_soc_dai *dai;
367
+ struct snd_soc_dai *cpu_dai;
283368 unsigned int rate, channels, sample_bits, symmetry, i;
284369
285370 rate = params_rate(params);
....@@ -287,40 +372,51 @@
287372 sample_bits = snd_pcm_format_physical_width(params_format(params));
288373
289374 /* reject unmatched parameters when applying symmetry */
290
- symmetry = cpu_dai->driver->symmetric_rates ||
291
- rtd->dai_link->symmetric_rates;
375
+ symmetry = rtd->dai_link->symmetric_rates;
292376
293
- for (i = 0; i < rtd->num_codecs; i++)
294
- symmetry |= rtd->codec_dais[i]->driver->symmetric_rates;
377
+ for_each_rtd_cpu_dais(rtd, i, dai)
378
+ symmetry |= dai->driver->symmetric_rates;
295379
296
- if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) {
297
- dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
298
- cpu_dai->rate, rate);
299
- return -EINVAL;
380
+ if (symmetry) {
381
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
382
+ if (cpu_dai->rate && cpu_dai->rate != rate) {
383
+ dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
384
+ cpu_dai->rate, rate);
385
+ return -EINVAL;
386
+ }
387
+ }
300388 }
301389
302
- symmetry = cpu_dai->driver->symmetric_channels ||
303
- rtd->dai_link->symmetric_channels;
390
+ symmetry = rtd->dai_link->symmetric_channels;
304391
305
- for (i = 0; i < rtd->num_codecs; i++)
306
- symmetry |= rtd->codec_dais[i]->driver->symmetric_channels;
392
+ for_each_rtd_dais(rtd, i, dai)
393
+ symmetry |= dai->driver->symmetric_channels;
307394
308
- if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) {
309
- dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
310
- cpu_dai->channels, channels);
311
- return -EINVAL;
395
+ if (symmetry) {
396
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
397
+ if (cpu_dai->channels &&
398
+ cpu_dai->channels != channels) {
399
+ dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
400
+ cpu_dai->channels, channels);
401
+ return -EINVAL;
402
+ }
403
+ }
312404 }
313405
314
- symmetry = cpu_dai->driver->symmetric_samplebits ||
315
- rtd->dai_link->symmetric_samplebits;
406
+ symmetry = rtd->dai_link->symmetric_samplebits;
316407
317
- for (i = 0; i < rtd->num_codecs; i++)
318
- symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits;
408
+ for_each_rtd_dais(rtd, i, dai)
409
+ symmetry |= dai->driver->symmetric_samplebits;
319410
320
- if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) {
321
- dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
322
- cpu_dai->sample_bits, sample_bits);
323
- return -EINVAL;
411
+ if (symmetry) {
412
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
413
+ if (cpu_dai->sample_bits &&
414
+ cpu_dai->sample_bits != sample_bits) {
415
+ dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
416
+ cpu_dai->sample_bits, sample_bits);
417
+ return -EINVAL;
418
+ }
419
+ }
324420 }
325421
326422 return 0;
....@@ -328,27 +424,27 @@
328424
329425 static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
330426 {
331
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
332
- struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver;
427
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
333428 struct snd_soc_dai_link *link = rtd->dai_link;
429
+ struct snd_soc_dai *dai;
334430 unsigned int symmetry, i;
335431
336
- symmetry = cpu_driver->symmetric_rates || link->symmetric_rates ||
337
- cpu_driver->symmetric_channels || link->symmetric_channels ||
338
- cpu_driver->symmetric_samplebits || link->symmetric_samplebits;
432
+ symmetry = link->symmetric_rates ||
433
+ link->symmetric_channels ||
434
+ link->symmetric_samplebits;
339435
340
- for (i = 0; i < rtd->num_codecs; i++)
436
+ for_each_rtd_dais(rtd, i, dai)
341437 symmetry = symmetry ||
342
- rtd->codec_dais[i]->driver->symmetric_rates ||
343
- rtd->codec_dais[i]->driver->symmetric_channels ||
344
- rtd->codec_dais[i]->driver->symmetric_samplebits;
438
+ dai->driver->symmetric_rates ||
439
+ dai->driver->symmetric_channels ||
440
+ dai->driver->symmetric_samplebits;
345441
346442 return symmetry;
347443 }
348444
349445 static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
350446 {
351
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
447
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
352448 int ret;
353449
354450 if (!bits)
....@@ -362,79 +458,99 @@
362458
363459 static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
364460 {
365
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
366
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
461
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
462
+ struct snd_soc_dai *cpu_dai;
367463 struct snd_soc_dai *codec_dai;
464
+ struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu;
465
+ int stream = substream->stream;
368466 int i;
369
- unsigned int bits = 0, cpu_bits;
467
+ unsigned int bits = 0, cpu_bits = 0;
370468
371
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
372
- for (i = 0; i < rtd->num_codecs; i++) {
373
- codec_dai = rtd->codec_dais[i];
374
- if (codec_dai->driver->playback.sig_bits == 0) {
375
- bits = 0;
376
- break;
377
- }
378
- bits = max(codec_dai->driver->playback.sig_bits, bits);
469
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
470
+ pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
471
+
472
+ if (pcm_codec->sig_bits == 0) {
473
+ bits = 0;
474
+ break;
379475 }
380
- cpu_bits = cpu_dai->driver->playback.sig_bits;
381
- } else {
382
- for (i = 0; i < rtd->num_codecs; i++) {
383
- codec_dai = rtd->codec_dais[i];
384
- if (codec_dai->driver->capture.sig_bits == 0) {
385
- bits = 0;
386
- break;
387
- }
388
- bits = max(codec_dai->driver->capture.sig_bits, bits);
476
+ bits = max(pcm_codec->sig_bits, bits);
477
+ }
478
+
479
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
480
+ pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
481
+
482
+ if (pcm_cpu->sig_bits == 0) {
483
+ cpu_bits = 0;
484
+ break;
389485 }
390
- cpu_bits = cpu_dai->driver->capture.sig_bits;
486
+ cpu_bits = max(pcm_cpu->sig_bits, cpu_bits);
391487 }
392488
393489 soc_pcm_set_msb(substream, bits);
394490 soc_pcm_set_msb(substream, cpu_bits);
395491 }
396492
397
-static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
493
+/**
494
+ * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream
495
+ * @rtd: ASoC PCM runtime
496
+ * @hw: PCM hardware parameters (output)
497
+ * @stream: Direction of the PCM stream
498
+ *
499
+ * Calculates the subset of stream parameters supported by all DAIs
500
+ * associated with the PCM stream.
501
+ */
502
+int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
503
+ struct snd_pcm_hardware *hw, int stream)
398504 {
399
- struct snd_pcm_runtime *runtime = substream->runtime;
400
- struct snd_pcm_hardware *hw = &runtime->hw;
401
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
402
- struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver;
403
- struct snd_soc_dai_driver *codec_dai_drv;
505
+ struct snd_soc_dai *codec_dai;
506
+ struct snd_soc_dai *cpu_dai;
404507 struct snd_soc_pcm_stream *codec_stream;
405508 struct snd_soc_pcm_stream *cpu_stream;
406509 unsigned int chan_min = 0, chan_max = UINT_MAX;
510
+ unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX;
407511 unsigned int rate_min = 0, rate_max = UINT_MAX;
408
- unsigned int rates = UINT_MAX;
512
+ unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX;
513
+ unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX;
409514 u64 formats = ULLONG_MAX;
410515 int i;
411516
412
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
413
- cpu_stream = &cpu_dai_drv->playback;
414
- else
415
- cpu_stream = &cpu_dai_drv->capture;
517
+ /* first calculate min/max only for CPUs in the DAI link */
518
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
416519
417
- /* first calculate min/max only for CODECs in the DAI link */
418
- for (i = 0; i < rtd->num_codecs; i++) {
520
+ /*
521
+ * Skip CPUs which don't support the current stream type.
522
+ * Otherwise, since the rate, channel, and format values will
523
+ * zero in that case, we would have no usable settings left,
524
+ * causing the resulting setup to fail.
525
+ */
526
+ if (!snd_soc_dai_stream_valid(cpu_dai, stream))
527
+ continue;
528
+
529
+ cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
530
+
531
+ cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min);
532
+ cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max);
533
+ cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min);
534
+ cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max);
535
+ formats &= cpu_stream->formats;
536
+ cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates,
537
+ cpu_rates);
538
+ }
539
+
540
+ /* second calculate min/max only for CODECs in the DAI link */
541
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
419542
420543 /*
421544 * Skip CODECs which don't support the current stream type.
422545 * Otherwise, since the rate, channel, and format values will
423546 * zero in that case, we would have no usable settings left,
424547 * causing the resulting setup to fail.
425
- * At least one CODEC should match, otherwise we should have
426
- * bailed out on a higher level, since there would be no
427
- * CODEC to support the transfer direction in that case.
428548 */
429
- if (!snd_soc_dai_stream_valid(rtd->codec_dais[i],
430
- substream->stream))
549
+ if (!snd_soc_dai_stream_valid(codec_dai, stream))
431550 continue;
432551
433
- codec_dai_drv = rtd->codec_dais[i]->driver;
434
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
435
- codec_stream = &codec_dai_drv->playback;
436
- else
437
- codec_stream = &codec_dai_drv->capture;
552
+ codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
553
+
438554 chan_min = max(chan_min, codec_stream->channels_min);
439555 chan_max = min(chan_max, codec_stream->channels_max);
440556 rate_min = max(rate_min, codec_stream->rate_min);
....@@ -443,53 +559,132 @@
443559 rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
444560 }
445561
562
+ /* Verify both a valid CPU DAI and a valid CODEC DAI were found */
563
+ if (!chan_min || !cpu_chan_min)
564
+ return -EINVAL;
565
+
446566 /*
447567 * chan min/max cannot be enforced if there are multiple CODEC DAIs
448
- * connected to a single CPU DAI, use CPU DAI's directly and let
568
+ * connected to CPU DAI(s), use CPU DAI's directly and let
449569 * channel allocation be fixed up later
450570 */
451571 if (rtd->num_codecs > 1) {
452
- chan_min = cpu_stream->channels_min;
453
- chan_max = cpu_stream->channels_max;
572
+ chan_min = cpu_chan_min;
573
+ chan_max = cpu_chan_max;
454574 }
455575
456
- hw->channels_min = max(chan_min, cpu_stream->channels_min);
457
- hw->channels_max = min(chan_max, cpu_stream->channels_max);
458
- if (hw->formats)
459
- hw->formats &= formats & cpu_stream->formats;
460
- else
461
- hw->formats = formats & cpu_stream->formats;
462
- hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates);
576
+ /* finally find a intersection between CODECs and CPUs */
577
+ hw->channels_min = max(chan_min, cpu_chan_min);
578
+ hw->channels_max = min(chan_max, cpu_chan_max);
579
+ hw->formats = formats;
580
+ hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates);
463581
464
- snd_pcm_limit_hw_rates(runtime);
582
+ snd_pcm_hw_limit_rates(hw);
465583
466
- hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
584
+ hw->rate_min = max(hw->rate_min, cpu_rate_min);
467585 hw->rate_min = max(hw->rate_min, rate_min);
468
- hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
586
+ hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max);
469587 hw->rate_max = min_not_zero(hw->rate_max, rate_max);
588
+
589
+ return 0;
590
+}
591
+EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw);
592
+
593
+static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
594
+{
595
+ struct snd_pcm_hardware *hw = &substream->runtime->hw;
596
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
597
+ u64 formats = hw->formats;
598
+
599
+ /*
600
+ * At least one CPU and one CODEC should match. Otherwise, we should
601
+ * have bailed out on a higher level, since there would be no CPU or
602
+ * CODEC to support the transfer direction in that case.
603
+ */
604
+ snd_soc_runtime_calc_hw(rtd, hw, substream->stream);
605
+
606
+ if (formats)
607
+ hw->formats &= formats;
608
+}
609
+
610
+static int soc_pcm_components_open(struct snd_pcm_substream *substream)
611
+{
612
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
613
+ struct snd_soc_component *component;
614
+ int i, ret = 0;
615
+
616
+ for_each_rtd_components(rtd, i, component) {
617
+ ret = snd_soc_component_module_get_when_open(component, substream);
618
+ if (ret < 0)
619
+ break;
620
+
621
+ ret = snd_soc_component_open(component, substream);
622
+ if (ret < 0)
623
+ break;
624
+ }
625
+
626
+ return ret;
470627 }
471628
472629 static int soc_pcm_components_close(struct snd_pcm_substream *substream,
473
- struct snd_soc_component *last)
630
+ int rollback)
474631 {
475
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
476
- struct snd_soc_rtdcom_list *rtdcom;
632
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
477633 struct snd_soc_component *component;
634
+ int i, r, ret = 0;
478635
479
- for_each_rtdcom(rtd, rtdcom) {
480
- component = rtdcom->component;
636
+ for_each_rtd_components(rtd, i, component) {
637
+ r = snd_soc_component_close(component, substream, rollback);
638
+ if (r < 0)
639
+ ret = r; /* use last ret */
481640
482
- if (component == last)
483
- break;
484
-
485
- if (!component->driver->ops ||
486
- !component->driver->ops->close)
487
- continue;
488
-
489
- component->driver->ops->close(substream);
641
+ snd_soc_component_module_put_when_close(component, substream, rollback);
490642 }
491643
644
+ return ret;
645
+}
646
+
647
+static int soc_pcm_clean(struct snd_pcm_substream *substream, int rollback)
648
+{
649
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
650
+ struct snd_soc_component *component;
651
+ struct snd_soc_dai *dai;
652
+ int i;
653
+
654
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
655
+
656
+ if (!rollback)
657
+ snd_soc_runtime_deactivate(rtd, substream->stream);
658
+
659
+ for_each_rtd_dais(rtd, i, dai)
660
+ snd_soc_dai_shutdown(dai, substream, rollback);
661
+
662
+ snd_soc_link_shutdown(substream, rollback);
663
+
664
+ soc_pcm_components_close(substream, rollback);
665
+
666
+ if (!rollback)
667
+ snd_soc_dapm_stream_stop(rtd, substream->stream);
668
+
669
+ mutex_unlock(&rtd->card->pcm_mutex);
670
+
671
+ snd_soc_pcm_component_pm_runtime_put(rtd, substream, rollback);
672
+
673
+ for_each_rtd_components(rtd, i, component)
674
+ if (!snd_soc_component_active(component))
675
+ pinctrl_pm_select_sleep_state(component->dev);
676
+
492677 return 0;
678
+}
679
+
680
+/*
681
+ * Called by ALSA when a PCM substream is closed. Private data can be
682
+ * freed here. The cpu DAI, codec DAI, machine and components are also
683
+ * shutdown.
684
+ */
685
+static int soc_pcm_close(struct snd_pcm_substream *substream)
686
+{
687
+ return soc_pcm_clean(substream, 0);
493688 }
494689
495690 /*
....@@ -499,83 +694,36 @@
499694 */
500695 static int soc_pcm_open(struct snd_pcm_substream *substream)
501696 {
502
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
697
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
503698 struct snd_pcm_runtime *runtime = substream->runtime;
504699 struct snd_soc_component *component;
505
- struct snd_soc_rtdcom_list *rtdcom;
506
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
507
- struct snd_soc_dai *codec_dai;
700
+ struct snd_soc_dai *dai;
508701 const char *codec_dai_name = "multicodec";
702
+ const char *cpu_dai_name = "multicpu";
509703 int i, ret = 0;
510704
511
- pinctrl_pm_select_default_state(cpu_dai->dev);
512
- for (i = 0; i < rtd->num_codecs; i++)
513
- pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev);
705
+ for_each_rtd_components(rtd, i, component)
706
+ pinctrl_pm_select_default_state(component->dev);
514707
515
- for_each_rtdcom(rtd, rtdcom) {
516
- component = rtdcom->component;
708
+ ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
709
+ if (ret < 0)
710
+ goto pm_err;
517711
518
- pm_runtime_get_sync(component->dev);
519
- }
712
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
520713
521
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
714
+ ret = soc_pcm_components_open(substream);
715
+ if (ret < 0)
716
+ goto err;
522717
523
- if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
524
- snd_soc_set_runtime_hwparams(substream, &no_host_hardware);
718
+ ret = snd_soc_link_startup(substream);
719
+ if (ret < 0)
720
+ goto err;
525721
526722 /* startup the audio subsystem */
527
- if (cpu_dai->driver->ops->startup) {
528
- ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
529
- if (ret < 0) {
530
- dev_err(cpu_dai->dev, "ASoC: can't open interface"
531
- " %s: %d\n", cpu_dai->name, ret);
532
- goto out;
533
- }
534
- }
535
-
536
- for_each_rtdcom(rtd, rtdcom) {
537
- component = rtdcom->component;
538
-
539
- if (!component->driver->ops ||
540
- !component->driver->ops->open)
541
- continue;
542
-
543
- ret = component->driver->ops->open(substream);
544
- if (ret < 0) {
545
- dev_err(component->dev,
546
- "ASoC: can't open component %s: %d\n",
547
- component->name, ret);
548
- goto component_err;
549
- }
550
- }
551
- component = NULL;
552
-
553
- for (i = 0; i < rtd->num_codecs; i++) {
554
- codec_dai = rtd->codec_dais[i];
555
- if (codec_dai->driver->ops->startup) {
556
- ret = codec_dai->driver->ops->startup(substream,
557
- codec_dai);
558
- if (ret < 0) {
559
- dev_err(codec_dai->dev,
560
- "ASoC: can't open codec %s: %d\n",
561
- codec_dai->name, ret);
562
- goto codec_dai_err;
563
- }
564
- }
565
-
566
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
567
- codec_dai->tx_mask = 0;
568
- else
569
- codec_dai->rx_mask = 0;
570
- }
571
-
572
- if (rtd->dai_link->ops->startup) {
573
- ret = rtd->dai_link->ops->startup(substream);
574
- if (ret < 0) {
575
- pr_err("ASoC: %s startup failed: %d\n",
576
- rtd->dai_link->name, ret);
577
- goto machine_err;
578
- }
723
+ for_each_rtd_dais(rtd, i, dai) {
724
+ ret = snd_soc_dai_startup(dai, substream);
725
+ if (ret < 0)
726
+ goto err;
579727 }
580728
581729 /* Dynamic PCM DAI links compat checks use dynamic capabilities */
....@@ -586,7 +734,10 @@
586734 soc_pcm_init_runtime_hw(substream);
587735
588736 if (rtd->num_codecs == 1)
589
- codec_dai_name = rtd->codec_dai->name;
737
+ codec_dai_name = asoc_rtd_to_codec(rtd, 0)->name;
738
+
739
+ if (rtd->num_cpus == 1)
740
+ cpu_dai_name = asoc_rtd_to_cpu(rtd, 0)->name;
590741
591742 if (soc_pcm_has_symmetry(substream))
592743 runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
....@@ -594,201 +745,59 @@
594745 ret = -EINVAL;
595746 if (!runtime->hw.rates) {
596747 printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
597
- codec_dai_name, cpu_dai->name);
598
- goto config_err;
748
+ codec_dai_name, cpu_dai_name);
749
+ goto err;
599750 }
600751 if (!runtime->hw.formats) {
601752 printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
602
- codec_dai_name, cpu_dai->name);
603
- goto config_err;
753
+ codec_dai_name, cpu_dai_name);
754
+ goto err;
604755 }
605756 if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
606757 runtime->hw.channels_min > runtime->hw.channels_max) {
607758 printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
608
- codec_dai_name, cpu_dai->name);
609
- goto config_err;
759
+ codec_dai_name, cpu_dai_name);
760
+ goto err;
610761 }
611762
612763 soc_pcm_apply_msb(substream);
613764
614765 /* Symmetry only applies if we've already got an active stream. */
615
- if (cpu_dai->active) {
616
- ret = soc_pcm_apply_symmetry(substream, cpu_dai);
617
- if (ret != 0)
618
- goto config_err;
619
- }
620
-
621
- for (i = 0; i < rtd->num_codecs; i++) {
622
- if (rtd->codec_dais[i]->active) {
623
- ret = soc_pcm_apply_symmetry(substream,
624
- rtd->codec_dais[i]);
766
+ for_each_rtd_dais(rtd, i, dai) {
767
+ if (snd_soc_dai_active(dai)) {
768
+ ret = soc_pcm_apply_symmetry(substream, dai);
625769 if (ret != 0)
626
- goto config_err;
770
+ goto err;
627771 }
628772 }
629773
630774 pr_debug("ASoC: %s <-> %s info:\n",
631
- codec_dai_name, cpu_dai->name);
775
+ codec_dai_name, cpu_dai_name);
632776 pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
633777 pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
634778 runtime->hw.channels_max);
635779 pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min,
636780 runtime->hw.rate_max);
637
-
638781 dynamic:
639
-
640782 snd_soc_runtime_activate(rtd, substream->stream);
641
-
642
- mutex_unlock(&rtd->pcm_mutex);
643
- return 0;
644
-
645
-config_err:
646
- if (rtd->dai_link->ops->shutdown)
647
- rtd->dai_link->ops->shutdown(substream);
648
-
649
-machine_err:
650
- i = rtd->num_codecs;
651
-
652
-codec_dai_err:
653
- while (--i >= 0) {
654
- codec_dai = rtd->codec_dais[i];
655
- if (codec_dai->driver->ops->shutdown)
656
- codec_dai->driver->ops->shutdown(substream, codec_dai);
657
- }
658
-
659
-component_err:
660
- soc_pcm_components_close(substream, component);
661
-
662
- if (cpu_dai->driver->ops->shutdown)
663
- cpu_dai->driver->ops->shutdown(substream, cpu_dai);
664
-out:
665
- mutex_unlock(&rtd->pcm_mutex);
666
-
667
- for_each_rtdcom(rtd, rtdcom) {
668
- component = rtdcom->component;
669
-
670
- pm_runtime_mark_last_busy(component->dev);
671
- pm_runtime_put_autosuspend(component->dev);
672
- }
673
-
674
- for (i = 0; i < rtd->num_codecs; i++) {
675
- if (!rtd->codec_dais[i]->active)
676
- pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
677
- }
678
- if (!cpu_dai->active)
679
- pinctrl_pm_select_sleep_state(cpu_dai->dev);
783
+ ret = 0;
784
+err:
785
+ mutex_unlock(&rtd->card->pcm_mutex);
786
+pm_err:
787
+ if (ret < 0)
788
+ soc_pcm_clean(substream, 1);
680789
681790 return ret;
682791 }
683792
684
-/*
685
- * Power down the audio subsystem pmdown_time msecs after close is called.
686
- * This is to ensure there are no pops or clicks in between any music tracks
687
- * due to DAPM power cycling.
688
- */
689
-static void close_delayed_work(struct work_struct *work)
793
+static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
690794 {
691
- struct snd_soc_pcm_runtime *rtd =
692
- container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
693
- struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
694
-
695
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
696
-
697
- dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
698
- codec_dai->driver->playback.stream_name,
699
- codec_dai->playback_active ? "active" : "inactive",
700
- rtd->pop_wait ? "yes" : "no");
701
-
702
- /* are we waiting on this codec DAI stream */
703
- if (rtd->pop_wait == 1) {
704
- rtd->pop_wait = 0;
705
- snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
706
- SND_SOC_DAPM_STREAM_STOP);
707
- }
708
-
709
- mutex_unlock(&rtd->pcm_mutex);
710
-}
711
-
712
-/*
713
- * Called by ALSA when a PCM substream is closed. Private data can be
714
- * freed here. The cpu DAI, codec DAI, machine and components are also
715
- * shutdown.
716
- */
717
-static int soc_pcm_close(struct snd_pcm_substream *substream)
718
-{
719
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
720
- struct snd_soc_component *component;
721
- struct snd_soc_rtdcom_list *rtdcom;
722
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
723
- struct snd_soc_dai *codec_dai;
724
- int i;
725
-
726
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
727
-
728
- snd_soc_runtime_deactivate(rtd, substream->stream);
729
-
730
- /* clear the corresponding DAIs rate when inactive */
731
- if (!cpu_dai->active)
732
- cpu_dai->rate = 0;
733
-
734
- for (i = 0; i < rtd->num_codecs; i++) {
735
- codec_dai = rtd->codec_dais[i];
736
- if (!codec_dai->active)
737
- codec_dai->rate = 0;
738
- }
739
-
740
- snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream);
741
-
742
- if (cpu_dai->driver->ops->shutdown)
743
- cpu_dai->driver->ops->shutdown(substream, cpu_dai);
744
-
745
- for (i = 0; i < rtd->num_codecs; i++) {
746
- codec_dai = rtd->codec_dais[i];
747
- if (codec_dai->driver->ops->shutdown)
748
- codec_dai->driver->ops->shutdown(substream, codec_dai);
749
- }
750
-
751
- if (rtd->dai_link->ops->shutdown)
752
- rtd->dai_link->ops->shutdown(substream);
753
-
754
- soc_pcm_components_close(substream, NULL);
755
-
756
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
757
- if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
758
- /* powered down playback stream now */
759
- snd_soc_dapm_stream_event(rtd,
760
- SNDRV_PCM_STREAM_PLAYBACK,
761
- SND_SOC_DAPM_STREAM_STOP);
762
- } else {
763
- /* start delayed pop wq here for playback streams */
764
- rtd->pop_wait = 1;
765
- queue_delayed_work(system_power_efficient_wq,
766
- &rtd->delayed_work,
767
- msecs_to_jiffies(rtd->pmdown_time));
768
- }
769
- } else {
770
- /* capture streams can be powered down now */
771
- snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
772
- SND_SOC_DAPM_STREAM_STOP);
773
- }
774
-
775
- mutex_unlock(&rtd->pcm_mutex);
776
-
777
- for_each_rtdcom(rtd, rtdcom) {
778
- component = rtdcom->component;
779
-
780
- pm_runtime_mark_last_busy(component->dev);
781
- pm_runtime_put_autosuspend(component->dev);
782
- }
783
-
784
- for (i = 0; i < rtd->num_codecs; i++) {
785
- if (!rtd->codec_dais[i]->active)
786
- pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
787
- }
788
- if (!cpu_dai->active)
789
- pinctrl_pm_select_sleep_state(cpu_dai->dev);
790
-
791
- return 0;
795
+ /*
796
+ * Currently nothing to do for c2c links
797
+ * Since c2c links are internal nodes in the DAPM graph and
798
+ * don't interface with the outside world or application layer
799
+ * we don't have to do any special handling on close.
800
+ */
792801 }
793802
794803 /*
....@@ -798,60 +807,24 @@
798807 */
799808 static int soc_pcm_prepare(struct snd_pcm_substream *substream)
800809 {
801
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
802
- struct snd_soc_component *component;
803
- struct snd_soc_rtdcom_list *rtdcom;
804
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
805
- struct snd_soc_dai *codec_dai;
810
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
811
+ struct snd_soc_dai *dai;
806812 int i, ret = 0;
807813
808
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
814
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
809815
810
- if (rtd->dai_link->ops->prepare) {
811
- ret = rtd->dai_link->ops->prepare(substream);
812
- if (ret < 0) {
813
- dev_err(rtd->card->dev, "ASoC: machine prepare error:"
814
- " %d\n", ret);
815
- goto out;
816
- }
817
- }
816
+ ret = snd_soc_link_prepare(substream);
817
+ if (ret < 0)
818
+ goto out;
818819
819
- for_each_rtdcom(rtd, rtdcom) {
820
- component = rtdcom->component;
820
+ ret = snd_soc_pcm_component_prepare(substream);
821
+ if (ret < 0)
822
+ goto out;
821823
822
- if (!component->driver->ops ||
823
- !component->driver->ops->prepare)
824
- continue;
825
-
826
- ret = component->driver->ops->prepare(substream);
827
- if (ret < 0) {
828
- dev_err(component->dev,
829
- "ASoC: platform prepare error: %d\n", ret);
830
- goto out;
831
- }
832
- }
833
-
834
- for (i = 0; i < rtd->num_codecs; i++) {
835
- codec_dai = rtd->codec_dais[i];
836
- if (codec_dai->driver->ops->prepare) {
837
- ret = codec_dai->driver->ops->prepare(substream,
838
- codec_dai);
839
- if (ret < 0) {
840
- dev_err(codec_dai->dev,
841
- "ASoC: codec DAI prepare error: %d\n",
842
- ret);
843
- goto out;
844
- }
845
- }
846
- }
847
-
848
- if (cpu_dai->driver->ops->prepare) {
849
- ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
850
- if (ret < 0) {
851
- dev_err(cpu_dai->dev,
852
- "ASoC: cpu DAI prepare error: %d\n", ret);
853
- goto out;
854
- }
824
+ ret = snd_soc_pcm_dai_prepare(substream);
825
+ if (ret < 0) {
826
+ dev_err(rtd->dev, "ASoC: DAI prepare error: %d\n", ret);
827
+ goto out;
855828 }
856829
857830 /* cancel any delayed stream shutdown that is pending */
....@@ -864,13 +837,11 @@
864837 snd_soc_dapm_stream_event(rtd, substream->stream,
865838 SND_SOC_DAPM_STREAM_START);
866839
867
- for (i = 0; i < rtd->num_codecs; i++)
868
- snd_soc_dai_digital_mute(rtd->codec_dais[i], 0,
869
- substream->stream);
870
- snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream);
840
+ for_each_rtd_dais(rtd, i, dai)
841
+ snd_soc_dai_digital_mute(dai, 0, substream->stream);
871842
872843 out:
873
- mutex_unlock(&rtd->pcm_mutex);
844
+ mutex_unlock(&rtd->card->pcm_mutex);
874845 return ret;
875846 }
876847
....@@ -885,59 +856,6 @@
885856 interval->max = channels;
886857 }
887858
888
-int soc_dai_hw_params(struct snd_pcm_substream *substream,
889
- struct snd_pcm_hw_params *params,
890
- struct snd_soc_dai *dai)
891
-{
892
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
893
- int ret;
894
-
895
- /* perform any topology hw_params fixups before DAI */
896
- if (rtd->dai_link->be_hw_params_fixup) {
897
- ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
898
- if (ret < 0) {
899
- dev_err(rtd->dev,
900
- "ASoC: hw_params topology fixup failed %d\n",
901
- ret);
902
- return ret;
903
- }
904
- }
905
-
906
- if (dai->driver->ops->hw_params) {
907
- ret = dai->driver->ops->hw_params(substream, params, dai);
908
- if (ret < 0) {
909
- dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n",
910
- dai->name, ret);
911
- return ret;
912
- }
913
- }
914
-
915
- return 0;
916
-}
917
-
918
-static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream,
919
- struct snd_soc_component *last)
920
-{
921
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
922
- struct snd_soc_rtdcom_list *rtdcom;
923
- struct snd_soc_component *component;
924
-
925
- for_each_rtdcom(rtd, rtdcom) {
926
- component = rtdcom->component;
927
-
928
- if (component == last)
929
- break;
930
-
931
- if (!component->driver->ops ||
932
- !component->driver->ops->hw_free)
933
- continue;
934
-
935
- component->driver->ops->hw_free(substream);
936
- }
937
-
938
- return 0;
939
-}
940
-
941859 /*
942860 * Called by ALSA when the hardware params are set by application. This
943861 * function can also be called multiple times and can allocate buffers
....@@ -946,35 +864,23 @@
946864 static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
947865 struct snd_pcm_hw_params *params)
948866 {
949
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
867
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
950868 struct snd_soc_component *component;
951
- struct snd_soc_rtdcom_list *rtdcom;
952
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
869
+ struct snd_soc_dai *cpu_dai;
870
+ struct snd_soc_dai *codec_dai;
953871 int i, ret = 0;
954872
955
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
873
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
956874
957
- /* perform any hw_params fixups */
958
- if ((rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) &&
959
- rtd->dai_link->be_hw_params_fixup) {
960
- ret = rtd->dai_link->be_hw_params_fixup(rtd,
961
- params);
962
- if (ret < 0)
963
- dev_err(rtd->card->dev, "ASoC: fixup failed for %s\n",
964
- rtd->dai_link->name);
965
- }
875
+ ret = soc_pcm_params_symmetry(substream, params);
876
+ if (ret)
877
+ goto out;
966878
967
- if (rtd->dai_link->ops->hw_params) {
968
- ret = rtd->dai_link->ops->hw_params(substream, params);
969
- if (ret < 0) {
970
- dev_err(rtd->card->dev, "ASoC: machine hw_params"
971
- " failed: %d\n", ret);
972
- goto out;
973
- }
974
- }
879
+ ret = snd_soc_link_hw_params(substream, params);
880
+ if (ret < 0)
881
+ goto out;
975882
976
- for (i = 0; i < rtd->num_codecs; i++) {
977
- struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
883
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
978884 struct snd_pcm_hw_params codec_params;
979885
980886 /*
....@@ -1008,7 +914,8 @@
1008914 soc_pcm_codec_params_fixup(&codec_params,
1009915 codec_dai->rx_mask);
1010916
1011
- ret = soc_dai_hw_params(substream, &codec_params, codec_dai);
917
+ ret = snd_soc_dai_hw_params(codec_dai, substream,
918
+ &codec_params);
1012919 if(ret < 0)
1013920 goto codec_err;
1014921
....@@ -1016,81 +923,67 @@
1016923 codec_dai->channels = params_channels(&codec_params);
1017924 codec_dai->sample_bits = snd_pcm_format_physical_width(
1018925 params_format(&codec_params));
926
+
927
+ snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
1019928 }
1020929
1021
- ret = soc_dai_hw_params(substream, params, cpu_dai);
1022
- if (ret < 0)
1023
- goto interface_err;
1024
-
1025
- for_each_rtdcom(rtd, rtdcom) {
1026
- component = rtdcom->component;
1027
-
1028
- if (!component->driver->ops ||
1029
- !component->driver->ops->hw_params)
930
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
931
+ /*
932
+ * Skip CPUs which don't support the current stream
933
+ * type. See soc_pcm_init_runtime_hw() for more details
934
+ */
935
+ if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
1030936 continue;
1031937
1032
- ret = component->driver->ops->hw_params(substream, params);
1033
- if (ret < 0) {
1034
- dev_err(component->dev,
1035
- "ASoC: %s hw params failed: %d\n",
1036
- component->name, ret);
1037
- goto component_err;
1038
- }
938
+ ret = snd_soc_dai_hw_params(cpu_dai, substream, params);
939
+ if (ret < 0)
940
+ goto interface_err;
941
+
942
+ /* store the parameters for each DAI */
943
+ cpu_dai->rate = params_rate(params);
944
+ cpu_dai->channels = params_channels(params);
945
+ cpu_dai->sample_bits =
946
+ snd_pcm_format_physical_width(params_format(params));
947
+
948
+ snd_soc_dapm_update_dai(substream, params, cpu_dai);
1039949 }
1040
- component = NULL;
1041950
1042
- /* store the parameters for each DAIs */
1043
- cpu_dai->rate = params_rate(params);
1044
- cpu_dai->channels = params_channels(params);
1045
- cpu_dai->sample_bits =
1046
- snd_pcm_format_physical_width(params_format(params));
1047
-
1048
- ret = soc_pcm_params_symmetry(substream, params);
1049
- if (ret)
951
+ ret = snd_soc_pcm_component_hw_params(substream, params, &component);
952
+ if (ret < 0)
1050953 goto component_err;
1051954
1052
- /* malloc a page for hostless IO.
1053
- * FIXME: rework with alsa-lib changes so that this malloc is
1054
- * not required.
1055
- */
1056
- if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
1057
- substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
1058
- substream->dma_buffer.dev.dev = rtd->dev;
1059
- substream->dma_buffer.dev.dev->coherent_dma_mask =
1060
- DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
1061
- substream->dma_buffer.private_data = NULL;
1062
-
1063
- arch_setup_dma_ops(substream->dma_buffer.dev.dev,
1064
- 0, 0, NULL, 0);
1065
- ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
1066
- if (ret < 0)
1067
- goto component_err;
1068
- }
1069955 out:
1070
- mutex_unlock(&rtd->pcm_mutex);
956
+ mutex_unlock(&rtd->card->pcm_mutex);
1071957 return ret;
1072958
1073959 component_err:
1074
- soc_pcm_components_hw_free(substream, component);
960
+ snd_soc_pcm_component_hw_free(substream, component);
1075961
1076
- if (cpu_dai->driver->ops->hw_free)
1077
- cpu_dai->driver->ops->hw_free(substream, cpu_dai);
962
+ i = rtd->num_cpus;
1078963
1079964 interface_err:
965
+ for_each_rtd_cpu_dais_rollback(rtd, i, cpu_dai) {
966
+ if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
967
+ continue;
968
+
969
+ snd_soc_dai_hw_free(cpu_dai, substream);
970
+ cpu_dai->rate = 0;
971
+ }
972
+
1080973 i = rtd->num_codecs;
1081974
1082975 codec_err:
1083
- while (--i >= 0) {
1084
- struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
1085
- if (codec_dai->driver->ops->hw_free)
1086
- codec_dai->driver->ops->hw_free(substream, codec_dai);
976
+ for_each_rtd_codec_dais_rollback(rtd, i, codec_dai) {
977
+ if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
978
+ continue;
979
+
980
+ snd_soc_dai_hw_free(codec_dai, substream);
1087981 codec_dai->rate = 0;
1088982 }
1089983
1090
- if (rtd->dai_link->ops->hw_free)
1091
- rtd->dai_link->ops->hw_free(substream);
984
+ snd_soc_link_hw_free(substream);
1092985
1093
- mutex_unlock(&rtd->pcm_mutex);
986
+ mutex_unlock(&rtd->card->pcm_mutex);
1094987 return ret;
1095988 }
1096989
....@@ -1099,132 +992,80 @@
1099992 */
1100993 static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
1101994 {
1102
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
1103
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1104
- struct snd_soc_dai *codec_dai;
1105
- bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
995
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
996
+ struct snd_soc_dai *dai;
1106997 int i;
1107998
1108
- mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
999
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
11091000
11101001 /* clear the corresponding DAIs parameters when going to be inactive */
1111
- if (cpu_dai->active == 1) {
1112
- cpu_dai->rate = 0;
1113
- cpu_dai->channels = 0;
1114
- cpu_dai->sample_bits = 0;
1115
- }
1002
+ for_each_rtd_dais(rtd, i, dai) {
1003
+ int active = snd_soc_dai_stream_active(dai, substream->stream);
11161004
1117
- for (i = 0; i < rtd->num_codecs; i++) {
1118
- codec_dai = rtd->codec_dais[i];
1119
- if (codec_dai->active == 1) {
1120
- codec_dai->rate = 0;
1121
- codec_dai->channels = 0;
1122
- codec_dai->sample_bits = 0;
1005
+ if (snd_soc_dai_active(dai) == 1) {
1006
+ dai->rate = 0;
1007
+ dai->channels = 0;
1008
+ dai->sample_bits = 0;
11231009 }
1124
- }
11251010
1126
- /* apply codec digital mute */
1127
- for (i = 0; i < rtd->num_codecs; i++) {
1128
- if ((playback && rtd->codec_dais[i]->playback_active == 1) ||
1129
- (!playback && rtd->codec_dais[i]->capture_active == 1))
1130
- snd_soc_dai_digital_mute(rtd->codec_dais[i], 1,
1131
- substream->stream);
1011
+ if (active == 1)
1012
+ snd_soc_dai_digital_mute(dai, 1, substream->stream);
11321013 }
11331014
11341015 /* free any machine hw params */
1135
- if (rtd->dai_link->ops->hw_free)
1136
- rtd->dai_link->ops->hw_free(substream);
1016
+ snd_soc_link_hw_free(substream);
11371017
11381018 /* free any component resources */
1139
- soc_pcm_components_hw_free(substream, NULL);
1019
+ snd_soc_pcm_component_hw_free(substream, NULL);
11401020
11411021 /* now free hw params for the DAIs */
1142
- for (i = 0; i < rtd->num_codecs; i++) {
1143
- codec_dai = rtd->codec_dais[i];
1144
- if (codec_dai->driver->ops->hw_free)
1145
- codec_dai->driver->ops->hw_free(substream, codec_dai);
1022
+ for_each_rtd_dais(rtd, i, dai) {
1023
+ if (!snd_soc_dai_stream_valid(dai, substream->stream))
1024
+ continue;
1025
+
1026
+ snd_soc_dai_hw_free(dai, substream);
11461027 }
11471028
1148
- if (cpu_dai->driver->ops->hw_free)
1149
- cpu_dai->driver->ops->hw_free(substream, cpu_dai);
1150
-
1151
- if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
1152
- snd_pcm_lib_free_pages(substream);
1153
- mutex_unlock(&rtd->pcm_mutex);
1029
+ mutex_unlock(&rtd->card->pcm_mutex);
11541030 return 0;
11551031 }
11561032
11571033 static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
11581034 {
1159
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
1160
- struct snd_soc_component *component;
1161
- struct snd_soc_rtdcom_list *rtdcom;
1162
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1163
- struct snd_soc_dai *codec_dai;
1164
- int i, ret;
1035
+ int ret = -EINVAL;
11651036
1166
- for (i = 0; i < rtd->num_codecs; i++) {
1167
- codec_dai = rtd->codec_dais[i];
1168
- if (codec_dai->driver->ops->trigger) {
1169
- ret = codec_dai->driver->ops->trigger(substream,
1170
- cmd, codec_dai);
1171
- if (ret < 0)
1172
- return ret;
1173
- }
1174
- }
1175
-
1176
- for_each_rtdcom(rtd, rtdcom) {
1177
- component = rtdcom->component;
1178
-
1179
- if (!component->driver->ops ||
1180
- !component->driver->ops->trigger)
1181
- continue;
1182
-
1183
- ret = component->driver->ops->trigger(substream, cmd);
1037
+ switch (cmd) {
1038
+ case SNDRV_PCM_TRIGGER_START:
1039
+ case SNDRV_PCM_TRIGGER_RESUME:
1040
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1041
+ ret = snd_soc_link_trigger(substream, cmd);
11841042 if (ret < 0)
1185
- return ret;
1186
- }
1043
+ break;
11871044
1188
- if (cpu_dai->driver->ops->trigger) {
1189
- ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
1045
+ ret = snd_soc_pcm_component_trigger(substream, cmd);
11901046 if (ret < 0)
1191
- return ret;
1192
- }
1047
+ break;
11931048
1194
- if (rtd->dai_link->ops->trigger) {
1195
- ret = rtd->dai_link->ops->trigger(substream, cmd);
1049
+ ret = snd_soc_pcm_dai_trigger(substream, cmd);
1050
+ break;
1051
+ case SNDRV_PCM_TRIGGER_STOP:
1052
+ case SNDRV_PCM_TRIGGER_SUSPEND:
1053
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1054
+ ret = snd_soc_pcm_dai_trigger(substream, cmd);
11961055 if (ret < 0)
1197
- return ret;
1056
+ break;
1057
+
1058
+ ret = snd_soc_pcm_component_trigger(substream, cmd);
1059
+ if (ret < 0)
1060
+ break;
1061
+
1062
+ ret = snd_soc_link_trigger(substream, cmd);
1063
+ break;
11981064 }
11991065
1200
- return 0;
1066
+ return ret;
12011067 }
12021068
1203
-static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
1204
- int cmd)
1205
-{
1206
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
1207
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1208
- struct snd_soc_dai *codec_dai;
1209
- int i, ret;
1210
-
1211
- for (i = 0; i < rtd->num_codecs; i++) {
1212
- codec_dai = rtd->codec_dais[i];
1213
- if (codec_dai->driver->ops->bespoke_trigger) {
1214
- ret = codec_dai->driver->ops->bespoke_trigger(substream,
1215
- cmd, codec_dai);
1216
- if (ret < 0)
1217
- return ret;
1218
- }
1219
- }
1220
-
1221
- if (cpu_dai->driver->ops->bespoke_trigger) {
1222
- ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
1223
- if (ret < 0)
1224
- return ret;
1225
- }
1226
- return 0;
1227
-}
12281069 /*
12291070 * soc level wrapper for pointer callback
12301071 * If cpu_dai, codec_dai, component driver has the delay callback, then
....@@ -1232,43 +1073,33 @@
12321073 */
12331074 static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
12341075 {
1235
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
1236
- struct snd_soc_component *component;
1237
- struct snd_soc_rtdcom_list *rtdcom;
1238
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1076
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1077
+ struct snd_soc_dai *cpu_dai;
12391078 struct snd_soc_dai *codec_dai;
12401079 struct snd_pcm_runtime *runtime = substream->runtime;
12411080 snd_pcm_uframes_t offset = 0;
12421081 snd_pcm_sframes_t delay = 0;
12431082 snd_pcm_sframes_t codec_delay = 0;
1083
+ snd_pcm_sframes_t cpu_delay = 0;
12441084 int i;
12451085
12461086 /* clearing the previous total delay */
12471087 runtime->delay = 0;
12481088
1249
- for_each_rtdcom(rtd, rtdcom) {
1250
- component = rtdcom->component;
1089
+ offset = snd_soc_pcm_component_pointer(substream);
12511090
1252
- if (!component->driver->ops ||
1253
- !component->driver->ops->pointer)
1254
- continue;
1255
-
1256
- /* FIXME: use 1st pointer */
1257
- offset = component->driver->ops->pointer(substream);
1258
- break;
1259
- }
12601091 /* base delay if assigned in pointer callback */
12611092 delay = runtime->delay;
12621093
1263
- if (cpu_dai->driver->ops->delay)
1264
- delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
1094
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
1095
+ cpu_delay = max(cpu_delay,
1096
+ snd_soc_dai_delay(cpu_dai, substream));
1097
+ }
1098
+ delay += cpu_delay;
12651099
1266
- for (i = 0; i < rtd->num_codecs; i++) {
1267
- codec_dai = rtd->codec_dais[i];
1268
- if (codec_dai->driver->ops->delay)
1269
- codec_delay = max(codec_delay,
1270
- codec_dai->driver->ops->delay(substream,
1271
- codec_dai));
1100
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
1101
+ codec_delay = max(codec_delay,
1102
+ snd_soc_dai_delay(codec_dai, substream));
12721103 }
12731104 delay += codec_delay;
12741105
....@@ -1282,9 +1113,10 @@
12821113 struct snd_soc_pcm_runtime *be, int stream)
12831114 {
12841115 struct snd_soc_dpcm *dpcm;
1116
+ unsigned long flags;
12851117
12861118 /* only add new dpcms */
1287
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1119
+ for_each_dpcm_be(fe, stream, dpcm) {
12881120 if (dpcm->be == be && dpcm->fe == fe)
12891121 return 0;
12901122 }
....@@ -1297,18 +1129,17 @@
12971129 dpcm->fe = fe;
12981130 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
12991131 dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
1132
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
13001133 list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
13011134 list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
1135
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
13021136
13031137 dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
13041138 stream ? "capture" : "playback", fe->dai_link->name,
13051139 stream ? "<-" : "->", be->dai_link->name);
13061140
1307
-#ifdef CONFIG_DEBUG_FS
1308
- if (fe->debugfs_dpcm_root)
1309
- dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
1310
- fe->debugfs_dpcm_root, &dpcm->state);
1311
-#endif
1141
+ dpcm_create_debugfs_state(dpcm, stream);
1142
+
13121143 return 1;
13131144 }
13141145
....@@ -1324,8 +1155,10 @@
13241155 return;
13251156
13261157 be_substream = snd_soc_dpcm_get_substream(be, stream);
1158
+ if (!be_substream)
1159
+ return;
13271160
1328
- list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
1161
+ for_each_dpcm_fe(be, stream, dpcm) {
13291162 if (dpcm->fe == fe)
13301163 continue;
13311164
....@@ -1344,8 +1177,9 @@
13441177 void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
13451178 {
13461179 struct snd_soc_dpcm *dpcm, *d;
1180
+ unsigned long flags;
13471181
1348
- list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
1182
+ for_each_dpcm_be_safe(fe, stream, dpcm, d) {
13491183 dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
13501184 stream ? "capture" : "playback",
13511185 dpcm->be->dai_link->name);
....@@ -1360,11 +1194,12 @@
13601194 /* BEs still alive need new FE */
13611195 dpcm_be_reparent(fe, dpcm->be, stream);
13621196
1363
-#ifdef CONFIG_DEBUG_FS
1364
- debugfs_remove(dpcm->debugfs_state);
1365
-#endif
1197
+ dpcm_remove_debugfs_state(dpcm);
1198
+
1199
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
13661200 list_del(&dpcm->list_be);
13671201 list_del(&dpcm->list_fe);
1202
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
13681203 kfree(dpcm);
13691204 }
13701205 }
....@@ -1374,75 +1209,41 @@
13741209 struct snd_soc_dapm_widget *widget, int stream)
13751210 {
13761211 struct snd_soc_pcm_runtime *be;
1212
+ struct snd_soc_dapm_widget *w;
1213
+ struct snd_soc_dai *dai;
13771214 int i;
13781215
13791216 dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name);
13801217
1381
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1382
- list_for_each_entry(be, &card->rtd_list, list) {
1218
+ for_each_card_rtds(card, be) {
13831219
1384
- if (!be->dai_link->no_pcm)
1385
- continue;
1220
+ if (!be->dai_link->no_pcm)
1221
+ continue;
1222
+
1223
+ for_each_rtd_dais(be, i, dai) {
1224
+ w = snd_soc_dai_get_widget(dai, stream);
13861225
13871226 dev_dbg(card->dev, "ASoC: try BE : %s\n",
1388
- be->cpu_dai->playback_widget ?
1389
- be->cpu_dai->playback_widget->name : "(not set)");
1227
+ w ? w->name : "(not set)");
13901228
1391
- if (be->cpu_dai->playback_widget == widget)
1229
+ if (w == widget)
13921230 return be;
1393
-
1394
- for (i = 0; i < be->num_codecs; i++) {
1395
- struct snd_soc_dai *dai = be->codec_dais[i];
1396
- if (dai->playback_widget == widget)
1397
- return be;
1398
- }
1399
- }
1400
- } else {
1401
-
1402
- list_for_each_entry(be, &card->rtd_list, list) {
1403
-
1404
- if (!be->dai_link->no_pcm)
1405
- continue;
1406
-
1407
- dev_dbg(card->dev, "ASoC: try BE %s\n",
1408
- be->cpu_dai->capture_widget ?
1409
- be->cpu_dai->capture_widget->name : "(not set)");
1410
-
1411
- if (be->cpu_dai->capture_widget == widget)
1412
- return be;
1413
-
1414
- for (i = 0; i < be->num_codecs; i++) {
1415
- struct snd_soc_dai *dai = be->codec_dais[i];
1416
- if (dai->capture_widget == widget)
1417
- return be;
1418
- }
14191231 }
14201232 }
14211233
1422
- /* dai link name and stream name set correctly ? */
1423
- dev_err(card->dev, "ASoC: can't get %s BE for %s\n",
1424
- stream ? "capture" : "playback", widget->name);
1234
+ /* Widget provided is not a BE */
14251235 return NULL;
1426
-}
1427
-
1428
-static inline struct snd_soc_dapm_widget *
1429
- dai_get_widget(struct snd_soc_dai *dai, int stream)
1430
-{
1431
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1432
- return dai->playback_widget;
1433
- else
1434
- return dai->capture_widget;
14351236 }
14361237
14371238 static int widget_in_list(struct snd_soc_dapm_widget_list *list,
14381239 struct snd_soc_dapm_widget *widget)
14391240 {
1241
+ struct snd_soc_dapm_widget *w;
14401242 int i;
14411243
1442
- for (i = 0; i < list->num_widgets; i++) {
1443
- if (widget == list->widgets[i])
1244
+ for_each_dapm_widgets(list, i, w)
1245
+ if (widget == w)
14441246 return 1;
1445
- }
14461247
14471248 return 0;
14481249 }
....@@ -1452,37 +1253,17 @@
14521253 {
14531254 struct snd_soc_card *card = widget->dapm->card;
14541255 struct snd_soc_pcm_runtime *rtd;
1455
- int i;
1256
+ int stream;
14561257
1457
- if (dir == SND_SOC_DAPM_DIR_OUT) {
1458
- list_for_each_entry(rtd, &card->rtd_list, list) {
1459
- if (!rtd->dai_link->no_pcm)
1460
- continue;
1258
+ /* adjust dir to stream */
1259
+ if (dir == SND_SOC_DAPM_DIR_OUT)
1260
+ stream = SNDRV_PCM_STREAM_PLAYBACK;
1261
+ else
1262
+ stream = SNDRV_PCM_STREAM_CAPTURE;
14611263
1462
- if (rtd->cpu_dai->playback_widget == widget)
1463
- return true;
1464
-
1465
- for (i = 0; i < rtd->num_codecs; ++i) {
1466
- struct snd_soc_dai *dai = rtd->codec_dais[i];
1467
- if (dai->playback_widget == widget)
1468
- return true;
1469
- }
1470
- }
1471
- } else { /* SND_SOC_DAPM_DIR_IN */
1472
- list_for_each_entry(rtd, &card->rtd_list, list) {
1473
- if (!rtd->dai_link->no_pcm)
1474
- continue;
1475
-
1476
- if (rtd->cpu_dai->capture_widget == widget)
1477
- return true;
1478
-
1479
- for (i = 0; i < rtd->num_codecs; ++i) {
1480
- struct snd_soc_dai *dai = rtd->codec_dais[i];
1481
- if (dai->capture_widget == widget)
1482
- return true;
1483
- }
1484
- }
1485
- }
1264
+ rtd = dpcm_get_be(card, widget, stream);
1265
+ if (rtd)
1266
+ return true;
14861267
14871268 return false;
14881269 }
....@@ -1490,12 +1271,21 @@
14901271 int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
14911272 int stream, struct snd_soc_dapm_widget_list **list)
14921273 {
1493
- struct snd_soc_dai *cpu_dai = fe->cpu_dai;
1274
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
14941275 int paths;
1276
+ bool chaining = false;
1277
+
1278
+ if (fe->num_cpus > 1) {
1279
+ dev_err(fe->dev,
1280
+ "%s doesn't support Multi CPU yet\n", __func__);
1281
+ return -EINVAL;
1282
+ }
1283
+
1284
+ trace_android_vh_snd_soc_card_get_comp_chain(&chaining);
14951285
14961286 /* get number of valid DAI paths and their widgets */
14971287 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list,
1498
- dpcm_end_walk_at_be);
1288
+ chaining ? NULL : dpcm_end_walk_at_be);
14991289
15001290 dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
15011291 stream ? "capture" : "playback");
....@@ -1503,34 +1293,43 @@
15031293 return paths;
15041294 }
15051295
1296
+void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
1297
+{
1298
+ snd_soc_dapm_dai_free_widgets(list);
1299
+}
1300
+
1301
+static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
1302
+ struct snd_soc_dapm_widget_list *list)
1303
+{
1304
+ struct snd_soc_dapm_widget *widget;
1305
+ struct snd_soc_dai *dai;
1306
+ unsigned int i;
1307
+
1308
+ /* is there a valid DAI widget for this BE */
1309
+ for_each_rtd_dais(dpcm->be, i, dai) {
1310
+ widget = snd_soc_dai_get_widget(dai, stream);
1311
+
1312
+ /*
1313
+ * The BE is pruned only if none of the dai
1314
+ * widgets are in the active list.
1315
+ */
1316
+ if (widget && widget_in_list(list, widget))
1317
+ return true;
1318
+ }
1319
+
1320
+ return false;
1321
+}
1322
+
15061323 static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
1507
- struct snd_soc_dapm_widget_list **list_)
1324
+ struct snd_soc_dapm_widget_list **list_)
15081325 {
15091326 struct snd_soc_dpcm *dpcm;
1510
- struct snd_soc_dapm_widget_list *list = *list_;
1511
- struct snd_soc_dapm_widget *widget;
15121327 int prune = 0;
15131328
15141329 /* Destroy any old FE <--> BE connections */
1515
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1516
- unsigned int i;
1517
-
1518
- /* is there a valid CPU DAI widget for this BE */
1519
- widget = dai_get_widget(dpcm->be->cpu_dai, stream);
1520
-
1521
- /* prune the BE if it's no longer in our active list */
1522
- if (widget && widget_in_list(list, widget))
1330
+ for_each_dpcm_be(fe, stream, dpcm) {
1331
+ if (dpcm_be_is_active(dpcm, stream, *list_))
15231332 continue;
1524
-
1525
- /* is there a valid CODEC DAI widget for this BE */
1526
- for (i = 0; i < dpcm->be->num_codecs; i++) {
1527
- struct snd_soc_dai *dai = dpcm->be->codec_dais[i];
1528
- widget = dai_get_widget(dai, stream);
1529
-
1530
- /* prune the BE if it's no longer in our active list */
1531
- if (widget && widget_in_list(list, widget))
1532
- continue;
1533
- }
15341333
15351334 dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
15361335 stream ? "capture" : "playback",
....@@ -1550,12 +1349,13 @@
15501349 struct snd_soc_card *card = fe->card;
15511350 struct snd_soc_dapm_widget_list *list = *list_;
15521351 struct snd_soc_pcm_runtime *be;
1352
+ struct snd_soc_dapm_widget *widget;
15531353 int i, new = 0, err;
15541354
15551355 /* Create any new FE <--> BE connections */
1556
- for (i = 0; i < list->num_widgets; i++) {
1356
+ for_each_dapm_widgets(list, i, widget) {
15571357
1558
- switch (list->widgets[i]->id) {
1358
+ switch (widget->id) {
15591359 case snd_soc_dapm_dai_in:
15601360 if (stream != SNDRV_PCM_STREAM_PLAYBACK)
15611361 continue;
....@@ -1569,16 +1369,12 @@
15691369 }
15701370
15711371 /* is there a valid BE rtd for this widget */
1572
- be = dpcm_get_be(card, list->widgets[i], stream);
1372
+ be = dpcm_get_be(card, widget, stream);
15731373 if (!be) {
15741374 dev_err(fe->dev, "ASoC: no BE found for %s\n",
1575
- list->widgets[i]->name);
1375
+ widget->name);
15761376 continue;
15771377 }
1578
-
1579
- /* make sure BE is a real BE */
1580
- if (!be->dai_link->no_pcm)
1581
- continue;
15821378
15831379 /* don't connect if FE is not running */
15841380 if (!fe->dpcm[stream].runtime && !fe->fe_compr)
....@@ -1588,7 +1384,7 @@
15881384 err = dpcm_be_connect(fe, be, stream);
15891385 if (err < 0) {
15901386 dev_err(fe->dev, "ASoC: can't connect %s\n",
1591
- list->widgets[i]->name);
1387
+ widget->name);
15921388 break;
15931389 } else if (err == 0) /* already connected */
15941390 continue;
....@@ -1618,10 +1414,13 @@
16181414 void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
16191415 {
16201416 struct snd_soc_dpcm *dpcm;
1417
+ unsigned long flags;
16211418
1622
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
1419
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
1420
+ for_each_dpcm_be(fe, stream, dpcm)
16231421 dpcm->be->dpcm[stream].runtime_update =
16241422 SND_SOC_DPCM_UPDATE_NO;
1423
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
16251424 }
16261425
16271426 static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
....@@ -1630,7 +1429,7 @@
16301429 struct snd_soc_dpcm *dpcm;
16311430
16321431 /* disable any enabled and non active backends */
1633
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1432
+ for_each_dpcm_be(fe, stream, dpcm) {
16341433
16351434 struct snd_soc_pcm_runtime *be = dpcm->be;
16361435 struct snd_pcm_substream *be_substream =
....@@ -1659,7 +1458,7 @@
16591458 int err, count = 0;
16601459
16611460 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
1662
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1461
+ for_each_dpcm_be(fe, stream, dpcm) {
16631462
16641463 struct snd_soc_pcm_runtime *be = dpcm->be;
16651464 struct snd_pcm_substream *be_substream =
....@@ -1713,7 +1512,7 @@
17131512
17141513 unwind:
17151514 /* disable any enabled and non active backends */
1716
- list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1515
+ for_each_dpcm_be_rollback(fe, stream, dpcm) {
17171516 struct snd_soc_pcm_runtime *be = dpcm->be;
17181517 struct snd_pcm_substream *be_substream =
17191518 snd_soc_dpcm_get_substream(be, stream);
....@@ -1757,8 +1556,9 @@
17571556 static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
17581557 u64 *formats)
17591558 {
1760
- struct snd_soc_pcm_runtime *fe = substream->private_data;
1559
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
17611560 struct snd_soc_dpcm *dpcm;
1561
+ struct snd_soc_dai *dai;
17621562 int stream = substream->stream;
17631563
17641564 if (!fe->dai_link->dpcm_merged_format)
....@@ -1769,26 +1569,20 @@
17691569 * if FE want to use it (= dpcm_merged_format)
17701570 */
17711571
1772
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1572
+ for_each_dpcm_be(fe, stream, dpcm) {
17731573 struct snd_soc_pcm_runtime *be = dpcm->be;
1774
- struct snd_soc_dai_driver *codec_dai_drv;
17751574 struct snd_soc_pcm_stream *codec_stream;
17761575 int i;
17771576
1778
- for (i = 0; i < be->num_codecs; i++) {
1577
+ for_each_rtd_codec_dais(be, i, dai) {
17791578 /*
17801579 * Skip CODECs which don't support the current stream
17811580 * type. See soc_pcm_init_runtime_hw() for more details
17821581 */
1783
- if (!snd_soc_dai_stream_valid(be->codec_dais[i],
1784
- stream))
1582
+ if (!snd_soc_dai_stream_valid(dai, stream))
17851583 continue;
17861584
1787
- codec_dai_drv = be->codec_dais[i]->driver;
1788
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1789
- codec_stream = &codec_dai_drv->playback;
1790
- else
1791
- codec_stream = &codec_dai_drv->capture;
1585
+ codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
17921586
17931587 *formats &= codec_stream->formats;
17941588 }
....@@ -1799,7 +1593,7 @@
17991593 unsigned int *channels_min,
18001594 unsigned int *channels_max)
18011595 {
1802
- struct snd_soc_pcm_runtime *fe = substream->private_data;
1596
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
18031597 struct snd_soc_dpcm *dpcm;
18041598 int stream = substream->stream;
18051599
....@@ -1811,32 +1605,35 @@
18111605 * if FE want to use it (= dpcm_merged_chan)
18121606 */
18131607
1814
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1608
+ for_each_dpcm_be(fe, stream, dpcm) {
18151609 struct snd_soc_pcm_runtime *be = dpcm->be;
1816
- struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver;
1817
- struct snd_soc_dai_driver *codec_dai_drv;
18181610 struct snd_soc_pcm_stream *codec_stream;
18191611 struct snd_soc_pcm_stream *cpu_stream;
1612
+ struct snd_soc_dai *dai;
1613
+ int i;
18201614
1821
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1822
- cpu_stream = &cpu_dai_drv->playback;
1823
- else
1824
- cpu_stream = &cpu_dai_drv->capture;
1615
+ for_each_rtd_cpu_dais(be, i, dai) {
1616
+ /*
1617
+ * Skip CPUs which don't support the current stream
1618
+ * type. See soc_pcm_init_runtime_hw() for more details
1619
+ */
1620
+ if (!snd_soc_dai_stream_valid(dai, stream))
1621
+ continue;
18251622
1826
- *channels_min = max(*channels_min, cpu_stream->channels_min);
1827
- *channels_max = min(*channels_max, cpu_stream->channels_max);
1623
+ cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
1624
+
1625
+ *channels_min = max(*channels_min,
1626
+ cpu_stream->channels_min);
1627
+ *channels_max = min(*channels_max,
1628
+ cpu_stream->channels_max);
1629
+ }
18281630
18291631 /*
18301632 * chan min/max cannot be enforced if there are multiple CODEC
18311633 * DAIs connected to a single CPU DAI, use CPU DAI's directly
18321634 */
18331635 if (be->num_codecs == 1) {
1834
- codec_dai_drv = be->codec_dais[0]->driver;
1835
-
1836
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1837
- codec_stream = &codec_dai_drv->playback;
1838
- else
1839
- codec_stream = &codec_dai_drv->capture;
1636
+ codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
18401637
18411638 *channels_min = max(*channels_min,
18421639 codec_stream->channels_min);
....@@ -1851,7 +1648,7 @@
18511648 unsigned int *rate_min,
18521649 unsigned int *rate_max)
18531650 {
1854
- struct snd_soc_pcm_runtime *fe = substream->private_data;
1651
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
18551652 struct snd_soc_dpcm *dpcm;
18561653 int stream = substream->stream;
18571654
....@@ -1863,43 +1660,25 @@
18631660 * if FE want to use it (= dpcm_merged_chan)
18641661 */
18651662
1866
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1663
+ for_each_dpcm_be(fe, stream, dpcm) {
18671664 struct snd_soc_pcm_runtime *be = dpcm->be;
1868
- struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver;
1869
- struct snd_soc_dai_driver *codec_dai_drv;
1870
- struct snd_soc_pcm_stream *codec_stream;
1871
- struct snd_soc_pcm_stream *cpu_stream;
1665
+ struct snd_soc_pcm_stream *pcm;
1666
+ struct snd_soc_dai *dai;
18721667 int i;
18731668
1874
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1875
- cpu_stream = &cpu_dai_drv->playback;
1876
- else
1877
- cpu_stream = &cpu_dai_drv->capture;
1878
-
1879
- *rate_min = max(*rate_min, cpu_stream->rate_min);
1880
- *rate_max = min_not_zero(*rate_max, cpu_stream->rate_max);
1881
- *rates = snd_pcm_rate_mask_intersect(*rates, cpu_stream->rates);
1882
-
1883
- for (i = 0; i < be->num_codecs; i++) {
1669
+ for_each_rtd_dais(be, i, dai) {
18841670 /*
1885
- * Skip CODECs which don't support the current stream
1671
+ * Skip DAIs which don't support the current stream
18861672 * type. See soc_pcm_init_runtime_hw() for more details
18871673 */
1888
- if (!snd_soc_dai_stream_valid(be->codec_dais[i],
1889
- stream))
1674
+ if (!snd_soc_dai_stream_valid(dai, stream))
18901675 continue;
18911676
1892
- codec_dai_drv = be->codec_dais[i]->driver;
1893
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1894
- codec_stream = &codec_dai_drv->playback;
1895
- else
1896
- codec_stream = &codec_dai_drv->capture;
1677
+ pcm = snd_soc_dai_get_pcm_stream(dai, stream);
18971678
1898
- *rate_min = max(*rate_min, codec_stream->rate_min);
1899
- *rate_max = min_not_zero(*rate_max,
1900
- codec_stream->rate_max);
1901
- *rates = snd_pcm_rate_mask_intersect(*rates,
1902
- codec_stream->rates);
1679
+ *rate_min = max(*rate_min, pcm->rate_min);
1680
+ *rate_max = min_not_zero(*rate_max, pcm->rate_max);
1681
+ *rates = snd_pcm_rate_mask_intersect(*rates, pcm->rates);
19031682 }
19041683 }
19051684 }
....@@ -1907,14 +1686,22 @@
19071686 static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
19081687 {
19091688 struct snd_pcm_runtime *runtime = substream->runtime;
1910
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
1911
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1912
- struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
1689
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1690
+ struct snd_soc_dai *cpu_dai;
1691
+ int i;
19131692
1914
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1915
- dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback);
1916
- else
1917
- dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture);
1693
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
1694
+ /*
1695
+ * Skip CPUs which don't support the current stream
1696
+ * type. See soc_pcm_init_runtime_hw() for more details
1697
+ */
1698
+ if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
1699
+ continue;
1700
+
1701
+ dpcm_init_runtime_hw(runtime,
1702
+ snd_soc_dai_get_pcm_stream(cpu_dai,
1703
+ substream->stream));
1704
+ }
19181705
19191706 dpcm_runtime_merge_format(substream, &runtime->hw.formats);
19201707 dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min,
....@@ -1950,29 +1737,38 @@
19501737 int stream)
19511738 {
19521739 struct snd_soc_dpcm *dpcm;
1953
- struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1954
- struct snd_soc_dai *fe_cpu_dai = fe->cpu_dai;
1955
- int err;
1740
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
1741
+ struct snd_soc_dai *fe_cpu_dai;
1742
+ int err = 0;
1743
+ int i;
19561744
19571745 /* apply symmetry for FE */
19581746 if (soc_pcm_has_symmetry(fe_substream))
19591747 fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
19601748
1961
- /* Symmetry only applies if we've got an active stream. */
1962
- if (fe_cpu_dai->active) {
1963
- err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
1964
- if (err < 0)
1965
- return err;
1749
+ for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) {
1750
+ /* Symmetry only applies if we've got an active stream. */
1751
+ if (snd_soc_dai_active(fe_cpu_dai)) {
1752
+ err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
1753
+ if (err < 0)
1754
+ return err;
1755
+ }
19661756 }
19671757
19681758 /* apply symmetry for BE */
1969
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1759
+ for_each_dpcm_be(fe, stream, dpcm) {
19701760 struct snd_soc_pcm_runtime *be = dpcm->be;
19711761 struct snd_pcm_substream *be_substream =
19721762 snd_soc_dpcm_get_substream(be, stream);
1973
- struct snd_soc_pcm_runtime *rtd = be_substream->private_data;
1763
+ struct snd_soc_pcm_runtime *rtd;
1764
+ struct snd_soc_dai *dai;
19741765 int i;
19751766
1767
+ /* A backend may not have the requested substream */
1768
+ if (!be_substream)
1769
+ continue;
1770
+
1771
+ rtd = asoc_substream_to_rtd(be_substream);
19761772 if (rtd->dai_link->be_hw_params_fixup)
19771773 continue;
19781774
....@@ -1980,17 +1776,9 @@
19801776 be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
19811777
19821778 /* Symmetry only applies if we've got an active stream. */
1983
- if (rtd->cpu_dai->active) {
1984
- err = soc_pcm_apply_symmetry(fe_substream,
1985
- rtd->cpu_dai);
1986
- if (err < 0)
1987
- return err;
1988
- }
1989
-
1990
- for (i = 0; i < rtd->num_codecs; i++) {
1991
- if (rtd->codec_dais[i]->active) {
1992
- err = soc_pcm_apply_symmetry(fe_substream,
1993
- rtd->codec_dais[i]);
1779
+ for_each_rtd_dais(rtd, i, dai) {
1780
+ if (snd_soc_dai_active(dai)) {
1781
+ err = soc_pcm_apply_symmetry(fe_substream, dai);
19941782 if (err < 0)
19951783 return err;
19961784 }
....@@ -2002,13 +1790,13 @@
20021790
20031791 static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
20041792 {
2005
- struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1793
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
20061794 struct snd_pcm_runtime *runtime = fe_substream->runtime;
20071795 int stream = fe_substream->stream, ret = 0;
20081796
20091797 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
20101798
2011
- ret = dpcm_be_dai_startup(fe, fe_substream->stream);
1799
+ ret = dpcm_be_dai_startup(fe, stream);
20121800 if (ret < 0) {
20131801 dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret);
20141802 goto be_err;
....@@ -2029,17 +1817,13 @@
20291817 snd_pcm_limit_hw_rates(runtime);
20301818
20311819 ret = dpcm_apply_symmetry(fe_substream, stream);
2032
- if (ret < 0) {
1820
+ if (ret < 0)
20331821 dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n",
20341822 ret);
2035
- goto unwind;
2036
- }
2037
-
2038
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2039
- return 0;
20401823
20411824 unwind:
2042
- dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
1825
+ if (ret < 0)
1826
+ dpcm_be_dai_startup_unwind(fe, stream);
20431827 be_err:
20441828 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
20451829 return ret;
....@@ -2050,7 +1834,7 @@
20501834 struct snd_soc_dpcm *dpcm;
20511835
20521836 /* only shutdown BEs that are either sinks or sources to this FE DAI */
2053
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1837
+ for_each_dpcm_be(fe, stream, dpcm) {
20541838
20551839 struct snd_soc_pcm_runtime *be = dpcm->be;
20561840 struct snd_pcm_substream *be_substream =
....@@ -2087,13 +1871,13 @@
20871871
20881872 static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
20891873 {
2090
- struct snd_soc_pcm_runtime *fe = substream->private_data;
1874
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
20911875 int stream = substream->stream;
20921876
20931877 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
20941878
20951879 /* shutdown the BEs */
2096
- dpcm_be_dai_shutdown(fe, substream->stream);
1880
+ dpcm_be_dai_shutdown(fe, stream);
20971881
20981882 dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
20991883
....@@ -2114,7 +1898,7 @@
21141898
21151899 /* only hw_params backends that are either sinks or sources
21161900 * to this frontend DAI */
2117
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1901
+ for_each_dpcm_be(fe, stream, dpcm) {
21181902
21191903 struct snd_soc_pcm_runtime *be = dpcm->be;
21201904 struct snd_pcm_substream *be_substream =
....@@ -2153,7 +1937,7 @@
21531937
21541938 static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
21551939 {
2156
- struct snd_soc_pcm_runtime *fe = substream->private_data;
1940
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
21571941 int err, stream = substream->stream;
21581942
21591943 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
....@@ -2183,7 +1967,7 @@
21831967 struct snd_soc_dpcm *dpcm;
21841968 int ret;
21851969
2186
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1970
+ for_each_dpcm_be(fe, stream, dpcm) {
21871971
21881972 struct snd_soc_pcm_runtime *be = dpcm->be;
21891973 struct snd_pcm_substream *be_substream =
....@@ -2198,16 +1982,13 @@
21981982 sizeof(struct snd_pcm_hw_params));
21991983
22001984 /* perform any hw_params fixups */
2201
- if (be->dai_link->be_hw_params_fixup) {
2202
- ret = be->dai_link->be_hw_params_fixup(be,
2203
- &dpcm->hw_params);
2204
- if (ret < 0) {
2205
- dev_err(be->dev,
2206
- "ASoC: hw_params BE fixup failed %d\n",
2207
- ret);
2208
- goto unwind;
2209
- }
2210
- }
1985
+ ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params);
1986
+ if (ret < 0)
1987
+ goto unwind;
1988
+
1989
+ /* copy the fixed-up hw params for BE dai */
1990
+ memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params,
1991
+ sizeof(struct snd_pcm_hw_params));
22111992
22121993 /* only allow hw_params() if no connected FEs are running */
22131994 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
....@@ -2234,7 +2015,7 @@
22342015
22352016 unwind:
22362017 /* disable any enabled and non active backends */
2237
- list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2018
+ for_each_dpcm_be_rollback(fe, stream, dpcm) {
22382019 struct snd_soc_pcm_runtime *be = dpcm->be;
22392020 struct snd_pcm_substream *be_substream =
22402021 snd_soc_dpcm_get_substream(be, stream);
....@@ -2261,15 +2042,15 @@
22612042 static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
22622043 struct snd_pcm_hw_params *params)
22632044 {
2264
- struct snd_soc_pcm_runtime *fe = substream->private_data;
2045
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
22652046 int ret, stream = substream->stream;
22662047
22672048 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
22682049 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
22692050
2270
- memcpy(&fe->dpcm[substream->stream].hw_params, params,
2051
+ memcpy(&fe->dpcm[stream].hw_params, params,
22712052 sizeof(struct snd_pcm_hw_params));
2272
- ret = dpcm_be_dai_hw_params(fe, substream->stream);
2053
+ ret = dpcm_be_dai_hw_params(fe, stream);
22732054 if (ret < 0) {
22742055 dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret);
22752056 goto out;
....@@ -2314,7 +2095,7 @@
23142095 struct snd_soc_dpcm *dpcm;
23152096 int ret = 0;
23162097
2317
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2098
+ for_each_dpcm_be(fe, stream, dpcm) {
23182099
23192100 struct snd_soc_pcm_runtime *be = dpcm->be;
23202101 struct snd_pcm_substream *be_substream =
....@@ -2407,7 +2188,7 @@
24072188 static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
24082189 int cmd, bool fe_first)
24092190 {
2410
- struct snd_soc_pcm_runtime *fe = substream->private_data;
2191
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
24112192 int ret;
24122193
24132194 /* call trigger on the frontend before the backend. */
....@@ -2438,7 +2219,7 @@
24382219
24392220 static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
24402221 {
2441
- struct snd_soc_pcm_runtime *fe = substream->private_data;
2222
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
24422223 int stream = substream->stream;
24432224 int ret = 0;
24442225 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
....@@ -2488,7 +2269,7 @@
24882269 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
24892270 fe->dai_link->name, cmd);
24902271
2491
- ret = soc_pcm_bespoke_trigger(substream, cmd);
2272
+ ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd);
24922273 break;
24932274 default:
24942275 dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
....@@ -2525,7 +2306,7 @@
25252306
25262307 static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
25272308 {
2528
- struct snd_soc_pcm_runtime *fe = substream->private_data;
2309
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
25292310 int stream = substream->stream;
25302311
25312312 /* if FE's runtime_update is already set, we're in race;
....@@ -2545,7 +2326,7 @@
25452326 struct snd_soc_dpcm *dpcm;
25462327 int ret = 0;
25472328
2548
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2329
+ for_each_dpcm_be(fe, stream, dpcm) {
25492330
25502331 struct snd_soc_pcm_runtime *be = dpcm->be;
25512332 struct snd_pcm_substream *be_substream =
....@@ -2553,6 +2334,9 @@
25532334
25542335 /* is this op for this BE ? */
25552336 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2337
+ continue;
2338
+
2339
+ if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
25562340 continue;
25572341
25582342 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
....@@ -2578,7 +2362,7 @@
25782362
25792363 static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
25802364 {
2581
- struct snd_soc_pcm_runtime *fe = substream->private_data;
2365
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
25822366 int stream = substream->stream, ret = 0;
25832367
25842368 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
....@@ -2595,7 +2379,7 @@
25952379 goto out;
25962380 }
25972381
2598
- ret = dpcm_be_dai_prepare(fe, substream->stream);
2382
+ ret = dpcm_be_dai_prepare(fe, stream);
25992383 if (ret < 0)
26002384 goto out;
26012385
....@@ -2618,27 +2402,6 @@
26182402 return ret;
26192403 }
26202404
2621
-static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
2622
- unsigned int cmd, void *arg)
2623
-{
2624
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
2625
- struct snd_soc_component *component;
2626
- struct snd_soc_rtdcom_list *rtdcom;
2627
-
2628
- for_each_rtdcom(rtd, rtdcom) {
2629
- component = rtdcom->component;
2630
-
2631
- if (!component->driver->ops ||
2632
- !component->driver->ops->ioctl)
2633
- continue;
2634
-
2635
- /* FIXME: use 1st ioctl */
2636
- return component->driver->ops->ioctl(substream, cmd, arg);
2637
- }
2638
-
2639
- return snd_pcm_lib_ioctl(substream, cmd, arg);
2640
-}
2641
-
26422405 static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
26432406 {
26442407 struct snd_pcm_substream *substream =
....@@ -2654,7 +2417,7 @@
26542417 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
26552418 fe->dai_link->name);
26562419
2657
- err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
2420
+ err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
26582421 if (err < 0)
26592422 dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
26602423 } else {
....@@ -2687,6 +2450,7 @@
26872450 struct snd_soc_dpcm *dpcm;
26882451 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
26892452 int ret;
2453
+ unsigned long flags;
26902454
26912455 dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
26922456 stream ? "capture" : "playback", fe->dai_link->name);
....@@ -2731,7 +2495,7 @@
27312495 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
27322496 fe->dai_link->name);
27332497
2734
- ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
2498
+ ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
27352499 if (ret < 0) {
27362500 dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret);
27372501 goto hw_free;
....@@ -2755,38 +2519,14 @@
27552519 close:
27562520 dpcm_be_dai_shutdown(fe, stream);
27572521 disconnect:
2758
- /* disconnect any non started BEs */
2759
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2522
+ /* disconnect any closed BEs */
2523
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
2524
+ for_each_dpcm_be(fe, stream, dpcm) {
27602525 struct snd_soc_pcm_runtime *be = dpcm->be;
2761
- if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
2762
- dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2526
+ if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
2527
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
27632528 }
2764
-
2765
- return ret;
2766
-}
2767
-
2768
-static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
2769
-{
2770
- int ret;
2771
-
2772
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
2773
- ret = dpcm_run_update_startup(fe, stream);
2774
- if (ret < 0)
2775
- dev_err(fe->dev, "ASoC: failed to startup some BEs\n");
2776
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2777
-
2778
- return ret;
2779
-}
2780
-
2781
-static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
2782
-{
2783
- int ret;
2784
-
2785
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
2786
- ret = dpcm_run_update_shutdown(fe, stream);
2787
- if (ret < 0)
2788
- dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
2789
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2529
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
27902530
27912531 return ret;
27922532 }
....@@ -2794,79 +2534,66 @@
27942534 static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
27952535 {
27962536 struct snd_soc_dapm_widget_list *list;
2537
+ int stream;
27972538 int count, paths;
2539
+ int ret;
27982540
27992541 if (!fe->dai_link->dynamic)
28002542 return 0;
28012543
2544
+ if (fe->num_cpus > 1) {
2545
+ dev_err(fe->dev,
2546
+ "%s doesn't support Multi CPU yet\n", __func__);
2547
+ return -EINVAL;
2548
+ }
2549
+
28022550 /* only check active links */
2803
- if (!fe->cpu_dai->active)
2551
+ if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0)))
28042552 return 0;
28052553
28062554 /* DAPM sync will call this to update DSP paths */
28072555 dev_dbg(fe->dev, "ASoC: DPCM %s runtime update for FE %s\n",
28082556 new ? "new" : "old", fe->dai_link->name);
28092557
2810
- /* skip if FE doesn't have playback capability */
2811
- if (!fe->cpu_dai->driver->playback.channels_min ||
2812
- !fe->codec_dai->driver->playback.channels_min)
2813
- goto capture;
2558
+ for_each_pcm_streams(stream) {
28142559
2815
- /* skip if FE isn't currently playing */
2816
- if (!fe->cpu_dai->playback_active || !fe->codec_dai->playback_active)
2817
- goto capture;
2560
+ /* skip if FE doesn't have playback/capture capability */
2561
+ if (!snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream) ||
2562
+ !snd_soc_dai_stream_valid(asoc_rtd_to_codec(fe, 0), stream))
2563
+ continue;
28182564
2819
- paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
2820
- if (paths < 0) {
2821
- dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
2822
- fe->dai_link->name, "playback");
2823
- return paths;
2565
+ /* skip if FE isn't currently playing/capturing */
2566
+ if (!snd_soc_dai_stream_active(asoc_rtd_to_cpu(fe, 0), stream) ||
2567
+ !snd_soc_dai_stream_active(asoc_rtd_to_codec(fe, 0), stream))
2568
+ continue;
2569
+
2570
+ paths = dpcm_path_get(fe, stream, &list);
2571
+ if (paths < 0) {
2572
+ dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
2573
+ fe->dai_link->name,
2574
+ stream == SNDRV_PCM_STREAM_PLAYBACK ?
2575
+ "playback" : "capture");
2576
+ return paths;
2577
+ }
2578
+
2579
+ /* update any playback/capture paths */
2580
+ count = dpcm_process_paths(fe, stream, &list, new);
2581
+ if (count) {
2582
+ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
2583
+ if (new)
2584
+ ret = dpcm_run_update_startup(fe, stream);
2585
+ else
2586
+ ret = dpcm_run_update_shutdown(fe, stream);
2587
+ if (ret < 0)
2588
+ dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
2589
+ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2590
+
2591
+ dpcm_clear_pending_state(fe, stream);
2592
+ dpcm_be_disconnect(fe, stream);
2593
+ }
2594
+
2595
+ dpcm_path_put(&list);
28242596 }
2825
-
2826
- /* update any playback paths */
2827
- count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, new);
2828
- if (count) {
2829
- if (new)
2830
- dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2831
- else
2832
- dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2833
-
2834
- dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK);
2835
- dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2836
- }
2837
-
2838
- dpcm_path_put(&list);
2839
-
2840
-capture:
2841
- /* skip if FE doesn't have capture capability */
2842
- if (!fe->cpu_dai->driver->capture.channels_min ||
2843
- !fe->codec_dai->driver->capture.channels_min)
2844
- return 0;
2845
-
2846
- /* skip if FE isn't currently capturing */
2847
- if (!fe->cpu_dai->capture_active || !fe->codec_dai->capture_active)
2848
- return 0;
2849
-
2850
- paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
2851
- if (paths < 0) {
2852
- dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
2853
- fe->dai_link->name, "capture");
2854
- return paths;
2855
- }
2856
-
2857
- /* update any old capture paths */
2858
- count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, new);
2859
- if (count) {
2860
- if (new)
2861
- dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2862
- else
2863
- dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2864
-
2865
- dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE);
2866
- dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2867
- }
2868
-
2869
- dpcm_path_put(&list);
28702597
28712598 return 0;
28722599 }
....@@ -2874,21 +2601,21 @@
28742601 /* Called by DAPM mixer/mux changes to update audio routing between PCMs and
28752602 * any DAI links.
28762603 */
2877
-int soc_dpcm_runtime_update(struct snd_soc_card *card)
2604
+int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
28782605 {
28792606 struct snd_soc_pcm_runtime *fe;
28802607 int ret = 0;
28812608
28822609 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
28832610 /* shutdown all old paths first */
2884
- list_for_each_entry(fe, &card->rtd_list, list) {
2611
+ for_each_card_rtds(card, fe) {
28852612 ret = soc_dpcm_fe_runtime_update(fe, 0);
28862613 if (ret)
28872614 goto out;
28882615 }
28892616
28902617 /* bring new paths up */
2891
- list_for_each_entry(fe, &card->rtd_list, list) {
2618
+ for_each_card_rtds(card, fe) {
28922619 ret = soc_dpcm_fe_runtime_update(fe, 1);
28932620 if (ret)
28942621 goto out;
....@@ -2898,40 +2625,40 @@
28982625 mutex_unlock(&card->mutex);
28992626 return ret;
29002627 }
2901
-int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
2628
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update);
2629
+
2630
+static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream)
29022631 {
2632
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
29032633 struct snd_soc_dpcm *dpcm;
2904
- struct list_head *clients =
2905
- &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients;
2634
+ int stream = fe_substream->stream;
29062635
2907
- list_for_each_entry(dpcm, clients, list_be) {
2636
+ /* mark FE's links ready to prune */
2637
+ for_each_dpcm_be(fe, stream, dpcm)
2638
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
29082639
2909
- struct snd_soc_pcm_runtime *be = dpcm->be;
2910
- int i;
2640
+ dpcm_be_disconnect(fe, stream);
29112641
2912
- if (be->dai_link->ignore_suspend)
2913
- continue;
2642
+ fe->dpcm[stream].runtime = NULL;
2643
+}
29142644
2915
- for (i = 0; i < be->num_codecs; i++) {
2916
- struct snd_soc_dai *dai = be->codec_dais[i];
2917
- struct snd_soc_dai_driver *drv = dai->driver;
2645
+static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2646
+{
2647
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
2648
+ int ret;
29182649
2919
- dev_dbg(be->dev, "ASoC: BE digital mute %s\n",
2920
- be->dai_link->name);
2650
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
2651
+ ret = dpcm_fe_dai_shutdown(fe_substream);
29212652
2922
- if (drv->ops && drv->ops->digital_mute &&
2923
- dai->playback_active)
2924
- drv->ops->digital_mute(dai, mute);
2925
- }
2926
- }
2653
+ dpcm_fe_dai_cleanup(fe_substream);
29272654
2928
- return 0;
2655
+ mutex_unlock(&fe->card->mutex);
2656
+ return ret;
29292657 }
29302658
29312659 static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
29322660 {
2933
- struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2934
- struct snd_soc_dpcm *dpcm;
2661
+ struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
29352662 struct snd_soc_dapm_widget_list *list;
29362663 int ret;
29372664 int stream = fe_substream->stream;
....@@ -2941,8 +2668,7 @@
29412668
29422669 ret = dpcm_path_get(fe, stream, &list);
29432670 if (ret < 0) {
2944
- mutex_unlock(&fe->card->mutex);
2945
- return ret;
2671
+ goto open_end;
29462672 } else if (ret == 0) {
29472673 dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
29482674 fe->dai_link->name, stream ? "capture" : "playback");
....@@ -2952,216 +2678,94 @@
29522678 dpcm_process_paths(fe, stream, &list, 1);
29532679
29542680 ret = dpcm_fe_dai_startup(fe_substream);
2955
- if (ret < 0) {
2956
- /* clean up all links */
2957
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
2958
- dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2959
-
2960
- dpcm_be_disconnect(fe, stream);
2961
- fe->dpcm[stream].runtime = NULL;
2962
- }
2681
+ if (ret < 0)
2682
+ dpcm_fe_dai_cleanup(fe_substream);
29632683
29642684 dpcm_clear_pending_state(fe, stream);
29652685 dpcm_path_put(&list);
2686
+open_end:
29662687 mutex_unlock(&fe->card->mutex);
29672688 return ret;
2968
-}
2969
-
2970
-static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2971
-{
2972
- struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2973
- struct snd_soc_dpcm *dpcm;
2974
- int stream = fe_substream->stream, ret;
2975
-
2976
- mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
2977
- ret = dpcm_fe_dai_shutdown(fe_substream);
2978
-
2979
- /* mark FE's links ready to prune */
2980
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
2981
- dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2982
-
2983
- dpcm_be_disconnect(fe, stream);
2984
-
2985
- fe->dpcm[stream].runtime = NULL;
2986
- mutex_unlock(&fe->card->mutex);
2987
- return ret;
2988
-}
2989
-
2990
-static void soc_pcm_private_free(struct snd_pcm *pcm)
2991
-{
2992
- struct snd_soc_pcm_runtime *rtd = pcm->private_data;
2993
- struct snd_soc_rtdcom_list *rtdcom;
2994
- struct snd_soc_component *component;
2995
-
2996
- /* need to sync the delayed work before releasing resources */
2997
- flush_delayed_work(&rtd->delayed_work);
2998
- for_each_rtdcom(rtd, rtdcom) {
2999
- component = rtdcom->component;
3000
-
3001
- if (component->driver->pcm_free)
3002
- component->driver->pcm_free(pcm);
3003
- }
3004
-}
3005
-
3006
-static int soc_rtdcom_ack(struct snd_pcm_substream *substream)
3007
-{
3008
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3009
- struct snd_soc_rtdcom_list *rtdcom;
3010
- struct snd_soc_component *component;
3011
-
3012
- for_each_rtdcom(rtd, rtdcom) {
3013
- component = rtdcom->component;
3014
-
3015
- if (!component->driver->ops ||
3016
- !component->driver->ops->ack)
3017
- continue;
3018
-
3019
- /* FIXME. it returns 1st ask now */
3020
- return component->driver->ops->ack(substream);
3021
- }
3022
-
3023
- return -EINVAL;
3024
-}
3025
-
3026
-static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel,
3027
- unsigned long pos, void __user *buf,
3028
- unsigned long bytes)
3029
-{
3030
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3031
- struct snd_soc_rtdcom_list *rtdcom;
3032
- struct snd_soc_component *component;
3033
-
3034
- for_each_rtdcom(rtd, rtdcom) {
3035
- component = rtdcom->component;
3036
-
3037
- if (!component->driver->ops ||
3038
- !component->driver->ops->copy_user)
3039
- continue;
3040
-
3041
- /* FIXME. it returns 1st copy now */
3042
- return component->driver->ops->copy_user(substream, channel,
3043
- pos, buf, bytes);
3044
- }
3045
-
3046
- return -EINVAL;
3047
-}
3048
-
3049
-static int soc_rtdcom_copy_kernel(struct snd_pcm_substream *substream, int channel,
3050
- unsigned long pos, void *buf, unsigned long bytes)
3051
-{
3052
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3053
- struct snd_soc_rtdcom_list *rtdcom;
3054
- struct snd_soc_component *component;
3055
-
3056
- for_each_rtdcom(rtd, rtdcom) {
3057
- component = rtdcom->component;
3058
-
3059
- if (!component->driver->ops ||
3060
- !component->driver->ops->copy_kernel)
3061
- continue;
3062
-
3063
- /* FIXME. it returns 1st copy now */
3064
- return component->driver->ops->copy_kernel(substream, channel,
3065
- pos, buf, bytes);
3066
- }
3067
-
3068
- return -EINVAL;
3069
-}
3070
-
3071
-static int soc_rtdcom_fill_silence(struct snd_pcm_substream *substream, int channel,
3072
- unsigned long pos, unsigned long bytes)
3073
-{
3074
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3075
- struct snd_soc_rtdcom_list *rtdcom;
3076
- struct snd_soc_component *component;
3077
-
3078
- for_each_rtdcom(rtd, rtdcom) {
3079
- component = rtdcom->component;
3080
-
3081
- if (!component->driver->ops ||
3082
- !component->driver->ops->fill_silence)
3083
- continue;
3084
-
3085
- /* FIXME. it returns 1st silence now */
3086
- return component->driver->ops->fill_silence(substream, channel,
3087
- pos, bytes);
3088
- }
3089
-
3090
- return -EINVAL;
3091
-}
3092
-
3093
-static struct page *soc_rtdcom_page(struct snd_pcm_substream *substream,
3094
- unsigned long offset)
3095
-{
3096
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3097
- struct snd_soc_rtdcom_list *rtdcom;
3098
- struct snd_soc_component *component;
3099
- struct page *page;
3100
-
3101
- for_each_rtdcom(rtd, rtdcom) {
3102
- component = rtdcom->component;
3103
-
3104
- if (!component->driver->ops ||
3105
- !component->driver->ops->page)
3106
- continue;
3107
-
3108
- /* FIXME. it returns 1st page now */
3109
- page = component->driver->ops->page(substream, offset);
3110
- if (page)
3111
- return page;
3112
- }
3113
-
3114
- return NULL;
3115
-}
3116
-
3117
-static int soc_rtdcom_mmap(struct snd_pcm_substream *substream,
3118
- struct vm_area_struct *vma)
3119
-{
3120
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
3121
- struct snd_soc_rtdcom_list *rtdcom;
3122
- struct snd_soc_component *component;
3123
-
3124
- for_each_rtdcom(rtd, rtdcom) {
3125
- component = rtdcom->component;
3126
-
3127
- if (!component->driver->ops ||
3128
- !component->driver->ops->mmap)
3129
- continue;
3130
-
3131
- /* FIXME. it returns 1st mmap now */
3132
- return component->driver->ops->mmap(substream, vma);
3133
- }
3134
-
3135
- return -EINVAL;
31362689 }
31372690
31382691 /* create a new pcm */
31392692 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
31402693 {
31412694 struct snd_soc_dai *codec_dai;
3142
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2695
+ struct snd_soc_dai *cpu_dai;
31432696 struct snd_soc_component *component;
3144
- struct snd_soc_rtdcom_list *rtdcom;
31452697 struct snd_pcm *pcm;
3146
- struct snd_pcm_str *stream;
31472698 char new_name[64];
31482699 int ret = 0, playback = 0, capture = 0;
2700
+ int stream;
31492701 int i;
31502702
2703
+ if (rtd->dai_link->dynamic && rtd->num_cpus > 1) {
2704
+ dev_err(rtd->dev,
2705
+ "DPCM doesn't support Multi CPU for Front-Ends yet\n");
2706
+ return -EINVAL;
2707
+ }
2708
+
31512709 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
3152
- playback = rtd->dai_link->dpcm_playback;
3153
- capture = rtd->dai_link->dpcm_capture;
2710
+ if (rtd->dai_link->dpcm_playback) {
2711
+ stream = SNDRV_PCM_STREAM_PLAYBACK;
2712
+
2713
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2714
+ if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2715
+ playback = 1;
2716
+ break;
2717
+ }
2718
+ }
2719
+
2720
+ if (!playback) {
2721
+ dev_err(rtd->card->dev,
2722
+ "No CPU DAIs support playback for stream %s\n",
2723
+ rtd->dai_link->stream_name);
2724
+ return -EINVAL;
2725
+ }
2726
+ }
2727
+ if (rtd->dai_link->dpcm_capture) {
2728
+ stream = SNDRV_PCM_STREAM_CAPTURE;
2729
+
2730
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2731
+ if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2732
+ capture = 1;
2733
+ break;
2734
+ }
2735
+ }
2736
+
2737
+ if (!capture) {
2738
+ dev_err(rtd->card->dev,
2739
+ "No CPU DAIs support capture for stream %s\n",
2740
+ rtd->dai_link->stream_name);
2741
+ return -EINVAL;
2742
+ }
2743
+ }
31542744 } else {
3155
- for (i = 0; i < rtd->num_codecs; i++) {
3156
- codec_dai = rtd->codec_dais[i];
3157
- if (codec_dai->driver->playback.channels_min)
2745
+ /* Adapt stream for codec2codec links */
2746
+ int cpu_capture = rtd->dai_link->params ?
2747
+ SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
2748
+ int cpu_playback = rtd->dai_link->params ?
2749
+ SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
2750
+
2751
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
2752
+ if (rtd->num_cpus == 1) {
2753
+ cpu_dai = asoc_rtd_to_cpu(rtd, 0);
2754
+ } else if (rtd->num_cpus == rtd->num_codecs) {
2755
+ cpu_dai = asoc_rtd_to_cpu(rtd, i);
2756
+ } else {
2757
+ dev_err(rtd->card->dev,
2758
+ "N cpus to M codecs link is not supported yet\n");
2759
+ return -EINVAL;
2760
+ }
2761
+
2762
+ if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
2763
+ snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
31582764 playback = 1;
3159
- if (codec_dai->driver->capture.channels_min)
2765
+ if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
2766
+ snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
31602767 capture = 1;
31612768 }
3162
-
3163
- capture = capture && cpu_dai->driver->capture.channels_min;
3164
- playback = playback && cpu_dai->driver->playback.channels_min;
31652769 }
31662770
31672771 if (rtd->dai_link->playback_only) {
....@@ -3175,7 +2779,13 @@
31752779 }
31762780
31772781 /* create the PCM */
3178
- if (rtd->dai_link->no_pcm) {
2782
+ if (rtd->dai_link->params) {
2783
+ snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
2784
+ rtd->dai_link->stream_name);
2785
+
2786
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
2787
+ playback, capture, &pcm);
2788
+ } else if (rtd->dai_link->no_pcm) {
31792789 snprintf(new_name, sizeof(new_name), "(%s)",
31802790 rtd->dai_link->stream_name);
31812791
....@@ -3189,47 +2799,34 @@
31892799 snprintf(new_name, sizeof(new_name), "%s %s-%d",
31902800 rtd->dai_link->stream_name,
31912801 (rtd->num_codecs > 1) ?
3192
- "multicodec" : rtd->codec_dai->name, num);
2802
+ "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num);
31932803
31942804 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
31952805 capture, &pcm);
31962806 }
31972807 if (ret < 0) {
3198
- dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n",
3199
- rtd->dai_link->name);
2808
+ dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n",
2809
+ new_name, rtd->dai_link->name, ret);
32002810 return ret;
32012811 }
32022812 dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
32032813
32042814 /* DAPM dai link stream work */
3205
- INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2815
+ if (rtd->dai_link->params)
2816
+ rtd->close_delayed_work_func = codec2codec_close_delayed_work;
2817
+ else
2818
+ rtd->close_delayed_work_func = snd_soc_close_delayed_work;
32062819
32072820 pcm->nonatomic = rtd->dai_link->nonatomic;
32082821 rtd->pcm = pcm;
32092822 pcm->private_data = rtd;
32102823
3211
- if (rtd->dai_link->no_pcm) {
2824
+ if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
32122825 if (playback)
32132826 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
32142827 if (capture)
32152828 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
32162829 goto out;
3217
- }
3218
-
3219
- /* setup any hostless PCMs - i.e. no host IO is performed */
3220
- if (rtd->dai_link->no_host_mode) {
3221
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
3222
- stream = &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
3223
- stream->substream->hw_no_buffer = 1;
3224
- snd_soc_set_runtime_hwparams(stream->substream,
3225
- &no_host_hardware);
3226
- }
3227
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
3228
- stream = &pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
3229
- stream->substream->hw_no_buffer = 1;
3230
- snd_soc_set_runtime_hwparams(stream->substream,
3231
- &no_host_hardware);
3232
- }
32332830 }
32342831
32352832 /* ASoC PCM operations */
....@@ -3241,7 +2838,6 @@
32412838 rtd->ops.hw_free = dpcm_fe_dai_hw_free;
32422839 rtd->ops.close = dpcm_fe_dai_close;
32432840 rtd->ops.pointer = soc_pcm_pointer;
3244
- rtd->ops.ioctl = soc_pcm_ioctl;
32452841 } else {
32462842 rtd->ops.open = soc_pcm_open;
32472843 rtd->ops.hw_params = soc_pcm_hw_params;
....@@ -3250,27 +2846,23 @@
32502846 rtd->ops.hw_free = soc_pcm_hw_free;
32512847 rtd->ops.close = soc_pcm_close;
32522848 rtd->ops.pointer = soc_pcm_pointer;
3253
- rtd->ops.ioctl = soc_pcm_ioctl;
32542849 }
32552850
3256
- for_each_rtdcom(rtd, rtdcom) {
3257
- const struct snd_pcm_ops *ops = rtdcom->component->driver->ops;
2851
+ for_each_rtd_components(rtd, i, component) {
2852
+ const struct snd_soc_component_driver *drv = component->driver;
32582853
3259
- if (!ops)
3260
- continue;
3261
-
3262
- if (ops->ack)
3263
- rtd->ops.ack = soc_rtdcom_ack;
3264
- if (ops->copy_user)
3265
- rtd->ops.copy_user = soc_rtdcom_copy_user;
3266
- if (ops->copy_kernel)
3267
- rtd->ops.copy_kernel = soc_rtdcom_copy_kernel;
3268
- if (ops->fill_silence)
3269
- rtd->ops.fill_silence = soc_rtdcom_fill_silence;
3270
- if (ops->page)
3271
- rtd->ops.page = soc_rtdcom_page;
3272
- if (ops->mmap)
3273
- rtd->ops.mmap = soc_rtdcom_mmap;
2854
+ if (drv->ioctl)
2855
+ rtd->ops.ioctl = snd_soc_pcm_component_ioctl;
2856
+ if (drv->sync_stop)
2857
+ rtd->ops.sync_stop = snd_soc_pcm_component_sync_stop;
2858
+ if (drv->copy_user)
2859
+ rtd->ops.copy_user = snd_soc_pcm_component_copy_user;
2860
+ if (drv->page)
2861
+ rtd->ops.page = snd_soc_pcm_component_page;
2862
+ if (drv->mmap)
2863
+ rtd->ops.mmap = snd_soc_pcm_component_mmap;
2864
+ if (drv->ack)
2865
+ rtd->ops.ack = snd_soc_pcm_component_ack;
32742866 }
32752867
32762868 if (playback)
....@@ -3279,26 +2871,18 @@
32792871 if (capture)
32802872 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
32812873
3282
- for_each_rtdcom(rtd, rtdcom) {
3283
- component = rtdcom->component;
3284
-
3285
- if (!component->driver->pcm_new)
3286
- continue;
3287
-
3288
- ret = component->driver->pcm_new(rtd);
3289
- if (ret < 0) {
3290
- dev_err(component->dev,
3291
- "ASoC: pcm constructor failed: %d\n",
3292
- ret);
3293
- return ret;
3294
- }
2874
+ ret = snd_soc_pcm_component_new(rtd);
2875
+ if (ret < 0) {
2876
+ dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n",
2877
+ new_name, rtd->dai_link->name, ret);
2878
+ return ret;
32952879 }
32962880
3297
- pcm->private_free = soc_pcm_private_free;
2881
+ pcm->no_device_suspend = true;
32982882 out:
3299
- dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
3300
- (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
3301
- cpu_dai->name);
2883
+ dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n",
2884
+ (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name,
2885
+ (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name);
33022886 return ret;
33032887 }
33042888
....@@ -3331,21 +2915,37 @@
33312915 }
33322916 EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream);
33332917
3334
-/* get the BE runtime state */
3335
-enum snd_soc_dpcm_state
3336
- snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream)
2918
+static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
2919
+ struct snd_soc_pcm_runtime *be,
2920
+ int stream,
2921
+ const enum snd_soc_dpcm_state *states,
2922
+ int num_states)
33372923 {
3338
- return be->dpcm[stream].state;
3339
-}
3340
-EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_get_state);
2924
+ struct snd_soc_dpcm *dpcm;
2925
+ int state;
2926
+ int ret = 1;
2927
+ unsigned long flags;
2928
+ int i;
33412929
3342
-/* set the BE runtime state */
3343
-void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be,
3344
- int stream, enum snd_soc_dpcm_state state)
3345
-{
3346
- be->dpcm[stream].state = state;
2930
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
2931
+ for_each_dpcm_fe(be, stream, dpcm) {
2932
+
2933
+ if (dpcm->fe == fe)
2934
+ continue;
2935
+
2936
+ state = dpcm->fe->dpcm[stream].state;
2937
+ for (i = 0; i < num_states; i++) {
2938
+ if (state == states[i]) {
2939
+ ret = 0;
2940
+ break;
2941
+ }
2942
+ }
2943
+ }
2944
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
2945
+
2946
+ /* it's safe to do this BE DAI */
2947
+ return ret;
33472948 }
3348
-EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_set_state);
33492949
33502950 /*
33512951 * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
....@@ -3354,23 +2954,13 @@
33542954 int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
33552955 struct snd_soc_pcm_runtime *be, int stream)
33562956 {
3357
- struct snd_soc_dpcm *dpcm;
3358
- int state;
2957
+ const enum snd_soc_dpcm_state state[] = {
2958
+ SND_SOC_DPCM_STATE_START,
2959
+ SND_SOC_DPCM_STATE_PAUSED,
2960
+ SND_SOC_DPCM_STATE_SUSPEND,
2961
+ };
33592962
3360
- list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
3361
-
3362
- if (dpcm->fe == fe)
3363
- continue;
3364
-
3365
- state = dpcm->fe->dpcm[stream].state;
3366
- if (state == SND_SOC_DPCM_STATE_START ||
3367
- state == SND_SOC_DPCM_STATE_PAUSED ||
3368
- state == SND_SOC_DPCM_STATE_SUSPEND)
3369
- return 0;
3370
- }
3371
-
3372
- /* it's safe to free/stop this BE DAI */
3373
- return 1;
2963
+ return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
33742964 }
33752965 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
33762966
....@@ -3381,163 +2971,30 @@
33812971 int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
33822972 struct snd_soc_pcm_runtime *be, int stream)
33832973 {
3384
- struct snd_soc_dpcm *dpcm;
3385
- int state;
2974
+ const enum snd_soc_dpcm_state state[] = {
2975
+ SND_SOC_DPCM_STATE_START,
2976
+ SND_SOC_DPCM_STATE_PAUSED,
2977
+ SND_SOC_DPCM_STATE_SUSPEND,
2978
+ SND_SOC_DPCM_STATE_PREPARE,
2979
+ };
33862980
3387
- list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
3388
-
3389
- if (dpcm->fe == fe)
3390
- continue;
3391
-
3392
- state = dpcm->fe->dpcm[stream].state;
3393
- if (state == SND_SOC_DPCM_STATE_START ||
3394
- state == SND_SOC_DPCM_STATE_PAUSED ||
3395
- state == SND_SOC_DPCM_STATE_SUSPEND ||
3396
- state == SND_SOC_DPCM_STATE_PREPARE)
3397
- return 0;
3398
- }
3399
-
3400
- /* it's safe to change hw_params */
3401
- return 1;
2981
+ return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
34022982 }
34032983 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
34042984
3405
-#ifdef CONFIG_DEBUG_FS
3406
-static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
2985
+/*
2986
+ * We can only prepare a BE DAI if any of it's FE are not prepared,
2987
+ * running or paused for the specified stream direction.
2988
+ */
2989
+int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
2990
+ struct snd_soc_pcm_runtime *be, int stream)
34072991 {
3408
- switch (state) {
3409
- case SND_SOC_DPCM_STATE_NEW:
3410
- return "new";
3411
- case SND_SOC_DPCM_STATE_OPEN:
3412
- return "open";
3413
- case SND_SOC_DPCM_STATE_HW_PARAMS:
3414
- return "hw_params";
3415
- case SND_SOC_DPCM_STATE_PREPARE:
3416
- return "prepare";
3417
- case SND_SOC_DPCM_STATE_START:
3418
- return "start";
3419
- case SND_SOC_DPCM_STATE_STOP:
3420
- return "stop";
3421
- case SND_SOC_DPCM_STATE_SUSPEND:
3422
- return "suspend";
3423
- case SND_SOC_DPCM_STATE_PAUSED:
3424
- return "paused";
3425
- case SND_SOC_DPCM_STATE_HW_FREE:
3426
- return "hw_free";
3427
- case SND_SOC_DPCM_STATE_CLOSE:
3428
- return "close";
3429
- }
2992
+ const enum snd_soc_dpcm_state state[] = {
2993
+ SND_SOC_DPCM_STATE_START,
2994
+ SND_SOC_DPCM_STATE_PAUSED,
2995
+ SND_SOC_DPCM_STATE_PREPARE,
2996
+ };
34302997
3431
- return "unknown";
2998
+ return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
34322999 }
3433
-
3434
-static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
3435
- int stream, char *buf, size_t size)
3436
-{
3437
- struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
3438
- struct snd_soc_dpcm *dpcm;
3439
- ssize_t offset = 0;
3440
-
3441
- /* FE state */
3442
- offset += scnprintf(buf + offset, size - offset,
3443
- "[%s - %s]\n", fe->dai_link->name,
3444
- stream ? "Capture" : "Playback");
3445
-
3446
- offset += scnprintf(buf + offset, size - offset, "State: %s\n",
3447
- dpcm_state_string(fe->dpcm[stream].state));
3448
-
3449
- if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
3450
- (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
3451
- offset += scnprintf(buf + offset, size - offset,
3452
- "Hardware Params: "
3453
- "Format = %s, Channels = %d, Rate = %d\n",
3454
- snd_pcm_format_name(params_format(params)),
3455
- params_channels(params),
3456
- params_rate(params));
3457
-
3458
- /* BEs state */
3459
- offset += scnprintf(buf + offset, size - offset, "Backends:\n");
3460
-
3461
- if (list_empty(&fe->dpcm[stream].be_clients)) {
3462
- offset += scnprintf(buf + offset, size - offset,
3463
- " No active DSP links\n");
3464
- goto out;
3465
- }
3466
-
3467
- list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
3468
- struct snd_soc_pcm_runtime *be = dpcm->be;
3469
- params = &dpcm->hw_params;
3470
-
3471
- offset += scnprintf(buf + offset, size - offset,
3472
- "- %s\n", be->dai_link->name);
3473
-
3474
- offset += scnprintf(buf + offset, size - offset,
3475
- " State: %s\n",
3476
- dpcm_state_string(be->dpcm[stream].state));
3477
-
3478
- if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
3479
- (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
3480
- offset += scnprintf(buf + offset, size - offset,
3481
- " Hardware Params: "
3482
- "Format = %s, Channels = %d, Rate = %d\n",
3483
- snd_pcm_format_name(params_format(params)),
3484
- params_channels(params),
3485
- params_rate(params));
3486
- }
3487
-
3488
-out:
3489
- return offset;
3490
-}
3491
-
3492
-static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
3493
- size_t count, loff_t *ppos)
3494
-{
3495
- struct snd_soc_pcm_runtime *fe = file->private_data;
3496
- ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
3497
- char *buf;
3498
-
3499
- buf = kmalloc(out_count, GFP_KERNEL);
3500
- if (!buf)
3501
- return -ENOMEM;
3502
-
3503
- if (fe->cpu_dai->driver->playback.channels_min)
3504
- offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
3505
- buf + offset, out_count - offset);
3506
-
3507
- if (fe->cpu_dai->driver->capture.channels_min)
3508
- offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
3509
- buf + offset, out_count - offset);
3510
-
3511
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
3512
-
3513
- kfree(buf);
3514
- return ret;
3515
-}
3516
-
3517
-static const struct file_operations dpcm_state_fops = {
3518
- .open = simple_open,
3519
- .read = dpcm_state_read_file,
3520
- .llseek = default_llseek,
3521
-};
3522
-
3523
-void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
3524
-{
3525
- if (!rtd->dai_link)
3526
- return;
3527
-
3528
- if (!rtd->card->debugfs_card_root)
3529
- return;
3530
-
3531
- rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
3532
- rtd->card->debugfs_card_root);
3533
- if (!rtd->debugfs_dpcm_root) {
3534
- dev_dbg(rtd->dev,
3535
- "ASoC: Failed to create dpcm debugfs directory %s\n",
3536
- rtd->dai_link->name);
3537
- return;
3538
- }
3539
-
3540
- debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
3541
- rtd, &dpcm_state_fops);
3542
-}
3543
-#endif
3000
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);