summaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-11-23 19:42:04 (GMT)
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-23 21:34:54 (GMT)
commit1633281b79fd276f1c7c2fb37c3b97da74e42ae5 (patch)
treebe8fe06be86f436efb3ddece45338e28a394ccdb /sound/soc/soc-dapm.c
parentd4a2eca781bfd7323bfd98dbc7fd63c7d613fef2 (diff)
downloadlinux-1633281b79fd276f1c7c2fb37c3b97da74e42ae5.tar.xz
ASoC: Implement fully_routed card property
A card is fully routed if the DAPM route table describes all connections on the board. When a card is fully routed, some operations can be automated by the ASoC core. The first, and currently only, such operation is described below, and implemented by this patch. Codecs often have a large number of external pins, and not all of these pins will be connected on all board designs. Some machine drivers therefore call snd_soc_dapm_nc_pin() for all the unused pins, in order to tell the ASoC core never to activate them. However, when a card is fully routed, the information needed to derive the set of unused pins is present in card->dapm_routes. In this case, have the ASoC core automatically call snd_soc_dapm_nc_pin() for each unused codec pin. This has been tested with soc/tegra/tegra_wm8903.c and soc/tegra/trimslice.c. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f42e8b9..1ecd1b4 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2947,6 +2947,79 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
+static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
+ struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_path *p;
+
+ list_for_each_entry(p, &card->paths, list) {
+ if ((p->source == w) || (p->sink == w)) {
+ dev_dbg(card->dev,
+ "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
+ p->source->name, p->source->id, p->source->dapm,
+ p->sink->name, p->sink->id, p->sink->dapm);
+
+ /* Connected to something other than the codec */
+ if (p->source->dapm != p->sink->dapm)
+ return true;
+ /*
+ * Loopback connection from codec external pin to
+ * codec external pin
+ */
+ if (p->sink->id == snd_soc_dapm_input) {
+ switch (p->source->id) {
+ case snd_soc_dapm_output:
+ case snd_soc_dapm_micbias:
+ return true;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
+ * @codec: The codec whose pins should be processed
+ *
+ * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
+ * which are unused. Pins are used if they are connected externally to the
+ * codec, whether that be to some other device, or a loop-back connection to
+ * the codec itself.
+ */
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
+{
+ struct snd_soc_card *card = codec->card;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct snd_soc_dapm_widget *w;
+
+ dev_dbg(card->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+ &card->dapm, &codec->dapm);
+
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
+ switch (w->id) {
+ case snd_soc_dapm_input:
+ case snd_soc_dapm_output:
+ case snd_soc_dapm_micbias:
+ dev_dbg(card->dev, "Auto NC: Checking widget %s\n",
+ w->name);
+ if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
+ dev_dbg(card->dev,
+ "... Not in map; disabling\n");
+ snd_soc_dapm_nc_pin(dapm, w->name);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/**
* snd_soc_dapm_free - free dapm resources
* @dapm: DAPM context