diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-06-13 11:42:29 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-06-13 13:59:33 -0400 |
commit | bf3a9e137cf1a1c664f44acfa36a487f0437f6aa (patch) | |
tree | 666892dd62a26bf38733d79386b5c5909c896b93 /sound/soc/soc-dapm.c | |
parent | 5bef44f9b4849d1c3af4ed2ea93061ff56e68cd7 (diff) |
ASoC: Add weak routes for sidetone style paths
Normally DAPM will power up any connected audio path. This is not ideal
for sidetone paths as with sidetone paths the audio path is not wanted in
itself, it is only desired if the two paths it provides a sidetone between
are both active. If the sidetone path causes a power up then it can be
hard to minimise pops as we first power up either the sidetone or the main
output path and then power the other, with the second power up potentially
introducing a DC offset.
Address this by introducing the concept of a weak path. If a path is marked
as weak then DAPM will ignore that path when walking the graph, though all
the relevant controls are still available to the application layer to allow
these paths to be configured.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fd2d774797bb..746349faf2db 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -593,6 +593,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) | |||
593 | } | 593 | } |
594 | 594 | ||
595 | list_for_each_entry(path, &widget->sinks, list_source) { | 595 | list_for_each_entry(path, &widget->sinks, list_source) { |
596 | if (path->weak) | ||
597 | continue; | ||
598 | |||
596 | if (path->walked) | 599 | if (path->walked) |
597 | continue; | 600 | continue; |
598 | 601 | ||
@@ -643,6 +646,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) | |||
643 | } | 646 | } |
644 | 647 | ||
645 | list_for_each_entry(path, &widget->sources, list_sink) { | 648 | list_for_each_entry(path, &widget->sources, list_sink) { |
649 | if (path->weak) | ||
650 | continue; | ||
651 | |||
646 | if (path->walked) | 652 | if (path->walked) |
647 | continue; | 653 | continue; |
648 | 654 | ||
@@ -724,6 +730,9 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
724 | 730 | ||
725 | /* Check if one of our outputs is connected */ | 731 | /* Check if one of our outputs is connected */ |
726 | list_for_each_entry(path, &w->sinks, list_source) { | 732 | list_for_each_entry(path, &w->sinks, list_source) { |
733 | if (path->weak) | ||
734 | continue; | ||
735 | |||
727 | if (path->connected && | 736 | if (path->connected && |
728 | !path->connected(path->source, path->sink)) | 737 | !path->connected(path->source, path->sink)) |
729 | continue; | 738 | continue; |
@@ -1806,6 +1815,84 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | |||
1806 | } | 1815 | } |
1807 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); | 1816 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); |
1808 | 1817 | ||
1818 | static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, | ||
1819 | const struct snd_soc_dapm_route *route) | ||
1820 | { | ||
1821 | struct snd_soc_dapm_widget *source = dapm_find_widget(dapm, | ||
1822 | route->source, | ||
1823 | true); | ||
1824 | struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm, | ||
1825 | route->sink, | ||
1826 | true); | ||
1827 | struct snd_soc_dapm_path *path; | ||
1828 | int count = 0; | ||
1829 | |||
1830 | if (!source) { | ||
1831 | dev_err(dapm->dev, "Unable to find source %s for weak route\n", | ||
1832 | route->source); | ||
1833 | return -ENODEV; | ||
1834 | } | ||
1835 | |||
1836 | if (!sink) { | ||
1837 | dev_err(dapm->dev, "Unable to find sink %s for weak route\n", | ||
1838 | route->sink); | ||
1839 | return -ENODEV; | ||
1840 | } | ||
1841 | |||
1842 | if (route->control || route->connected) | ||
1843 | dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n", | ||
1844 | route->source, route->sink); | ||
1845 | |||
1846 | list_for_each_entry(path, &source->sinks, list_source) { | ||
1847 | if (path->sink == sink) { | ||
1848 | path->weak = 1; | ||
1849 | count++; | ||
1850 | } | ||
1851 | } | ||
1852 | |||
1853 | if (count == 0) | ||
1854 | dev_err(dapm->dev, "No path found for weak route %s->%s\n", | ||
1855 | route->source, route->sink); | ||
1856 | if (count > 1) | ||
1857 | dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n", | ||
1858 | count, route->source, route->sink); | ||
1859 | |||
1860 | return 0; | ||
1861 | } | ||
1862 | |||
1863 | /** | ||
1864 | * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak | ||
1865 | * @dapm: DAPM context | ||
1866 | * @route: audio routes | ||
1867 | * @num: number of routes | ||
1868 | * | ||
1869 | * Mark existing routes matching those specified in the passed array | ||
1870 | * as being weak, meaning that they are ignored for the purpose of | ||
1871 | * power decisions. The main intended use case is for sidetone paths | ||
1872 | * which couple audio between other independent paths if they are both | ||
1873 | * active in order to make the combination work better at the user | ||
1874 | * level but which aren't intended to be "used". | ||
1875 | * | ||
1876 | * Note that CODEC drivers should not use this as sidetone type paths | ||
1877 | * can frequently also be used as bypass paths. | ||
1878 | */ | ||
1879 | int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, | ||
1880 | const struct snd_soc_dapm_route *route, int num) | ||
1881 | { | ||
1882 | int i, err; | ||
1883 | int ret = 0; | ||
1884 | |||
1885 | for (i = 0; i < num; i++) { | ||
1886 | err = snd_soc_dapm_weak_route(dapm, route); | ||
1887 | if (err) | ||
1888 | ret = err; | ||
1889 | route++; | ||
1890 | } | ||
1891 | |||
1892 | return ret; | ||
1893 | } | ||
1894 | EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes); | ||
1895 | |||
1809 | /** | 1896 | /** |
1810 | * snd_soc_dapm_new_widgets - add new dapm widgets | 1897 | * snd_soc_dapm_new_widgets - add new dapm widgets |
1811 | * @dapm: DAPM context | 1898 | * @dapm: DAPM context |