Commit bf3a9e137cf1a1c664f44acfa36a487f0437f6aa

Authored by Mark Brown
1 parent 5bef44f9b4

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>

Showing 2 changed files with 89 additions and 0 deletions Side-by-side Diff

include/sound/soc-dapm.h
... ... @@ -348,6 +348,8 @@
348 348 void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
349 349 int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
350 350 const struct snd_soc_dapm_route *route, int num);
  351 +int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
  352 + const struct snd_soc_dapm_route *route, int num);
351 353  
352 354 /* dapm events */
353 355 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
sound/soc/soc-dapm.c
... ... @@ -593,6 +593,9 @@
593 593 }
594 594  
595 595 list_for_each_entry(path, &widget->sinks, list_source) {
  596 + if (path->weak)
  597 + continue;
  598 +
596 599 if (path->walked)
597 600 continue;
598 601  
... ... @@ -643,6 +646,9 @@
643 646 }
644 647  
645 648 list_for_each_entry(path, &widget->sources, list_sink) {
  649 + if (path->weak)
  650 + continue;
  651 +
646 652 if (path->walked)
647 653 continue;
648 654  
... ... @@ -724,6 +730,9 @@
724 730  
725 731 /* Check if one of our outputs is connected */
726 732 list_for_each_entry(path, &w->sinks, list_source) {
  733 + if (path->weak)
  734 + continue;
  735 +
727 736 if (path->connected &&
728 737 !path->connected(path->source, path->sink))
729 738 continue;
... ... @@ -1805,6 +1814,84 @@
1805 1814 return 0;
1806 1815 }
1807 1816 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
  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);
1808 1895  
1809 1896 /**
1810 1897 * snd_soc_dapm_new_widgets - add new dapm widgets