summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorJarkko Nikula <jhnikula@gmail.com>2010-12-14 12:18:31 +0200
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-12-15 18:01:01 +0000
commit97c866defc0fc6e18b49603ac19f732f53e79c46 (patch)
tree66ba8412fad0974ebf9a30c45ad5d81f26607e6e /sound/soc/soc-dapm.c
parent8ddab3f5107c3955e70e87a632d4d179ddba1189 (diff)
downloadlinux-97c866defc0fc6e18b49603ac19f732f53e79c46.tar.gz
linux-97c866defc0fc6e18b49603ac19f732f53e79c46.tar.bz2
linux-97c866defc0fc6e18b49603ac19f732f53e79c46.zip
ASoC: Move widgets from DAPM context to snd_soc_card
Decoupling widgets from DAPM context is required when extending the ASoC core to cross-device paths. Even the list of widgets are now kept in struct snd_soc_card, the widget listing in sysfs and debugs remain sorted per device. This patch makes possible to build cross-device paths but does not extend yet the DAPM to handle codec bias and widget power changes of an another device. Cross-device paths are registered by listing the widgets from device A in a map for device B. In case of conflicting widget names between the devices, a uniform name prefix is needed to separate them. See commit ead9b91 "ASoC: Add optional name_prefix for kcontrol, widget and route names" for help. An example below shows a path that connects MONO out of A into Line In of B: static const struct snd_soc_dapm_route mapA[] = { {"MONO", NULL, "DAC"}, }; static const struct snd_soc_dapm_route mapB[] = { {"Line In", NULL, "MONO"}, }; Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c69
1 files changed, 49 insertions, 20 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 5d9ec4a3a9f1..8731e89646ae 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -940,7 +940,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down.
*/
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
switch (w->id) {
case snd_soc_dapm_pre:
dapm_seq_insert(w, &down_list, dapm_down_seq);
@@ -978,7 +980,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* If there are no DAPM widgets then try to figure out power from the
* event type.
*/
- if (list_empty(&dapm->widgets)) {
+ if (!dapm->n_widgets) {
switch (event) {
case SND_SOC_DAPM_STREAM_START:
case SND_SOC_DAPM_STREAM_RESUME:
@@ -1145,8 +1147,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm)
if (!dapm->debugfs_dapm)
return;
- list_for_each_entry(w, &dapm->widgets, list) {
- if (!w->name)
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (!w->name || w->dapm != dapm)
continue;
d = debugfs_create_file(w->name, 0444,
@@ -1241,7 +1243,9 @@ static ssize_t dapm_widget_show(struct device *dev,
int count = 0;
char *state = "not set";
- list_for_each_entry(w, &codec->dapm.widgets, list) {
+ list_for_each_entry(w, &codec->card->widgets, list) {
+ if (w->dapm != &codec->dapm)
+ continue;
/* only display widgets that burnm power */
switch (w->id) {
@@ -1303,7 +1307,9 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
struct snd_soc_dapm_widget *w, *next_w;
struct snd_soc_dapm_path *p, *next_p;
- list_for_each_entry_safe(w, next_w, &dapm->widgets, list) {
+ list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
list_del(&w->list);
/*
* remove source and sink paths associated to this widget.
@@ -1334,7 +1340,9 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
if (!strcmp(w->name, pin)) {
dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n",
pin, status);
@@ -1370,6 +1378,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_path *path;
struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
+ struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
const char *sink;
const char *control = route->control;
const char *source;
@@ -1389,17 +1398,28 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
source = route->source;
}
- /* find src and dest widgets */
- list_for_each_entry(w, &dapm->widgets, list) {
-
+ /*
+ * find src and dest widgets over all widgets but favor a widget from
+ * current DAPM context
+ */
+ list_for_each_entry(w, &dapm->card->widgets, list) {
if (!wsink && !(strcmp(w->name, sink))) {
- wsink = w;
+ wtsink = w;
+ if (w->dapm == dapm)
+ wsink = w;
continue;
}
if (!wsource && !(strcmp(w->name, source))) {
- wsource = w;
+ wtsource = w;
+ if (w->dapm == dapm)
+ wsource = w;
}
}
+ /* use widget from another DAPM context if not found from this */
+ if (!wsink)
+ wsink = wtsink;
+ if (!wsource)
+ wsource = wtsource;
if (wsource == NULL || wsink == NULL)
return -ENODEV;
@@ -1537,7 +1557,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list)
+ list_for_each_entry(w, &dapm->card->widgets, list)
{
if (w->new)
continue;
@@ -2037,12 +2057,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
else
snprintf(w->name, name_len, "%s", widget->name);
+ dapm->n_widgets++;
w->dapm = dapm;
w->codec = dapm->codec;
INIT_LIST_HEAD(&w->sources);
INIT_LIST_HEAD(&w->sinks);
INIT_LIST_HEAD(&w->list);
- list_add(&w->list, &dapm->widgets);
+ list_add(&w->list, &dapm->card->widgets);
/* machine layer set ups unconnected pins and insertions */
w->connected = 1;
@@ -2085,9 +2106,9 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list)
+ list_for_each_entry(w, &dapm->card->widgets, list)
{
- if (!w->sname)
+ if (!w->sname || w->dapm != dapm)
continue;
dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
w->name, w->sname, stream, event);
@@ -2170,7 +2191,9 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
if (!strcmp(w->name, pin)) {
dev_dbg(w->dapm->dev,
"dapm: force enable pin %s\n", pin);
@@ -2235,7 +2258,9 @@ int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
if (!strcmp(w->name, pin))
return w->connected;
}
@@ -2260,7 +2285,9 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
if (!strcmp(w->name, pin)) {
w->ignore_suspend = 1;
return 0;
@@ -2291,7 +2318,9 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
LIST_HEAD(down_list);
int powerdown = 0;
- list_for_each_entry(w, &dapm->widgets, list) {
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
if (w->power) {
dapm_seq_insert(w, &down_list, dapm_down_seq);
w->power = 0;