summaryrefslogtreecommitdiffstats
path: root/sound/soc/qcom/qdsp6/topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/qcom/qdsp6/topology.c')
-rw-r--r--sound/soc/qcom/qdsp6/topology.c105
1 files changed, 94 insertions, 11 deletions
diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
index 0c4886d30131..f66d7054177c 100644
--- a/sound/soc/qcom/qdsp6/topology.c
+++ b/sound/soc/qcom/qdsp6/topology.c
@@ -872,7 +872,21 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp,
return 0;
}
-static struct audioreach_module *audioreach_find_widget(struct snd_soc_component *comp,
+static struct snd_ar_control *audioreach_find_widget(struct snd_soc_component *comp,
+ const char *name)
+{
+ struct q6apm *apm = dev_get_drvdata(comp->dev);
+ struct snd_ar_control *control;
+
+ list_for_each_entry(control, &apm->widget_list, node) {
+ if (control->w && !strcmp(name, control->w->name))
+ return control;
+ }
+
+ return NULL;
+}
+
+static struct audioreach_module *audioreach_find_module(struct snd_soc_component *comp,
const char *name)
{
struct q6apm *apm = dev_get_drvdata(comp->dev);
@@ -890,14 +904,41 @@ static struct audioreach_module *audioreach_find_widget(struct snd_soc_component
static int audioreach_route_load(struct snd_soc_component *scomp, int index,
struct snd_soc_dapm_route *route)
{
- struct audioreach_module *src, *sink;
-
- src = audioreach_find_widget(scomp, route->source);
- sink = audioreach_find_widget(scomp, route->sink);
+ struct audioreach_module *src_module, *sink_module;
+ struct snd_ar_control *control;
+ struct snd_soc_dapm_widget *w;
+ int i;
+
+ /* check if these are actual modules */
+ src_module = audioreach_find_module(scomp, route->source);
+ sink_module = audioreach_find_module(scomp, route->sink);
+
+ if (sink_module && !src_module) {
+ control = audioreach_find_widget(scomp, route->source);
+ if (control)
+ control->module_instance_id = sink_module->instance_id;
+
+ } else if (!sink_module && src_module && route->control) {
+ /* check if this is a virtual mixer */
+ control = audioreach_find_widget(scomp, route->sink);
+ if (!control || !control->w)
+ return 0;
+
+ w = control->w;
+
+ for (i = 0; i < w->num_kcontrols; i++) {
+ if (!strcmp(route->control, w->kcontrol_news[i].name)) {
+ struct soc_mixer_control *sm;
+ struct snd_soc_dobj *dobj;
+ struct snd_ar_control *scontrol;
+
+ sm = (struct soc_mixer_control *)w->kcontrol_news[i].private_value;
+ dobj = &sm->dobj;
+ scontrol = dobj->private;
+ scontrol->module_instance_id = src_module->instance_id;
+ }
+ }
- if (src && sink) {
- src->dst_mod_inst_id = sink->instance_id;
- sink->src_mod_inst_id = src->instance_id;
}
return 0;
@@ -928,6 +969,48 @@ static int audioreach_link_load(struct snd_soc_component *component, int index,
return 0;
}
+static void audioreach_connect_sub_graphs(struct q6apm *apm,
+ struct snd_ar_control *m1,
+ struct snd_ar_control *m2,
+ bool connect)
+{
+ struct audioreach_graph_info *info;
+
+ mutex_lock(&apm->lock);
+ info = idr_find(&apm->graph_info_idr, m2->graph_id);
+ mutex_unlock(&apm->lock);
+
+ if (connect) {
+ info->src_mod_inst_id = m1->module_instance_id;
+ info->src_mod_op_port_id = 1;
+ info->dst_mod_inst_id = m2->module_instance_id;
+ info->dst_mod_ip_port_id = 2;
+
+ } else {
+ info->src_mod_inst_id = 0;
+ info->src_mod_op_port_id = 0;
+ info->dst_mod_inst_id = 0;
+ info->dst_mod_ip_port_id = 0;
+ }
+}
+
+static bool audioreach_is_vmixer_connected(struct q6apm *apm,
+ struct snd_ar_control *m1,
+ struct snd_ar_control *m2)
+{
+ struct audioreach_graph_info *info;
+
+ mutex_lock(&apm->lock);
+ info = idr_find(&apm->graph_info_idr, m2->graph_id);
+ mutex_unlock(&apm->lock);
+
+ if (info->dst_mod_inst_id == m2->module_instance_id &&
+ info->src_mod_inst_id == m1->module_instance_id)
+ return true;
+
+ return false;
+}
+
static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -940,7 +1023,7 @@ static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol,
struct q6apm *data = dev_get_drvdata(c->dev);
bool connected;
- connected = q6apm_is_sub_graphs_connected(data, scontrol->sgid, dapm_scontrol->sgid);
+ connected = audioreach_is_vmixer_connected(data, scontrol, dapm_scontrol);
if (connected)
ucontrol->value.integer.value[0] = 1;
else
@@ -961,10 +1044,10 @@ static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol,
struct q6apm *data = dev_get_drvdata(c->dev);
if (ucontrol->value.integer.value[0]) {
- q6apm_connect_sub_graphs(data, scontrol->sgid, dapm_scontrol->sgid, true);
+ audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, true);
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, NULL);
} else {
- q6apm_connect_sub_graphs(data, scontrol->sgid, dapm_scontrol->sgid, false);
+ audioreach_connect_sub_graphs(data, scontrol, dapm_scontrol, false);
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, NULL);
}
return 0;