aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2015-07-26 13:04:59 -0400
committerMark Brown <broonie@kernel.org>2015-07-29 09:01:38 -0400
commit1ce43acff0c078fd560ee0f2a4ae10b8da28e388 (patch)
treee162557def119e3f5c643b6abcb5d308dbfaa8fa
parent787126ebdb9821f1a19b1dfd1ab1bbb74b8c80b8 (diff)
ASoC: dapm: Simplify list creation in dapm_dai_get_connected_widgets()
When running dapm_dai_get_connected_widgets() currently in is_connected_{input,output}_ep() for each widget that gets added the array is resized and the code also loops over all existing entries to avoid adding a widget multiple times. The former can be avoided by collecting the widgets in a linked list and only once we have all widgets allocate the array. The later can be avoided by changing when the widget is added. Currently it is added when walking the neighbor lists of a widget. Since a widget can be neighbors with multiple other widgets it could get added twice and hence the check is necessary. But the main body of is_connected_{input,output}_ep is guaranteed to be only executed at most once per widget. So adding the widget to the list at the beginning of the function automatically makes sure that each widget gets only added once. The only difference is that using this method the starting point itself will also end up on the list, but it can easily be skipped when creating the array. Overall this reduces the code size and speeds things slightly up. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/soc-dapm.c101
-rw-r--r--sound/soc/soc-pcm.c11
2 files changed, 38 insertions, 74 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f80b7ded0721..4586f95c676b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1032,43 +1032,27 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
1032 } 1032 }
1033} 1033}
1034 1034
1035/* add widget to list if it's not already in the list */ 1035static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
1036static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list, 1036 struct list_head *widgets)
1037 struct snd_soc_dapm_widget *w)
1038{ 1037{
1039 struct snd_soc_dapm_widget_list *wlist; 1038 struct snd_soc_dapm_widget *w;
1040 int wlistsize, wlistentries, i; 1039 struct list_head *it;
1041 1040 unsigned int size = 0;
1042 if (*list == NULL) 1041 unsigned int i = 0;
1043 return -EINVAL;
1044
1045 wlist = *list;
1046 1042
1047 /* is this widget already in the list */ 1043 list_for_each(it, widgets)
1048 for (i = 0; i < wlist->num_widgets; i++) { 1044 size++;
1049 if (wlist->widgets[i] == w)
1050 return 0;
1051 }
1052 1045
1053 /* allocate some new space */ 1046 *list = kzalloc(sizeof(**list) + size * sizeof(*w), GFP_KERNEL);
1054 wlistentries = wlist->num_widgets + 1; 1047 if (*list == NULL)
1055 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
1056 wlistentries * sizeof(struct snd_soc_dapm_widget *);
1057 *list = krealloc(wlist, wlistsize, GFP_KERNEL);
1058 if (*list == NULL) {
1059 dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
1060 w->name);
1061 return -ENOMEM; 1048 return -ENOMEM;
1062 }
1063 wlist = *list;
1064 1049
1065 /* insert the widget */ 1050 list_for_each_entry(w, widgets, work_list)
1066 dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n", 1051 (*list)->widgets[i++] = w;
1067 w->name, wlist->num_widgets);
1068 1052
1069 wlist->widgets[wlist->num_widgets] = w; 1053 (*list)->num_widgets = i;
1070 wlist->num_widgets++; 1054
1071 return 1; 1055 return 0;
1072} 1056}
1073 1057
1074/* 1058/*
@@ -1076,7 +1060,7 @@ static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
1076 * output widget. Returns number of complete paths. 1060 * output widget. Returns number of complete paths.
1077 */ 1061 */
1078static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, 1062static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
1079 struct snd_soc_dapm_widget_list **list) 1063 struct list_head *list)
1080{ 1064{
1081 struct snd_soc_dapm_path *path; 1065 struct snd_soc_dapm_path *path;
1082 int con = 0; 1066 int con = 0;
@@ -1086,6 +1070,10 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
1086 1070
1087 DAPM_UPDATE_STAT(widget, path_checks); 1071 DAPM_UPDATE_STAT(widget, path_checks);
1088 1072
1073 /* do we need to add this widget to the list ? */
1074 if (list)
1075 list_add_tail(&widget->work_list, list);
1076
1089 if (widget->is_sink && widget->connected) { 1077 if (widget->is_sink && widget->connected) {
1090 widget->outputs = snd_soc_dapm_suspend_check(widget); 1078 widget->outputs = snd_soc_dapm_suspend_check(widget);
1091 return widget->outputs; 1079 return widget->outputs;
@@ -1104,22 +1092,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
1104 1092
1105 if (path->connect) { 1093 if (path->connect) {
1106 path->walking = 1; 1094 path->walking = 1;
1107
1108 /* do we need to add this widget to the list ? */
1109 if (list) {
1110 int err;
1111 err = dapm_list_add_widget(list, path->sink);
1112 if (err < 0) {
1113 dev_err(widget->dapm->dev,
1114 "ASoC: could not add widget %s\n",
1115 widget->name);
1116 path->walking = 0;
1117 return con;
1118 }
1119 }
1120
1121 con += is_connected_output_ep(path->sink, list); 1095 con += is_connected_output_ep(path->sink, list);
1122
1123 path->walking = 0; 1096 path->walking = 0;
1124 } 1097 }
1125 } 1098 }
@@ -1134,7 +1107,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
1134 * input widget. Returns number of complete paths. 1107 * input widget. Returns number of complete paths.
1135 */ 1108 */
1136static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, 1109static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
1137 struct snd_soc_dapm_widget_list **list) 1110 struct list_head *list)
1138{ 1111{
1139 struct snd_soc_dapm_path *path; 1112 struct snd_soc_dapm_path *path;
1140 int con = 0; 1113 int con = 0;
@@ -1144,6 +1117,10 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
1144 1117
1145 DAPM_UPDATE_STAT(widget, path_checks); 1118 DAPM_UPDATE_STAT(widget, path_checks);
1146 1119
1120 /* do we need to add this widget to the list ? */
1121 if (list)
1122 list_add_tail(&widget->work_list, list);
1123
1147 if (widget->is_source && widget->connected) { 1124 if (widget->is_source && widget->connected) {
1148 widget->inputs = snd_soc_dapm_suspend_check(widget); 1125 widget->inputs = snd_soc_dapm_suspend_check(widget);
1149 return widget->inputs; 1126 return widget->inputs;
@@ -1162,22 +1139,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
1162 1139
1163 if (path->connect) { 1140 if (path->connect) {
1164 path->walking = 1; 1141 path->walking = 1;
1165
1166 /* do we need to add this widget to the list ? */
1167 if (list) {
1168 int err;
1169 err = dapm_list_add_widget(list, path->source);
1170 if (err < 0) {
1171 dev_err(widget->dapm->dev,
1172 "ASoC: could not add widget %s\n",
1173 widget->name);
1174 path->walking = 0;
1175 return con;
1176 }
1177 }
1178
1179 con += is_connected_input_ep(path->source, list); 1142 con += is_connected_input_ep(path->source, list);
1180
1181 path->walking = 0; 1143 path->walking = 0;
1182 } 1144 }
1183 } 1145 }
@@ -1204,7 +1166,9 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
1204{ 1166{
1205 struct snd_soc_card *card = dai->component->card; 1167 struct snd_soc_card *card = dai->component->card;
1206 struct snd_soc_dapm_widget *w; 1168 struct snd_soc_dapm_widget *w;
1169 LIST_HEAD(widgets);
1207 int paths; 1170 int paths;
1171 int ret;
1208 1172
1209 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 1173 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1210 1174
@@ -1218,9 +1182,16 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
1218 } 1182 }
1219 1183
1220 if (stream == SNDRV_PCM_STREAM_PLAYBACK) 1184 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1221 paths = is_connected_output_ep(dai->playback_widget, list); 1185 paths = is_connected_output_ep(dai->playback_widget, &widgets);
1222 else 1186 else
1223 paths = is_connected_input_ep(dai->capture_widget, list); 1187 paths = is_connected_input_ep(dai->capture_widget, &widgets);
1188
1189 /* Drop starting point */
1190 list_del(widgets.next);
1191
1192 ret = dapm_widget_list_create(list, &widgets);
1193 if (ret)
1194 return ret;
1224 1195
1225 trace_snd_soc_dapm_connected(paths, stream); 1196 trace_snd_soc_dapm_connected(paths, stream);
1226 mutex_unlock(&card->dapm_mutex); 1197 mutex_unlock(&card->dapm_mutex);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 256b9c91aa94..7aed170f31bc 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1231,24 +1231,17 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list,
1231} 1231}
1232 1232
1233int dpcm_path_get(struct snd_soc_pcm_runtime *fe, 1233int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
1234 int stream, struct snd_soc_dapm_widget_list **list_) 1234 int stream, struct snd_soc_dapm_widget_list **list)
1235{ 1235{
1236 struct snd_soc_dai *cpu_dai = fe->cpu_dai; 1236 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
1237 struct snd_soc_dapm_widget_list *list;
1238 int paths; 1237 int paths;
1239 1238
1240 list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
1241 sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
1242 if (list == NULL)
1243 return -ENOMEM;
1244
1245 /* get number of valid DAI paths and their widgets */ 1239 /* get number of valid DAI paths and their widgets */
1246 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list); 1240 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list);
1247 1241
1248 dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, 1242 dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
1249 stream ? "capture" : "playback"); 1243 stream ? "capture" : "playback");
1250 1244
1251 *list_ = list;
1252 return paths; 1245 return paths;
1253} 1246}
1254 1247