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;