aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-13 11:42:29 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-13 13:59:33 -0400
commitbf3a9e137cf1a1c664f44acfa36a487f0437f6aa (patch)
tree666892dd62a26bf38733d79386b5c5909c896b93 /sound/soc/soc-dapm.c
parent5bef44f9b4849d1c3af4ed2ea93061ff56e68cd7 (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.c87
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}
1807EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); 1816EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1808 1817
1818static 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 */
1879int 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}
1894EXPORT_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