obj->prop_id_port.max_op_port = module->max_op_port;
}
-struct audioreach_module *audioreach_get_container_last_module(
- struct audioreach_container *container)
-{
- struct audioreach_module *module;
-
- list_for_each_entry(module, &container->modules_list, node) {
- if (module->dst_mod_inst_id == 0)
- return module;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(audioreach_get_container_last_module);
-
-static bool is_module_in_container(struct audioreach_container *container, int module_iid)
-{
- struct audioreach_module *module;
-
- list_for_each_entry(module, &container->modules_list, node) {
- if (module->instance_id == module_iid)
- return true;
- }
-
- return false;
-}
-
-struct audioreach_module *audioreach_get_container_first_module(
- struct audioreach_container *container)
-{
- struct audioreach_module *module;
-
- /* get the first module from both connected or un-connected containers */
- list_for_each_entry(module, &container->modules_list, node) {
- if (module->src_mod_inst_id == 0 ||
- !is_module_in_container(container, module->src_mod_inst_id))
- return module;
- }
- return NULL;
-}
-EXPORT_SYMBOL_GPL(audioreach_get_container_first_module);
-
-struct audioreach_module *audioreach_get_container_next_module(
- struct audioreach_container *container,
- struct audioreach_module *module)
-{
- int nmodule_iid = module->dst_mod_inst_id;
- struct audioreach_module *nmodule;
-
- list_for_each_entry(nmodule, &container->modules_list, node) {
- if (nmodule->instance_id == nmodule_iid)
- return nmodule;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(audioreach_get_container_next_module);
-
static void apm_populate_module_list_obj(struct apm_mod_list_obj *obj,
struct audioreach_container *container,
int sub_graph_id)
obj->container_id = container->container_id;
obj->num_modules = container->num_modules;
i = 0;
- list_for_each_container_module(module, container) {
+ list_for_each_entry(module, &container->modules_list, node) {
obj->mod_cfg[i].module_id = module->module_id;
obj->mod_cfg[i].instance_id = module->instance_id;
i++;
}
}
-static void audioreach_populate_graph(struct apm_graph_open_params *open,
+static void audioreach_populate_graph(struct q6apm *apm, struct audioreach_graph_info *info,
+ struct apm_graph_open_params *open,
struct list_head *sg_list,
int num_sub_graphs)
{
mlobj = &ml_data->mod_list_obj[0];
+
+ if (info->dst_mod_inst_id && info->src_mod_inst_id) {
+ conn_obj = &mc_data->conn_obj[nconn];
+ conn_obj->src_mod_inst_id = info->src_mod_inst_id;
+ conn_obj->src_mod_op_port_id = info->src_mod_op_port_id;
+ conn_obj->dst_mod_inst_id = info->dst_mod_inst_id;
+ conn_obj->dst_mod_ip_port_id = info->dst_mod_ip_port_id;
+ nconn++;
+ }
+
list_for_each_entry(sg, sg_list, node) {
struct apm_sub_graph_data *sg_cfg = &sg_data->sg_cfg[i++];
apm_populate_container_config(cobj, container);
apm_populate_module_list_obj(mlobj, container, sg->sub_graph_id);
- list_for_each_container_module(module, container) {
+ list_for_each_entry(module, &container->modules_list, node) {
uint32_t src_mod_inst_id;
src_mod_inst_id = module->src_mod_inst_id;
}
}
-void *audioreach_alloc_graph_pkt(struct q6apm *apm, struct list_head *sg_list, int graph_id)
+void *audioreach_alloc_graph_pkt(struct q6apm *apm, struct audioreach_graph_info *info)
{
int payload_size, sg_sz, cont_sz, ml_sz, mp_sz, mc_sz;
struct apm_module_param_data *param_data;
struct audioreach_module *module;
struct audioreach_sub_graph *sgs;
struct apm_mod_list_obj *mlobj;
+ struct list_head *sg_list;
int num_modules_per_list;
int num_connections = 0;
int num_containers = 0;
struct gpr_pkt *pkt;
void *p;
+ sg_list = &info->sg_list;
+ ml_sz = 0;
+
+ /* add FE-BE connections */
+ if (info->dst_mod_inst_id && info->src_mod_inst_id)
+ num_connections++;
+
list_for_each_entry(sgs, sg_list, node) {
num_sub_graphs++;
list_for_each_entry(container, &sgs->container_list, node) {
num_containers++;
num_modules += container->num_modules;
- list_for_each_container_module(module, container) {
+ list_for_each_entry(module, &container->modules_list, node) {
if (module->src_mod_inst_id)
num_connections++;
}
params.mod_conn_list_data->num_connections = num_connections;
p += mc_sz;
- audioreach_populate_graph(¶ms, sg_list, num_sub_graphs);
+ audioreach_populate_graph(apm, info, ¶ms, sg_list, num_sub_graphs);
return pkt;
}
int id;
uint32_t num_sub_graphs;
struct list_head sg_list;
+ /* DPCM connection from FE Graph to BE graph */
+ uint32_t src_mod_inst_id;
+ uint32_t src_mod_op_port_id;
+ uint32_t dst_mod_inst_id;
+ uint32_t dst_mod_ip_port_id;
};
struct audioreach_sub_graph {
void *audioreach_alloc_pkt(int payload_size, uint32_t opcode,
uint32_t token, uint32_t src_port,
uint32_t dest_port);
-void *audioreach_alloc_graph_pkt(struct q6apm *apm,
- struct list_head *sg_list,
- int graph_id);
+void *audioreach_alloc_graph_pkt(struct q6apm *apm, struct audioreach_graph_info
+ *info);
/* Topology specific */
int audioreach_tplg_init(struct snd_soc_component *component);
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph);
int audioreach_gain_set_vol_ctrl(struct q6apm *apm,
struct audioreach_module *module, int vol);
-struct audioreach_module *audioreach_get_container_last_module(
- struct audioreach_container *container);
-struct audioreach_module *audioreach_get_container_first_module(
- struct audioreach_container *container);
-struct audioreach_module *audioreach_get_container_next_module(
- struct audioreach_container *container,
- struct audioreach_module *module);
-#define list_for_each_container_module(mod, cont) \
- for (mod = audioreach_get_container_first_module(cont); mod != NULL; \
- mod = audioreach_get_container_next_module(cont, mod))
#endif /* __AUDIOREACH_H__ */
graph->info = info;
graph->id = graph_id;
- graph->graph = audioreach_alloc_graph_pkt(apm, &info->sg_list, graph_id);
+ graph->graph = audioreach_alloc_graph_pkt(apm, info);
if (IS_ERR(graph->graph)) {
void *err = graph->graph;
return NULL;
}
-static struct audioreach_module *q6apm_graph_get_last_module(struct q6apm *apm, u32 sgid)
-{
- struct audioreach_container *container;
- struct audioreach_module *module;
- struct audioreach_sub_graph *sg;
-
- mutex_lock(&apm->lock);
- sg = idr_find(&apm->sub_graphs_idr, sgid);
- mutex_unlock(&apm->lock);
- if (!sg)
- return NULL;
-
- container = list_last_entry(&sg->container_list, struct audioreach_container, node);
- module = audioreach_get_container_last_module(container);
-
- return module;
-}
-
-static struct audioreach_module *q6apm_graph_get_first_module(struct q6apm *apm, u32 sgid)
-{
- struct audioreach_container *container;
- struct audioreach_module *module;
- struct audioreach_sub_graph *sg;
-
- mutex_lock(&apm->lock);
- sg = idr_find(&apm->sub_graphs_idr, sgid);
- mutex_unlock(&apm->lock);
- if (!sg)
- return NULL;
-
- container = list_first_entry(&sg->container_list, struct audioreach_container, node);
- module = audioreach_get_container_first_module(container);
-
- return module;
-}
-
-bool q6apm_is_sub_graphs_connected(struct q6apm *apm, u32 src_sgid, u32 dst_sgid)
-{
- struct audioreach_module *module;
- u32 iid;
-
- module = q6apm_graph_get_last_module(apm, src_sgid);
- if (!module)
- return false;
-
- iid = module->instance_id;
- module = q6apm_graph_get_first_module(apm, dst_sgid);
- if (!module)
- return false;
-
- if (module->src_mod_inst_id == iid)
- return true;
-
- return false;
-}
-
-int q6apm_connect_sub_graphs(struct q6apm *apm, u32 src_sgid, u32 dst_sgid, bool connect)
-{
- struct audioreach_module *module;
- u32 iid;
-
- if (connect) {
- module = q6apm_graph_get_last_module(apm, src_sgid);
- if (!module)
- return -ENODEV;
-
- iid = module->instance_id;
- } else {
- iid = 0;
- }
-
- module = q6apm_graph_get_first_module(apm, dst_sgid);
- if (!module)
- return -ENODEV;
-
- /* set src module in dst subgraph first module */
- module->src_mod_inst_id = iid;
-
- return 0;
-}
-
int q6apm_graph_media_format_shmem(struct q6apm_graph *graph,
struct audioreach_module_config *cfg)
{
/* Callback for graph specific */
struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph,
uint32_t mid);
-
void q6apm_set_fe_dai_ops(struct snd_soc_dai_driver *dai_drv);
-int q6apm_connect_sub_graphs(struct q6apm *apm, u32 src_sgid, u32 dst_sgid,
- bool connect);
-bool q6apm_is_sub_graphs_connected(struct q6apm *apm, u32 src_sgid,
- u32 dst_sgid);
int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph);
#endif /* __APM_GRAPH_ */
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);
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;
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)
{
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
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;