summaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c380
1 files changed, 344 insertions, 36 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1790f83ee66..4f69ef40f07 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -47,6 +47,8 @@
#include <trace/events/asoc.h>
+static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm);
+
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 0,
@@ -123,6 +125,243 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
}
+static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
+{
+ if (w->codec)
+ return snd_soc_read(w->codec, reg);
+ else if (w->platform)
+ return snd_soc_platform_read(w->platform, reg);
+ return 0;
+}
+
+static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
+{
+ if (w->codec)
+ return snd_soc_write(w->codec, reg, val);
+ else if (w->platform)
+ return snd_soc_platform_write(w->platform, reg, val);
+ return 0;
+}
+
+int soc_widget_update_bits(struct snd_soc_dapm_widget *w, unsigned short reg,
+ unsigned int mask, unsigned int value)
+{
+ int change;
+ unsigned int old, new;
+
+ old = soc_widget_read(w, reg);
+ new = (old & ~mask) | value;
+ change = old != new;
+// if (change)
+ soc_widget_write(w, reg, new);
+
+ return change;
+}
+
+int soc_widget_test_bits(struct snd_soc_dapm_widget *w, unsigned short reg,
+ unsigned int mask, unsigned int value)
+{
+ int change;
+ unsigned int old, new;
+
+ old = soc_widget_read(w, reg);
+ new = (old & ~mask) | value;
+ change = old != new;
+
+ return change;
+}
+
+#define MAX_HOPS 16
+
+static void scenario_clear_paths(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_dapm_path *p;
+ struct snd_soc_dapm_widget *w;
+ struct list_head *l;
+
+ list_for_each(l, &dapm->card->paths) {
+ p = list_entry(l, struct snd_soc_dapm_path, list);
+ p->length = 0;
+ }
+ list_for_each(l, &dapm->card->widgets) {
+ w = list_entry(l, struct snd_soc_dapm_widget, list);
+ w->hops = 0;
+ }
+ dapm_clear_walk(dapm);
+}
+
+/*
+ * find all the paths between source and sink
+ */
+static int scenario_find_playback_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink,
+ int hops)
+{
+ struct list_head *lp;
+ struct snd_soc_dapm_path *path;
+ int dist = 0;
+
+ if (hops > MAX_HOPS)
+ return 0;
+
+ if (source == sink) {
+ dev_dbg(dapm->dev,"** found route with length %d\n", hops);
+ dapm->num_valid_paths++;
+ return 1;
+ }
+
+ if (source->hops && source->hops <= hops)
+ return 0;
+ source->hops = hops;
+
+ /*
+ * check all the output paths on this source widget
+ * by walking from source to sink
+ */
+ list_for_each(lp, &source->sinks) {
+ path = list_entry(lp, struct snd_soc_dapm_path, list_source);
+
+ dev_dbg(dapm->dev,"%d:try source %s path %s to %s len %d connect %d\n",
+ hops, source->name, path->name, path->sink->name,
+ path->length, path->connect);
+
+ /* been here before ? */
+ if (path->length && path->length <= hops)
+ continue;
+
+ /* check down the next path if connected */
+ if (path->sink && path->connect &&
+ scenario_find_playback_paths(dapm, path->sink, sink, hops + 1)) {
+ path->length = hops;
+ if (!dist || dist > path->length)
+ dist = path->length;
+ }
+ }
+
+ return dist;
+}
+
+static int scenario_find_capture_paths (struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink,
+ int hops)
+{
+ struct list_head *lp;
+ struct snd_soc_dapm_path *path;
+ int dist = 0;
+
+ if (hops > MAX_HOPS)
+ return 0;
+
+ if (source == sink) {
+ dev_dbg(dapm->dev,"** found route with length %d\n", hops);
+ dapm->num_valid_paths++;
+ return 1;
+ }
+
+ if (sink->hops && sink->hops <= hops)
+ return 0;
+ sink->hops = hops;
+
+ /*
+ * check all the output paths on this source widget
+ * by walking from sink to source
+ */
+ list_for_each(lp, &sink->sources) {
+ path = list_entry(lp, struct snd_soc_dapm_path, list_sink);
+
+ dev_dbg(dapm->dev,"%d:try sink %s path %s to %s len %d connect %d\n",
+ hops, sink->name, path->name, path->source->name,
+ path->length, path->connect);
+
+ /* been here before ? */
+ if (path->length && path->length <= hops)
+ continue;
+
+ /* check down the next path if connected */
+ if (path->source && path->connect &&
+ scenario_find_capture_paths(dapm, source, path->source, hops + 1)) {
+ path->length = hops;
+ if (!dist || dist > path->length)
+ dist = path->length;
+ }
+ }
+
+ return dist;
+}
+
+/*
+ * traverse the tree from sink to source via the shortest path
+ */
+static int scenario_get_playback_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink)
+{
+ dapm->num_valid_paths = 0;
+
+ dev_dbg(dapm->dev, "check playback path from %s to %s\n",
+ source->name, sink->name);
+ scenario_find_playback_paths(dapm, source, sink, 1);
+ return dapm->num_valid_paths;
+}
+
+static int scenario_get_capture_paths(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink)
+{
+ dapm->num_valid_paths = 0;
+ dev_dbg(dapm->dev, "check capture path to %s from %s\n",
+ source->name, sink->name);
+ scenario_find_capture_paths(dapm, sink, source, 1);
+ return dapm->num_valid_paths;
+}
+
+/**
+ * snd_soc_scenario_set_path - set new scenario path
+ * @codec: the soc codec
+ * @scenario: the sceanrio path
+ *
+ * Sets up a new audio path within the audio susbsytem.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_scenario_set_path(struct snd_soc_dapm_context *dapm,
+ const char *source_name, const char *sink_name, int stream)
+{
+ struct snd_soc_dapm_widget *sink = NULL, *source = NULL;
+ struct list_head *l = NULL;
+ int routes;
+
+ /* find source */
+ list_for_each(l, &dapm->card->widgets) {
+ struct snd_soc_dapm_widget *w;
+ w = list_entry(l, struct snd_soc_dapm_widget, list);
+
+ if(!source && !strncmp(w->name, source_name, 16)) {
+ source = w;
+ continue;
+ }
+ if(!sink && !strncmp(w->name, sink_name, 16)) {
+ sink = w;
+ }
+ }
+
+ if(!source) {
+ printk(KERN_ERR "soc: invalid scenario source %s\n", source_name);
+ return -EINVAL;
+ }
+ if(!sink) {
+ printk(KERN_ERR "soc: invalid scenario sink %s\n", sink_name);
+ return -EINVAL;
+ }
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ routes = scenario_get_playback_paths(dapm, source, sink);
+ else
+ routes = scenario_get_capture_paths(dapm, source, sink);
+ scenario_clear_paths(dapm);
+
+ return routes;
+}
+EXPORT_SYMBOL_GPL(snd_soc_scenario_set_path);
+
/**
* snd_soc_dapm_set_bias_level - set the bias level for the system
* @card: audio device
@@ -193,7 +432,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- val = snd_soc_read(w->codec, reg);
+ val = soc_widget_read(w, reg);
val = (val >> shift) & mask;
if ((invert && !val) || (!invert && val))
@@ -208,7 +447,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
- val = snd_soc_read(w->codec, e->reg);
+ val = soc_widget_read(w, e->reg);
item = (val >> e->shift_l) & (bitmask - 1);
p->connect = 0;
@@ -237,7 +476,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
w->kcontrols[i].private_value;
int val, item;
- val = snd_soc_read(w->codec, e->reg);
+ val = soc_widget_read(w, e->reg);
val = (val >> e->shift_l) & e->mask;
for (item = 0; item < e->max; item++) {
if (val == e->values[item])
@@ -326,7 +565,6 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
{
int change, power;
unsigned int old, new;
- struct snd_soc_codec *codec = widget->codec;
struct snd_soc_dapm_context *dapm = widget->dapm;
struct snd_soc_card *card = dapm->card;
@@ -343,7 +581,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
if (widget->invert)
power = (power ? 0:1);
- old = snd_soc_read(codec, widget->reg);
+ old = soc_widget_read(widget, widget->reg);
new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
change = old != new;
@@ -353,7 +591,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
widget->name, widget->power ? "on" : "off",
card->pop_time);
pop_wait(card->pop_time);
- snd_soc_write(codec, widget->reg, new);
+ soc_widget_write(widget, widget->reg, new);
}
dev_dbg(dapm->dev, "reg %x old %x new %x change %d\n", widget->reg,
old, new, change);
@@ -367,7 +605,14 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
int i, ret = 0;
size_t name_len;
struct snd_soc_dapm_path *path;
- struct snd_card *card = dapm->codec->card->snd_card;
+ struct snd_card *card;
+
+ if (dapm->codec)
+ card = dapm->codec->card->snd_card;
+ if (dapm->platform)
+ card = dapm->platform->card->snd_card;
+ if (!card)
+ return -ENODEV;
/* add kcontrol */
for (i = 0; i < w->num_kcontrols; i++) {
@@ -429,9 +674,16 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_path *path = NULL;
struct snd_kcontrol *kcontrol;
- struct snd_card *card = dapm->codec->card->snd_card;
+ struct snd_card *card;
int ret = 0;
+ if (dapm->codec)
+ card = dapm->codec->card->snd_card;
+ if (dapm->platform)
+ card = dapm->platform->card->snd_card;
+ if (!card)
+ return -ENODEV;
+
if (!w->num_kcontrols) {
dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name);
return -EINVAL;
@@ -479,7 +731,17 @@ static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
*/
static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
{
- int level = snd_power_get_state(widget->dapm->codec->card->snd_card);
+ struct snd_card *card;
+ int level;
+
+ if (widget->codec)
+ card = widget->codec->card->snd_card;
+ else if (widget->platform)
+ card = widget->platform->card->snd_card;
+ else
+ return 0;
+
+ level = snd_power_get_state(card);
switch (level) {
case SNDRV_CTL_POWER_D3hot:
@@ -601,7 +863,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
else
val = w->off_val;
- snd_soc_update_bits(w->codec, -(w->reg + 1),
+ soc_widget_update_bits(w, -(w->reg + 1),
w->mask << w->shift, val << w->shift);
return 0;
@@ -811,7 +1073,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
struct list_head *pending)
{
struct snd_soc_card *card = dapm->card;
- struct snd_soc_dapm_widget *w;
+ struct snd_soc_dapm_widget *w, *wf;
int reg, power;
unsigned int value = 0;
unsigned int mask = 0;
@@ -819,6 +1081,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
reg = list_first_entry(pending, struct snd_soc_dapm_widget,
power_list)->reg;
+ wf = list_first_entry(pending, struct snd_soc_dapm_widget,
+ power_list);
list_for_each_entry(w, pending, power_list) {
cur_mask = 1 << w->shift;
@@ -847,7 +1111,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
value, mask, reg, card->pop_time);
pop_wait(card->pop_time);
- snd_soc_update_bits(dapm->codec, reg, mask, value);
+ soc_widget_update_bits(wf, reg, mask, value);
}
list_for_each_entry(w, pending, power_list) {
@@ -990,7 +1254,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
*/
static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
{
- struct snd_soc_card *card = dapm->codec->card;
+ struct snd_soc_card *card = NULL;
struct snd_soc_dapm_widget *w;
struct snd_soc_dapm_context *d;
LIST_HEAD(up_list);
@@ -998,6 +1262,13 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
int ret = 0;
int power;
+ if (dapm->codec)
+ card = dapm->codec->card;
+ if (dapm->platform)
+ card = dapm->platform->card;
+ if (!card)
+ return -ENODEV;
+
trace_snd_soc_dapm_start(card);
list_for_each_entry(d, &card->dapm_list, list)
@@ -1007,6 +1278,7 @@ 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.
*/
+ mutex_lock(&card->dapm_mutex);
list_for_each_entry(w, &card->widgets, list) {
switch (w->id) {
case snd_soc_dapm_pre:
@@ -1041,6 +1313,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
break;
}
}
+ mutex_unlock(&card->dapm_mutex);
/* If there are no DAPM widgets then try to figure out power from the
* event type.
@@ -1244,7 +1517,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int change,
int mux, struct soc_enum *e)
{
@@ -1280,10 +1553,11 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
- struct snd_kcontrol *kcontrol, int connect)
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
int found = 0;
@@ -1309,6 +1583,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
@@ -1464,7 +1739,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
char prefixed_source[80];
int ret = 0;
- if (dapm->codec->name_prefix) {
+ if (dapm->codec && dapm->codec->name_prefix) {
snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
dapm->codec->name_prefix, route->sink);
sink = prefixed_sink;
@@ -1686,7 +1961,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
}
/* Read the initial power state from the device */
- if (w->reg >= 0) {
+ if (w->reg >= 0 && w->codec) {
val = snd_soc_read(w->codec, w->reg);
val &= 1 << w->shift;
if (w->invert)
@@ -1704,6 +1979,23 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
+const char *snd_soc_dapm_get_aif(struct snd_soc_dapm_context *dapm,
+ const char *stream_name, enum snd_soc_dapm_type type)
+{
+ struct snd_soc_dapm_widget *w;
+
+ list_for_each_entry(w, &dapm->card->widgets, list) {
+
+ if (!w->sname)
+ continue;
+
+ if (w->id == type && strstr(w->sname, stream_name))
+ return w->name;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_aif);
+
/**
* snd_soc_dapm_get_volsw - dapm mixer get callback
* @kcontrol: mixer control
@@ -1727,10 +2019,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
unsigned int mask = (1 << fls(max)) - 1;
ucontrol->value.integer.value[0] =
- (snd_soc_read(widget->codec, reg) >> shift) & mask;
+ (soc_widget_read(widget, reg) >> shift) & mask;
if (shift != rshift)
ucontrol->value.integer.value[1] =
- (snd_soc_read(widget->codec, reg) >> rshift) & mask;
+ (soc_widget_read(widget, reg) >> rshift) & mask;
if (invert) {
ucontrol->value.integer.value[0] =
max - ucontrol->value.integer.value[0];
@@ -1777,7 +2069,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
mutex_lock(&widget->codec->mutex);
widget->value = val;
- change = snd_soc_test_bits(widget->codec, reg, mask, val);
+ change = soc_widget_test_bits(widget, reg, mask, val);
if (change) {
if (val)
/* new connection */
@@ -1793,7 +2085,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mixer_update_power(widget, kcontrol, connect);
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
@@ -1821,7 +2113,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
- val = snd_soc_read(widget->codec, e->reg);
+ val = soc_widget_read(widget, e->reg);
ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
if (e->shift_l != e->shift_r)
ucontrol->value.enumerated.item[1] =
@@ -1865,7 +2157,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock(&widget->codec->mutex);
widget->value = val;
- change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
+ change = soc_widget_test_bits(widget, e->reg, mask, val);
update.kcontrol = kcontrol;
update.widget = widget;
@@ -1874,7 +2166,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
@@ -1924,7 +2216,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
change = widget->value != ucontrol->value.enumerated.item[0];
widget->value = ucontrol->value.enumerated.item[0];
- dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
mutex_unlock(&widget->codec->mutex);
return ret;
@@ -1951,7 +2243,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int reg_val, val, mux;
- reg_val = snd_soc_read(widget->codec, e->reg);
+ reg_val = soc_widget_read(widget, e->reg);
val = (reg_val >> e->shift_l) & e->mask;
for (mux = 0; mux < e->max; mux++) {
if (val == e->values[mux])
@@ -2007,7 +2299,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock(&widget->codec->mutex);
widget->value = val;
- change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
+ change = soc_widget_test_bits(widget, e->reg, mask, val);
update.kcontrol = kcontrol;
update.widget = widget;
@@ -2016,7 +2308,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
@@ -2114,14 +2406,14 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
return -ENOMEM;
name_len = strlen(widget->name) + 1;
- if (dapm->codec->name_prefix)
+ if (dapm->codec && dapm->codec->name_prefix)
name_len += 1 + strlen(dapm->codec->name_prefix);
w->name = kmalloc(name_len, GFP_KERNEL);
if (w->name == NULL) {
kfree(w);
return -ENOMEM;
}
- if (dapm->codec->name_prefix)
+ if (dapm->codec && dapm->codec->name_prefix)
snprintf(w->name, name_len, "%s %s",
dapm->codec->name_prefix, widget->name);
else
@@ -2130,6 +2422,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
dapm->n_widgets++;
w->dapm = dapm;
w->codec = dapm->codec;
+ w->platform = dapm->platform;
INIT_LIST_HEAD(&w->sources);
INIT_LIST_HEAD(&w->sinks);
INIT_LIST_HEAD(&w->list);
@@ -2200,6 +2493,10 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
}
dapm_power_widgets(dapm, event);
+
+ /* do we need to notify any clients that DAPM stream is complete */
+ if (dapm->stream_event)
+ dapm->stream_event(dapm);
}
/**
@@ -2214,16 +2511,27 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
* Returns 0 for success else error.
*/
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event)
+ int dir, const char *stream, int event)
{
- struct snd_soc_codec *codec = rtd->codec;
+ int i;
if (stream == NULL)
return 0;
- mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
- mutex_unlock(&codec->mutex);
+ if (rtd->dai_link->dynamic) {
+ for (i = 0; i < rtd->num_be[dir]; i++) {
+ struct snd_soc_platform *platform = rtd->be_rtd[i][dir]->platform;
+
+ soc_dapm_stream_event(&platform->dapm, stream, event);
+ }
+ } else {
+ struct snd_soc_codec *codec = rtd->codec;
+
+ mutex_lock(&codec->mutex);
+ soc_dapm_stream_event(&(codec->dapm), stream, event);
+ mutex_unlock(&codec->mutex);
+ }
+
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);