aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h4
-rw-r--r--sound/soc/soc-dapm.c210
2 files changed, 95 insertions, 119 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index ebb93f29e4f3..8cf3aad30864 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -543,11 +543,13 @@ struct snd_soc_dapm_widget {
543 unsigned char active:1; /* active stream on DAC, ADC's */ 543 unsigned char active:1; /* active stream on DAC, ADC's */
544 unsigned char connected:1; /* connected codec pin */ 544 unsigned char connected:1; /* connected codec pin */
545 unsigned char new:1; /* cnew complete */ 545 unsigned char new:1; /* cnew complete */
546 unsigned char ext:1; /* has external widgets */
547 unsigned char force:1; /* force state */ 546 unsigned char force:1; /* force state */
548 unsigned char ignore_suspend:1; /* kept enabled over suspend */ 547 unsigned char ignore_suspend:1; /* kept enabled over suspend */
549 unsigned char new_power:1; /* power from this run */ 548 unsigned char new_power:1; /* power from this run */
550 unsigned char power_checked:1; /* power checked this run */ 549 unsigned char power_checked:1; /* power checked this run */
550 unsigned char is_supply:1; /* Widget is a supply type widget */
551 unsigned char is_sink:1; /* Widget is a sink type widget */
552 unsigned char is_source:1; /* Widget is a source type widget */
551 int subseq; /* sort within widget type */ 553 int subseq; /* sort within widget type */
552 554
553 int (*power_check)(struct snd_soc_dapm_widget *w); 555 int (*power_check)(struct snd_soc_dapm_widget *w);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c49df10d1c33..2cad5f77ec60 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -821,43 +821,12 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
821 821
822 DAPM_UPDATE_STAT(widget, path_checks); 822 DAPM_UPDATE_STAT(widget, path_checks);
823 823
824 switch (widget->id) { 824 if (widget->is_supply)
825 case snd_soc_dapm_supply:
826 case snd_soc_dapm_regulator_supply:
827 case snd_soc_dapm_clock_supply:
828 case snd_soc_dapm_kcontrol:
829 return 0; 825 return 0;
830 default:
831 break;
832 }
833 826
834 switch (widget->id) { 827 if (widget->is_sink && widget->connected) {
835 case snd_soc_dapm_adc: 828 widget->outputs = snd_soc_dapm_suspend_check(widget);
836 case snd_soc_dapm_aif_out: 829 return widget->outputs;
837 case snd_soc_dapm_dai_out:
838 if (widget->active) {
839 widget->outputs = snd_soc_dapm_suspend_check(widget);
840 return widget->outputs;
841 }
842 default:
843 break;
844 }
845
846 if (widget->connected) {
847 /* connected pin ? */
848 if (widget->id == snd_soc_dapm_output && !widget->ext) {
849 widget->outputs = snd_soc_dapm_suspend_check(widget);
850 return widget->outputs;
851 }
852
853 /* connected jack or spk ? */
854 if (widget->id == snd_soc_dapm_hp ||
855 widget->id == snd_soc_dapm_spk ||
856 (widget->id == snd_soc_dapm_line &&
857 !list_empty(&widget->sources))) {
858 widget->outputs = snd_soc_dapm_suspend_check(widget);
859 return widget->outputs;
860 }
861 } 830 }
862 831
863 list_for_each_entry(path, &widget->sinks, list_source) { 832 list_for_each_entry(path, &widget->sinks, list_source) {
@@ -913,55 +882,12 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
913 882
914 DAPM_UPDATE_STAT(widget, path_checks); 883 DAPM_UPDATE_STAT(widget, path_checks);
915 884
916 switch (widget->id) { 885 if (widget->is_supply)
917 case snd_soc_dapm_supply:
918 case snd_soc_dapm_regulator_supply:
919 case snd_soc_dapm_clock_supply:
920 case snd_soc_dapm_kcontrol:
921 return 0; 886 return 0;
922 default:
923 break;
924 }
925
926 /* active stream ? */
927 switch (widget->id) {
928 case snd_soc_dapm_dac:
929 case snd_soc_dapm_aif_in:
930 case snd_soc_dapm_dai_in:
931 if (widget->active) {
932 widget->inputs = snd_soc_dapm_suspend_check(widget);
933 return widget->inputs;
934 }
935 default:
936 break;
937 }
938
939 if (widget->connected) {
940 /* connected pin ? */
941 if (widget->id == snd_soc_dapm_input && !widget->ext) {
942 widget->inputs = snd_soc_dapm_suspend_check(widget);
943 return widget->inputs;
944 }
945 887
946 /* connected VMID/Bias for lower pops */ 888 if (widget->is_source && widget->connected) {
947 if (widget->id == snd_soc_dapm_vmid) { 889 widget->inputs = snd_soc_dapm_suspend_check(widget);
948 widget->inputs = snd_soc_dapm_suspend_check(widget); 890 return widget->inputs;
949 return widget->inputs;
950 }
951
952 /* connected jack ? */
953 if (widget->id == snd_soc_dapm_mic ||
954 (widget->id == snd_soc_dapm_line &&
955 !list_empty(&widget->sinks))) {
956 widget->inputs = snd_soc_dapm_suspend_check(widget);
957 return widget->inputs;
958 }
959
960 /* signal generator */
961 if (widget->id == snd_soc_dapm_siggen) {
962 widget->inputs = snd_soc_dapm_suspend_check(widget);
963 return widget->inputs;
964 }
965 } 891 }
966 892
967 list_for_each_entry(path, &widget->sources, list_sink) { 893 list_for_each_entry(path, &widget->sources, list_sink) {
@@ -1554,18 +1480,11 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1554 list_for_each_entry(path, &w->sources, list_sink) 1480 list_for_each_entry(path, &w->sources, list_sink)
1555 dapm_widget_set_peer_power(path->source, power, path->connect); 1481 dapm_widget_set_peer_power(path->source, power, path->connect);
1556 1482
1557 switch (w->id) { 1483 /* Supplies can't affect their outputs, only their inputs */
1558 case snd_soc_dapm_supply: 1484 if (!w->is_supply) {
1559 case snd_soc_dapm_regulator_supply:
1560 case snd_soc_dapm_clock_supply:
1561 case snd_soc_dapm_kcontrol:
1562 /* Supplies can't affect their outputs, only their inputs */
1563 break;
1564 default:
1565 list_for_each_entry(path, &w->sinks, list_source) 1485 list_for_each_entry(path, &w->sinks, list_source)
1566 dapm_widget_set_peer_power(path->sink, power, 1486 dapm_widget_set_peer_power(path->sink, power,
1567 path->connect); 1487 path->connect);
1568 break;
1569 } 1488 }
1570 1489
1571 if (power) 1490 if (power)
@@ -2226,6 +2145,53 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
2226} 2145}
2227EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 2146EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2228 2147
2148/*
2149 * dapm_update_widget_flags() - Re-compute widget sink and source flags
2150 * @w: The widget for which to update the flags
2151 *
2152 * Some widgets have a dynamic category which depends on which neighbors they
2153 * are connected to. This function update the category for these widgets.
2154 *
2155 * This function must be called whenever a path is added or removed to a widget.
2156 */
2157static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)
2158{
2159 struct snd_soc_dapm_path *p;
2160
2161 switch (w->id) {
2162 case snd_soc_dapm_input:
2163 w->is_source = 1;
2164 list_for_each_entry(p, &w->sources, list_sink) {
2165 if (p->source->id == snd_soc_dapm_micbias ||
2166 p->source->id == snd_soc_dapm_mic ||
2167 p->source->id == snd_soc_dapm_line ||
2168 p->source->id == snd_soc_dapm_output) {
2169 w->is_source = 0;
2170 break;
2171 }
2172 }
2173 break;
2174 case snd_soc_dapm_output:
2175 w->is_sink = 1;
2176 list_for_each_entry(p, &w->sinks, list_source) {
2177 if (p->sink->id == snd_soc_dapm_spk ||
2178 p->sink->id == snd_soc_dapm_hp ||
2179 p->sink->id == snd_soc_dapm_line ||
2180 p->sink->id == snd_soc_dapm_input) {
2181 w->is_sink = 0;
2182 break;
2183 }
2184 }
2185 break;
2186 case snd_soc_dapm_line:
2187 w->is_sink = !list_empty(&w->sources);
2188 w->is_source = !list_empty(&w->sinks);
2189 break;
2190 default:
2191 break;
2192 }
2193}
2194
2229static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, 2195static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2230 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, 2196 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
2231 const char *control, 2197 const char *control,
@@ -2247,22 +2213,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2247 INIT_LIST_HEAD(&path->list_source); 2213 INIT_LIST_HEAD(&path->list_source);
2248 INIT_LIST_HEAD(&path->list_sink); 2214 INIT_LIST_HEAD(&path->list_sink);
2249 2215
2250 /* check for external widgets */
2251 if (wsink->id == snd_soc_dapm_input) {
2252 if (wsource->id == snd_soc_dapm_micbias ||
2253 wsource->id == snd_soc_dapm_mic ||
2254 wsource->id == snd_soc_dapm_line ||
2255 wsource->id == snd_soc_dapm_output)
2256 wsink->ext = 1;
2257 }
2258 if (wsource->id == snd_soc_dapm_output) {
2259 if (wsink->id == snd_soc_dapm_spk ||
2260 wsink->id == snd_soc_dapm_hp ||
2261 wsink->id == snd_soc_dapm_line ||
2262 wsink->id == snd_soc_dapm_input)
2263 wsource->ext = 1;
2264 }
2265
2266 /* connect static paths */ 2216 /* connect static paths */
2267 if (control == NULL) { 2217 if (control == NULL) {
2268 path->connect = 1; 2218 path->connect = 1;
@@ -2294,6 +2244,9 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2294 list_add(&path->list_sink, &wsink->sources); 2244 list_add(&path->list_sink, &wsink->sources);
2295 list_add(&path->list_source, &wsource->sinks); 2245 list_add(&path->list_source, &wsource->sinks);
2296 2246
2247 dapm_update_widget_flags(wsource);
2248 dapm_update_widget_flags(wsink);
2249
2297 dapm_mark_dirty(wsource, "Route added"); 2250 dapm_mark_dirty(wsource, "Route added");
2298 dapm_mark_dirty(wsink, "Route added"); 2251 dapm_mark_dirty(wsink, "Route added");
2299 2252
@@ -2377,6 +2330,7 @@ err:
2377static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, 2330static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
2378 const struct snd_soc_dapm_route *route) 2331 const struct snd_soc_dapm_route *route)
2379{ 2332{
2333 struct snd_soc_dapm_widget *wsource, *wsink;
2380 struct snd_soc_dapm_path *path, *p; 2334 struct snd_soc_dapm_path *path, *p;
2381 const char *sink; 2335 const char *sink;
2382 const char *source; 2336 const char *source;
@@ -2414,10 +2368,17 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
2414 } 2368 }
2415 2369
2416 if (path) { 2370 if (path) {
2417 dapm_mark_dirty(path->source, "Route removed"); 2371 wsource = path->source;
2418 dapm_mark_dirty(path->sink, "Route removed"); 2372 wsink = path->sink;
2373
2374 dapm_mark_dirty(wsource, "Route removed");
2375 dapm_mark_dirty(wsink, "Route removed");
2419 2376
2420 dapm_free_path(path); 2377 dapm_free_path(path);
2378
2379 /* Update any path related flags */
2380 dapm_update_widget_flags(wsource);
2381 dapm_update_widget_flags(wsink);
2421 } else { 2382 } else {
2422 dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", 2383 dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
2423 source, sink); 2384 source, sink);
@@ -2975,26 +2936,33 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2975 } 2936 }
2976 2937
2977 switch (w->id) { 2938 switch (w->id) {
2978 case snd_soc_dapm_switch: 2939 case snd_soc_dapm_mic:
2979 case snd_soc_dapm_mixer: 2940 case snd_soc_dapm_input:
2980 case snd_soc_dapm_mixer_named_ctl: 2941 w->is_source = 1;
2981 w->power_check = dapm_generic_check_power; 2942 w->power_check = dapm_generic_check_power;
2982 break; 2943 break;
2983 case snd_soc_dapm_mux: 2944 case snd_soc_dapm_spk:
2945 case snd_soc_dapm_hp:
2946 case snd_soc_dapm_output:
2947 w->is_sink = 1;
2984 w->power_check = dapm_generic_check_power; 2948 w->power_check = dapm_generic_check_power;
2985 break; 2949 break;
2950 case snd_soc_dapm_vmid:
2951 case snd_soc_dapm_siggen:
2952 w->is_source = 1;
2953 w->power_check = dapm_always_on_check_power;
2954 break;
2955 case snd_soc_dapm_mux:
2956 case snd_soc_dapm_switch:
2957 case snd_soc_dapm_mixer:
2958 case snd_soc_dapm_mixer_named_ctl:
2986 case snd_soc_dapm_adc: 2959 case snd_soc_dapm_adc:
2987 case snd_soc_dapm_aif_out: 2960 case snd_soc_dapm_aif_out:
2988 case snd_soc_dapm_dac: 2961 case snd_soc_dapm_dac:
2989 case snd_soc_dapm_aif_in: 2962 case snd_soc_dapm_aif_in:
2990 case snd_soc_dapm_pga: 2963 case snd_soc_dapm_pga:
2991 case snd_soc_dapm_out_drv: 2964 case snd_soc_dapm_out_drv:
2992 case snd_soc_dapm_input:
2993 case snd_soc_dapm_output:
2994 case snd_soc_dapm_micbias: 2965 case snd_soc_dapm_micbias:
2995 case snd_soc_dapm_spk:
2996 case snd_soc_dapm_hp:
2997 case snd_soc_dapm_mic:
2998 case snd_soc_dapm_line: 2966 case snd_soc_dapm_line:
2999 case snd_soc_dapm_dai_link: 2967 case snd_soc_dapm_dai_link:
3000 case snd_soc_dapm_dai_out: 2968 case snd_soc_dapm_dai_out:
@@ -3005,6 +2973,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3005 case snd_soc_dapm_regulator_supply: 2973 case snd_soc_dapm_regulator_supply:
3006 case snd_soc_dapm_clock_supply: 2974 case snd_soc_dapm_clock_supply:
3007 case snd_soc_dapm_kcontrol: 2975 case snd_soc_dapm_kcontrol:
2976 w->is_supply = 1;
3008 w->power_check = dapm_supply_check_power; 2977 w->power_check = dapm_supply_check_power;
3009 break; 2978 break;
3010 default: 2979 default:
@@ -3368,6 +3337,11 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
3368 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: 3337 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
3369 break; 3338 break;
3370 } 3339 }
3340
3341 if (w->id == snd_soc_dapm_dai_in)
3342 w->is_source = w->active;
3343 else
3344 w->is_sink = w->active;
3371 } 3345 }
3372} 3346}
3373 3347