hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/sound/soc/soc-dapm.c
....@@ -18,7 +18,6 @@
1818 // device reopen.
1919
2020 #include <linux/module.h>
21
-#include <linux/moduleparam.h>
2221 #include <linux/init.h>
2322 #include <linux/async.h>
2423 #include <linux/delay.h>
....@@ -63,87 +62,89 @@
6362 snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
6463 const struct snd_soc_dapm_widget *widget);
6564
65
+static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg);
66
+
6667 /* dapm power sequences - make this per codec in the future */
6768 static int dapm_up_seq[] = {
68
- [snd_soc_dapm_pre] = 0,
69
- [snd_soc_dapm_regulator_supply] = 1,
70
- [snd_soc_dapm_pinctrl] = 1,
71
- [snd_soc_dapm_clock_supply] = 1,
72
- [snd_soc_dapm_supply] = 2,
73
- [snd_soc_dapm_micbias] = 3,
74
- [snd_soc_dapm_vmid] = 3,
75
- [snd_soc_dapm_dai_link] = 2,
76
- [snd_soc_dapm_dai_in] = 4,
77
- [snd_soc_dapm_dai_out] = 4,
78
- [snd_soc_dapm_aif_in] = 4,
79
- [snd_soc_dapm_aif_out] = 4,
80
- [snd_soc_dapm_mic] = 5,
81
- [snd_soc_dapm_siggen] = 5,
82
- [snd_soc_dapm_input] = 5,
83
- [snd_soc_dapm_output] = 5,
84
- [snd_soc_dapm_mux] = 6,
85
- [snd_soc_dapm_demux] = 6,
86
- [snd_soc_dapm_dac] = 7,
87
- [snd_soc_dapm_switch] = 8,
88
- [snd_soc_dapm_mixer] = 8,
89
- [snd_soc_dapm_mixer_named_ctl] = 8,
90
- [snd_soc_dapm_pga] = 9,
91
- [snd_soc_dapm_buffer] = 9,
92
- [snd_soc_dapm_scheduler] = 9,
93
- [snd_soc_dapm_effect] = 9,
94
- [snd_soc_dapm_src] = 9,
95
- [snd_soc_dapm_asrc] = 9,
96
- [snd_soc_dapm_encoder] = 9,
97
- [snd_soc_dapm_decoder] = 9,
98
- [snd_soc_dapm_adc] = 10,
99
- [snd_soc_dapm_out_drv] = 11,
100
- [snd_soc_dapm_hp] = 11,
101
- [snd_soc_dapm_spk] = 11,
102
- [snd_soc_dapm_line] = 11,
103
- [snd_soc_dapm_sink] = 11,
104
- [snd_soc_dapm_kcontrol] = 12,
105
- [snd_soc_dapm_post] = 13,
69
+ [snd_soc_dapm_pre] = 1,
70
+ [snd_soc_dapm_regulator_supply] = 2,
71
+ [snd_soc_dapm_pinctrl] = 2,
72
+ [snd_soc_dapm_clock_supply] = 2,
73
+ [snd_soc_dapm_supply] = 3,
74
+ [snd_soc_dapm_micbias] = 4,
75
+ [snd_soc_dapm_vmid] = 4,
76
+ [snd_soc_dapm_dai_link] = 3,
77
+ [snd_soc_dapm_dai_in] = 5,
78
+ [snd_soc_dapm_dai_out] = 5,
79
+ [snd_soc_dapm_aif_in] = 5,
80
+ [snd_soc_dapm_aif_out] = 5,
81
+ [snd_soc_dapm_mic] = 6,
82
+ [snd_soc_dapm_siggen] = 6,
83
+ [snd_soc_dapm_input] = 6,
84
+ [snd_soc_dapm_output] = 6,
85
+ [snd_soc_dapm_mux] = 7,
86
+ [snd_soc_dapm_demux] = 7,
87
+ [snd_soc_dapm_dac] = 8,
88
+ [snd_soc_dapm_switch] = 9,
89
+ [snd_soc_dapm_mixer] = 9,
90
+ [snd_soc_dapm_mixer_named_ctl] = 9,
91
+ [snd_soc_dapm_pga] = 10,
92
+ [snd_soc_dapm_buffer] = 10,
93
+ [snd_soc_dapm_scheduler] = 10,
94
+ [snd_soc_dapm_effect] = 10,
95
+ [snd_soc_dapm_src] = 10,
96
+ [snd_soc_dapm_asrc] = 10,
97
+ [snd_soc_dapm_encoder] = 10,
98
+ [snd_soc_dapm_decoder] = 10,
99
+ [snd_soc_dapm_adc] = 11,
100
+ [snd_soc_dapm_out_drv] = 12,
101
+ [snd_soc_dapm_hp] = 12,
102
+ [snd_soc_dapm_spk] = 12,
103
+ [snd_soc_dapm_line] = 12,
104
+ [snd_soc_dapm_sink] = 12,
105
+ [snd_soc_dapm_kcontrol] = 13,
106
+ [snd_soc_dapm_post] = 14,
106107 };
107108
108109 static int dapm_down_seq[] = {
109
- [snd_soc_dapm_pre] = 0,
110
- [snd_soc_dapm_kcontrol] = 1,
111
- [snd_soc_dapm_adc] = 2,
112
- [snd_soc_dapm_hp] = 3,
113
- [snd_soc_dapm_spk] = 3,
114
- [snd_soc_dapm_line] = 3,
115
- [snd_soc_dapm_out_drv] = 3,
116
- [snd_soc_dapm_sink] = 3,
117
- [snd_soc_dapm_pga] = 4,
118
- [snd_soc_dapm_buffer] = 4,
119
- [snd_soc_dapm_scheduler] = 4,
120
- [snd_soc_dapm_effect] = 4,
121
- [snd_soc_dapm_src] = 4,
122
- [snd_soc_dapm_asrc] = 4,
123
- [snd_soc_dapm_encoder] = 4,
124
- [snd_soc_dapm_decoder] = 4,
125
- [snd_soc_dapm_switch] = 5,
126
- [snd_soc_dapm_mixer_named_ctl] = 5,
127
- [snd_soc_dapm_mixer] = 5,
128
- [snd_soc_dapm_dac] = 6,
129
- [snd_soc_dapm_mic] = 7,
130
- [snd_soc_dapm_siggen] = 7,
131
- [snd_soc_dapm_input] = 7,
132
- [snd_soc_dapm_output] = 7,
133
- [snd_soc_dapm_micbias] = 8,
134
- [snd_soc_dapm_vmid] = 8,
135
- [snd_soc_dapm_mux] = 9,
136
- [snd_soc_dapm_demux] = 9,
137
- [snd_soc_dapm_aif_in] = 10,
138
- [snd_soc_dapm_aif_out] = 10,
139
- [snd_soc_dapm_dai_in] = 10,
140
- [snd_soc_dapm_dai_out] = 10,
141
- [snd_soc_dapm_dai_link] = 11,
142
- [snd_soc_dapm_supply] = 12,
143
- [snd_soc_dapm_clock_supply] = 13,
144
- [snd_soc_dapm_pinctrl] = 13,
145
- [snd_soc_dapm_regulator_supply] = 13,
146
- [snd_soc_dapm_post] = 14,
110
+ [snd_soc_dapm_pre] = 1,
111
+ [snd_soc_dapm_kcontrol] = 2,
112
+ [snd_soc_dapm_adc] = 3,
113
+ [snd_soc_dapm_hp] = 4,
114
+ [snd_soc_dapm_spk] = 4,
115
+ [snd_soc_dapm_line] = 4,
116
+ [snd_soc_dapm_out_drv] = 4,
117
+ [snd_soc_dapm_sink] = 4,
118
+ [snd_soc_dapm_pga] = 5,
119
+ [snd_soc_dapm_buffer] = 5,
120
+ [snd_soc_dapm_scheduler] = 5,
121
+ [snd_soc_dapm_effect] = 5,
122
+ [snd_soc_dapm_src] = 5,
123
+ [snd_soc_dapm_asrc] = 5,
124
+ [snd_soc_dapm_encoder] = 5,
125
+ [snd_soc_dapm_decoder] = 5,
126
+ [snd_soc_dapm_switch] = 6,
127
+ [snd_soc_dapm_mixer_named_ctl] = 6,
128
+ [snd_soc_dapm_mixer] = 6,
129
+ [snd_soc_dapm_dac] = 7,
130
+ [snd_soc_dapm_mic] = 8,
131
+ [snd_soc_dapm_siggen] = 8,
132
+ [snd_soc_dapm_input] = 8,
133
+ [snd_soc_dapm_output] = 8,
134
+ [snd_soc_dapm_micbias] = 9,
135
+ [snd_soc_dapm_vmid] = 9,
136
+ [snd_soc_dapm_mux] = 10,
137
+ [snd_soc_dapm_demux] = 10,
138
+ [snd_soc_dapm_aif_in] = 11,
139
+ [snd_soc_dapm_aif_out] = 11,
140
+ [snd_soc_dapm_dai_in] = 11,
141
+ [snd_soc_dapm_dai_out] = 11,
142
+ [snd_soc_dapm_dai_link] = 12,
143
+ [snd_soc_dapm_supply] = 13,
144
+ [snd_soc_dapm_clock_supply] = 14,
145
+ [snd_soc_dapm_pinctrl] = 14,
146
+ [snd_soc_dapm_regulator_supply] = 14,
147
+ [snd_soc_dapm_post] = 15,
147148 };
148149
149150 static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
....@@ -158,6 +159,7 @@
158159 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
159160 }
160161
162
+__printf(3, 4)
161163 static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
162164 {
163165 va_list args;
....@@ -302,7 +304,7 @@
302304
303305 mutex_lock(&card->dapm_mutex);
304306
305
- list_for_each_entry(w, &card->widgets, list) {
307
+ for_each_card_widgets(card, w) {
306308 if (w->is_ep) {
307309 dapm_mark_dirty(w, "Rechecking endpoints");
308310 if (w->is_ep & SND_SOC_DAPM_EP_SINK)
....@@ -320,7 +322,24 @@
320322 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
321323 const struct snd_soc_dapm_widget *_widget)
322324 {
323
- return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
325
+ struct snd_soc_dapm_widget *w;
326
+
327
+ w = kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
328
+ if (!w)
329
+ return NULL;
330
+
331
+ /*
332
+ * w->name is duplicated in caller, but w->sname isn't.
333
+ * Duplicate it here if defined
334
+ */
335
+ if (_widget->sname) {
336
+ w->sname = kstrdup_const(_widget->sname, GFP_KERNEL);
337
+ if (!w->sname) {
338
+ kfree(w);
339
+ return NULL;
340
+ }
341
+ }
342
+ return w;
324343 }
325344
326345 struct dapm_kcontrol_data {
....@@ -388,10 +407,6 @@
388407 ret = PTR_ERR(data->widget);
389408 goto err_data;
390409 }
391
- if (!data->widget) {
392
- ret = -ENOMEM;
393
- goto err_data;
394
- }
395410 }
396411 break;
397412 case snd_soc_dapm_demux:
....@@ -426,13 +441,12 @@
426441 ret = PTR_ERR(data->widget);
427442 goto err_data;
428443 }
429
- if (!data->widget) {
430
- ret = -ENOMEM;
431
- goto err_data;
432
- }
433444
434445 snd_soc_dapm_add_path(widget->dapm, data->widget,
435446 widget, NULL, NULL);
447
+ } else if (e->reg != SND_SOC_NOPM) {
448
+ data->value = soc_dapm_read(widget->dapm, e->reg) &
449
+ (e->mask << e->shift_l);
436450 }
437451 break;
438452 default:
....@@ -478,7 +492,8 @@
478492 n = 1;
479493
480494 new_wlist = krealloc(data->wlist,
481
- sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
495
+ struct_size(new_wlist, widgets, n),
496
+ GFP_KERNEL);
482497 if (!new_wlist)
483498 return -ENOMEM;
484499
....@@ -593,7 +608,7 @@
593608
594609 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
595610
596
- list_for_each_entry(w, &card->widgets, list) {
611
+ for_each_card_widgets(card, w) {
597612 w->new_power = w->power;
598613 w->power_checked = false;
599614 }
....@@ -606,12 +621,11 @@
606621 return dapm->component->name_prefix;
607622 }
608623
609
-static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg,
610
- unsigned int *value)
624
+static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg)
611625 {
612626 if (!dapm->component)
613627 return -EIO;
614
- return snd_soc_component_read(dapm->component, reg, value);
628
+ return snd_soc_component_read(dapm->component, reg);
615629 }
616630
617631 static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
....@@ -688,8 +702,8 @@
688702 {
689703 int ret = 0;
690704
691
- if (dapm->set_bias_level)
692
- ret = dapm->set_bias_level(dapm, level);
705
+ if (dapm->component)
706
+ ret = snd_soc_component_set_bias_level(dapm->component, level);
693707
694708 if (ret == 0)
695709 dapm->bias_level = level;
....@@ -715,8 +729,7 @@
715729
716730 trace_snd_soc_bias_level_start(card, level);
717731
718
- if (card && card->set_bias_level)
719
- ret = card->set_bias_level(card, dapm, level);
732
+ ret = snd_soc_card_set_bias_level(card, dapm, level);
720733 if (ret != 0)
721734 goto out;
722735
....@@ -726,8 +739,7 @@
726739 if (ret != 0)
727740 goto out;
728741
729
- if (card && card->set_bias_level_post)
730
- ret = card->set_bias_level_post(card, dapm, level);
742
+ ret = snd_soc_card_set_bias_level_post(card, dapm, level);
731743 out:
732744 trace_snd_soc_bias_level_done(card, level);
733745
....@@ -745,7 +757,7 @@
745757 int i;
746758
747759 if (e->reg != SND_SOC_NOPM) {
748
- soc_dapm_read(dapm, e->reg, &val);
760
+ val = soc_dapm_read(dapm, e->reg);
749761 val = (val >> e->shift_l) & e->mask;
750762 item = snd_soc_enum_val_to_item(e, val);
751763 } else {
....@@ -782,7 +794,7 @@
782794 unsigned int val;
783795
784796 if (reg != SND_SOC_NOPM) {
785
- soc_dapm_read(p->sink->dapm, reg, &val);
797
+ val = soc_dapm_read(p->sink->dapm, reg);
786798 /*
787799 * The nth_path argument allows this function to know
788800 * which path of a kcontrol it is setting the initial
....@@ -797,7 +809,7 @@
797809 */
798810 if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) {
799811 if (reg != mc->rreg)
800
- soc_dapm_read(p->sink->dapm, mc->rreg, &val);
812
+ val = soc_dapm_read(p->sink->dapm, mc->rreg);
801813 val = (val >> mc->rshift) & mask;
802814 } else {
803815 val = (val >> shift) & mask;
....@@ -843,7 +855,7 @@
843855
844856 *kcontrol = NULL;
845857
846
- list_for_each_entry(w, &dapm->card->widgets, list) {
858
+ for_each_card_widgets(dapm->card, w) {
847859 if (w == kcontrolw || w->dapm != kcontrolw->dapm)
848860 continue;
849861 for (i = 0; i < w->num_kcontrols; i++) {
....@@ -894,6 +906,7 @@
894906 case snd_soc_dapm_switch:
895907 case snd_soc_dapm_mixer:
896908 case snd_soc_dapm_pga:
909
+ case snd_soc_dapm_effect:
897910 case snd_soc_dapm_out_drv:
898911 wname_in_long_name = true;
899912 kcname_in_long_name = true;
....@@ -1070,9 +1083,10 @@
10701083 struct snd_kcontrol *kcontrol;
10711084 struct snd_soc_dapm_context *dapm = w->dapm;
10721085 struct snd_card *card = dapm->card->snd_card;
1086
+ struct snd_soc_pcm_runtime *rtd = w->priv;
10731087
10741088 /* create control for links with > 1 config */
1075
- if (w->num_params <= 1)
1089
+ if (rtd->dai_link->num_params <= 1)
10761090 return 0;
10771091
10781092 /* add kcontrol */
....@@ -1113,6 +1127,11 @@
11131127 }
11141128 }
11151129
1130
+static void dapm_widget_list_free(struct snd_soc_dapm_widget_list **list)
1131
+{
1132
+ kfree(*list);
1133
+}
1134
+
11161135 static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
11171136 struct list_head *widgets)
11181137 {
....@@ -1134,6 +1153,34 @@
11341153 (*list)->num_widgets = i;
11351154
11361155 return 0;
1156
+}
1157
+
1158
+/*
1159
+ * Recursively reset the cached number of inputs or outputs for the specified
1160
+ * widget and all widgets that can be reached via incoming or outcoming paths
1161
+ * from the widget.
1162
+ */
1163
+static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget,
1164
+ enum snd_soc_dapm_direction dir)
1165
+{
1166
+ enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
1167
+ struct snd_soc_dapm_path *path;
1168
+
1169
+ widget->endpoints[dir] = -1;
1170
+
1171
+ snd_soc_dapm_widget_for_each_path(widget, rdir, path) {
1172
+ if (path->weak || path->is_supply)
1173
+ continue;
1174
+
1175
+ if (path->walking)
1176
+ return;
1177
+
1178
+ if (path->connect) {
1179
+ path->walking = 1;
1180
+ invalidate_paths_ep(path->node[dir], dir);
1181
+ path->walking = 0;
1182
+ }
1183
+ }
11371184 }
11381185
11391186 /*
....@@ -1234,7 +1281,7 @@
12341281 }
12351282
12361283 /**
1237
- * snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
1284
+ * snd_soc_dapm_dai_get_connected_widgets - query audio path and it's widgets.
12381285 * @dai: the soc DAI.
12391286 * @stream: stream direction.
12401287 * @list: list of active widgets for this stream.
....@@ -1265,21 +1312,17 @@
12651312
12661313 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
12671314
1268
- /*
1269
- * For is_connected_{output,input}_ep fully discover the graph we need
1270
- * to reset the cached number of inputs and outputs.
1271
- */
1272
- list_for_each_entry(w, &card->widgets, list) {
1273
- w->endpoints[SND_SOC_DAPM_DIR_IN] = -1;
1274
- w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1;
1315
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1316
+ w = dai->playback_widget;
1317
+ invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT);
1318
+ paths = is_connected_output_ep(w, &widgets,
1319
+ custom_stop_condition);
1320
+ } else {
1321
+ w = dai->capture_widget;
1322
+ invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN);
1323
+ paths = is_connected_input_ep(w, &widgets,
1324
+ custom_stop_condition);
12751325 }
1276
-
1277
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1278
- paths = is_connected_output_ep(dai->playback_widget, &widgets,
1279
- custom_stop_condition);
1280
- else
1281
- paths = is_connected_input_ep(dai->capture_widget, &widgets,
1282
- custom_stop_condition);
12831326
12841327 /* Drop starting point */
12851328 list_del(widgets.next);
....@@ -1292,6 +1335,11 @@
12921335 mutex_unlock(&card->dapm_mutex);
12931336
12941337 return paths;
1338
+}
1339
+
1340
+void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list)
1341
+{
1342
+ dapm_widget_list_free(list);
12951343 }
12961344
12971345 /*
....@@ -1364,14 +1412,13 @@
13641412
13651413 soc_dapm_async_complete(w->dapm);
13661414
1367
-#ifdef CONFIG_HAVE_CLK
13681415 if (SND_SOC_DAPM_EVENT_ON(event)) {
13691416 return clk_prepare_enable(w->clk);
13701417 } else {
13711418 clk_disable_unprepare(w->clk);
13721419 return 0;
13731420 }
1374
-#endif
1421
+
13751422 return 0;
13761423 }
13771424 EXPORT_SYMBOL_GPL(dapm_clock_event);
....@@ -1439,10 +1486,16 @@
14391486 {
14401487 int *sort;
14411488
1489
+ BUILD_BUG_ON(ARRAY_SIZE(dapm_up_seq) != SND_SOC_DAPM_TYPE_COUNT);
1490
+ BUILD_BUG_ON(ARRAY_SIZE(dapm_down_seq) != SND_SOC_DAPM_TYPE_COUNT);
1491
+
14421492 if (power_up)
14431493 sort = dapm_up_seq;
14441494 else
14451495 sort = dapm_down_seq;
1496
+
1497
+ WARN_ONCE(sort[a->id] == 0, "offset a->id %d not initialized\n", a->id);
1498
+ WARN_ONCE(sort[b->id] == 0, "offset b->id %d not initialized\n", b->id);
14461499
14471500 if (sort[a->id] != sort[b->id])
14481501 return sort[a->id] - sort[b->id];
....@@ -1611,15 +1664,15 @@
16111664 /* Do we need to apply any queued changes? */
16121665 if (sort[w->id] != cur_sort || w->reg != cur_reg ||
16131666 w->dapm != cur_dapm || w->subseq != cur_subseq) {
1614
- if (cur_dapm && !list_empty(&pending))
1667
+ if (!list_empty(&pending))
16151668 dapm_seq_run_coalesced(card, &pending);
16161669
1617
- if (cur_dapm && cur_dapm->seq_notifier) {
1670
+ if (cur_dapm && cur_dapm->component) {
16181671 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
16191672 if (sort[i] == cur_sort)
1620
- cur_dapm->seq_notifier(cur_dapm,
1621
- i,
1622
- cur_subseq);
1673
+ snd_soc_component_seq_notifier(
1674
+ cur_dapm->component,
1675
+ i, cur_subseq);
16231676 }
16241677
16251678 if (cur_dapm && w->dapm != cur_dapm)
....@@ -1635,8 +1688,7 @@
16351688 switch (w->id) {
16361689 case snd_soc_dapm_pre:
16371690 if (!w->event)
1638
- list_for_each_entry_safe_continue(w, n, list,
1639
- power_list);
1691
+ continue;
16401692
16411693 if (event == SND_SOC_DAPM_STREAM_START)
16421694 ret = w->event(w,
....@@ -1648,8 +1700,7 @@
16481700
16491701 case snd_soc_dapm_post:
16501702 if (!w->event)
1651
- list_for_each_entry_safe_continue(w, n, list,
1652
- power_list);
1703
+ continue;
16531704
16541705 if (event == SND_SOC_DAPM_STREAM_START)
16551706 ret = w->event(w,
....@@ -1674,19 +1725,19 @@
16741725 "ASoC: Failed to apply widget power: %d\n", ret);
16751726 }
16761727
1677
- if (cur_dapm && !list_empty(&pending))
1728
+ if (!list_empty(&pending))
16781729 dapm_seq_run_coalesced(card, &pending);
16791730
1680
- if (cur_dapm && cur_dapm->seq_notifier) {
1731
+ if (cur_dapm && cur_dapm->component) {
16811732 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
16821733 if (sort[i] == cur_sort)
1683
- cur_dapm->seq_notifier(cur_dapm,
1684
- i, cur_subseq);
1734
+ snd_soc_component_seq_notifier(
1735
+ cur_dapm->component,
1736
+ i, cur_subseq);
16851737 }
16861738
1687
- list_for_each_entry(d, &card->dapm_list, list) {
1739
+ for_each_card_dapms(card, d)
16881740 soc_dapm_async_complete(d);
1689
- }
16901741 }
16911742
16921743 static void dapm_widget_update(struct snd_soc_card *card)
....@@ -1702,9 +1753,7 @@
17021753
17031754 wlist = dapm_kcontrol_get_wlist(update->kcontrol);
17041755
1705
- for (wi = 0; wi < wlist->num_widgets; wi++) {
1706
- w = wlist->widgets[wi];
1707
-
1756
+ for_each_dapm_widgets(wlist, wi, w) {
17081757 if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
17091758 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
17101759 if (ret != 0)
....@@ -1731,9 +1780,7 @@
17311780 w->name, ret);
17321781 }
17331782
1734
- for (wi = 0; wi < wlist->num_widgets; wi++) {
1735
- w = wlist->widgets[wi];
1736
-
1783
+ for_each_dapm_widgets(wlist, wi, w) {
17371784 if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
17381785 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
17391786 if (ret != 0)
....@@ -1754,7 +1801,7 @@
17541801 /* If we're off and we're not supposed to go into STANDBY */
17551802 if (d->bias_level == SND_SOC_BIAS_OFF &&
17561803 d->target_bias_level != SND_SOC_BIAS_OFF) {
1757
- if (d->dev)
1804
+ if (d->dev && cookie)
17581805 pm_runtime_get_sync(d->dev);
17591806
17601807 ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
....@@ -1801,7 +1848,7 @@
18011848 dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
18021849 ret);
18031850
1804
- if (d->dev)
1851
+ if (d->dev && cookie)
18051852 pm_runtime_put(d->dev);
18061853 }
18071854
....@@ -1915,13 +1962,13 @@
19151962 LIST_HEAD(down_list);
19161963 ASYNC_DOMAIN_EXCLUSIVE(async_domain);
19171964 enum snd_soc_bias_level bias;
1965
+ int ret;
19181966
19191967 lockdep_assert_held(&card->dapm_mutex);
19201968
19211969 trace_snd_soc_dapm_start(card);
1922
- mutex_lock(&card->dapm_power_mutex);
19231970
1924
- list_for_each_entry(d, &card->dapm_list, list) {
1971
+ for_each_card_dapms(card, d) {
19251972 if (dapm_idle_bias_off(d))
19261973 d->target_bias_level = SND_SOC_BIAS_OFF;
19271974 else
....@@ -1940,7 +1987,7 @@
19401987 dapm_power_one_widget(w, &up_list, &down_list);
19411988 }
19421989
1943
- list_for_each_entry(w, &card->widgets, list) {
1990
+ for_each_card_widgets(card, w) {
19441991 switch (w->id) {
19451992 case snd_soc_dapm_pre:
19461993 case snd_soc_dapm_post:
....@@ -1985,10 +2032,10 @@
19852032 * they're not ground referenced.
19862033 */
19872034 bias = SND_SOC_BIAS_OFF;
1988
- list_for_each_entry(d, &card->dapm_list, list)
2035
+ for_each_card_dapms(card, d)
19892036 if (d->target_bias_level > bias)
19902037 bias = d->target_bias_level;
1991
- list_for_each_entry(d, &card->dapm_list, list)
2038
+ for_each_card_dapms(card, d)
19922039 if (!dapm_idle_bias_off(d))
19932040 d->target_bias_level = bias;
19942041
....@@ -1997,8 +2044,8 @@
19972044 /* Run card bias changes at first */
19982045 dapm_pre_sequence_async(&card->dapm, 0);
19992046 /* Run other bias changes in parallel */
2000
- list_for_each_entry(d, &card->dapm_list, list) {
2001
- if (d != &card->dapm)
2047
+ for_each_card_dapms(card, d) {
2048
+ if (d != &card->dapm && d->bias_level != d->target_bias_level)
20022049 async_schedule_domain(dapm_pre_sequence_async, d,
20032050 &async_domain);
20042051 }
....@@ -2021,8 +2068,8 @@
20212068 dapm_seq_run(card, &up_list, event, true);
20222069
20232070 /* Run all the bias changes in parallel */
2024
- list_for_each_entry(d, &card->dapm_list, list) {
2025
- if (d != &card->dapm)
2071
+ for_each_card_dapms(card, d) {
2072
+ if (d != &card->dapm && d->bias_level != d->target_bias_level)
20262073 async_schedule_domain(dapm_post_sequence_async, d,
20272074 &async_domain);
20282075 }
....@@ -2031,15 +2078,18 @@
20312078 dapm_post_sequence_async(&card->dapm, 0);
20322079
20332080 /* do we need to notify any clients that DAPM event is complete */
2034
- list_for_each_entry(d, &card->dapm_list, list) {
2035
- if (d->stream_event)
2036
- d->stream_event(d, event);
2081
+ for_each_card_dapms(card, d) {
2082
+ if (!d->component)
2083
+ continue;
2084
+
2085
+ ret = snd_soc_component_stream_event(d->component, event);
2086
+ if (ret < 0)
2087
+ return ret;
20372088 }
20382089
20392090 pop_dbg(card->dev, card->pop_time,
20402091 "DAPM sequencing finished, waiting %dms\n", card->pop_time);
20412092 pop_wait(card->pop_time);
2042
- mutex_unlock(&card->dapm_power_mutex);
20432093
20442094 trace_snd_soc_dapm_done(card);
20452095
....@@ -2159,49 +2209,30 @@
21592209 void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
21602210 struct dentry *parent)
21612211 {
2162
- struct dentry *d;
2163
-
21642212 if (!parent || IS_ERR(parent))
21652213 return;
21662214
21672215 dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
21682216
2169
- if (IS_ERR(dapm->debugfs_dapm)) {
2170
- dev_warn(dapm->dev,
2171
- "ASoC: Failed to create DAPM debugfs directory %ld\n",
2172
- PTR_ERR(dapm->debugfs_dapm));
2173
- return;
2174
- }
2175
-
2176
- d = debugfs_create_file("bias_level", 0444,
2177
- dapm->debugfs_dapm, dapm,
2178
- &dapm_bias_fops);
2179
- if (IS_ERR(d))
2180
- dev_warn(dapm->dev,
2181
- "ASoC: Failed to create bias level debugfs file: %ld\n",
2182
- PTR_ERR(d));
2217
+ debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm,
2218
+ &dapm_bias_fops);
21832219 }
21842220
21852221 static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
21862222 {
21872223 struct snd_soc_dapm_context *dapm = w->dapm;
2188
- struct dentry *d;
21892224
21902225 if (!dapm->debugfs_dapm || !w->name)
21912226 return;
21922227
2193
- d = debugfs_create_file(w->name, 0444,
2194
- dapm->debugfs_dapm, w,
2195
- &dapm_widget_power_fops);
2196
- if (IS_ERR(d))
2197
- dev_warn(w->dapm->dev,
2198
- "ASoC: Failed to create %s debugfs file: %ld\n",
2199
- w->name, PTR_ERR(d));
2228
+ debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w,
2229
+ &dapm_widget_power_fops);
22002230 }
22012231
22022232 static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
22032233 {
22042234 debugfs_remove_recursive(dapm->debugfs_dapm);
2235
+ dapm->debugfs_dapm = NULL;
22052236 }
22062237
22072238 #else
....@@ -2253,7 +2284,7 @@
22532284 dapm_kcontrol_for_each_path(path, kcontrol) {
22542285 found = 1;
22552286 /* we now need to match the string in the enum to the path */
2256
- if (!(strcmp(path->name, e->texts[mux])))
2287
+ if (e && !(strcmp(path->name, e->texts[mux])))
22572288 connect = true;
22582289 else
22592290 connect = false;
....@@ -2280,7 +2311,7 @@
22802311 card->update = NULL;
22812312 mutex_unlock(&card->dapm_mutex);
22822313 if (ret > 0)
2283
- soc_dpcm_runtime_update(card);
2314
+ snd_soc_dpcm_runtime_update(card);
22842315 return ret;
22852316 }
22862317 EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
....@@ -2345,7 +2376,7 @@
23452376 card->update = NULL;
23462377 mutex_unlock(&card->dapm_mutex);
23472378 if (ret > 0)
2348
- soc_dpcm_runtime_update(card);
2379
+ snd_soc_dpcm_runtime_update(card);
23492380 return ret;
23502381 }
23512382 EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
....@@ -2365,7 +2396,7 @@
23652396 if (!cmpnt->card)
23662397 return 0;
23672398
2368
- list_for_each_entry(w, &cmpnt->card->widgets, list) {
2399
+ for_each_card_widgets(cmpnt->card, w) {
23692400 if (w->dapm != dapm)
23702401 continue;
23712402
....@@ -2379,6 +2410,7 @@
23792410 case snd_soc_dapm_dac:
23802411 case snd_soc_dapm_adc:
23812412 case snd_soc_dapm_pga:
2413
+ case snd_soc_dapm_effect:
23822414 case snd_soc_dapm_out_drv:
23832415 case snd_soc_dapm_mixer:
23842416 case snd_soc_dapm_mixer_named_ctl:
....@@ -2419,12 +2451,13 @@
24192451 struct device_attribute *attr, char *buf)
24202452 {
24212453 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
2454
+ struct snd_soc_dai *codec_dai;
24222455 int i, count = 0;
24232456
24242457 mutex_lock(&rtd->card->dapm_mutex);
24252458
2426
- for (i = 0; i < rtd->num_codecs; i++) {
2427
- struct snd_soc_component *cmpnt = rtd->codec_dais[i]->component;
2459
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
2460
+ struct snd_soc_component *cmpnt = codec_dai->component;
24282461
24292462 count += dapm_widget_show_component(cmpnt, buf + count);
24302463 }
....@@ -2469,6 +2502,7 @@
24692502
24702503 kfree(w->kcontrols);
24712504 kfree_const(w->name);
2505
+ kfree_const(w->sname);
24722506 kfree(w);
24732507 }
24742508
....@@ -2483,7 +2517,7 @@
24832517 {
24842518 struct snd_soc_dapm_widget *w, *next_w;
24852519
2486
- list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
2520
+ for_each_card_widgets_safe(dapm->card, w, next_w) {
24872521 if (w->dapm != dapm)
24882522 continue;
24892523 snd_soc_dapm_free_widget(w);
....@@ -2497,9 +2531,20 @@
24972531 {
24982532 struct snd_soc_dapm_widget *w;
24992533 struct snd_soc_dapm_widget *fallback = NULL;
2534
+ char prefixed_pin[80];
2535
+ const char *pin_name;
2536
+ const char *prefix = soc_dapm_prefix(dapm);
25002537
2501
- list_for_each_entry(w, &dapm->card->widgets, list) {
2502
- if (!strcmp(w->name, pin)) {
2538
+ if (prefix) {
2539
+ snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
2540
+ prefix, pin);
2541
+ pin_name = prefixed_pin;
2542
+ } else {
2543
+ pin_name = pin;
2544
+ }
2545
+
2546
+ for_each_card_widgets(dapm->card, w) {
2547
+ if (!strcmp(w->name, pin_name)) {
25032548 if (w->dapm == dapm)
25042549 return w;
25052550 else
....@@ -2600,6 +2645,78 @@
26002645 return ret;
26012646 }
26022647 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2648
+
2649
+static int dapm_update_dai_chan(struct snd_soc_dapm_path *p,
2650
+ struct snd_soc_dapm_widget *w,
2651
+ int channels)
2652
+{
2653
+ switch (w->id) {
2654
+ case snd_soc_dapm_aif_out:
2655
+ case snd_soc_dapm_aif_in:
2656
+ break;
2657
+ default:
2658
+ return 0;
2659
+ }
2660
+
2661
+ dev_dbg(w->dapm->dev, "%s DAI route %s -> %s\n",
2662
+ w->channel < channels ? "Connecting" : "Disconnecting",
2663
+ p->source->name, p->sink->name);
2664
+
2665
+ if (w->channel < channels)
2666
+ soc_dapm_connect_path(p, true, "dai update");
2667
+ else
2668
+ soc_dapm_connect_path(p, false, "dai update");
2669
+
2670
+ return 0;
2671
+}
2672
+
2673
+static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream,
2674
+ struct snd_pcm_hw_params *params,
2675
+ struct snd_soc_dai *dai)
2676
+{
2677
+ int dir = substream->stream;
2678
+ int channels = params_channels(params);
2679
+ struct snd_soc_dapm_path *p;
2680
+ struct snd_soc_dapm_widget *w;
2681
+ int ret;
2682
+
2683
+ w = snd_soc_dai_get_widget(dai, dir);
2684
+
2685
+ if (!w)
2686
+ return 0;
2687
+
2688
+ dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name,
2689
+ dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
2690
+
2691
+ snd_soc_dapm_widget_for_each_sink_path(w, p) {
2692
+ ret = dapm_update_dai_chan(p, p->sink, channels);
2693
+ if (ret < 0)
2694
+ return ret;
2695
+ }
2696
+
2697
+ snd_soc_dapm_widget_for_each_source_path(w, p) {
2698
+ ret = dapm_update_dai_chan(p, p->source, channels);
2699
+ if (ret < 0)
2700
+ return ret;
2701
+ }
2702
+
2703
+ return 0;
2704
+}
2705
+
2706
+int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
2707
+ struct snd_pcm_hw_params *params,
2708
+ struct snd_soc_dai *dai)
2709
+{
2710
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
2711
+ int ret;
2712
+
2713
+ mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2714
+ ret = dapm_update_dai_unlocked(substream, params, dai);
2715
+ mutex_unlock(&rtd->card->dapm_mutex);
2716
+
2717
+ return ret;
2718
+}
2719
+EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai);
26032720
26042721 /*
26052722 * dapm_update_widget_flags() - Re-compute widget sink and source flags
....@@ -2817,6 +2934,8 @@
28172934 char prefixed_sink[80];
28182935 char prefixed_source[80];
28192936 const char *prefix;
2937
+ unsigned int sink_ref = 0;
2938
+ unsigned int source_ref = 0;
28202939 int ret;
28212940
28222941 prefix = soc_dapm_prefix(dapm);
....@@ -2842,7 +2961,7 @@
28422961 * find src and dest widgets over all widgets but favor a widget from
28432962 * current DAPM context
28442963 */
2845
- list_for_each_entry(w, &dapm->card->widgets, list) {
2964
+ for_each_card_widgets(dapm->card, w) {
28462965 if (!wsink && !(strcmp(w->name, sink))) {
28472966 wtsink = w;
28482967 if (w->dapm == dapm) {
....@@ -2850,6 +2969,11 @@
28502969 if (wsource)
28512970 break;
28522971 }
2972
+ sink_ref++;
2973
+ if (sink_ref > 1)
2974
+ dev_warn(dapm->dev,
2975
+ "ASoC: sink widget %s overwritten\n",
2976
+ w->name);
28532977 continue;
28542978 }
28552979 if (!wsource && !(strcmp(w->name, source))) {
....@@ -2859,6 +2983,11 @@
28592983 if (wsink)
28602984 break;
28612985 }
2986
+ source_ref++;
2987
+ if (source_ref > 1)
2988
+ dev_warn(dapm->dev,
2989
+ "ASoC: source widget %s overwritten\n",
2990
+ w->name);
28622991 }
28632992 }
28642993 /* use widget from another DAPM context if not found from this */
....@@ -3111,7 +3240,7 @@
31113240
31123241 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
31133242
3114
- list_for_each_entry(w, &card->widgets, list)
3243
+ for_each_card_widgets(card, w)
31153244 {
31163245 if (w->new)
31173246 continue;
....@@ -3137,6 +3266,7 @@
31373266 dapm_new_mux(w);
31383267 break;
31393268 case snd_soc_dapm_pga:
3269
+ case snd_soc_dapm_effect:
31403270 case snd_soc_dapm_out_drv:
31413271 dapm_new_pga(w);
31423272 break;
....@@ -3149,7 +3279,7 @@
31493279
31503280 /* Read the initial power state from the device */
31513281 if (w->reg >= 0) {
3152
- soc_dapm_read(w->dapm, w->reg, &val);
3282
+ val = soc_dapm_read(w->dapm, w->reg);
31533283 val = val >> w->shift;
31543284 val &= w->mask;
31553285 if (val == w->on_val)
....@@ -3191,15 +3321,14 @@
31913321 unsigned int mask = (1 << fls(max)) - 1;
31923322 unsigned int invert = mc->invert;
31933323 unsigned int reg_val, val, rval = 0;
3194
- int ret = 0;
31953324
31963325 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
31973326 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
3198
- ret = soc_dapm_read(dapm, reg, &reg_val);
3327
+ reg_val = soc_dapm_read(dapm, reg);
31993328 val = (reg_val >> shift) & mask;
32003329
3201
- if (ret == 0 && reg != mc->rreg)
3202
- ret = soc_dapm_read(dapm, mc->rreg, &reg_val);
3330
+ if (reg != mc->rreg)
3331
+ reg_val = soc_dapm_read(dapm, mc->rreg);
32033332
32043333 if (snd_soc_volsw_is_stereo(mc))
32053334 rval = (reg_val >> mc->rshift) & mask;
....@@ -3211,9 +3340,6 @@
32113340 rval = (reg_val >> width) & mask;
32123341 }
32133342 mutex_unlock(&card->dapm_mutex);
3214
-
3215
- if (ret)
3216
- return ret;
32173343
32183344 if (invert)
32193345 ucontrol->value.integer.value[0] = max - val;
....@@ -3227,7 +3353,7 @@
32273353 ucontrol->value.integer.value[1] = rval;
32283354 }
32293355
3230
- return ret;
3356
+ return 0;
32313357 }
32323358 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
32333359
....@@ -3306,7 +3432,6 @@
33063432 update.val = val;
33073433 card->update = &update;
33083434 }
3309
- change |= reg_change;
33103435
33113436 ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
33123437 rconnect);
....@@ -3317,7 +3442,7 @@
33173442 mutex_unlock(&card->dapm_mutex);
33183443
33193444 if (ret > 0)
3320
- soc_dpcm_runtime_update(card);
3445
+ snd_soc_dpcm_runtime_update(card);
33213446
33223447 return change;
33233448 }
....@@ -3342,11 +3467,7 @@
33423467
33433468 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
33443469 if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) {
3345
- int ret = soc_dapm_read(dapm, e->reg, &reg_val);
3346
- if (ret) {
3347
- mutex_unlock(&card->dapm_mutex);
3348
- return ret;
3349
- }
3470
+ reg_val = soc_dapm_read(dapm, e->reg);
33503471 } else {
33513472 reg_val = dapm_kcontrol_get_value(kcontrol);
33523473 }
....@@ -3412,7 +3533,6 @@
34123533 update.val = val;
34133534 card->update = &update;
34143535 }
3415
- change |= reg_change;
34163536
34173537 ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
34183538
....@@ -3422,7 +3542,7 @@
34223542 mutex_unlock(&card->dapm_mutex);
34233543
34243544 if (ret > 0)
3425
- soc_dpcm_runtime_update(card);
3545
+ snd_soc_dpcm_runtime_update(card);
34263546
34273547 return change;
34283548 }
....@@ -3495,35 +3615,6 @@
34953615 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
34963616
34973617 struct snd_soc_dapm_widget *
3498
-snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3499
- const struct snd_soc_dapm_widget *widget)
3500
-{
3501
- struct snd_soc_dapm_widget *w;
3502
-
3503
- mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3504
- w = snd_soc_dapm_new_control_unlocked(dapm, widget);
3505
- /* Do not nag about probe deferrals */
3506
- if (IS_ERR(w)) {
3507
- int ret = PTR_ERR(w);
3508
-
3509
- if (ret != -EPROBE_DEFER)
3510
- dev_err(dapm->dev,
3511
- "ASoC: Failed to create DAPM control %s (%d)\n",
3512
- widget->name, ret);
3513
- goto out_unlock;
3514
- }
3515
- if (!w)
3516
- dev_err(dapm->dev,
3517
- "ASoC: Failed to create DAPM control %s\n",
3518
- widget->name);
3519
-
3520
-out_unlock:
3521
- mutex_unlock(&dapm->card->dapm_mutex);
3522
- return w;
3523
-}
3524
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
3525
-
3526
-struct snd_soc_dapm_widget *
35273618 snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
35283619 const struct snd_soc_dapm_widget *widget)
35293620 {
....@@ -3533,24 +3624,20 @@
35333624 int ret;
35343625
35353626 if ((w = dapm_cnew_widget(widget)) == NULL)
3536
- return NULL;
3627
+ return ERR_PTR(-ENOMEM);
35373628
35383629 switch (w->id) {
35393630 case snd_soc_dapm_regulator_supply:
35403631 w->regulator = devm_regulator_get(dapm->dev, w->name);
35413632 if (IS_ERR(w->regulator)) {
35423633 ret = PTR_ERR(w->regulator);
3543
- if (ret == -EPROBE_DEFER)
3544
- return ERR_PTR(ret);
3545
- dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3546
- w->name, ret);
3547
- return NULL;
3634
+ goto request_failed;
35483635 }
35493636
35503637 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
35513638 ret = regulator_allow_bypass(w->regulator, true);
35523639 if (ret != 0)
3553
- dev_warn(w->dapm->dev,
3640
+ dev_warn(dapm->dev,
35543641 "ASoC: Failed to bypass %s: %d\n",
35553642 w->name, ret);
35563643 }
....@@ -3559,27 +3646,18 @@
35593646 w->pinctrl = devm_pinctrl_get(dapm->dev);
35603647 if (IS_ERR(w->pinctrl)) {
35613648 ret = PTR_ERR(w->pinctrl);
3562
- if (ret == -EPROBE_DEFER)
3563
- return ERR_PTR(ret);
3564
- dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3565
- w->name, ret);
3566
- return NULL;
3649
+ goto request_failed;
35673650 }
3651
+
3652
+ /* set to sleep_state when initializing */
3653
+ dapm_pinctrl_event(w, NULL, SND_SOC_DAPM_POST_PMD);
35683654 break;
35693655 case snd_soc_dapm_clock_supply:
3570
-#ifdef CONFIG_CLKDEV_LOOKUP
35713656 w->clk = devm_clk_get(dapm->dev, w->name);
35723657 if (IS_ERR(w->clk)) {
35733658 ret = PTR_ERR(w->clk);
3574
- if (ret == -EPROBE_DEFER)
3575
- return ERR_PTR(ret);
3576
- dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3577
- w->name, ret);
3578
- return NULL;
3659
+ goto request_failed;
35793660 }
3580
-#else
3581
- return NULL;
3582
-#endif
35833661 break;
35843662 default:
35853663 break;
....@@ -3591,8 +3669,9 @@
35913669 else
35923670 w->name = kstrdup_const(widget->name, GFP_KERNEL);
35933671 if (w->name == NULL) {
3672
+ kfree_const(w->sname);
35943673 kfree(w);
3595
- return NULL;
3674
+ return ERR_PTR(-ENOMEM);
35963675 }
35973676
35983677 switch (w->id) {
....@@ -3635,6 +3714,13 @@
36353714 case snd_soc_dapm_dac:
36363715 case snd_soc_dapm_aif_in:
36373716 case snd_soc_dapm_pga:
3717
+ case snd_soc_dapm_buffer:
3718
+ case snd_soc_dapm_scheduler:
3719
+ case snd_soc_dapm_effect:
3720
+ case snd_soc_dapm_src:
3721
+ case snd_soc_dapm_asrc:
3722
+ case snd_soc_dapm_encoder:
3723
+ case snd_soc_dapm_decoder:
36383724 case snd_soc_dapm_out_drv:
36393725 case snd_soc_dapm_micbias:
36403726 case snd_soc_dapm_line:
....@@ -3659,6 +3745,7 @@
36593745 w->dapm = dapm;
36603746 INIT_LIST_HEAD(&w->list);
36613747 INIT_LIST_HEAD(&w->dirty);
3748
+ /* see for_each_card_widgets */
36623749 list_add_tail(&w->list, &dapm->card->widgets);
36633750
36643751 snd_soc_dapm_for_each_direction(dir) {
....@@ -3669,7 +3756,39 @@
36693756 /* machine layer sets up unconnected pins and insertions */
36703757 w->connected = 1;
36713758 return w;
3759
+
3760
+request_failed:
3761
+ if (ret != -EPROBE_DEFER)
3762
+ dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
3763
+ w->name, ret);
3764
+
3765
+ kfree_const(w->sname);
3766
+ kfree(w);
3767
+ return ERR_PTR(ret);
36723768 }
3769
+
3770
+/**
3771
+ * snd_soc_dapm_new_control - create new dapm control
3772
+ * @dapm: DAPM context
3773
+ * @widget: widget template
3774
+ *
3775
+ * Creates new DAPM control based upon a template.
3776
+ *
3777
+ * Returns a widget pointer on success or an error pointer on failure
3778
+ */
3779
+struct snd_soc_dapm_widget *
3780
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3781
+ const struct snd_soc_dapm_widget *widget)
3782
+{
3783
+ struct snd_soc_dapm_widget *w;
3784
+
3785
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3786
+ w = snd_soc_dapm_new_control_unlocked(dapm, widget);
3787
+ mutex_unlock(&dapm->card->dapm_mutex);
3788
+
3789
+ return w;
3790
+}
3791
+EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
36733792
36743793 /**
36753794 * snd_soc_dapm_new_controls - create new dapm controls
....@@ -3694,19 +3813,6 @@
36943813 w = snd_soc_dapm_new_control_unlocked(dapm, widget);
36953814 if (IS_ERR(w)) {
36963815 ret = PTR_ERR(w);
3697
- /* Do not nag about probe deferrals */
3698
- if (ret == -EPROBE_DEFER)
3699
- break;
3700
- dev_err(dapm->dev,
3701
- "ASoC: Failed to create DAPM control %s (%d)\n",
3702
- widget->name, ret);
3703
- break;
3704
- }
3705
- if (!w) {
3706
- dev_err(dapm->dev,
3707
- "ASoC: Failed to create DAPM control %s\n",
3708
- widget->name);
3709
- ret = -ENOMEM;
37103816 break;
37113817 }
37123818 widget++;
....@@ -3716,34 +3822,70 @@
37163822 }
37173823 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
37183824
3719
-static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
3720
- struct snd_kcontrol *kcontrol, int event)
3825
+static int
3826
+snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,
3827
+ struct snd_pcm_substream *substream)
37213828 {
3722
- struct snd_soc_dapm_path *source_p, *sink_p;
3829
+ struct snd_soc_dapm_path *path;
37233830 struct snd_soc_dai *source, *sink;
3724
- struct snd_soc_pcm_runtime *rtd = w->priv;
3725
- const struct snd_soc_pcm_stream *config = w->params + w->params_select;
3726
- struct snd_pcm_substream substream;
3831
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
37273832 struct snd_pcm_hw_params *params = NULL;
3833
+ const struct snd_soc_pcm_stream *config = NULL;
37283834 struct snd_pcm_runtime *runtime = NULL;
37293835 unsigned int fmt;
37303836 int ret = 0;
37313837
3732
- if (WARN_ON(!config) ||
3733
- WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||
3734
- list_empty(&w->edges[SND_SOC_DAPM_DIR_IN])))
3735
- return -EINVAL;
3838
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
3839
+ if (!params)
3840
+ return -ENOMEM;
37363841
3737
- /* We only support a single source and sink, pick the first */
3738
- source_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_OUT],
3739
- struct snd_soc_dapm_path,
3740
- list_node[SND_SOC_DAPM_DIR_OUT]);
3741
- sink_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_IN],
3742
- struct snd_soc_dapm_path,
3743
- list_node[SND_SOC_DAPM_DIR_IN]);
3842
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
3843
+ if (!runtime) {
3844
+ ret = -ENOMEM;
3845
+ goto out;
3846
+ }
37443847
3745
- source = source_p->source->priv;
3746
- sink = sink_p->sink->priv;
3848
+ substream->runtime = runtime;
3849
+
3850
+ substream->stream = SNDRV_PCM_STREAM_CAPTURE;
3851
+ snd_soc_dapm_widget_for_each_source_path(w, path) {
3852
+ source = path->source->priv;
3853
+
3854
+ ret = snd_soc_dai_startup(source, substream);
3855
+ if (ret < 0) {
3856
+ dev_err(source->dev,
3857
+ "ASoC: startup() failed: %d\n", ret);
3858
+ goto out;
3859
+ }
3860
+ snd_soc_dai_activate(source, substream->stream);
3861
+ }
3862
+
3863
+ substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
3864
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
3865
+ sink = path->sink->priv;
3866
+
3867
+ ret = snd_soc_dai_startup(sink, substream);
3868
+ if (ret < 0) {
3869
+ dev_err(sink->dev,
3870
+ "ASoC: startup() failed: %d\n", ret);
3871
+ goto out;
3872
+ }
3873
+ snd_soc_dai_activate(sink, substream->stream);
3874
+ }
3875
+
3876
+ substream->hw_opened = 1;
3877
+
3878
+ /*
3879
+ * Note: getting the config after .startup() gives a chance to
3880
+ * either party on the link to alter the configuration if
3881
+ * necessary
3882
+ */
3883
+ config = rtd->dai_link->params + rtd->params_select;
3884
+ if (WARN_ON(!config)) {
3885
+ dev_err(w->dapm->dev, "ASoC: link config missing\n");
3886
+ ret = -EINVAL;
3887
+ goto out;
3888
+ }
37473889
37483890 /* Be a little careful as we don't want to overflow the mask array */
37493891 if (config->formats) {
....@@ -3751,95 +3893,127 @@
37513893 } else {
37523894 dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
37533895 config->formats);
3754
- fmt = 0;
3755
- }
37563896
3757
- /* Currently very limited parameter selection */
3758
- params = kzalloc(sizeof(*params), GFP_KERNEL);
3759
- if (!params) {
3760
- ret = -ENOMEM;
3897
+ ret = -EINVAL;
37613898 goto out;
37623899 }
3763
- snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
37643900
3901
+ snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
37653902 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
37663903 config->rate_min;
37673904 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
37683905 config->rate_max;
3769
-
37703906 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
37713907 = config->channels_min;
37723908 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
37733909 = config->channels_max;
37743910
3775
- memset(&substream, 0, sizeof(substream));
3911
+ substream->stream = SNDRV_PCM_STREAM_CAPTURE;
3912
+ snd_soc_dapm_widget_for_each_source_path(w, path) {
3913
+ source = path->source->priv;
37763914
3777
- /* Allocate a dummy snd_pcm_runtime for startup() and other ops() */
3778
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
3779
- if (!runtime) {
3780
- ret = -ENOMEM;
3781
- goto out;
3915
+ ret = snd_soc_dai_hw_params(source, substream, params);
3916
+ if (ret < 0)
3917
+ goto out;
3918
+
3919
+ dapm_update_dai_unlocked(substream, params, source);
37823920 }
3783
- substream.runtime = runtime;
3784
- substream.private_data = rtd;
3921
+
3922
+ substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
3923
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
3924
+ sink = path->sink->priv;
3925
+
3926
+ ret = snd_soc_dai_hw_params(sink, substream, params);
3927
+ if (ret < 0)
3928
+ goto out;
3929
+
3930
+ dapm_update_dai_unlocked(substream, params, sink);
3931
+ }
3932
+
3933
+ runtime->format = params_format(params);
3934
+ runtime->subformat = params_subformat(params);
3935
+ runtime->channels = params_channels(params);
3936
+ runtime->rate = params_rate(params);
3937
+
3938
+out:
3939
+ kfree(params);
3940
+ return ret;
3941
+}
3942
+
3943
+static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
3944
+ struct snd_kcontrol *kcontrol, int event)
3945
+{
3946
+ struct snd_soc_dapm_path *path;
3947
+ struct snd_soc_dai *source, *sink;
3948
+ struct snd_pcm_substream *substream = w->priv;
3949
+ int ret = 0, saved_stream = substream->stream;
3950
+
3951
+ if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||
3952
+ list_empty(&w->edges[SND_SOC_DAPM_DIR_IN])))
3953
+ return -EINVAL;
37853954
37863955 switch (event) {
37873956 case SND_SOC_DAPM_PRE_PMU:
3788
- substream.stream = SNDRV_PCM_STREAM_CAPTURE;
3789
- if (source->driver->ops->startup) {
3790
- ret = source->driver->ops->startup(&substream, source);
3791
- if (ret < 0) {
3792
- dev_err(source->dev,
3793
- "ASoC: startup() failed: %d\n", ret);
3794
- goto out;
3795
- }
3796
- source->active++;
3797
- }
3798
- ret = soc_dai_hw_params(&substream, params, source);
3957
+ ret = snd_soc_dai_link_event_pre_pmu(w, substream);
37993958 if (ret < 0)
38003959 goto out;
38013960
3802
- substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
3803
- if (sink->driver->ops->startup) {
3804
- ret = sink->driver->ops->startup(&substream, sink);
3805
- if (ret < 0) {
3806
- dev_err(sink->dev,
3807
- "ASoC: startup() failed: %d\n", ret);
3808
- goto out;
3809
- }
3810
- sink->active++;
3811
- }
3812
- ret = soc_dai_hw_params(&substream, params, sink);
3813
- if (ret < 0)
3814
- goto out;
38153961 break;
38163962
38173963 case SND_SOC_DAPM_POST_PMU:
3818
- ret = snd_soc_dai_digital_mute(sink, 0,
3819
- SNDRV_PCM_STREAM_PLAYBACK);
3820
- if (ret != 0 && ret != -ENOTSUPP)
3821
- dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
3822
- ret = 0;
3964
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
3965
+ sink = path->sink->priv;
3966
+
3967
+ ret = snd_soc_dai_digital_mute(sink, 0,
3968
+ SNDRV_PCM_STREAM_PLAYBACK);
3969
+ if (ret != 0 && ret != -ENOTSUPP)
3970
+ dev_warn(sink->dev,
3971
+ "ASoC: Failed to unmute: %d\n", ret);
3972
+ ret = 0;
3973
+ }
38233974 break;
38243975
38253976 case SND_SOC_DAPM_PRE_PMD:
3826
- ret = snd_soc_dai_digital_mute(sink, 1,
3827
- SNDRV_PCM_STREAM_PLAYBACK);
3828
- if (ret != 0 && ret != -ENOTSUPP)
3829
- dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
3830
- ret = 0;
3977
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
3978
+ sink = path->sink->priv;
38313979
3832
- source->active--;
3833
- if (source->driver->ops->shutdown) {
3834
- substream.stream = SNDRV_PCM_STREAM_CAPTURE;
3835
- source->driver->ops->shutdown(&substream, source);
3980
+ ret = snd_soc_dai_digital_mute(sink, 1,
3981
+ SNDRV_PCM_STREAM_PLAYBACK);
3982
+ if (ret != 0 && ret != -ENOTSUPP)
3983
+ dev_warn(sink->dev,
3984
+ "ASoC: Failed to mute: %d\n", ret);
3985
+ ret = 0;
38363986 }
38373987
3838
- sink->active--;
3839
- if (sink->driver->ops->shutdown) {
3840
- substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
3841
- sink->driver->ops->shutdown(&substream, sink);
3988
+ substream->stream = SNDRV_PCM_STREAM_CAPTURE;
3989
+ snd_soc_dapm_widget_for_each_source_path(w, path) {
3990
+ source = path->source->priv;
3991
+ snd_soc_dai_hw_free(source, substream);
38423992 }
3993
+
3994
+ substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
3995
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
3996
+ sink = path->sink->priv;
3997
+ snd_soc_dai_hw_free(sink, substream);
3998
+ }
3999
+
4000
+ substream->stream = SNDRV_PCM_STREAM_CAPTURE;
4001
+ snd_soc_dapm_widget_for_each_source_path(w, path) {
4002
+ source = path->source->priv;
4003
+ snd_soc_dai_deactivate(source, substream->stream);
4004
+ snd_soc_dai_shutdown(source, substream, 0);
4005
+ }
4006
+
4007
+ substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
4008
+ snd_soc_dapm_widget_for_each_sink_path(w, path) {
4009
+ sink = path->sink->priv;
4010
+ snd_soc_dai_deactivate(sink, substream->stream);
4011
+ snd_soc_dai_shutdown(sink, substream, 0);
4012
+ }
4013
+ break;
4014
+
4015
+ case SND_SOC_DAPM_POST_PMD:
4016
+ kfree(substream->runtime);
38434017 break;
38444018
38454019 default:
....@@ -3848,8 +4022,8 @@
38484022 }
38494023
38504024 out:
3851
- kfree(runtime);
3852
- kfree(params);
4025
+ /* Restore the substream direction */
4026
+ substream->stream = saved_stream;
38534027 return ret;
38544028 }
38554029
....@@ -3857,8 +4031,9 @@
38574031 struct snd_ctl_elem_value *ucontrol)
38584032 {
38594033 struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
4034
+ struct snd_soc_pcm_runtime *rtd = w->priv;
38604035
3861
- ucontrol->value.enumerated.item[0] = w->params_select;
4036
+ ucontrol->value.enumerated.item[0] = rtd->params_select;
38624037
38634038 return 0;
38644039 }
....@@ -3867,18 +4042,19 @@
38674042 struct snd_ctl_elem_value *ucontrol)
38684043 {
38694044 struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
4045
+ struct snd_soc_pcm_runtime *rtd = w->priv;
38704046
38714047 /* Can't change the config when widget is already powered */
38724048 if (w->power)
38734049 return -EBUSY;
38744050
3875
- if (ucontrol->value.enumerated.item[0] == w->params_select)
4051
+ if (ucontrol->value.enumerated.item[0] == rtd->params_select)
38764052 return 0;
38774053
3878
- if (ucontrol->value.enumerated.item[0] >= w->num_params)
4054
+ if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params)
38794055 return -EINVAL;
38804056
3881
- w->params_select = ucontrol->value.enumerated.item[0];
4057
+ rtd->params_select = ucontrol->value.enumerated.item[0];
38824058
38834059 return 1;
38844060 }
....@@ -3969,24 +4145,23 @@
39694145 return NULL;
39704146 }
39714147
3972
-int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
3973
- struct snd_soc_pcm_runtime *rtd,
3974
- const struct snd_soc_pcm_stream *params,
3975
- unsigned int num_params,
3976
- struct snd_soc_dapm_widget *source,
3977
- struct snd_soc_dapm_widget *sink)
4148
+static struct snd_soc_dapm_widget *
4149
+snd_soc_dapm_new_dai(struct snd_soc_card *card,
4150
+ struct snd_pcm_substream *substream,
4151
+ char *id)
39784152 {
4153
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
39794154 struct snd_soc_dapm_widget template;
39804155 struct snd_soc_dapm_widget *w;
39814156 const char **w_param_text;
3982
- unsigned long private_value;
4157
+ unsigned long private_value = 0;
39834158 char *link_name;
39844159 int ret;
39854160
39864161 link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
3987
- source->name, sink->name);
4162
+ rtd->dai_link->name, id);
39884163 if (!link_name)
3989
- return -ENOMEM;
4164
+ return ERR_PTR(-ENOMEM);
39904165
39914166 memset(&template, 0, sizeof(template));
39924167 template.reg = SND_SOC_NOPM;
....@@ -3994,13 +4169,14 @@
39944169 template.name = link_name;
39954170 template.event = snd_soc_dai_link_event;
39964171 template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
3997
- SND_SOC_DAPM_PRE_PMD;
4172
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD;
39984173 template.kcontrol_news = NULL;
39994174
40004175 /* allocate memory for control, only in case of multiple configs */
4001
- if (num_params > 1) {
4002
- w_param_text = devm_kcalloc(card->dev, num_params,
4003
- sizeof(char *), GFP_KERNEL);
4176
+ if (rtd->dai_link->num_params > 1) {
4177
+ w_param_text = devm_kcalloc(card->dev,
4178
+ rtd->dai_link->num_params,
4179
+ sizeof(char *), GFP_KERNEL);
40044180 if (!w_param_text) {
40054181 ret = -ENOMEM;
40064182 goto param_fail;
....@@ -4009,7 +4185,9 @@
40094185 template.num_kcontrols = 1;
40104186 template.kcontrol_news =
40114187 snd_soc_dapm_alloc_kcontrol(card,
4012
- link_name, params, num_params,
4188
+ link_name,
4189
+ rtd->dai_link->params,
4190
+ rtd->dai_link->num_params,
40134191 w_param_text, &private_value);
40144192 if (!template.kcontrol_news) {
40154193 ret = -ENOMEM;
....@@ -4023,37 +4201,22 @@
40234201 w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
40244202 if (IS_ERR(w)) {
40254203 ret = PTR_ERR(w);
4026
- /* Do not nag about probe deferrals */
4027
- if (ret != -EPROBE_DEFER)
4028
- dev_err(card->dev,
4029
- "ASoC: Failed to create %s widget (%d)\n",
4030
- link_name, ret);
4031
- goto outfree_kcontrol_news;
4032
- }
4033
- if (!w) {
4034
- dev_err(card->dev, "ASoC: Failed to create %s widget\n",
4035
- link_name);
4036
- ret = -ENOMEM;
4204
+ dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
4205
+ link_name, ret);
40374206 goto outfree_kcontrol_news;
40384207 }
40394208
4040
- w->params = params;
4041
- w->num_params = num_params;
4042
- w->priv = rtd;
4209
+ w->priv = substream;
40434210
4044
- ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
4045
- if (ret)
4046
- goto outfree_w;
4047
- return snd_soc_dapm_add_path(&card->dapm, w, sink, NULL, NULL);
4211
+ return w;
40484212
4049
-outfree_w:
4050
- devm_kfree(card->dev, w);
40514213 outfree_kcontrol_news:
40524214 devm_kfree(card->dev, (void *)template.kcontrol_news);
4053
- snd_soc_dapm_free_kcontrol(card, &private_value, num_params, w_param_text);
4215
+ snd_soc_dapm_free_kcontrol(card, &private_value,
4216
+ rtd->dai_link->num_params, w_param_text);
40544217 param_fail:
40554218 devm_kfree(card->dev, link_name);
4056
- return ret;
4219
+ return ERR_PTR(ret);
40574220 }
40584221
40594222 int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
....@@ -4076,21 +4239,8 @@
40764239 template.name);
40774240
40784241 w = snd_soc_dapm_new_control_unlocked(dapm, &template);
4079
- if (IS_ERR(w)) {
4080
- int ret = PTR_ERR(w);
4081
-
4082
- /* Do not nag about probe deferrals */
4083
- if (ret != -EPROBE_DEFER)
4084
- dev_err(dapm->dev,
4085
- "ASoC: Failed to create %s widget (%d)\n",
4086
- dai->driver->playback.stream_name, ret);
4087
- return ret;
4088
- }
4089
- if (!w) {
4090
- dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
4091
- dai->driver->playback.stream_name);
4092
- return -ENOMEM;
4093
- }
4242
+ if (IS_ERR(w))
4243
+ return PTR_ERR(w);
40944244
40954245 w->priv = dai;
40964246 dai->playback_widget = w;
....@@ -4105,21 +4255,8 @@
41054255 template.name);
41064256
41074257 w = snd_soc_dapm_new_control_unlocked(dapm, &template);
4108
- if (IS_ERR(w)) {
4109
- int ret = PTR_ERR(w);
4110
-
4111
- /* Do not nag about probe deferrals */
4112
- if (ret != -EPROBE_DEFER)
4113
- dev_err(dapm->dev,
4114
- "ASoC: Failed to create %s widget (%d)\n",
4115
- dai->driver->playback.stream_name, ret);
4116
- return ret;
4117
- }
4118
- if (!w) {
4119
- dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
4120
- dai->driver->capture.stream_name);
4121
- return -ENOMEM;
4122
- }
4258
+ if (IS_ERR(w))
4259
+ return PTR_ERR(w);
41234260
41244261 w->priv = dai;
41254262 dai->capture_widget = w;
....@@ -4135,7 +4272,7 @@
41354272 struct snd_soc_dai *dai;
41364273
41374274 /* For each DAI widget... */
4138
- list_for_each_entry(dai_w, &card->widgets, list) {
4275
+ for_each_card_widgets(card, dai_w) {
41394276 switch (dai_w->id) {
41404277 case snd_soc_dapm_dai_in:
41414278 case snd_soc_dapm_dai_out:
....@@ -4154,7 +4291,7 @@
41544291 dai = dai_w->priv;
41554292
41564293 /* ...find all widgets with the same stream and link them */
4157
- list_for_each_entry(w, &card->widgets, list) {
4294
+ for_each_card_widgets(card, w) {
41584295 if (w->dapm != dai_w->dapm)
41594296 continue;
41604297
....@@ -4184,39 +4321,76 @@
41844321 return 0;
41854322 }
41864323
4187
-static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
4188
- struct snd_soc_pcm_runtime *rtd)
4324
+static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,
4325
+ struct snd_soc_dai *src_dai,
4326
+ struct snd_soc_dapm_widget *src,
4327
+ struct snd_soc_dapm_widget *dai,
4328
+ struct snd_soc_dai *sink_dai,
4329
+ struct snd_soc_dapm_widget *sink)
41894330 {
4190
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
4191
- struct snd_soc_dapm_widget *sink, *source;
4192
- int i;
4331
+ dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",
4332
+ src_dai->component->name, src->name,
4333
+ sink_dai->component->name, sink->name);
41934334
4194
- for (i = 0; i < rtd->num_codecs; i++) {
4195
- struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
4335
+ if (dai) {
4336
+ snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);
4337
+ src = dai;
4338
+ }
41964339
4197
- /* connect BE DAI playback if widgets are valid */
4198
- if (codec_dai->playback_widget && cpu_dai->playback_widget) {
4199
- source = cpu_dai->playback_widget;
4200
- sink = codec_dai->playback_widget;
4201
- dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
4202
- cpu_dai->component->name, source->name,
4203
- codec_dai->component->name, sink->name);
4340
+ snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);
4341
+}
42044342
4205
- snd_soc_dapm_add_path(&card->dapm, source, sink,
4206
- NULL, NULL);
4343
+static void dapm_connect_dai_pair(struct snd_soc_card *card,
4344
+ struct snd_soc_pcm_runtime *rtd,
4345
+ struct snd_soc_dai *codec_dai,
4346
+ struct snd_soc_dai *cpu_dai)
4347
+{
4348
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
4349
+ struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu;
4350
+ struct snd_pcm_substream *substream;
4351
+ struct snd_pcm_str *streams = rtd->pcm->streams;
4352
+
4353
+ if (dai_link->params) {
4354
+ playback_cpu = cpu_dai->capture_widget;
4355
+ capture_cpu = cpu_dai->playback_widget;
4356
+ } else {
4357
+ playback_cpu = cpu_dai->playback_widget;
4358
+ capture_cpu = cpu_dai->capture_widget;
4359
+ }
4360
+
4361
+ /* connect BE DAI playback if widgets are valid */
4362
+ codec = codec_dai->playback_widget;
4363
+
4364
+ if (playback_cpu && codec) {
4365
+ if (dai_link->params && !rtd->playback_widget) {
4366
+ substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
4367
+ dai = snd_soc_dapm_new_dai(card, substream, "playback");
4368
+ if (IS_ERR(dai))
4369
+ goto capture;
4370
+ rtd->playback_widget = dai;
42074371 }
42084372
4209
- /* connect BE DAI capture if widgets are valid */
4210
- if (codec_dai->capture_widget && cpu_dai->capture_widget) {
4211
- source = codec_dai->capture_widget;
4212
- sink = cpu_dai->capture_widget;
4213
- dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
4214
- codec_dai->component->name, source->name,
4215
- cpu_dai->component->name, sink->name);
4373
+ dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu,
4374
+ rtd->playback_widget,
4375
+ codec_dai, codec);
4376
+ }
42164377
4217
- snd_soc_dapm_add_path(&card->dapm, source, sink,
4218
- NULL, NULL);
4378
+capture:
4379
+ /* connect BE DAI capture if widgets are valid */
4380
+ codec = codec_dai->capture_widget;
4381
+
4382
+ if (codec && capture_cpu) {
4383
+ if (dai_link->params && !rtd->capture_widget) {
4384
+ substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream;
4385
+ dai = snd_soc_dapm_new_dai(card, substream, "capture");
4386
+ if (IS_ERR(dai))
4387
+ return;
4388
+ rtd->capture_widget = dai;
42194389 }
4390
+
4391
+ dapm_connect_dai_routes(&card->dapm, codec_dai, codec,
4392
+ rtd->capture_widget,
4393
+ cpu_dai, capture_cpu);
42204394 }
42214395 }
42224396
....@@ -4226,10 +4400,7 @@
42264400 struct snd_soc_dapm_widget *w;
42274401 unsigned int ep;
42284402
4229
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
4230
- w = dai->playback_widget;
4231
- else
4232
- w = dai->capture_widget;
4403
+ w = snd_soc_dai_get_widget(dai, stream);
42334404
42344405 if (w) {
42354406 dapm_mark_dirty(w, "stream event");
....@@ -4263,29 +4434,41 @@
42634434 void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
42644435 {
42654436 struct snd_soc_pcm_runtime *rtd;
4437
+ struct snd_soc_dai *codec_dai;
4438
+ int i;
42664439
42674440 /* for each BE DAI link... */
4268
- list_for_each_entry(rtd, &card->rtd_list, list) {
4441
+ for_each_card_rtds(card, rtd) {
42694442 /*
42704443 * dynamic FE links have no fixed DAI mapping.
42714444 * CODEC<->CODEC links have no direct connection.
42724445 */
4273
- if (rtd->dai_link->dynamic || rtd->dai_link->params ||
4274
- rtd->dai_link->dynamic_be)
4446
+ if (rtd->dai_link->dynamic)
42754447 continue;
42764448
4277
- dapm_connect_dai_link_widgets(card, rtd);
4449
+ if (rtd->num_cpus == 1) {
4450
+ for_each_rtd_codec_dais(rtd, i, codec_dai)
4451
+ dapm_connect_dai_pair(card, rtd, codec_dai,
4452
+ asoc_rtd_to_cpu(rtd, 0));
4453
+ } else if (rtd->num_codecs == rtd->num_cpus) {
4454
+ for_each_rtd_codec_dais(rtd, i, codec_dai)
4455
+ dapm_connect_dai_pair(card, rtd, codec_dai,
4456
+ asoc_rtd_to_cpu(rtd, i));
4457
+ } else {
4458
+ dev_err(card->dev,
4459
+ "N cpus to M codecs link is not supported yet\n");
4460
+ }
42784461 }
42794462 }
42804463
42814464 static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
42824465 int event)
42834466 {
4467
+ struct snd_soc_dai *dai;
42844468 int i;
42854469
4286
- soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
4287
- for (i = 0; i < rtd->num_codecs; i++)
4288
- soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);
4470
+ for_each_rtd_dais(rtd, i, dai)
4471
+ soc_dapm_dai_stream_event(dai, stream, event);
42894472
42904473 dapm_power_widgets(rtd->card, event);
42914474 }
....@@ -4310,6 +4493,29 @@
43104493 soc_dapm_stream_event(rtd, stream, event);
43114494 mutex_unlock(&card->dapm_mutex);
43124495 }
4496
+
4497
+void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream)
4498
+{
4499
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
4500
+ if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
4501
+ /* powered down playback stream now */
4502
+ snd_soc_dapm_stream_event(rtd,
4503
+ SNDRV_PCM_STREAM_PLAYBACK,
4504
+ SND_SOC_DAPM_STREAM_STOP);
4505
+ } else {
4506
+ /* start delayed pop wq here for playback streams */
4507
+ rtd->pop_wait = 1;
4508
+ queue_delayed_work(system_power_efficient_wq,
4509
+ &rtd->delayed_work,
4510
+ msecs_to_jiffies(rtd->pmdown_time));
4511
+ }
4512
+ } else {
4513
+ /* capture streams can be powered down now */
4514
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
4515
+ SND_SOC_DAPM_STREAM_STOP);
4516
+ }
4517
+}
4518
+EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_stop);
43134519
43144520 /**
43154521 * snd_soc_dapm_enable_pin_unlocked - enable pin.
....@@ -4581,6 +4787,28 @@
45814787 }
45824788 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
45834789
4790
+void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm,
4791
+ struct snd_soc_card *card,
4792
+ struct snd_soc_component *component)
4793
+{
4794
+ dapm->card = card;
4795
+ dapm->component = component;
4796
+ dapm->bias_level = SND_SOC_BIAS_OFF;
4797
+
4798
+ if (component) {
4799
+ dapm->dev = component->dev;
4800
+ dapm->idle_bias_off = !component->driver->idle_bias_on,
4801
+ dapm->suspend_bias_off = component->driver->suspend_bias_off;
4802
+ } else {
4803
+ dapm->dev = card->dev;
4804
+ }
4805
+
4806
+ INIT_LIST_HEAD(&dapm->list);
4807
+ /* see for_each_card_dapms */
4808
+ list_add(&dapm->list, &card->dapm_list);
4809
+}
4810
+EXPORT_SYMBOL_GPL(snd_soc_dapm_init);
4811
+
45844812 static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
45854813 {
45864814 struct snd_soc_card *card = dapm->card;
....@@ -4590,7 +4818,7 @@
45904818
45914819 mutex_lock(&card->dapm_mutex);
45924820
4593
- list_for_each_entry(w, &dapm->card->widgets, list) {
4821
+ for_each_card_widgets(dapm->card, w) {
45944822 if (w->dapm != dapm)
45954823 continue;
45964824 if (w->power) {
....@@ -4623,7 +4851,7 @@
46234851 {
46244852 struct snd_soc_dapm_context *dapm;
46254853
4626
- list_for_each_entry(dapm, &card->dapm_list, list) {
4854
+ for_each_card_dapms(card, dapm) {
46274855 if (dapm != &card->dapm) {
46284856 soc_dapm_shutdown_dapm(dapm);
46294857 if (dapm->bias_level == SND_SOC_BIAS_STANDBY)