1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/pinctrl/consumer.h>
17#include <linux/pm_runtime.h>
18#include <linux/slab.h>
19#include <linux/workqueue.h>
20#include <linux/export.h>
21#include <linux/debugfs.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dpcm.h>
27#include <sound/soc-link.h>
28#include <sound/initval.h>
29
30static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd)
31{
32 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
33}
34
35static inline void snd_soc_dpcm_mutex_unlock(struct snd_soc_pcm_runtime *rtd)
36{
37 mutex_unlock(&rtd->card->pcm_mutex);
38}
39
40#define snd_soc_dpcm_mutex_assert_held(rtd) \
41 lockdep_assert_held(&(rtd)->card->pcm_mutex)
42
43static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd,
44 int stream)
45{
46 snd_pcm_stream_lock_irq(snd_soc_dpcm_get_substream(rtd, stream));
47}
48
49#define snd_soc_dpcm_stream_lock_irqsave_nested(rtd, stream, flags) \
50 snd_pcm_stream_lock_irqsave_nested(snd_soc_dpcm_get_substream(rtd, stream), flags)
51
52static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd,
53 int stream)
54{
55 snd_pcm_stream_unlock_irq(snd_soc_dpcm_get_substream(rtd, stream));
56}
57
58#define snd_soc_dpcm_stream_unlock_irqrestore(rtd, stream, flags) \
59 snd_pcm_stream_unlock_irqrestore(snd_soc_dpcm_get_substream(rtd, stream), flags)
60
61#define DPCM_MAX_BE_USERS 8
62
63static inline const char *soc_cpu_dai_name(struct snd_soc_pcm_runtime *rtd)
64{
65 return (rtd)->num_cpus == 1 ? asoc_rtd_to_cpu(rtd, 0)->name : "multicpu";
66}
67static inline const char *soc_codec_dai_name(struct snd_soc_pcm_runtime *rtd)
68{
69 return (rtd)->num_codecs == 1 ? asoc_rtd_to_codec(rtd, 0)->name : "multicodec";
70}
71
72#ifdef CONFIG_DEBUG_FS
73static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
74{
75 switch (state) {
76 case SND_SOC_DPCM_STATE_NEW:
77 return "new";
78 case SND_SOC_DPCM_STATE_OPEN:
79 return "open";
80 case SND_SOC_DPCM_STATE_HW_PARAMS:
81 return "hw_params";
82 case SND_SOC_DPCM_STATE_PREPARE:
83 return "prepare";
84 case SND_SOC_DPCM_STATE_START:
85 return "start";
86 case SND_SOC_DPCM_STATE_STOP:
87 return "stop";
88 case SND_SOC_DPCM_STATE_SUSPEND:
89 return "suspend";
90 case SND_SOC_DPCM_STATE_PAUSED:
91 return "paused";
92 case SND_SOC_DPCM_STATE_HW_FREE:
93 return "hw_free";
94 case SND_SOC_DPCM_STATE_CLOSE:
95 return "close";
96 }
97
98 return "unknown";
99}
100
101static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
102 int stream, char *buf, size_t size)
103{
104 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
105 struct snd_soc_dpcm *dpcm;
106 ssize_t offset = 0;
107
108
109 offset += scnprintf(buf + offset, size - offset,
110 "[%s - %s]\n", fe->dai_link->name,
111 stream ? "Capture" : "Playback");
112
113 offset += scnprintf(buf + offset, size - offset, "State: %s\n",
114 dpcm_state_string(fe->dpcm[stream].state));
115
116 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
117 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
118 offset += scnprintf(buf + offset, size - offset,
119 "Hardware Params: "
120 "Format = %s, Channels = %d, Rate = %d\n",
121 snd_pcm_format_name(params_format(params)),
122 params_channels(params),
123 params_rate(params));
124
125
126 offset += scnprintf(buf + offset, size - offset, "Backends:\n");
127
128 if (list_empty(&fe->dpcm[stream].be_clients)) {
129 offset += scnprintf(buf + offset, size - offset,
130 " No active DSP links\n");
131 goto out;
132 }
133
134 for_each_dpcm_be(fe, stream, dpcm) {
135 struct snd_soc_pcm_runtime *be = dpcm->be;
136 params = &dpcm->hw_params;
137
138 offset += scnprintf(buf + offset, size - offset,
139 "- %s\n", be->dai_link->name);
140
141 offset += scnprintf(buf + offset, size - offset,
142 " State: %s\n",
143 dpcm_state_string(be->dpcm[stream].state));
144
145 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
146 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
147 offset += scnprintf(buf + offset, size - offset,
148 " Hardware Params: "
149 "Format = %s, Channels = %d, Rate = %d\n",
150 snd_pcm_format_name(params_format(params)),
151 params_channels(params),
152 params_rate(params));
153 }
154out:
155 return offset;
156}
157
158static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
159 size_t count, loff_t *ppos)
160{
161 struct snd_soc_pcm_runtime *fe = file->private_data;
162 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
163 int stream;
164 char *buf;
165
166 if (fe->num_cpus > 1) {
167 dev_err(fe->dev,
168 "%s doesn't support Multi CPU yet\n", __func__);
169 return -EINVAL;
170 }
171
172 buf = kmalloc(out_count, GFP_KERNEL);
173 if (!buf)
174 return -ENOMEM;
175
176 snd_soc_dpcm_mutex_lock(fe);
177 for_each_pcm_streams(stream)
178 if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream))
179 offset += dpcm_show_state(fe, stream,
180 buf + offset,
181 out_count - offset);
182 snd_soc_dpcm_mutex_unlock(fe);
183
184 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
185
186 kfree(buf);
187 return ret;
188}
189
190static const struct file_operations dpcm_state_fops = {
191 .open = simple_open,
192 .read = dpcm_state_read_file,
193 .llseek = default_llseek,
194};
195
196void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
197{
198 if (!rtd->dai_link->dynamic)
199 return;
200
201 if (!rtd->card->debugfs_card_root)
202 return;
203
204 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
205 rtd->card->debugfs_card_root);
206
207 debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
208 rtd, &dpcm_state_fops);
209}
210
211static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream)
212{
213 char *name;
214
215 name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name,
216 stream ? "capture" : "playback");
217 if (name) {
218 dpcm->debugfs_state = debugfs_create_dir(
219 name, dpcm->fe->debugfs_dpcm_root);
220 debugfs_create_u32("state", 0644, dpcm->debugfs_state,
221 &dpcm->state);
222 kfree(name);
223 }
224}
225
226static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
227{
228 debugfs_remove_recursive(dpcm->debugfs_state);
229}
230
231#else
232static inline void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm,
233 int stream)
234{
235}
236
237static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
238{
239}
240#endif
241
242
243
244
245
246
247static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
248static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
249 int stream, enum snd_soc_dpcm_update state)
250{
251 struct snd_pcm_substream *substream =
252 snd_soc_dpcm_get_substream(fe, stream);
253
254 snd_soc_dpcm_stream_lock_irq(fe, stream);
255 if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
256 dpcm_fe_dai_do_trigger(substream,
257 fe->dpcm[stream].trigger_pending - 1);
258 fe->dpcm[stream].trigger_pending = 0;
259 }
260 fe->dpcm[stream].runtime_update = state;
261 snd_soc_dpcm_stream_unlock_irq(fe, stream);
262}
263
264static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be,
265 int stream, enum snd_soc_dpcm_update state)
266{
267 be->dpcm[stream].runtime_update = state;
268}
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
284 int stream, int action)
285{
286 struct snd_soc_dai *dai;
287 int i;
288
289 snd_soc_dpcm_mutex_assert_held(rtd);
290
291 for_each_rtd_dais(rtd, i, dai)
292 snd_soc_dai_action(dai, stream, action);
293}
294EXPORT_SYMBOL_GPL(snd_soc_runtime_action);
295
296
297
298
299
300
301
302
303
304
305bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
306{
307 struct snd_soc_component *component;
308 bool ignore = true;
309 int i;
310
311 if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
312 return true;
313
314 for_each_rtd_components(rtd, i, component)
315 ignore &= !component->driver->use_pmdown_time;
316
317 return ignore;
318}
319
320
321
322
323
324
325
326
327int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
328 const struct snd_pcm_hardware *hw)
329{
330 substream->runtime->hw = *hw;
331
332 return 0;
333}
334EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
335
336
337int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
338 int event)
339{
340 struct snd_soc_dpcm *dpcm;
341
342 snd_soc_dpcm_mutex_assert_held(fe);
343
344 for_each_dpcm_be(fe, dir, dpcm) {
345
346 struct snd_soc_pcm_runtime *be = dpcm->be;
347
348 dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n",
349 be->dai_link->name, event, dir);
350
351 if ((event == SND_SOC_DAPM_STREAM_STOP) &&
352 (be->dpcm[dir].users >= 1))
353 continue;
354
355 snd_soc_dapm_stream_event(be, dir, event);
356 }
357
358 snd_soc_dapm_stream_event(fe, dir, event);
359
360 return 0;
361}
362
363static void soc_pcm_set_dai_params(struct snd_soc_dai *dai,
364 struct snd_pcm_hw_params *params)
365{
366 if (params) {
367 dai->rate = params_rate(params);
368 dai->channels = params_channels(params);
369 dai->sample_bits = snd_pcm_format_physical_width(params_format(params));
370 } else {
371 dai->rate = 0;
372 dai->channels = 0;
373 dai->sample_bits = 0;
374 }
375}
376
377static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
378 struct snd_soc_dai *soc_dai)
379{
380 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
381 int ret;
382
383 if (!snd_soc_dai_active(soc_dai))
384 return 0;
385
386#define __soc_pcm_apply_symmetry(name, NAME) \
387 if (soc_dai->name && (soc_dai->driver->symmetric_##name || \
388 rtd->dai_link->symmetric_##name)) { \
389 dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\
390 #name, soc_dai->name); \
391 \
392 ret = snd_pcm_hw_constraint_single(substream->runtime, \
393 SNDRV_PCM_HW_PARAM_##NAME,\
394 soc_dai->name); \
395 if (ret < 0) { \
396 dev_err(soc_dai->dev, \
397 "ASoC: Unable to apply %s constraint: %d\n",\
398 #name, ret); \
399 return ret; \
400 } \
401 }
402
403 __soc_pcm_apply_symmetry(rate, RATE);
404 __soc_pcm_apply_symmetry(channels, CHANNELS);
405 __soc_pcm_apply_symmetry(sample_bits, SAMPLE_BITS);
406
407 return 0;
408}
409
410static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
411 struct snd_pcm_hw_params *params)
412{
413 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
414 struct snd_soc_dai d;
415 struct snd_soc_dai *dai;
416 struct snd_soc_dai *cpu_dai;
417 unsigned int symmetry, i;
418
419 d.name = __func__;
420 soc_pcm_set_dai_params(&d, params);
421
422#define __soc_pcm_params_symmetry(xxx) \
423 symmetry = rtd->dai_link->symmetric_##xxx; \
424 for_each_rtd_dais(rtd, i, dai) \
425 symmetry |= dai->driver->symmetric_##xxx; \
426 \
427 if (symmetry) \
428 for_each_rtd_cpu_dais(rtd, i, cpu_dai) \
429 if (!snd_soc_dai_is_dummy(cpu_dai) && \
430 cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \
431 dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \
432 #xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \
433 return -EINVAL; \
434 }
435
436
437 __soc_pcm_params_symmetry(rate);
438 __soc_pcm_params_symmetry(channels);
439 __soc_pcm_params_symmetry(sample_bits);
440
441 return 0;
442}
443
444static void soc_pcm_update_symmetry(struct snd_pcm_substream *substream)
445{
446 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
447 struct snd_soc_dai_link *link = rtd->dai_link;
448 struct snd_soc_dai *dai;
449 unsigned int symmetry, i;
450
451 symmetry = link->symmetric_rate ||
452 link->symmetric_channels ||
453 link->symmetric_sample_bits;
454
455 for_each_rtd_dais(rtd, i, dai)
456 symmetry = symmetry ||
457 dai->driver->symmetric_rate ||
458 dai->driver->symmetric_channels ||
459 dai->driver->symmetric_sample_bits;
460
461 if (symmetry)
462 substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
463}
464
465static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
466{
467 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
468 int ret;
469
470 if (!bits)
471 return;
472
473 ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 0, bits);
474 if (ret != 0)
475 dev_warn(rtd->dev, "ASoC: Failed to set MSB %d: %d\n",
476 bits, ret);
477}
478
479static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
480{
481 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
482 struct snd_soc_dai *cpu_dai;
483 struct snd_soc_dai *codec_dai;
484 int stream = substream->stream;
485 int i;
486 unsigned int bits = 0, cpu_bits = 0;
487
488 for_each_rtd_codec_dais(rtd, i, codec_dai) {
489 struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
490
491 if (pcm_codec->sig_bits == 0) {
492 bits = 0;
493 break;
494 }
495 bits = max(pcm_codec->sig_bits, bits);
496 }
497
498 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
499 struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
500
501 if (pcm_cpu->sig_bits == 0) {
502 cpu_bits = 0;
503 break;
504 }
505 cpu_bits = max(pcm_cpu->sig_bits, cpu_bits);
506 }
507
508 soc_pcm_set_msb(substream, bits);
509 soc_pcm_set_msb(substream, cpu_bits);
510}
511
512static void soc_pcm_hw_init(struct snd_pcm_hardware *hw)
513{
514 hw->rates = UINT_MAX;
515 hw->rate_min = 0;
516 hw->rate_max = UINT_MAX;
517 hw->channels_min = 0;
518 hw->channels_max = UINT_MAX;
519 hw->formats = ULLONG_MAX;
520}
521
522static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw,
523 struct snd_soc_pcm_stream *p)
524{
525 hw->rates = snd_pcm_rate_mask_intersect(hw->rates, p->rates);
526
527
528 snd_pcm_hw_limit_rates(hw);
529
530
531 hw->rate_min = max(hw->rate_min, p->rate_min);
532 hw->rate_max = min_not_zero(hw->rate_max, p->rate_max);
533}
534
535static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw,
536 struct snd_soc_pcm_stream *p)
537{
538 hw->channels_min = max(hw->channels_min, p->channels_min);
539 hw->channels_max = min(hw->channels_max, p->channels_max);
540}
541
542static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw,
543 struct snd_soc_pcm_stream *p)
544{
545 hw->formats &= p->formats;
546}
547
548
549
550
551
552
553
554
555
556
557int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
558 struct snd_pcm_hardware *hw, int stream)
559{
560 struct snd_soc_dai *codec_dai;
561 struct snd_soc_dai *cpu_dai;
562 struct snd_soc_pcm_stream *codec_stream;
563 struct snd_soc_pcm_stream *cpu_stream;
564 unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX;
565 int i;
566
567 soc_pcm_hw_init(hw);
568
569
570 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
571
572
573
574
575
576
577
578 if (!snd_soc_dai_stream_valid(cpu_dai, stream))
579 continue;
580
581 cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
582
583 soc_pcm_hw_update_chan(hw, cpu_stream);
584 soc_pcm_hw_update_rate(hw, cpu_stream);
585 soc_pcm_hw_update_format(hw, cpu_stream);
586 }
587 cpu_chan_min = hw->channels_min;
588 cpu_chan_max = hw->channels_max;
589
590
591 for_each_rtd_codec_dais(rtd, i, codec_dai) {
592
593
594
595
596
597
598
599 if (!snd_soc_dai_stream_valid(codec_dai, stream))
600 continue;
601
602 codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
603
604 soc_pcm_hw_update_chan(hw, codec_stream);
605 soc_pcm_hw_update_rate(hw, codec_stream);
606 soc_pcm_hw_update_format(hw, codec_stream);
607 }
608
609
610 if (!hw->channels_min)
611 return -EINVAL;
612
613
614
615
616
617
618 if (rtd->num_codecs > 1) {
619 hw->channels_min = cpu_chan_min;
620 hw->channels_max = cpu_chan_max;
621 }
622
623 return 0;
624}
625EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw);
626
627static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
628{
629 struct snd_pcm_hardware *hw = &substream->runtime->hw;
630 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
631 u64 formats = hw->formats;
632
633
634
635
636
637
638 snd_soc_runtime_calc_hw(rtd, hw, substream->stream);
639
640 if (formats)
641 hw->formats &= formats;
642}
643
644static int soc_pcm_components_open(struct snd_pcm_substream *substream)
645{
646 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
647 struct snd_soc_component *component;
648 int i, ret = 0;
649
650 for_each_rtd_components(rtd, i, component) {
651 ret = snd_soc_component_module_get_when_open(component, substream);
652 if (ret < 0)
653 break;
654
655 ret = snd_soc_component_open(component, substream);
656 if (ret < 0)
657 break;
658 }
659
660 return ret;
661}
662
663static int soc_pcm_components_close(struct snd_pcm_substream *substream,
664 int rollback)
665{
666 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
667 struct snd_soc_component *component;
668 int i, ret = 0;
669
670 for_each_rtd_components(rtd, i, component) {
671 int r = snd_soc_component_close(component, substream, rollback);
672 if (r < 0)
673 ret = r;
674
675 snd_soc_component_module_put_when_close(component, substream, rollback);
676 }
677
678 return ret;
679}
680
681static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
682 struct snd_pcm_substream *substream, int rollback)
683{
684 struct snd_soc_component *component;
685 struct snd_soc_dai *dai;
686 int i;
687
688 snd_soc_dpcm_mutex_assert_held(rtd);
689
690 if (!rollback)
691 snd_soc_runtime_deactivate(rtd, substream->stream);
692
693 for_each_rtd_dais(rtd, i, dai)
694 snd_soc_dai_shutdown(dai, substream, rollback);
695
696 snd_soc_link_shutdown(substream, rollback);
697
698 soc_pcm_components_close(substream, rollback);
699
700 snd_soc_pcm_component_pm_runtime_put(rtd, substream, rollback);
701
702 for_each_rtd_components(rtd, i, component)
703 if (!snd_soc_component_active(component))
704 pinctrl_pm_select_sleep_state(component->dev);
705
706 return 0;
707}
708
709
710
711
712
713
714static int __soc_pcm_close(struct snd_soc_pcm_runtime *rtd,
715 struct snd_pcm_substream *substream)
716{
717 return soc_pcm_clean(rtd, substream, 0);
718}
719
720
721static int soc_pcm_close(struct snd_pcm_substream *substream)
722{
723 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
724
725 snd_soc_dpcm_mutex_lock(rtd);
726 soc_pcm_clean(rtd, substream, 0);
727 snd_soc_dpcm_mutex_unlock(rtd);
728 return 0;
729}
730
731static int soc_hw_sanity_check(struct snd_pcm_substream *substream)
732{
733 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
734 struct snd_pcm_hardware *hw = &substream->runtime->hw;
735 const char *name_cpu = soc_cpu_dai_name(rtd);
736 const char *name_codec = soc_codec_dai_name(rtd);
737 const char *err_msg;
738 struct device *dev = rtd->dev;
739
740 err_msg = "rates";
741 if (!hw->rates)
742 goto config_err;
743
744 err_msg = "formats";
745 if (!hw->formats)
746 goto config_err;
747
748 err_msg = "channels";
749 if (!hw->channels_min || !hw->channels_max ||
750 hw->channels_min > hw->channels_max)
751 goto config_err;
752
753 dev_dbg(dev, "ASoC: %s <-> %s info:\n", name_codec,
754 name_cpu);
755 dev_dbg(dev, "ASoC: rate mask 0x%x\n", hw->rates);
756 dev_dbg(dev, "ASoC: ch min %d max %d\n", hw->channels_min,
757 hw->channels_max);
758 dev_dbg(dev, "ASoC: rate min %d max %d\n", hw->rate_min,
759 hw->rate_max);
760
761 return 0;
762
763config_err:
764 dev_err(dev, "ASoC: %s <-> %s No matching %s\n",
765 name_codec, name_cpu, err_msg);
766 return -EINVAL;
767}
768
769
770
771
772
773
774static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd,
775 struct snd_pcm_substream *substream)
776{
777 struct snd_soc_component *component;
778 struct snd_soc_dai *dai;
779 int i, ret = 0;
780
781 snd_soc_dpcm_mutex_assert_held(rtd);
782
783 for_each_rtd_components(rtd, i, component)
784 pinctrl_pm_select_default_state(component->dev);
785
786 ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
787 if (ret < 0)
788 goto err;
789
790 ret = soc_pcm_components_open(substream);
791 if (ret < 0)
792 goto err;
793
794 ret = snd_soc_link_startup(substream);
795 if (ret < 0)
796 goto err;
797
798
799 for_each_rtd_dais(rtd, i, dai) {
800 ret = snd_soc_dai_startup(dai, substream);
801 if (ret < 0)
802 goto err;
803
804 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
805 dai->tx_mask = 0;
806 else
807 dai->rx_mask = 0;
808 }
809
810
811 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
812 goto dynamic;
813
814
815 soc_pcm_init_runtime_hw(substream);
816
817 soc_pcm_update_symmetry(substream);
818
819 ret = soc_hw_sanity_check(substream);
820 if (ret < 0)
821 goto err;
822
823 soc_pcm_apply_msb(substream);
824
825
826 for_each_rtd_dais(rtd, i, dai) {
827 ret = soc_pcm_apply_symmetry(substream, dai);
828 if (ret != 0)
829 goto err;
830 }
831dynamic:
832 snd_soc_runtime_activate(rtd, substream->stream);
833 ret = 0;
834err:
835 if (ret < 0) {
836 soc_pcm_clean(rtd, substream, 1);
837 dev_err(rtd->dev, "%s() failed (%d)", __func__, ret);
838 }
839
840 return ret;
841}
842
843
844static int soc_pcm_open(struct snd_pcm_substream *substream)
845{
846 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
847 int ret;
848
849 snd_soc_dpcm_mutex_lock(rtd);
850 ret = __soc_pcm_open(rtd, substream);
851 snd_soc_dpcm_mutex_unlock(rtd);
852 return ret;
853}
854
855static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
856{
857
858
859
860
861
862
863}
864
865
866
867
868
869
870static int __soc_pcm_prepare(struct snd_soc_pcm_runtime *rtd,
871 struct snd_pcm_substream *substream)
872{
873 struct snd_soc_dai *dai;
874 int i, ret = 0;
875
876 snd_soc_dpcm_mutex_assert_held(rtd);
877
878 ret = snd_soc_link_prepare(substream);
879 if (ret < 0)
880 goto out;
881
882 ret = snd_soc_pcm_component_prepare(substream);
883 if (ret < 0)
884 goto out;
885
886 ret = snd_soc_pcm_dai_prepare(substream);
887 if (ret < 0)
888 goto out;
889
890
891 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
892 rtd->pop_wait) {
893 rtd->pop_wait = 0;
894 cancel_delayed_work(&rtd->delayed_work);
895 }
896
897 snd_soc_dapm_stream_event(rtd, substream->stream,
898 SND_SOC_DAPM_STREAM_START);
899
900 for_each_rtd_dais(rtd, i, dai)
901 snd_soc_dai_digital_mute(dai, 0, substream->stream);
902
903out:
904 if (ret < 0)
905 dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
906
907 return ret;
908}
909
910
911static int soc_pcm_prepare(struct snd_pcm_substream *substream)
912{
913 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
914 int ret;
915
916 snd_soc_dpcm_mutex_lock(rtd);
917 ret = __soc_pcm_prepare(rtd, substream);
918 snd_soc_dpcm_mutex_unlock(rtd);
919 return ret;
920}
921
922static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
923 unsigned int mask)
924{
925 struct snd_interval *interval;
926 int channels = hweight_long(mask);
927
928 interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
929 interval->min = channels;
930 interval->max = channels;
931}
932
933static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd,
934 struct snd_pcm_substream *substream, int rollback)
935{
936 struct snd_soc_dai *dai;
937 int i;
938
939 snd_soc_dpcm_mutex_assert_held(rtd);
940
941
942 for_each_rtd_dais(rtd, i, dai) {
943 if (snd_soc_dai_active(dai) == 1)
944 soc_pcm_set_dai_params(dai, NULL);
945
946 if (snd_soc_dai_stream_active(dai, substream->stream) == 1)
947 snd_soc_dai_digital_mute(dai, 1, substream->stream);
948 }
949
950
951 snd_soc_dapm_stream_stop(rtd, substream->stream);
952
953
954 snd_soc_link_hw_free(substream, rollback);
955
956
957 snd_soc_pcm_component_hw_free(substream, rollback);
958
959
960 for_each_rtd_dais(rtd, i, dai)
961 if (snd_soc_dai_stream_valid(dai, substream->stream))
962 snd_soc_dai_hw_free(dai, substream, rollback);
963
964 return 0;
965}
966
967
968
969
970static int __soc_pcm_hw_free(struct snd_soc_pcm_runtime *rtd,
971 struct snd_pcm_substream *substream)
972{
973 return soc_pcm_hw_clean(rtd, substream, 0);
974}
975
976
977static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
978{
979 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
980 int ret;
981
982 snd_soc_dpcm_mutex_lock(rtd);
983 ret = __soc_pcm_hw_free(rtd, substream);
984 snd_soc_dpcm_mutex_unlock(rtd);
985 return ret;
986}
987
988
989
990
991
992
993static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
994 struct snd_pcm_substream *substream,
995 struct snd_pcm_hw_params *params)
996{
997 struct snd_soc_dai *cpu_dai;
998 struct snd_soc_dai *codec_dai;
999 int i, ret = 0;
1000
1001 snd_soc_dpcm_mutex_assert_held(rtd);
1002
1003 ret = soc_pcm_params_symmetry(substream, params);
1004 if (ret)
1005 goto out;
1006
1007 ret = snd_soc_link_hw_params(substream, params);
1008 if (ret < 0)
1009 goto out;
1010
1011 for_each_rtd_codec_dais(rtd, i, codec_dai) {
1012 struct snd_pcm_hw_params codec_params;
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028 if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
1029 continue;
1030
1031
1032 codec_params = *params;
1033
1034
1035 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
1036 codec_dai->tx_mask)
1037 soc_pcm_codec_params_fixup(&codec_params,
1038 codec_dai->tx_mask);
1039
1040 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
1041 codec_dai->rx_mask)
1042 soc_pcm_codec_params_fixup(&codec_params,
1043 codec_dai->rx_mask);
1044
1045 ret = snd_soc_dai_hw_params(codec_dai, substream,
1046 &codec_params);
1047 if(ret < 0)
1048 goto out;
1049
1050 soc_pcm_set_dai_params(codec_dai, &codec_params);
1051 snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
1052 }
1053
1054 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
1055
1056
1057
1058
1059 if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
1060 continue;
1061
1062 ret = snd_soc_dai_hw_params(cpu_dai, substream, params);
1063 if (ret < 0)
1064 goto out;
1065
1066
1067 soc_pcm_set_dai_params(cpu_dai, params);
1068 snd_soc_dapm_update_dai(substream, params, cpu_dai);
1069 }
1070
1071 ret = snd_soc_pcm_component_hw_params(substream, params);
1072out:
1073 if (ret < 0) {
1074 soc_pcm_hw_clean(rtd, substream, 1);
1075 dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
1076 }
1077
1078 return ret;
1079}
1080
1081
1082static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
1083 struct snd_pcm_hw_params *params)
1084{
1085 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1086 int ret;
1087
1088 snd_soc_dpcm_mutex_lock(rtd);
1089 ret = __soc_pcm_hw_params(rtd, substream, params);
1090 snd_soc_dpcm_mutex_unlock(rtd);
1091 return ret;
1092}
1093
1094static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1095{
1096 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1097 int ret = -EINVAL, _ret = 0;
1098 int rollback = 0;
1099
1100 switch (cmd) {
1101 case SNDRV_PCM_TRIGGER_START:
1102 case SNDRV_PCM_TRIGGER_RESUME:
1103 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1104 ret = snd_soc_link_trigger(substream, cmd, 0);
1105 if (ret < 0)
1106 goto start_err;
1107
1108 ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
1109 if (ret < 0)
1110 goto start_err;
1111
1112 ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
1113start_err:
1114 if (ret < 0)
1115 rollback = 1;
1116 }
1117
1118 if (rollback) {
1119 _ret = ret;
1120 switch (cmd) {
1121 case SNDRV_PCM_TRIGGER_START:
1122 cmd = SNDRV_PCM_TRIGGER_STOP;
1123 break;
1124 case SNDRV_PCM_TRIGGER_RESUME:
1125 cmd = SNDRV_PCM_TRIGGER_SUSPEND;
1126 break;
1127 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1128 cmd = SNDRV_PCM_TRIGGER_PAUSE_PUSH;
1129 break;
1130 }
1131 }
1132
1133 switch (cmd) {
1134 case SNDRV_PCM_TRIGGER_STOP:
1135 case SNDRV_PCM_TRIGGER_SUSPEND:
1136 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1137 if (rtd->dai_link->stop_dma_first) {
1138 ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
1139 if (ret < 0)
1140 break;
1141
1142 ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
1143 if (ret < 0)
1144 break;
1145 } else {
1146 ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
1147 if (ret < 0)
1148 break;
1149
1150 ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
1151 if (ret < 0)
1152 break;
1153 }
1154 ret = snd_soc_link_trigger(substream, cmd, rollback);
1155 break;
1156 }
1157
1158 if (_ret)
1159 ret = _ret;
1160
1161 return ret;
1162}
1163
1164
1165
1166
1167
1168
1169static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
1170{
1171 struct snd_pcm_runtime *runtime = substream->runtime;
1172 snd_pcm_uframes_t offset = 0;
1173 snd_pcm_sframes_t codec_delay = 0;
1174 snd_pcm_sframes_t cpu_delay = 0;
1175
1176 offset = snd_soc_pcm_component_pointer(substream);
1177
1178
1179 snd_soc_pcm_dai_delay(substream, &cpu_delay, &codec_delay);
1180 snd_soc_pcm_component_delay(substream, &cpu_delay, &codec_delay);
1181
1182 runtime->delay = cpu_delay + codec_delay;
1183
1184 return offset;
1185}
1186
1187
1188static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
1189 struct snd_soc_pcm_runtime *be, int stream)
1190{
1191 struct snd_pcm_substream *fe_substream;
1192 struct snd_pcm_substream *be_substream;
1193 struct snd_soc_dpcm *dpcm;
1194
1195 snd_soc_dpcm_mutex_assert_held(fe);
1196
1197
1198 for_each_dpcm_be(fe, stream, dpcm) {
1199 if (dpcm->be == be && dpcm->fe == fe)
1200 return 0;
1201 }
1202
1203 fe_substream = snd_soc_dpcm_get_substream(fe, stream);
1204 be_substream = snd_soc_dpcm_get_substream(be, stream);
1205
1206 if (!fe_substream->pcm->nonatomic && be_substream->pcm->nonatomic) {
1207 dev_err(be->dev, "%s: FE is atomic but BE is nonatomic, invalid configuration\n",
1208 __func__);
1209 return -EINVAL;
1210 }
1211 if (fe_substream->pcm->nonatomic && !be_substream->pcm->nonatomic) {
1212 dev_warn(be->dev, "%s: FE is nonatomic but BE is not, forcing BE as nonatomic\n",
1213 __func__);
1214 be_substream->pcm->nonatomic = 1;
1215 }
1216
1217 dpcm = kzalloc(sizeof(struct snd_soc_dpcm), GFP_ATOMIC);
1218 if (!dpcm)
1219 return -ENOMEM;
1220
1221 dpcm->be = be;
1222 dpcm->fe = fe;
1223 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
1224 dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
1225 snd_soc_dpcm_stream_lock_irq(fe, stream);
1226 list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
1227 list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
1228 snd_soc_dpcm_stream_unlock_irq(fe, stream);
1229
1230 dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
1231 stream ? "capture" : "playback", fe->dai_link->name,
1232 stream ? "<-" : "->", be->dai_link->name);
1233
1234 dpcm_create_debugfs_state(dpcm, stream);
1235
1236 return 1;
1237}
1238
1239
1240static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
1241 struct snd_soc_pcm_runtime *be, int stream)
1242{
1243 struct snd_soc_dpcm *dpcm;
1244 struct snd_pcm_substream *fe_substream, *be_substream;
1245
1246
1247 if (!be->dpcm[stream].users)
1248 return;
1249
1250 be_substream = snd_soc_dpcm_get_substream(be, stream);
1251
1252 for_each_dpcm_fe(be, stream, dpcm) {
1253 if (dpcm->fe == fe)
1254 continue;
1255
1256 dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
1257 stream ? "capture" : "playback",
1258 dpcm->fe->dai_link->name,
1259 stream ? "<-" : "->", dpcm->be->dai_link->name);
1260
1261 fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, stream);
1262 be_substream->runtime = fe_substream->runtime;
1263 break;
1264 }
1265}
1266
1267
1268void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
1269{
1270 struct snd_soc_dpcm *dpcm, *d;
1271 LIST_HEAD(deleted_dpcms);
1272
1273 snd_soc_dpcm_mutex_assert_held(fe);
1274
1275 snd_soc_dpcm_stream_lock_irq(fe, stream);
1276 for_each_dpcm_be_safe(fe, stream, dpcm, d) {
1277 dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
1278 stream ? "capture" : "playback",
1279 dpcm->be->dai_link->name);
1280
1281 if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
1282 continue;
1283
1284 dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n",
1285 stream ? "capture" : "playback", fe->dai_link->name,
1286 stream ? "<-" : "->", dpcm->be->dai_link->name);
1287
1288
1289 dpcm_be_reparent(fe, dpcm->be, stream);
1290
1291 list_del(&dpcm->list_be);
1292 list_move(&dpcm->list_fe, &deleted_dpcms);
1293 }
1294 snd_soc_dpcm_stream_unlock_irq(fe, stream);
1295
1296 while (!list_empty(&deleted_dpcms)) {
1297 dpcm = list_first_entry(&deleted_dpcms, struct snd_soc_dpcm,
1298 list_fe);
1299 list_del(&dpcm->list_fe);
1300 dpcm_remove_debugfs_state(dpcm);
1301 kfree(dpcm);
1302 }
1303}
1304
1305
1306static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
1307 struct snd_soc_dapm_widget *widget, int stream)
1308{
1309 struct snd_soc_pcm_runtime *be;
1310 struct snd_soc_dapm_widget *w;
1311 struct snd_soc_dai *dai;
1312 int i;
1313
1314 dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name);
1315
1316 for_each_card_rtds(card, be) {
1317
1318 if (!be->dai_link->no_pcm)
1319 continue;
1320
1321 for_each_rtd_dais(be, i, dai) {
1322 w = snd_soc_dai_get_widget(dai, stream);
1323
1324 dev_dbg(card->dev, "ASoC: try BE : %s\n",
1325 w ? w->name : "(not set)");
1326
1327 if (w == widget)
1328 return be;
1329 }
1330 }
1331
1332
1333 return NULL;
1334}
1335
1336static int widget_in_list(struct snd_soc_dapm_widget_list *list,
1337 struct snd_soc_dapm_widget *widget)
1338{
1339 struct snd_soc_dapm_widget *w;
1340 int i;
1341
1342 for_each_dapm_widgets(list, i, w)
1343 if (widget == w)
1344 return 1;
1345
1346 return 0;
1347}
1348
1349bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir)
1350{
1351 struct snd_soc_card *card = widget->dapm->card;
1352 struct snd_soc_pcm_runtime *rtd;
1353 int stream;
1354
1355
1356 if (dir == SND_SOC_DAPM_DIR_OUT)
1357 stream = SNDRV_PCM_STREAM_PLAYBACK;
1358 else
1359 stream = SNDRV_PCM_STREAM_CAPTURE;
1360
1361 rtd = dpcm_get_be(card, widget, stream);
1362 if (rtd)
1363 return true;
1364
1365 return false;
1366}
1367EXPORT_SYMBOL_GPL(dpcm_end_walk_at_be);
1368
1369int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
1370 int stream, struct snd_soc_dapm_widget_list **list)
1371{
1372 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
1373 int paths;
1374
1375 if (fe->num_cpus > 1) {
1376 dev_err(fe->dev,
1377 "%s doesn't support Multi CPU yet\n", __func__);
1378 return -EINVAL;
1379 }
1380
1381
1382 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list,
1383 fe->card->component_chaining ?
1384 NULL : dpcm_end_walk_at_be);
1385
1386 if (paths > 0)
1387 dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
1388 stream ? "capture" : "playback");
1389 else if (paths == 0)
1390 dev_dbg(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name,
1391 stream ? "capture" : "playback");
1392
1393 return paths;
1394}
1395
1396void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
1397{
1398 snd_soc_dapm_dai_free_widgets(list);
1399}
1400
1401static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
1402 struct snd_soc_dapm_widget_list *list)
1403{
1404 struct snd_soc_dai *dai;
1405 unsigned int i;
1406
1407
1408 for_each_rtd_dais(dpcm->be, i, dai) {
1409 struct snd_soc_dapm_widget *widget = snd_soc_dai_get_widget(dai, stream);
1410
1411
1412
1413
1414
1415 if (widget && widget_in_list(list, widget))
1416 return true;
1417 }
1418
1419 return false;
1420}
1421
1422static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
1423 struct snd_soc_dapm_widget_list **list_)
1424{
1425 struct snd_soc_dpcm *dpcm;
1426 int prune = 0;
1427
1428
1429 for_each_dpcm_be(fe, stream, dpcm) {
1430 if (dpcm_be_is_active(dpcm, stream, *list_))
1431 continue;
1432
1433 dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
1434 stream ? "capture" : "playback",
1435 dpcm->be->dai_link->name, fe->dai_link->name);
1436 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
1437 dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE);
1438 prune++;
1439 }
1440
1441 dev_dbg(fe->dev, "ASoC: found %d old BE paths for pruning\n", prune);
1442 return prune;
1443}
1444
1445static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
1446 struct snd_soc_dapm_widget_list **list_)
1447{
1448 struct snd_soc_card *card = fe->card;
1449 struct snd_soc_dapm_widget_list *list = *list_;
1450 struct snd_soc_pcm_runtime *be;
1451 struct snd_soc_dapm_widget *widget;
1452 int i, new = 0, err;
1453
1454
1455 for_each_dapm_widgets(list, i, widget) {
1456
1457 switch (widget->id) {
1458 case snd_soc_dapm_dai_in:
1459 if (stream != SNDRV_PCM_STREAM_PLAYBACK)
1460 continue;
1461 break;
1462 case snd_soc_dapm_dai_out:
1463 if (stream != SNDRV_PCM_STREAM_CAPTURE)
1464 continue;
1465 break;
1466 default:
1467 continue;
1468 }
1469
1470
1471 be = dpcm_get_be(card, widget, stream);
1472 if (!be) {
1473 dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
1474 widget->name);
1475 continue;
1476 }
1477
1478
1479 if (!fe->dpcm[stream].runtime && !fe->fe_compr)
1480 continue;
1481
1482
1483
1484
1485
1486
1487 if (fe->card->component_chaining &&
1488 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1489 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1490 continue;
1491
1492
1493 err = dpcm_be_connect(fe, be, stream);
1494 if (err < 0) {
1495 dev_err(fe->dev, "ASoC: can't connect %s\n",
1496 widget->name);
1497 break;
1498 } else if (err == 0)
1499 continue;
1500
1501
1502 dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
1503 new++;
1504 }
1505
1506 dev_dbg(fe->dev, "ASoC: found %d new BE paths\n", new);
1507 return new;
1508}
1509
1510
1511
1512
1513
1514int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
1515 int stream, struct snd_soc_dapm_widget_list **list, int new)
1516{
1517 if (new)
1518 return dpcm_add_paths(fe, stream, list);
1519 else
1520 return dpcm_prune_paths(fe, stream, list);
1521}
1522
1523void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
1524{
1525 struct snd_soc_dpcm *dpcm;
1526
1527 for_each_dpcm_be(fe, stream, dpcm)
1528 dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO);
1529}
1530
1531void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
1532 int do_hw_free, struct snd_soc_dpcm *last)
1533{
1534 struct snd_soc_dpcm *dpcm;
1535
1536
1537 for_each_dpcm_be(fe, stream, dpcm) {
1538 struct snd_soc_pcm_runtime *be = dpcm->be;
1539 struct snd_pcm_substream *be_substream =
1540 snd_soc_dpcm_get_substream(be, stream);
1541
1542 if (dpcm == last)
1543 return;
1544
1545
1546 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1547 continue;
1548
1549 if (be->dpcm[stream].users == 0) {
1550 dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
1551 stream ? "capture" : "playback",
1552 be->dpcm[stream].state);
1553 continue;
1554 }
1555
1556 if (--be->dpcm[stream].users != 0)
1557 continue;
1558
1559 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) {
1560 if (!do_hw_free)
1561 continue;
1562
1563 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) {
1564 __soc_pcm_hw_free(be, be_substream);
1565 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1566 }
1567 }
1568
1569 __soc_pcm_close(be, be_substream);
1570 be_substream->runtime = NULL;
1571 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1572 }
1573}
1574
1575int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
1576{
1577 struct snd_soc_pcm_runtime *be;
1578 struct snd_soc_dpcm *dpcm;
1579 int err, count = 0;
1580
1581
1582 for_each_dpcm_be(fe, stream, dpcm) {
1583 struct snd_pcm_substream *be_substream;
1584
1585 be = dpcm->be;
1586 be_substream = snd_soc_dpcm_get_substream(be, stream);
1587
1588 if (!be_substream) {
1589 dev_err(be->dev, "ASoC: no backend %s stream\n",
1590 stream ? "capture" : "playback");
1591 continue;
1592 }
1593
1594
1595 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1596 continue;
1597
1598
1599 if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) {
1600 dev_err(be->dev, "ASoC: too many users %s at open %d\n",
1601 stream ? "capture" : "playback",
1602 be->dpcm[stream].state);
1603 continue;
1604 }
1605
1606 if (be->dpcm[stream].users++ != 0)
1607 continue;
1608
1609 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1610 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1611 continue;
1612
1613 dev_dbg(be->dev, "ASoC: open %s BE %s\n",
1614 stream ? "capture" : "playback", be->dai_link->name);
1615
1616 be_substream->runtime = be->dpcm[stream].runtime;
1617 err = __soc_pcm_open(be, be_substream);
1618 if (err < 0) {
1619 be->dpcm[stream].users--;
1620 if (be->dpcm[stream].users < 0)
1621 dev_err(be->dev, "ASoC: no users %s at unwind %d\n",
1622 stream ? "capture" : "playback",
1623 be->dpcm[stream].state);
1624
1625 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1626 goto unwind;
1627 }
1628 be->dpcm[stream].be_start = 0;
1629 be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1630 count++;
1631 }
1632
1633 return count;
1634
1635unwind:
1636 dpcm_be_dai_startup_rollback(fe, stream, dpcm);
1637
1638 dev_err(fe->dev, "ASoC: %s() failed at %s (%d)\n",
1639 __func__, be->dai_link->name, err);
1640
1641 return err;
1642}
1643
1644static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream)
1645{
1646 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1647 struct snd_pcm_runtime *runtime = substream->runtime;
1648 struct snd_pcm_hardware *hw = &runtime->hw;
1649 struct snd_soc_dai *dai;
1650 int stream = substream->stream;
1651 int i;
1652
1653 soc_pcm_hw_init(hw);
1654
1655 for_each_rtd_cpu_dais(fe, i, dai) {
1656 struct snd_soc_pcm_stream *cpu_stream;
1657
1658
1659
1660
1661
1662 if (!snd_soc_dai_stream_valid(dai, stream))
1663 continue;
1664
1665 cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
1666
1667 soc_pcm_hw_update_rate(hw, cpu_stream);
1668 soc_pcm_hw_update_chan(hw, cpu_stream);
1669 soc_pcm_hw_update_format(hw, cpu_stream);
1670 }
1671
1672}
1673
1674static void dpcm_runtime_setup_be_format(struct snd_pcm_substream *substream)
1675{
1676 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1677 struct snd_pcm_runtime *runtime = substream->runtime;
1678 struct snd_pcm_hardware *hw = &runtime->hw;
1679 struct snd_soc_dpcm *dpcm;
1680 struct snd_soc_dai *dai;
1681 int stream = substream->stream;
1682
1683 if (!fe->dai_link->dpcm_merged_format)
1684 return;
1685
1686
1687
1688
1689
1690
1691 for_each_dpcm_be(fe, stream, dpcm) {
1692 struct snd_soc_pcm_runtime *be = dpcm->be;
1693 struct snd_soc_pcm_stream *codec_stream;
1694 int i;
1695
1696 for_each_rtd_codec_dais(be, i, dai) {
1697
1698
1699
1700
1701 if (!snd_soc_dai_stream_valid(dai, stream))
1702 continue;
1703
1704 codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
1705
1706 soc_pcm_hw_update_format(hw, codec_stream);
1707 }
1708 }
1709}
1710
1711static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
1712{
1713 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1714 struct snd_pcm_runtime *runtime = substream->runtime;
1715 struct snd_pcm_hardware *hw = &runtime->hw;
1716 struct snd_soc_dpcm *dpcm;
1717 int stream = substream->stream;
1718
1719 if (!fe->dai_link->dpcm_merged_chan)
1720 return;
1721
1722
1723
1724
1725
1726
1727 for_each_dpcm_be(fe, stream, dpcm) {
1728 struct snd_soc_pcm_runtime *be = dpcm->be;
1729 struct snd_soc_pcm_stream *cpu_stream;
1730 struct snd_soc_dai *dai;
1731 int i;
1732
1733 for_each_rtd_cpu_dais(be, i, dai) {
1734
1735
1736
1737
1738 if (!snd_soc_dai_stream_valid(dai, stream))
1739 continue;
1740
1741 cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
1742
1743 soc_pcm_hw_update_chan(hw, cpu_stream);
1744 }
1745
1746
1747
1748
1749
1750 if (be->num_codecs == 1) {
1751 struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream(
1752 asoc_rtd_to_codec(be, 0), stream);
1753
1754 soc_pcm_hw_update_chan(hw, codec_stream);
1755 }
1756 }
1757}
1758
1759static void dpcm_runtime_setup_be_rate(struct snd_pcm_substream *substream)
1760{
1761 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1762 struct snd_pcm_runtime *runtime = substream->runtime;
1763 struct snd_pcm_hardware *hw = &runtime->hw;
1764 struct snd_soc_dpcm *dpcm;
1765 int stream = substream->stream;
1766
1767 if (!fe->dai_link->dpcm_merged_rate)
1768 return;
1769
1770
1771
1772
1773
1774
1775 for_each_dpcm_be(fe, stream, dpcm) {
1776 struct snd_soc_pcm_runtime *be = dpcm->be;
1777 struct snd_soc_pcm_stream *pcm;
1778 struct snd_soc_dai *dai;
1779 int i;
1780
1781 for_each_rtd_dais(be, i, dai) {
1782
1783
1784
1785
1786 if (!snd_soc_dai_stream_valid(dai, stream))
1787 continue;
1788
1789 pcm = snd_soc_dai_get_pcm_stream(dai, stream);
1790
1791 soc_pcm_hw_update_rate(hw, pcm);
1792 }
1793 }
1794}
1795
1796static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
1797 int stream)
1798{
1799 struct snd_soc_dpcm *dpcm;
1800 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
1801 struct snd_soc_dai *fe_cpu_dai;
1802 int err = 0;
1803 int i;
1804
1805
1806 soc_pcm_update_symmetry(fe_substream);
1807
1808 for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) {
1809
1810 err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
1811 if (err < 0)
1812 goto error;
1813 }
1814
1815
1816 for_each_dpcm_be(fe, stream, dpcm) {
1817 struct snd_soc_pcm_runtime *be = dpcm->be;
1818 struct snd_pcm_substream *be_substream =
1819 snd_soc_dpcm_get_substream(be, stream);
1820 struct snd_soc_pcm_runtime *rtd;
1821 struct snd_soc_dai *dai;
1822
1823
1824 if (!be_substream)
1825 continue;
1826
1827 rtd = asoc_substream_to_rtd(be_substream);
1828 if (rtd->dai_link->be_hw_params_fixup)
1829 continue;
1830
1831 soc_pcm_update_symmetry(be_substream);
1832
1833
1834 for_each_rtd_dais(rtd, i, dai) {
1835 err = soc_pcm_apply_symmetry(fe_substream, dai);
1836 if (err < 0)
1837 goto error;
1838 }
1839 }
1840error:
1841 if (err < 0)
1842 dev_err(fe->dev, "ASoC: %s failed (%d)\n", __func__, err);
1843
1844 return err;
1845}
1846
1847static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1848{
1849 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
1850 int stream = fe_substream->stream, ret = 0;
1851
1852 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
1853
1854 ret = dpcm_be_dai_startup(fe, stream);
1855 if (ret < 0)
1856 goto be_err;
1857
1858 dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name);
1859
1860
1861 ret = __soc_pcm_open(fe, fe_substream);
1862 if (ret < 0)
1863 goto unwind;
1864
1865 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1866
1867 dpcm_runtime_setup_fe(fe_substream);
1868
1869 dpcm_runtime_setup_be_format(fe_substream);
1870 dpcm_runtime_setup_be_chan(fe_substream);
1871 dpcm_runtime_setup_be_rate(fe_substream);
1872
1873 ret = dpcm_apply_symmetry(fe_substream, stream);
1874
1875unwind:
1876 if (ret < 0)
1877 dpcm_be_dai_startup_unwind(fe, stream);
1878be_err:
1879 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
1880
1881 if (ret < 0)
1882 dev_err(fe->dev, "%s() failed (%d)\n", __func__, ret);
1883
1884 return ret;
1885}
1886
1887static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
1888{
1889 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1890 int stream = substream->stream;
1891
1892 snd_soc_dpcm_mutex_assert_held(fe);
1893
1894 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
1895
1896
1897 dpcm_be_dai_shutdown(fe, stream);
1898
1899 dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
1900
1901
1902 __soc_pcm_close(fe, substream);
1903
1904
1905 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
1906
1907 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1908 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
1909 return 0;
1910}
1911
1912void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1913{
1914 struct snd_soc_dpcm *dpcm;
1915
1916
1917
1918 for_each_dpcm_be(fe, stream, dpcm) {
1919
1920 struct snd_soc_pcm_runtime *be = dpcm->be;
1921 struct snd_pcm_substream *be_substream =
1922 snd_soc_dpcm_get_substream(be, stream);
1923
1924
1925 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1926 continue;
1927
1928
1929 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1930 continue;
1931
1932
1933 if (be->dpcm[stream].users > 1)
1934 continue;
1935
1936 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1937 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1938 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1939 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
1940 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
1941 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1942 continue;
1943
1944 dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
1945 be->dai_link->name);
1946
1947 __soc_pcm_hw_free(be, be_substream);
1948
1949 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1950 }
1951}
1952
1953static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1954{
1955 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
1956 int stream = substream->stream;
1957
1958 snd_soc_dpcm_mutex_lock(fe);
1959 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
1960
1961 dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
1962
1963
1964 soc_pcm_hw_clean(fe, substream, 0);
1965
1966
1967
1968 dpcm_be_dai_hw_free(fe, stream);
1969
1970 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1971 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
1972
1973 snd_soc_dpcm_mutex_unlock(fe);
1974 return 0;
1975}
1976
1977int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
1978{
1979 struct snd_soc_pcm_runtime *be;
1980 struct snd_pcm_substream *be_substream;
1981 struct snd_soc_dpcm *dpcm;
1982 int ret;
1983
1984 for_each_dpcm_be(fe, stream, dpcm) {
1985 be = dpcm->be;
1986 be_substream = snd_soc_dpcm_get_substream(be, stream);
1987
1988
1989 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1990 continue;
1991
1992
1993 memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
1994 sizeof(struct snd_pcm_hw_params));
1995
1996
1997 ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params);
1998 if (ret < 0)
1999 goto unwind;
2000
2001
2002 memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params,
2003 sizeof(struct snd_pcm_hw_params));
2004
2005
2006 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
2007 continue;
2008
2009 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
2010 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
2011 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
2012 continue;
2013
2014 dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
2015 be->dai_link->name);
2016
2017 ret = __soc_pcm_hw_params(be, be_substream, &dpcm->hw_params);
2018 if (ret < 0)
2019 goto unwind;
2020
2021 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
2022 }
2023 return 0;
2024
2025unwind:
2026 dev_dbg(fe->dev, "ASoC: %s() failed at %s (%d)\n",
2027 __func__, be->dai_link->name, ret);
2028
2029
2030 for_each_dpcm_be_rollback(fe, stream, dpcm) {
2031 be = dpcm->be;
2032 be_substream = snd_soc_dpcm_get_substream(be, stream);
2033
2034 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2035 continue;
2036
2037
2038 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
2039 continue;
2040
2041 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
2042 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
2043 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
2044 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
2045 continue;
2046
2047 __soc_pcm_hw_free(be, be_substream);
2048 }
2049
2050 return ret;
2051}
2052
2053static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
2054 struct snd_pcm_hw_params *params)
2055{
2056 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
2057 int ret, stream = substream->stream;
2058
2059 snd_soc_dpcm_mutex_lock(fe);
2060 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
2061
2062 memcpy(&fe->dpcm[stream].hw_params, params,
2063 sizeof(struct snd_pcm_hw_params));
2064 ret = dpcm_be_dai_hw_params(fe, stream);
2065 if (ret < 0)
2066 goto out;
2067
2068 dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n",
2069 fe->dai_link->name, params_rate(params),
2070 params_channels(params), params_format(params));
2071
2072
2073 ret = __soc_pcm_hw_params(fe, substream, params);
2074 if (ret < 0)
2075 dpcm_be_dai_hw_free(fe, stream);
2076 else
2077 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
2078
2079out:
2080 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2081 snd_soc_dpcm_mutex_unlock(fe);
2082
2083 if (ret < 0)
2084 dev_err(fe->dev, "ASoC: %s failed (%d)\n", __func__, ret);
2085
2086 return ret;
2087}
2088
2089int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
2090 int cmd)
2091{
2092 struct snd_soc_pcm_runtime *be;
2093 struct snd_soc_dpcm *dpcm;
2094 unsigned long flags;
2095 int ret = 0;
2096
2097 for_each_dpcm_be(fe, stream, dpcm) {
2098 struct snd_pcm_substream *be_substream;
2099
2100 be = dpcm->be;
2101 be_substream = snd_soc_dpcm_get_substream(be, stream);
2102
2103 snd_soc_dpcm_stream_lock_irqsave_nested(be, stream, flags);
2104
2105
2106 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2107 goto next;
2108
2109 dev_dbg(be->dev, "ASoC: trigger BE %s cmd %d\n",
2110 be->dai_link->name, cmd);
2111
2112 switch (cmd) {
2113 case SNDRV_PCM_TRIGGER_START:
2114 if (!be->dpcm[stream].be_start &&
2115 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
2116 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
2117 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2118 goto next;
2119
2120 be->dpcm[stream].be_start++;
2121 if (be->dpcm[stream].be_start != 1)
2122 goto next;
2123
2124 ret = soc_pcm_trigger(be_substream, cmd);
2125 if (ret) {
2126 be->dpcm[stream].be_start--;
2127 goto next;
2128 }
2129
2130 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
2131 break;
2132 case SNDRV_PCM_TRIGGER_RESUME:
2133 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
2134 goto next;
2135
2136 be->dpcm[stream].be_start++;
2137 if (be->dpcm[stream].be_start != 1)
2138 goto next;
2139
2140 ret = soc_pcm_trigger(be_substream, cmd);
2141 if (ret) {
2142 be->dpcm[stream].be_start--;
2143 goto next;
2144 }
2145
2146 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
2147 break;
2148 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2149 if (!be->dpcm[stream].be_start &&
2150 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
2151 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
2152 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2153 goto next;
2154
2155 be->dpcm[stream].be_start++;
2156 if (be->dpcm[stream].be_start != 1)
2157 goto next;
2158
2159 ret = soc_pcm_trigger(be_substream, cmd);
2160 if (ret) {
2161 be->dpcm[stream].be_start--;
2162 goto next;
2163 }
2164
2165 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
2166 break;
2167 case SNDRV_PCM_TRIGGER_STOP:
2168 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
2169 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2170 goto next;
2171
2172 if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_START)
2173 be->dpcm[stream].be_start--;
2174
2175 if (be->dpcm[stream].be_start != 0)
2176 goto next;
2177
2178 ret = soc_pcm_trigger(be_substream, cmd);
2179 if (ret) {
2180 if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_START)
2181 be->dpcm[stream].be_start++;
2182 goto next;
2183 }
2184
2185 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
2186 break;
2187 case SNDRV_PCM_TRIGGER_SUSPEND:
2188 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
2189 goto next;
2190
2191 be->dpcm[stream].be_start--;
2192 if (be->dpcm[stream].be_start != 0)
2193 goto next;
2194
2195 ret = soc_pcm_trigger(be_substream, cmd);
2196 if (ret) {
2197 be->dpcm[stream].be_start++;
2198 goto next;
2199 }
2200
2201 be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
2202 break;
2203 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2204 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
2205 goto next;
2206
2207 be->dpcm[stream].be_start--;
2208 if (be->dpcm[stream].be_start != 0)
2209 goto next;
2210
2211 ret = soc_pcm_trigger(be_substream, cmd);
2212 if (ret) {
2213 be->dpcm[stream].be_start++;
2214 goto next;
2215 }
2216
2217 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
2218 break;
2219 }
2220next:
2221 snd_soc_dpcm_stream_unlock_irqrestore(be, stream, flags);
2222 if (ret)
2223 break;
2224 }
2225 if (ret < 0)
2226 dev_err(fe->dev, "ASoC: %s() failed at %s (%d)\n",
2227 __func__, be->dai_link->name, ret);
2228 return ret;
2229}
2230EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
2231
2232static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
2233 int cmd, bool fe_first)
2234{
2235 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
2236 int ret;
2237
2238
2239 if (fe_first) {
2240 dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
2241 fe->dai_link->name, cmd);
2242
2243 ret = soc_pcm_trigger(substream, cmd);
2244 if (ret < 0)
2245 return ret;
2246
2247 ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
2248 return ret;
2249 }
2250
2251
2252 ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
2253 if (ret < 0)
2254 return ret;
2255
2256 dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
2257 fe->dai_link->name, cmd);
2258
2259 ret = soc_pcm_trigger(substream, cmd);
2260
2261 return ret;
2262}
2263
2264static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
2265{
2266 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
2267 int stream = substream->stream;
2268 int ret = 0;
2269 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
2270
2271 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
2272
2273 switch (trigger) {
2274 case SND_SOC_DPCM_TRIGGER_PRE:
2275 switch (cmd) {
2276 case SNDRV_PCM_TRIGGER_START:
2277 case SNDRV_PCM_TRIGGER_RESUME:
2278 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2279 case SNDRV_PCM_TRIGGER_DRAIN:
2280 ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
2281 break;
2282 case SNDRV_PCM_TRIGGER_STOP:
2283 case SNDRV_PCM_TRIGGER_SUSPEND:
2284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2285 ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
2286 break;
2287 default:
2288 ret = -EINVAL;
2289 break;
2290 }
2291 break;
2292 case SND_SOC_DPCM_TRIGGER_POST:
2293 switch (cmd) {
2294 case SNDRV_PCM_TRIGGER_START:
2295 case SNDRV_PCM_TRIGGER_RESUME:
2296 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2297 case SNDRV_PCM_TRIGGER_DRAIN:
2298 ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
2299 break;
2300 case SNDRV_PCM_TRIGGER_STOP:
2301 case SNDRV_PCM_TRIGGER_SUSPEND:
2302 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2303 ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
2304 break;
2305 default:
2306 ret = -EINVAL;
2307 break;
2308 }
2309 break;
2310 case SND_SOC_DPCM_TRIGGER_BESPOKE:
2311
2312
2313 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
2314 fe->dai_link->name, cmd);
2315
2316 ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd);
2317 break;
2318 default:
2319 dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
2320 fe->dai_link->name);
2321 ret = -EINVAL;
2322 goto out;
2323 }
2324
2325 if (ret < 0) {
2326 dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n",
2327 cmd, ret);
2328 goto out;
2329 }
2330
2331 switch (cmd) {
2332 case SNDRV_PCM_TRIGGER_START:
2333 case SNDRV_PCM_TRIGGER_RESUME:
2334 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2335 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
2336 break;
2337 case SNDRV_PCM_TRIGGER_STOP:
2338 case SNDRV_PCM_TRIGGER_SUSPEND:
2339 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
2340 break;
2341 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2342 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
2343 break;
2344 }
2345
2346out:
2347 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
2348 return ret;
2349}
2350
2351static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
2352{
2353 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
2354 int stream = substream->stream;
2355
2356
2357
2358
2359 if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) {
2360 fe->dpcm[stream].trigger_pending = cmd + 1;
2361 return 0;
2362 }
2363
2364
2365 return dpcm_fe_dai_do_trigger(substream, cmd);
2366}
2367
2368int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
2369{
2370 struct snd_soc_dpcm *dpcm;
2371 int ret = 0;
2372
2373 for_each_dpcm_be(fe, stream, dpcm) {
2374
2375 struct snd_soc_pcm_runtime *be = dpcm->be;
2376 struct snd_pcm_substream *be_substream =
2377 snd_soc_dpcm_get_substream(be, stream);
2378
2379
2380 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2381 continue;
2382
2383 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
2384 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
2385 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
2386 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2387 continue;
2388
2389 dev_dbg(be->dev, "ASoC: prepare BE %s\n",
2390 be->dai_link->name);
2391
2392 ret = __soc_pcm_prepare(be, be_substream);
2393 if (ret < 0)
2394 break;
2395
2396 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
2397 }
2398
2399 if (ret < 0)
2400 dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
2401
2402 return ret;
2403}
2404
2405static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
2406{
2407 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
2408 int stream = substream->stream, ret = 0;
2409
2410 snd_soc_dpcm_mutex_lock(fe);
2411
2412 dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
2413
2414 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
2415
2416
2417 if (list_empty(&fe->dpcm[stream].be_clients)) {
2418 dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
2419 fe->dai_link->name);
2420 ret = -EINVAL;
2421 goto out;
2422 }
2423
2424 ret = dpcm_be_dai_prepare(fe, stream);
2425 if (ret < 0)
2426 goto out;
2427
2428
2429 ret = __soc_pcm_prepare(fe, substream);
2430 if (ret < 0)
2431 goto out;
2432
2433 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
2434
2435out:
2436 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2437 snd_soc_dpcm_mutex_unlock(fe);
2438
2439 if (ret < 0)
2440 dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
2441
2442 return ret;
2443}
2444
2445static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
2446{
2447 struct snd_pcm_substream *substream =
2448 snd_soc_dpcm_get_substream(fe, stream);
2449 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
2450 int err;
2451
2452 dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n",
2453 stream ? "capture" : "playback", fe->dai_link->name);
2454
2455 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
2456
2457 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
2458 fe->dai_link->name);
2459
2460 err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
2461 } else {
2462 dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n",
2463 fe->dai_link->name);
2464
2465 err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
2466 }
2467
2468 dpcm_be_dai_hw_free(fe, stream);
2469
2470 dpcm_be_dai_shutdown(fe, stream);
2471
2472
2473 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
2474
2475 if (err < 0)
2476 dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, err);
2477
2478 return err;
2479}
2480
2481static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
2482{
2483 struct snd_pcm_substream *substream =
2484 snd_soc_dpcm_get_substream(fe, stream);
2485 struct snd_soc_dpcm *dpcm;
2486 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
2487 int ret = 0;
2488
2489 dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
2490 stream ? "capture" : "playback", fe->dai_link->name);
2491
2492
2493 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
2494 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) {
2495 dev_err(fe->dev, "ASoC: FE %s is not ready %d\n",
2496 fe->dai_link->name, fe->dpcm[stream].state);
2497 ret = -EINVAL;
2498 goto disconnect;
2499 }
2500
2501
2502 ret = dpcm_be_dai_startup(fe, stream);
2503 if (ret < 0)
2504 goto disconnect;
2505
2506
2507 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
2508 return 0;
2509
2510 ret = dpcm_be_dai_hw_params(fe, stream);
2511 if (ret < 0)
2512 goto close;
2513
2514
2515 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
2516 return 0;
2517
2518 ret = dpcm_be_dai_prepare(fe, stream);
2519 if (ret < 0)
2520 goto hw_free;
2521
2522
2523 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
2524
2525
2526 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
2527 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
2528 return 0;
2529
2530 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
2531
2532 dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
2533 fe->dai_link->name);
2534
2535 ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
2536 if (ret < 0)
2537 goto hw_free;
2538 } else {
2539 dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n",
2540 fe->dai_link->name);
2541
2542 ret = dpcm_be_dai_trigger(fe, stream,
2543 SNDRV_PCM_TRIGGER_START);
2544 if (ret < 0)
2545 goto hw_free;
2546 }
2547
2548 return 0;
2549
2550hw_free:
2551 dpcm_be_dai_hw_free(fe, stream);
2552close:
2553 dpcm_be_dai_shutdown(fe, stream);
2554disconnect:
2555
2556 for_each_dpcm_be(fe, stream, dpcm) {
2557 struct snd_soc_pcm_runtime *be = dpcm->be;
2558
2559
2560 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2561 continue;
2562
2563 if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE ||
2564 be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW)
2565 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2566 }
2567
2568 if (ret < 0)
2569 dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
2570
2571 return ret;
2572}
2573
2574static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
2575{
2576 struct snd_soc_dapm_widget_list *list;
2577 int stream;
2578 int count, paths;
2579
2580 if (!fe->dai_link->dynamic)
2581 return 0;
2582
2583 if (fe->num_cpus > 1) {
2584 dev_err(fe->dev,
2585 "%s doesn't support Multi CPU yet\n", __func__);
2586 return -EINVAL;
2587 }
2588
2589
2590 if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0)))
2591 return 0;
2592
2593
2594 dev_dbg(fe->dev, "ASoC: DPCM %s runtime update for FE %s\n",
2595 new ? "new" : "old", fe->dai_link->name);
2596
2597 for_each_pcm_streams(stream) {
2598
2599
2600 if (!snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream) ||
2601 !snd_soc_dai_stream_valid(asoc_rtd_to_codec(fe, 0), stream))
2602 continue;
2603
2604
2605 if (!snd_soc_dai_stream_active(asoc_rtd_to_cpu(fe, 0), stream) ||
2606 !snd_soc_dai_stream_active(asoc_rtd_to_codec(fe, 0), stream))
2607 continue;
2608
2609 paths = dpcm_path_get(fe, stream, &list);
2610 if (paths < 0)
2611 return paths;
2612
2613
2614 count = dpcm_process_paths(fe, stream, &list, new);
2615 if (count) {
2616 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
2617 if (new)
2618 dpcm_run_update_startup(fe, stream);
2619 else
2620 dpcm_run_update_shutdown(fe, stream);
2621 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
2622
2623 dpcm_clear_pending_state(fe, stream);
2624 dpcm_be_disconnect(fe, stream);
2625 }
2626
2627 dpcm_path_put(&list);
2628 }
2629
2630 return 0;
2631}
2632
2633
2634
2635
2636int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
2637{
2638 struct snd_soc_pcm_runtime *fe;
2639 int ret = 0;
2640
2641 mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass);
2642
2643 for_each_card_rtds(card, fe) {
2644 ret = soc_dpcm_fe_runtime_update(fe, 0);
2645 if (ret)
2646 goto out;
2647 }
2648
2649
2650 for_each_card_rtds(card, fe) {
2651 ret = soc_dpcm_fe_runtime_update(fe, 1);
2652 if (ret)
2653 goto out;
2654 }
2655
2656out:
2657 mutex_unlock(&card->pcm_mutex);
2658 return ret;
2659}
2660EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update);
2661
2662static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream)
2663{
2664 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
2665 struct snd_soc_dpcm *dpcm;
2666 int stream = fe_substream->stream;
2667
2668 snd_soc_dpcm_mutex_assert_held(fe);
2669
2670
2671 for_each_dpcm_be(fe, stream, dpcm)
2672 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2673
2674 dpcm_be_disconnect(fe, stream);
2675
2676 fe->dpcm[stream].runtime = NULL;
2677}
2678
2679static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2680{
2681 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
2682 int ret;
2683
2684 snd_soc_dpcm_mutex_lock(fe);
2685 ret = dpcm_fe_dai_shutdown(fe_substream);
2686
2687 dpcm_fe_dai_cleanup(fe_substream);
2688
2689 snd_soc_dpcm_mutex_unlock(fe);
2690 return ret;
2691}
2692
2693static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
2694{
2695 struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
2696 struct snd_soc_dapm_widget_list *list;
2697 int ret;
2698 int stream = fe_substream->stream;
2699
2700 snd_soc_dpcm_mutex_lock(fe);
2701 fe->dpcm[stream].runtime = fe_substream->runtime;
2702
2703 ret = dpcm_path_get(fe, stream, &list);
2704 if (ret < 0)
2705 goto open_end;
2706
2707
2708 dpcm_process_paths(fe, stream, &list, 1);
2709
2710 ret = dpcm_fe_dai_startup(fe_substream);
2711 if (ret < 0)
2712 dpcm_fe_dai_cleanup(fe_substream);
2713
2714 dpcm_clear_pending_state(fe, stream);
2715 dpcm_path_put(&list);
2716open_end:
2717 snd_soc_dpcm_mutex_unlock(fe);
2718 return ret;
2719}
2720
2721static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
2722 int *playback, int *capture)
2723{
2724 struct snd_soc_dai *cpu_dai;
2725 int i;
2726
2727 if (rtd->dai_link->dynamic && rtd->num_cpus > 1) {
2728 dev_err(rtd->dev,
2729 "DPCM doesn't support Multi CPU for Front-Ends yet\n");
2730 return -EINVAL;
2731 }
2732
2733 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2734 int stream;
2735
2736 if (rtd->dai_link->dpcm_playback) {
2737 stream = SNDRV_PCM_STREAM_PLAYBACK;
2738
2739 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2740 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2741 *playback = 1;
2742 break;
2743 }
2744 }
2745 if (!*playback) {
2746 dev_err(rtd->card->dev,
2747 "No CPU DAIs support playback for stream %s\n",
2748 rtd->dai_link->stream_name);
2749 return -EINVAL;
2750 }
2751 }
2752 if (rtd->dai_link->dpcm_capture) {
2753 stream = SNDRV_PCM_STREAM_CAPTURE;
2754
2755 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2756 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2757 *capture = 1;
2758 break;
2759 }
2760 }
2761
2762 if (!*capture) {
2763 dev_err(rtd->card->dev,
2764 "No CPU DAIs support capture for stream %s\n",
2765 rtd->dai_link->stream_name);
2766 return -EINVAL;
2767 }
2768 }
2769 } else {
2770 struct snd_soc_dai *codec_dai;
2771
2772
2773 int cpu_capture = rtd->dai_link->params ?
2774 SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
2775 int cpu_playback = rtd->dai_link->params ?
2776 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
2777
2778 for_each_rtd_codec_dais(rtd, i, codec_dai) {
2779 if (rtd->num_cpus == 1) {
2780 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
2781 } else if (rtd->num_cpus == rtd->num_codecs) {
2782 cpu_dai = asoc_rtd_to_cpu(rtd, i);
2783 } else {
2784 dev_err(rtd->card->dev,
2785 "N cpus to M codecs link is not supported yet\n");
2786 return -EINVAL;
2787 }
2788
2789 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
2790 snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
2791 *playback = 1;
2792 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
2793 snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
2794 *capture = 1;
2795 }
2796 }
2797
2798 if (rtd->dai_link->playback_only) {
2799 *playback = 1;
2800 *capture = 0;
2801 }
2802
2803 if (rtd->dai_link->capture_only) {
2804 *playback = 0;
2805 *capture = 1;
2806 }
2807
2808 return 0;
2809}
2810
2811static int soc_create_pcm(struct snd_pcm **pcm,
2812 struct snd_soc_pcm_runtime *rtd,
2813 int playback, int capture, int num)
2814{
2815 char new_name[64];
2816 int ret;
2817
2818
2819 if (rtd->dai_link->params) {
2820 snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
2821 rtd->dai_link->stream_name);
2822
2823 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
2824 playback, capture, pcm);
2825 } else if (rtd->dai_link->no_pcm) {
2826 snprintf(new_name, sizeof(new_name), "(%s)",
2827 rtd->dai_link->stream_name);
2828
2829 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
2830 playback, capture, pcm);
2831 } else {
2832 if (rtd->dai_link->dynamic)
2833 snprintf(new_name, sizeof(new_name), "%s (*)",
2834 rtd->dai_link->stream_name);
2835 else
2836 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2837 rtd->dai_link->stream_name,
2838 soc_codec_dai_name(rtd), num);
2839
2840 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
2841 capture, pcm);
2842 }
2843 if (ret < 0) {
2844 dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n",
2845 new_name, rtd->dai_link->name, ret);
2846 return ret;
2847 }
2848 dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
2849
2850 return 0;
2851}
2852
2853
2854int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2855{
2856 struct snd_soc_component *component;
2857 struct snd_pcm *pcm;
2858 int ret = 0, playback = 0, capture = 0;
2859 int i;
2860
2861 ret = soc_get_playback_capture(rtd, &playback, &capture);
2862 if (ret < 0)
2863 return ret;
2864
2865 ret = soc_create_pcm(&pcm, rtd, playback, capture, num);
2866 if (ret < 0)
2867 return ret;
2868
2869
2870 if (rtd->dai_link->params)
2871 rtd->close_delayed_work_func = codec2codec_close_delayed_work;
2872 else
2873 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
2874
2875 rtd->pcm = pcm;
2876 pcm->nonatomic = rtd->dai_link->nonatomic;
2877 pcm->private_data = rtd;
2878
2879 if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
2880 if (playback)
2881 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
2882 if (capture)
2883 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
2884 goto out;
2885 }
2886
2887
2888 if (rtd->dai_link->dynamic) {
2889 rtd->ops.open = dpcm_fe_dai_open;
2890 rtd->ops.hw_params = dpcm_fe_dai_hw_params;
2891 rtd->ops.prepare = dpcm_fe_dai_prepare;
2892 rtd->ops.trigger = dpcm_fe_dai_trigger;
2893 rtd->ops.hw_free = dpcm_fe_dai_hw_free;
2894 rtd->ops.close = dpcm_fe_dai_close;
2895 rtd->ops.pointer = soc_pcm_pointer;
2896 } else {
2897 rtd->ops.open = soc_pcm_open;
2898 rtd->ops.hw_params = soc_pcm_hw_params;
2899 rtd->ops.prepare = soc_pcm_prepare;
2900 rtd->ops.trigger = soc_pcm_trigger;
2901 rtd->ops.hw_free = soc_pcm_hw_free;
2902 rtd->ops.close = soc_pcm_close;
2903 rtd->ops.pointer = soc_pcm_pointer;
2904 }
2905
2906 for_each_rtd_components(rtd, i, component) {
2907 const struct snd_soc_component_driver *drv = component->driver;
2908
2909 if (drv->ioctl)
2910 rtd->ops.ioctl = snd_soc_pcm_component_ioctl;
2911 if (drv->sync_stop)
2912 rtd->ops.sync_stop = snd_soc_pcm_component_sync_stop;
2913 if (drv->copy_user)
2914 rtd->ops.copy_user = snd_soc_pcm_component_copy_user;
2915 if (drv->page)
2916 rtd->ops.page = snd_soc_pcm_component_page;
2917 if (drv->mmap)
2918 rtd->ops.mmap = snd_soc_pcm_component_mmap;
2919 if (drv->ack)
2920 rtd->ops.ack = snd_soc_pcm_component_ack;
2921 }
2922
2923 if (playback)
2924 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
2925
2926 if (capture)
2927 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
2928
2929 ret = snd_soc_pcm_component_new(rtd);
2930 if (ret < 0)
2931 return ret;
2932
2933 pcm->no_device_suspend = true;
2934out:
2935 dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n",
2936 soc_codec_dai_name(rtd), soc_cpu_dai_name(rtd));
2937 return ret;
2938}
2939
2940
2941int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream)
2942{
2943 if (fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE)
2944 return 1;
2945 return 0;
2946}
2947EXPORT_SYMBOL_GPL(snd_soc_dpcm_fe_can_update);
2948
2949
2950int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
2951 struct snd_soc_pcm_runtime *be, int stream)
2952{
2953 if ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) ||
2954 ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_BE) &&
2955 be->dpcm[stream].runtime_update))
2956 return 1;
2957 return 0;
2958}
2959EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_can_update);
2960
2961
2962struct snd_pcm_substream *
2963 snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream)
2964{
2965 return be->pcm->streams[stream].substream;
2966}
2967EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream);
2968
2969static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
2970 struct snd_soc_pcm_runtime *be,
2971 int stream,
2972 const enum snd_soc_dpcm_state *states,
2973 int num_states)
2974{
2975 struct snd_soc_dpcm *dpcm;
2976 int state;
2977 int ret = 1;
2978 int i;
2979
2980 for_each_dpcm_fe(be, stream, dpcm) {
2981
2982 if (dpcm->fe == fe)
2983 continue;
2984
2985 state = dpcm->fe->dpcm[stream].state;
2986 for (i = 0; i < num_states; i++) {
2987 if (state == states[i]) {
2988 ret = 0;
2989 break;
2990 }
2991 }
2992 }
2993
2994
2995 return ret;
2996}
2997
2998
2999
3000
3001
3002int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
3003 struct snd_soc_pcm_runtime *be, int stream)
3004{
3005 const enum snd_soc_dpcm_state state[] = {
3006 SND_SOC_DPCM_STATE_START,
3007 SND_SOC_DPCM_STATE_PAUSED,
3008 SND_SOC_DPCM_STATE_SUSPEND,
3009 };
3010
3011 return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3012}
3013EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
3014
3015
3016
3017
3018
3019int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
3020 struct snd_soc_pcm_runtime *be, int stream)
3021{
3022 const enum snd_soc_dpcm_state state[] = {
3023 SND_SOC_DPCM_STATE_START,
3024 SND_SOC_DPCM_STATE_PAUSED,
3025 SND_SOC_DPCM_STATE_SUSPEND,
3026 SND_SOC_DPCM_STATE_PREPARE,
3027 };
3028
3029 return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3030}
3031EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
3032