diff options
-rw-r--r-- | include/sound/soc-dapm.h | 4 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 210 |
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 | } |
2227 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 2146 | EXPORT_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 | */ | ||
2157 | static 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 | |||
2229 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | 2195 | static 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: | |||
2377 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | 2330 | static 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 | ||