* [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
@ 2012-02-15 16:02 Liam Girdwood
2012-02-15 16:02 ` [PATCH 2/2] ASoC: core - Add support for direct DAI -> widget mapping stream events Liam Girdwood
2012-02-15 16:24 ` [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Mark Brown
0 siblings, 2 replies; 8+ messages in thread
From: Liam Girdwood @ 2012-02-15 16:02 UTC (permalink / raw)
To: Mark Brown; +Cc: alsa-devel, Liam Girdwood
Currently we map DAI streams to DAPM widgets based on a string stream name.
This can lead to some limitations when working with lots of DAI links as there
is a risk of naming collision with similar stream names.
This patch creates a 1:N mapping between a DAI and it's DAPM widgets. It's
still string based, but we now directly reference the widget names with
the DAI and bind the DAI to the widget ptrs at initialisation. The binding
also tales into consideration the parent codec or platform that the DAI and
widget belong to so that we can easily support multiple components with
the same widget names.
This patch still works in conjunction with the stream based events, but it
is intended to eventually replace the DAI stream name.
e.g. to map twl6040 headset DACs to headset DAI
static const char *headset_widgets[] = {"HSDAC Left", "HSDAC Right"};
static struct snd_soc_dai_driver twl6040_dai[] = {
...
{
.name = "twl6040-dl1",
.playback = {
.stream_name = "Headset Playback",
.channel_widgets = headset_widgets,
.channels_min = 1,
.channels_max = ARRAY_SIZE(headset_widgets),
.rates = TWL6040_RATES,
.formats = TWL6040_FORMATS,
},
.ops = &twl6040_dai_ops,
},
This patch will allow DAI connection to any widget type as not all DAIs connect
directly to DACs or ADCs, some can connect via a mux that can swap channels etc.
This patch is also intended to be the starting point for future DAPM channel
mapping support as we now have a direct link between PCMs and DAPM widgets.
e.g. In the example above we map channel 0 (left) to "HSDAC Left" and channel 1
(right) to "HSDAC Right".
Signed-off-by: Liam Girdwood <lrg@ti.com>
---
include/sound/soc-dai.h | 11 ++-
include/sound/soc.h | 1 +
sound/soc/soc-core.c | 42 +++++++++++++
sound/soc/soc-dapm.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 205 insertions(+), 4 deletions(-)
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 2413acc..ce5beea 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -246,14 +246,17 @@ struct snd_soc_dai {
unsigned int rate;
/* parent platform/codec */
- union {
- struct snd_soc_platform *platform;
- struct snd_soc_codec *codec;
- };
+ struct snd_soc_platform *platform;
+ struct snd_soc_codec *codec;
struct snd_soc_card *card;
struct list_head list;
struct list_head card_list;
+
+ /* runtime widgets */
+ struct snd_soc_dapm_widget **playback_widgets;
+ struct snd_soc_dapm_widget **capture_widgets;
+ bool dapm_bind_complete;
};
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8fa4dca..bace9b8 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -507,6 +507,7 @@ struct snd_soc_pcm_stream {
unsigned int rates; /* SNDRV_PCM_RATE_* */
unsigned int rate_min; /* min rate */
unsigned int rate_max; /* max rate */
+ const char **channel_widgets; /* DAPM channel widget names */
unsigned int channels_min; /* min channels */
unsigned int channels_max; /* max channels */
unsigned int sig_bits; /* number of bits of content */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6bad7cd..733f5de 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -68,6 +68,8 @@ static int pmdown_time = 5000;
module_param(pmdown_time, int, 0);
MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
+int dapm_bind_dai_widgets(struct snd_soc_dai *dai, int stream);
+
/* returns the minimum number of bytes needed to represent
* a particular given value */
static int min_bytes_needed(unsigned long val)
@@ -1392,6 +1394,41 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
return 0;
}
+static int soc_init_card_dai_widgets(struct snd_soc_card *card)
+{
+ struct snd_soc_dai *dai;
+ int ret = 0;
+
+ list_for_each_entry(dai, &card->dai_dev_list, card_list) {
+
+ /* only process DAIs that use the new API until
+ * the old "stream name" API is fully deprecated */
+ if (!dai->driver->playback.channel_widgets &&
+ !dai->driver->capture.channel_widgets)
+ continue;
+
+ /* skip if already instanciated */
+ if (dai->dapm_bind_complete)
+ continue;
+
+ /* bind DAI widget name to component widget */
+ if (dai->driver->playback.channels_max) {
+ ret = dapm_bind_dai_widgets(dai, SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret < 0)
+ return ret;
+ }
+ if (dai->driver->capture.channels_max) {
+ ret = dapm_bind_dai_widgets(dai, SNDRV_PCM_STREAM_CAPTURE);
+ if (ret < 0)
+ return ret;
+ }
+
+ dai->dapm_bind_complete = 1;
+ }
+
+ return ret;
+}
+
static void snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
@@ -1556,6 +1593,9 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
snd_soc_dapm_new_widgets(&card->dapm);
+ ret = soc_init_card_dai_widgets(card);
+ if (ret < 0)
+ goto probe_aux_dev_err;
if (card->fully_routed)
list_for_each_entry(codec, &card->codec_dev_list, card_list)
@@ -3139,6 +3179,8 @@ found:
pr_debug("Unregistered DAI '%s'\n", dai->name);
kfree(dai->name);
+ kfree(dai->playback_widgets);
+ kfree(dai->capture_widgets);
kfree(dai);
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 63a5614..5f99842 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -829,6 +829,161 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
return con;
}
+static struct snd_soc_dapm_widget *
+ dapm_get_codec_widget(struct snd_soc_codec *codec, const char *name)
+{
+ struct snd_soc_card *card = codec->card;
+ struct snd_soc_dapm_widget *w;
+
+ /* find widget for this codec and widget name */
+ list_for_each_entry(w, &card->widgets, list) {
+
+ /* make sure the widget belongs to the DAI codec */
+ if (w->codec && w->codec != codec)
+ continue;
+
+ if (!strcmp(w->name, name))
+ return w;
+ }
+
+ return NULL;
+}
+
+static struct snd_soc_dapm_widget *
+ dapm_get_platform_widget(struct snd_soc_platform *platform,
+ const char *name)
+{
+ struct snd_soc_card *card = platform->card;
+ struct snd_soc_dapm_widget *w;
+
+ /* find widget for this platform and widget name */
+ list_for_each_entry(w, &card->widgets, list) {
+
+ /* make sure the widget belongs to the DAI platform */
+ if (w->platform && w->platform != platform)
+ continue;
+
+ if (!strcmp(w->name, name))
+ return w;
+ }
+
+ return NULL;
+}
+
+int dapm_bind_dai_playback_widgets(struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = dai->card;
+ struct snd_soc_dapm_widget *w = NULL;
+ const char *widget_name;
+ int i;
+
+ if (!dai->driver->playback.channel_widgets)
+ return 0;
+
+ dai->playback_widgets =
+ kzalloc(sizeof(struct snd_soc_dapm_widget *) *
+ dai->driver->playback.channels_max, GFP_KERNEL);
+ if (!dai->playback_widgets)
+ return -ENOMEM;
+
+ for (i = 0; i < dai->driver->playback.channels_max; i++) {
+ widget_name = dai->driver->playback.channel_widgets[i];
+
+ if (dai->codec) {
+ struct snd_soc_codec *codec;
+
+ list_for_each_entry(codec, &card->codec_dev_list, card_list) {
+ w = dapm_get_codec_widget(codec, widget_name);
+ if (w) {
+ dev_dbg(dai->dev, "bind %s to %s\n", w->name, codec->name);
+ break;
+ }
+ }
+ } else if (dai->platform) {
+ struct snd_soc_platform *platform;
+
+ list_for_each_entry(platform, &card->platform_dev_list, card_list) {
+ w = dapm_get_platform_widget(platform, widget_name);
+ if (w) {
+ dev_dbg(dai->dev, "bind %s to %s\n", w->name, platform->name);
+ break;
+ }
+ }
+ }
+
+ if (w)
+ dai->playback_widgets[i] = w;
+ else {
+ dev_err(dai->dev, "unable to find playback DAI AIF %s\n",
+ widget_name);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int dapm_bind_dai_capture_widgets(struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = dai->card;
+ struct snd_soc_dapm_widget *w = NULL;
+ const char *widget_name;
+ int i;
+
+ if (!dai->driver->capture.channel_widgets)
+ return 0;
+
+ dai->capture_widgets =
+ kzalloc(sizeof(struct snd_soc_dapm_widget *) *
+ dai->driver->capture.channels_max, GFP_KERNEL);
+ if (!dai->capture_widgets)
+ return -ENOMEM;
+
+ for (i = 0; i < dai->driver->capture.channels_max; i++) {
+ widget_name = dai->driver->capture.channel_widgets[i];
+
+ if (dai->codec) {
+ struct snd_soc_codec *codec;
+
+ list_for_each_entry(codec, &card->codec_dev_list, card_list) {
+ w = dapm_get_codec_widget(codec, widget_name);
+ if (w) {
+ dev_dbg(dai->dev, "bind %s to %s\n", w->name, codec->name);
+ break;
+ }
+ }
+ } else if (dai->platform) {
+ struct snd_soc_platform *platform;
+
+ list_for_each_entry(platform, &card->platform_dev_list, card_list) {
+ w = dapm_get_platform_widget(platform, widget_name);
+ if (w) {
+ dev_dbg(dai->dev, "bind %s to %s\n", w->name, platform->name);
+ break;
+ }
+ }
+ }
+
+ if (w)
+ dai->capture_widgets[i] = w;
+ else {
+ dev_err(dai->dev, "unable to find playback DAI AIF %s\n",
+ widget_name);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int dapm_bind_dai_widgets(struct snd_soc_dai *dai, int stream)
+{
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return dapm_bind_dai_playback_widgets(dai);
+ else
+ return dapm_bind_dai_capture_widgets(dai);
+}
+
/*
* Handler for generic register modifier widget.
*/
--
1.7.5.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] ASoC: core - Add support for direct DAI -> widget mapping stream events.
2012-02-15 16:02 [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Liam Girdwood
@ 2012-02-15 16:02 ` Liam Girdwood
2012-02-15 16:24 ` [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Mark Brown
1 sibling, 0 replies; 8+ messages in thread
From: Liam Girdwood @ 2012-02-15 16:02 UTC (permalink / raw)
To: Mark Brown; +Cc: alsa-devel, Liam Girdwood
Currently a DAPM stream event is strstr() matched on the DAI stream name
and the card widget names. This has some performance and naming scope
limitations for larger and more modern sound cards.
This patch adds the capability to perform a stream event based upon the new
DAI widget pointers if they exist and modifies snd_soc_dapm_stream_event() by
removing the stream name and adding the stream direction and power widgets
parameters.
void snd_soc_dapm_rtd_stream_event(struct snd_soc_pcm_runtime *rtd,
int stream, int event, int power_widgets);
The stream event now checks whether the RTD DAIs have widget pointers and if
so will perfiorm a stream event using the widget pointers. If no widget pointer
is found then it reverts to the existing stream event logic to guarantee correct
operation for existing drivers.
The "power widgets" parameter will only walk the DAPM graph and power the
widgets when true. This allows the dynamic PCM core to coalesce several
stream events togother.
Signed-off-by: Liam Girdwood <lrg@ti.com>
---
include/sound/soc-dapm.h | 4 +-
sound/soc/soc-core.c | 22 +++-----
sound/soc/soc-dapm.c | 133 +++++++++++++++++++++++++++++++++++++++++----
sound/soc/soc-pcm.c | 25 ++++-----
4 files changed, 141 insertions(+), 43 deletions(-)
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index db8435a..21b3b06 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -367,8 +367,8 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);
/* dapm events */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event);
+void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ int event, int power);
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
/* external DAPM widget events */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 733f5de..1423a01 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -575,18 +575,15 @@ int snd_soc_suspend(struct device *dev)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i], SNDRV_PCM_STREAM_PLAYBACK,
+ SND_SOC_DAPM_STREAM_SUSPEND, 0);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i], SNDRV_PCM_STREAM_CAPTURE,
+ SND_SOC_DAPM_STREAM_SUSPEND, 1);
}
/* suspend all CODECs */
@@ -689,18 +686,15 @@ static void soc_resume_deferred(struct work_struct *work)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i], SNDRV_PCM_STREAM_PLAYBACK,
+ SND_SOC_DAPM_STREAM_RESUME, 0);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i], SNDRV_PCM_STREAM_CAPTURE,
+ SND_SOC_DAPM_STREAM_RESUME, 1);
}
/* unmute any active DACs */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 5f99842..27f7858f 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -3017,29 +3017,138 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
dapm_power_widgets(dapm, event);
}
+static void widget_playback_stream_update(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai, int event)
+{
+ struct snd_soc_dapm_widget *w;
+ int i;
+
+ if (!dai->playback_widgets)
+ return;
+
+ for (i = 0; i < dai->driver->playback.channels_max; i++) {
+ w = dai->playback_widgets[i];
+
+ if (!w)
+ return;
+
+ dapm_mark_dirty(w, "stream event");
+
+ switch(event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+ }
+}
+
+static void widget_capture_stream_update(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai, int event)
+{
+ struct snd_soc_dapm_widget *w;
+ int i;
+
+ if (!dai->capture_widgets)
+ return;
+
+ for (i = 0; i < dai->driver->capture.channels_max; i++) {
+ w = dai->capture_widgets[i];
+
+ if (!w)
+ return;
+
+ dapm_mark_dirty(w, "stream event");
+
+ switch(event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+ }
+}
+
+static void soc_dapm_rtd_stream_event(struct snd_soc_pcm_runtime *rtd,
+ int stream, int event, int power_widgets)
+{
+ struct snd_soc_dapm_context *platform_dapm = &rtd->platform->dapm;
+ struct snd_soc_dapm_context *codec_dapm = &rtd->codec->dapm;
+
+ dev_dbg(rtd->dev, "dai link stream %d event %d\n", stream, event);
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ widget_playback_stream_update(platform_dapm, rtd->cpu_dai, event);
+ widget_playback_stream_update(codec_dapm, rtd->codec_dai, event);
+ } else {
+ widget_capture_stream_update(platform_dapm, rtd->cpu_dai, event);
+ widget_capture_stream_update(codec_dapm, rtd->codec_dai, event);
+ }
+
+ if (power_widgets)
+ dapm_power_widgets(codec_dapm, event);
+}
+
+/* legacy strstr() based stream event - now deprecated */
+static int soc_dapm_stream_event_str(struct snd_soc_pcm_runtime *rtd,
+ int event)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ const char *stream = rtd->codec_dai->driver->playback.stream_name;
+
+ if (stream == NULL)
+ return 0;
+
+ mutex_lock(&codec->mutex);
+ soc_dapm_stream_event(&codec->dapm, stream, event);
+ mutex_unlock(&codec->mutex);
+ return 0;
+}
+
/**
* snd_soc_dapm_stream_event - send a stream event to the dapm core
* @rtd: PCM runtime data
- * @stream: stream name
+ * @stream: stream direction
* @event: stream event
*
+ * This function support both widget based and the deprecated string based
+ * stream events. The intention is to eventually remove the deprecated string
+ * support.
+ *
* Sends a stream event to the dapm core. The core then makes any
* necessary widget power changes.
- *
- * Returns 0 for success else error.
*/
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event)
+void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ int event, int power)
{
- struct snd_soc_codec *codec = rtd->codec;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (stream == NULL)
- return 0;
+ if (rtd->cpu_dai->playback_widgets && rtd->codec_dai->playback_widgets)
+ soc_dapm_rtd_stream_event(rtd, stream, event, power);
+ else
+ soc_dapm_stream_event_str(rtd, event);
- mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
- mutex_unlock(&codec->mutex);
- return 0;
+ } else {
+
+ if (rtd->cpu_dai->capture_widgets && rtd->codec_dai->capture_widgets)
+ soc_dapm_rtd_stream_event(rtd, stream, event, power);
+ else
+ soc_dapm_stream_event_str(rtd, event);
+ }
}
/**
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 15816ec..4cd8eee 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -307,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
codec_dai->pop_wait = 0;
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ SND_SOC_DAPM_STREAM_STOP, 1);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -372,9 +371,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
rtd->dai_link->ignore_pmdown_time) {
/* powered down playback stream now */
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ SND_SOC_DAPM_STREAM_STOP, 1);
} else {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
@@ -383,9 +381,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
}
} else {
/* capture streams can be powered down now */
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+ SND_SOC_DAPM_STREAM_STOP, 1);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -455,13 +452,11 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ SND_SOC_DAPM_STREAM_START, 1);
else
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+ SND_SOC_DAPM_STREAM_START, 1);
snd_soc_dai_digital_mute(codec_dai, 0);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-15 16:02 [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Liam Girdwood
2012-02-15 16:02 ` [PATCH 2/2] ASoC: core - Add support for direct DAI -> widget mapping stream events Liam Girdwood
@ 2012-02-15 16:24 ` Mark Brown
2012-02-16 13:35 ` Liam Girdwood
1 sibling, 1 reply; 8+ messages in thread
From: Mark Brown @ 2012-02-15 16:24 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel
[-- Attachment #1.1: Type: text/plain, Size: 1607 bytes --]
On Wed, Feb 15, 2012 at 04:02:54PM +0000, Liam Girdwood wrote:
> Currently we map DAI streams to DAPM widgets based on a string stream name.
> This can lead to some limitations when working with lots of DAI links as there
> is a risk of naming collision with similar stream names.
> This patch creates a 1:N mapping between a DAI and it's DAPM widgets. It's
> still string based, but we now directly reference the widget names with
> the DAI and bind the DAI to the widget ptrs at initialisation. The binding
> also tales into consideration the parent codec or platform that the DAI and
> widget belong to so that we can easily support multiple components with
> the same widget names.
> This patch still works in conjunction with the stream based events, but it
> is intended to eventually replace the DAI stream name.
I was thinking about something close to this myself as part of the
CODEC<->CODEC automatic DAPM stuff I keep mentioning. In order to make
that work what I was going to do was instead of mapping the widgets
directly onto the DAI was to add a DAPM widget that represented the
stream and link the DAI to that, probably created automatically from the
DAI definition. We'd then have the DAIs sitting in the DAPM graph and
it gets much simpler to just connect the playback DAI on one device to
the capture device on another (and vice versa).
In terms of the API and end result it's pretty similar to what you've
got here except it'd probably end up with the DAI<->widget links
specified through the DAPM map. What do you think? I'd rather not
churn the API more often than we have to.
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-15 16:24 ` [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Mark Brown
@ 2012-02-16 13:35 ` Liam Girdwood
2012-02-16 17:59 ` Mark Brown
0 siblings, 1 reply; 8+ messages in thread
From: Liam Girdwood @ 2012-02-16 13:35 UTC (permalink / raw)
To: Mark Brown; +Cc: alsa-devel
On Wed, 2012-02-15 at 08:24 -0800, Mark Brown wrote:
> On Wed, Feb 15, 2012 at 04:02:54PM +0000, Liam Girdwood wrote:
> > Currently we map DAI streams to DAPM widgets based on a string stream name.
> > This can lead to some limitations when working with lots of DAI links as there
> > is a risk of naming collision with similar stream names.
>
> > This patch creates a 1:N mapping between a DAI and it's DAPM widgets. It's
> > still string based, but we now directly reference the widget names with
> > the DAI and bind the DAI to the widget ptrs at initialisation. The binding
> > also tales into consideration the parent codec or platform that the DAI and
> > widget belong to so that we can easily support multiple components with
> > the same widget names.
>
> > This patch still works in conjunction with the stream based events, but it
> > is intended to eventually replace the DAI stream name.
>
> I was thinking about something close to this myself as part of the
> CODEC<->CODEC automatic DAPM stuff I keep mentioning. In order to make
> that work what I was going to do was instead of mapping the widgets
> directly onto the DAI was to add a DAPM widget that represented the
> stream and link the DAI to that, probably created automatically from the
> DAI definition. We'd then have the DAIs sitting in the DAPM graph and
> it gets much simpler to just connect the playback DAI on one device to
> the capture device on another (and vice versa).
>
> In terms of the API and end result it's pretty similar to what you've
> got here except it'd probably end up with the DAI<->widget links
> specified through the DAPM map. What do you think? I'd rather not
> churn the API more often than we have to.
I'm easy enough, but I'm not sure how we could map specific PCM channels
via the DAPM graph. e.g. we could connect the L and R DAC widgets to the
DAI widget but how would we associate the L DAC widget with PCM channel
0 etc.
I do have a subsequent patch that does this based on the mapping atm :-
@@ -1405,6 +1405,17 @@ static int soc_init_card_dai_widgets(struct snd_soc_card *card)
return ret;
}
+ /* create unique channels masks for each DAI in the sound card */
+ dai->playback_channel_map =
+ ((1 << dai->driver->playback.channels_max) - 1)
+ << card->num_playback_channels;
+ card->num_playback_channels += dai->driver->playback.channels_max;
+
+ dai->capture_channel_map =
+ ((1 << dai->driver->capture.channels_max) - 1)
+ << card->num_capture_channels;
+ card->num_capture_channels += dai->driver->capture.channels_max;
+
dai->dapm_bind_complete = 1;
}
To give us a unique channel ID for each PCM channel propagating through
each widget (since I can map PCM channels atm).
I did connect the DAIs together in the mach driver via DAPM, but I agree
it would be nicer connect the DAI widgets together here rather than
DACs, etc.
The dynamic PCM patch is also blocking on having some sort of DAI ->
widget mapping so we would need something upstream soonish.
I'll take a quick look and see if I can modify this and try and include
a DAI widget too whilst retaining the channel mapping before you have
breakfast.
Liam
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-16 13:35 ` Liam Girdwood
@ 2012-02-16 17:59 ` Mark Brown
2012-02-17 5:40 ` Vinod Koul
0 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2012-02-16 17:59 UTC (permalink / raw)
To: Liam Girdwood; +Cc: alsa-devel
[-- Attachment #1.1: Type: text/plain, Size: 2340 bytes --]
On Thu, Feb 16, 2012 at 01:35:58PM +0000, Liam Girdwood wrote:
> On Wed, 2012-02-15 at 08:24 -0800, Mark Brown wrote:
> > I was thinking about something close to this myself as part of the
> > CODEC<->CODEC automatic DAPM stuff I keep mentioning. In order to make
> > that work what I was going to do was instead of mapping the widgets
> > directly onto the DAI was to add a DAPM widget that represented the
> > stream and link the DAI to that, probably created automatically from the
> > DAI definition. We'd then have the DAIs sitting in the DAPM graph and
> I'm easy enough, but I'm not sure how we could map specific PCM channels
> via the DAPM graph. e.g. we could connect the L and R DAC widgets to the
> DAI widget but how would we associate the L DAC widget with PCM channel
> 0 etc.
We actually need to do that anyway for the CODEC<->CODEC links, I've got
use cases where there are multiple independant streams going over the
same DAI on different channels (eg, stereo pair on 0 and 1, another
stereo pair on 2 and 3).
I can see two ways of doing this. One is simply to teach DAPM about
these shiny new things like channel numbers in the same way it knows
about mixers and muxes. Obviously that's a bit invasive but clearly
it'll do the trick. The other is to hang this in using the connected
callback on the route, have the callback look at the DAI to see what
channels are active and then report if the link is present or not. The
infrastructure for that is there in DAPM itself already which is nice.
> To give us a unique channel ID for each PCM channel propagating through
> each widget (since I can map PCM channels atm).
> I did connect the DAIs together in the mach driver via DAPM, but I agree
> it would be nicer connect the DAI widgets together here rather than
> DACs, etc.
> The dynamic PCM patch is also blocking on having some sort of DAI ->
> widget mapping so we would need something upstream soonish.
> I'll take a quick look and see if I can modify this and try and include
> a DAI widget too whilst retaining the channel mapping before you have
> breakfast.
I *think* can get something working quickly that doesn't fill in the
blanks for CODEC-CODEC links, though the conference is looking quite
interesting today. I'll try to send something later.
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-16 17:59 ` Mark Brown
@ 2012-02-17 5:40 ` Vinod Koul
2012-02-17 5:43 ` Mark Brown
0 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2012-02-17 5:40 UTC (permalink / raw)
To: Mark Brown; +Cc: alsa-devel, Liam Girdwood
On Thu, 2012-02-16 at 09:59 -0800, Mark Brown wrote:
> On Thu, Feb 16, 2012 at 01:35:58PM +0000, Liam Girdwood wrote:
> > On Wed, 2012-02-15 at 08:24 -0800, Mark Brown wrote:
>
> > > I was thinking about something close to this myself as part of the
> > > CODEC<->CODEC automatic DAPM stuff I keep mentioning. In order to make
> > > that work what I was going to do was instead of mapping the widgets
> > > directly onto the DAI was to add a DAPM widget that represented the
> > > stream and link the DAI to that, probably created automatically from the
> > > DAI definition. We'd then have the DAIs sitting in the DAPM graph and
>
> > I'm easy enough, but I'm not sure how we could map specific PCM channels
> > via the DAPM graph. e.g. we could connect the L and R DAC widgets to the
> > DAI widget but how would we associate the L DAC widget with PCM channel
> > 0 etc.
>
> We actually need to do that anyway for the CODEC<->CODEC links, I've got
> use cases where there are multiple independant streams going over the
> same DAI on different channels (eg, stereo pair on 0 and 1, another
> stereo pair on 2 and 3).
Is this a TDM DAI you are referring to?
>
> I can see two ways of doing this. One is simply to teach DAPM about
> these shiny new things like channel numbers in the same way it knows
> about mixers and muxes. Obviously that's a bit invasive but clearly
> it'll do the trick. The other is to hang this in using the connected
> callback on the route, have the callback look at the DAI to see what
> channels are active and then report if the link is present or not. The
> infrastructure for that is there in DAPM itself already which is nice.
My +1 for teaching DAPM about channel numbering. Today I have DAI
associated with a stream. This DAI can take 4 channels. But DAPM turns
ON all 4 channels even if we have mono or stereo being turned on.
>
> > To give us a unique channel ID for each PCM channel propagating through
> > each widget (since I can map PCM channels atm).
>
> > I did connect the DAIs together in the mach driver via DAPM, but I agree
> > it would be nicer connect the DAI widgets together here rather than
> > DACs, etc.
>
> > The dynamic PCM patch is also blocking on having some sort of DAI ->
> > widget mapping so we would need something upstream soonish.
>
> > I'll take a quick look and see if I can modify this and try and include
> > a DAI widget too whilst retaining the channel mapping before you have
> > breakfast.
>
> I *think* can get something working quickly that doesn't fill in the
> blanks for CODEC-CODEC links, though the conference is looking quite
> interesting today. I'll try to send something later.
On conference, when are we planing our next ASoC conference?
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-17 5:40 ` Vinod Koul
@ 2012-02-17 5:43 ` Mark Brown
2012-02-17 10:47 ` Liam Girdwood
0 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2012-02-17 5:43 UTC (permalink / raw)
To: Vinod Koul; +Cc: alsa-devel, Liam Girdwood
[-- Attachment #1.1: Type: text/plain, Size: 937 bytes --]
On Fri, Feb 17, 2012 at 11:10:53AM +0530, Vinod Koul wrote:
> On Thu, 2012-02-16 at 09:59 -0800, Mark Brown wrote:
> > We actually need to do that anyway for the CODEC<->CODEC links, I've got
> > use cases where there are multiple independant streams going over the
> > same DAI on different channels (eg, stereo pair on 0 and 1, another
> > stereo pair on 2 and 3).
> Is this a TDM DAI you are referring to?
They can be, they can also be grouped together to make multi-channel
links. It's entirely flexible to software on the devices I'm thinking
of.
> > I *think* can get something working quickly that doesn't fill in the
> > blanks for CODEC-CODEC links, though the conference is looking quite
> > interesting today. I'll try to send something later.
> On conference, when are we planing our next ASoC conference?
Not at present. It would probably have been colocated with ELC but
that didn't happen.
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM
2012-02-17 5:43 ` Mark Brown
@ 2012-02-17 10:47 ` Liam Girdwood
0 siblings, 0 replies; 8+ messages in thread
From: Liam Girdwood @ 2012-02-17 10:47 UTC (permalink / raw)
To: Mark Brown; +Cc: Vinod Koul, alsa-devel
On Thu, 2012-02-16 at 21:43 -0800, Mark Brown wrote:
> On Fri, Feb 17, 2012 at 11:10:53AM +0530, Vinod Koul wrote:
> > On Thu, 2012-02-16 at 09:59 -0800, Mark Brown wrote:
>
> > > I *think* can get something working quickly that doesn't fill in the
> > > blanks for CODEC-CODEC links, though the conference is looking quite
> > > interesting today. I'll try to send something later.
>
> > On conference, when are we planing our next ASoC conference?
>
> Not at present. It would probably have been colocated with ELC but
> that didn't happen.
Sadly I didn't have enough time to set this up for ELC but I should have
more time after Dynamic PCM is upstream. I've had some discussions with
the Linux Foundation and they are happy to co-locate. Lets discuss when
you get back in the UK.
Liam
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-02-17 10:48 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-15 16:02 [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Liam Girdwood
2012-02-15 16:02 ` [PATCH 2/2] ASoC: core - Add support for direct DAI -> widget mapping stream events Liam Girdwood
2012-02-15 16:24 ` [PATCH 1/2] ASoC: core - Add direct mapping between DAIs and DAPM Mark Brown
2012-02-16 13:35 ` Liam Girdwood
2012-02-16 17:59 ` Mark Brown
2012-02-17 5:40 ` Vinod Koul
2012-02-17 5:43 ` Mark Brown
2012-02-17 10:47 ` Liam Girdwood
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).