aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorSzymon Mielczarek <szymonx.mielczarek@linux.intel.com>2019-08-09 04:40:34 -0400
committerMark Brown <broonie@kernel.org>2019-08-12 09:01:59 -0400
commit872f3ac583cb00c14a4dc86b1511cf98618dd671 (patch)
tree473478d040e1e0f6dd3373dc4a93a43a302707c1 /sound
parentcac974a51ebb955f3be260a9633836e1413c8672 (diff)
ASoC: dapm: Invalidate only paths reachable for a given stream
By resetting the cached number of endpoints for all card's widgets we may overwrite previously cached values for other streams. The situation may happen especially when running streams simultaneously. Signed-off-by: Szymon Mielczarek <szymonx.mielczarek@linux.intel.com> Link: https://lore.kernel.org/r/20190809084034.26220-1-szymonx.mielczarek@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-dapm.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d09bdca63c62..10819b3e0b98 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1129,6 +1129,34 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
1129} 1129}
1130 1130
1131/* 1131/*
1132 * Recursively reset the cached number of inputs or outputs for the specified
1133 * widget and all widgets that can be reached via incoming or outcoming paths
1134 * from the widget.
1135 */
1136static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget,
1137 enum snd_soc_dapm_direction dir)
1138{
1139 enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
1140 struct snd_soc_dapm_path *path;
1141
1142 widget->endpoints[dir] = -1;
1143
1144 snd_soc_dapm_widget_for_each_path(widget, rdir, path) {
1145 if (path->weak || path->is_supply)
1146 continue;
1147
1148 if (path->walking)
1149 return;
1150
1151 if (path->connect) {
1152 path->walking = 1;
1153 invalidate_paths_ep(path->node[dir], dir);
1154 path->walking = 0;
1155 }
1156 }
1157}
1158
1159/*
1132 * Common implementation for is_connected_output_ep() and 1160 * Common implementation for is_connected_output_ep() and
1133 * is_connected_input_ep(). The function is inlined since the combined size of 1161 * is_connected_input_ep(). The function is inlined since the combined size of
1134 * the two specialized functions is only marginally larger then the size of the 1162 * the two specialized functions is only marginally larger then the size of the
@@ -1257,21 +1285,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
1257 1285
1258 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 1286 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1259 1287
1260 /* 1288 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1261 * For is_connected_{output,input}_ep fully discover the graph we need 1289 w = dai->playback_widget;
1262 * to reset the cached number of inputs and outputs. 1290 invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT);
1263 */ 1291 paths = is_connected_output_ep(w, &widgets,
1264 list_for_each_entry(w, &card->widgets, list) {
1265 w->endpoints[SND_SOC_DAPM_DIR_IN] = -1;
1266 w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1;
1267 }
1268
1269 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1270 paths = is_connected_output_ep(dai->playback_widget, &widgets,
1271 custom_stop_condition); 1292 custom_stop_condition);
1272 else 1293 } else {
1273 paths = is_connected_input_ep(dai->capture_widget, &widgets, 1294 w = dai->capture_widget;
1295 invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN);
1296 paths = is_connected_input_ep(w, &widgets,
1274 custom_stop_condition); 1297 custom_stop_condition);
1298 }
1275 1299
1276 /* Drop starting point */ 1300 /* Drop starting point */
1277 list_del(widgets.next); 1301 list_del(widgets.next);