dsp: preload voice and copp topologies
Set topology info to q6core service in ADSP so that the
modules in a topology can be loaded before the usecase starts,
thus reducing usecase setup latency. The same topology is
unloaded before vocproc or copp is destroyed or replaced.
Change-Id: I5f8872130fb09f049e080c61edb8bb0b05e5e2de
Signed-off-by: Vikram Panduranga <vpandura@codeaurora.org>
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 5e82550..bd02392 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -147,6 +147,9 @@
static int msm_routing_send_device_pp_params(int port_id, int copp_idx,
int fe_id);
+static void msm_routing_load_topology(size_t data_size, void *data);
+static void msm_routing_unload_topology(uint32_t topology_id);
+
static int msm_routing_get_bit_width(unsigned int format)
{
int bit_width;
@@ -1547,6 +1550,7 @@
}
topology = adm_get_topology_for_port_copp_idx(
msm_bedais[i].port_id, idx);
+ msm_routing_unload_topology(topology);
adm_close(msm_bedais[i].port_id, fdai->perf_mode, idx);
pr_debug("%s:copp:%ld,idx bit fe:%d,type:%d,be:%d\n",
__func__, copp, fedai_id, session_type, i);
@@ -1745,6 +1749,7 @@
port_id = msm_bedais[reg].port_id;
topology = adm_get_topology_for_port_copp_idx(port_id,
idx);
+ msm_routing_unload_topology(topology);
adm_close(msm_bedais[reg].port_id, fdai->perf_mode,
idx);
pr_debug("%s: copp: %ld, reset idx bit fe:%d, type: %d, be:%d topology=0x%x\n",
@@ -16308,6 +16313,7 @@
port_id = bedai->port_id;
topology = adm_get_topology_for_port_copp_idx(port_id,
idx);
+ msm_routing_unload_topology(topology);
adm_close(bedai->port_id, fdai->perf_mode, idx);
pr_debug("%s: copp:%ld,idx bit fe:%d, type:%d,be:%d topology=0x%x\n",
__func__, copp, i, session_type, be_id,
@@ -16600,6 +16606,60 @@
return 0;
}
+static uint32_t msm_routing_get_topology(size_t data_size, void *data)
+{
+ uint32_t topology = NULL_COPP_TOPOLOGY;
+ void *cal_info = NULL;
+ uint32_t size = 0;
+
+ /* Retrieve cal_info size from cal data*/
+ size = data_size - sizeof(struct audio_cal_type_basic);
+ cal_info = kzalloc(size, GFP_KERNEL);
+
+ if (!cal_info)
+ goto done;
+
+ memcpy(cal_info,
+ ((uint8_t *)data + sizeof(struct audio_cal_type_basic)), size);
+
+ topology = ((struct audio_cal_info_adm_top *)cal_info)->topology;
+ kfree(cal_info);
+ cal_info = NULL;
+
+done:
+ pr_debug("%s: Using topology %d\n", __func__, topology);
+
+ return topology;
+}
+
+static void msm_routing_load_topology(size_t data_size, void *data)
+{
+ uint32_t topology_id;
+ int ret;
+
+ topology_id = msm_routing_get_topology(data_size, data);
+ if (topology_id != NULL_COPP_TOPOLOGY)
+ ret = q6core_load_unload_topo_modules(topology_id,
+ CORE_LOAD_TOPOLOGY);
+ if (ret < 0)
+ pr_debug("%s %d load topology failed\n",
+ __func__, topology_id);
+
+}
+
+static void msm_routing_unload_topology(uint32_t topology_id)
+{
+ int ret;
+
+ if (topology_id != NULL_COPP_TOPOLOGY)
+ ret = q6core_load_unload_topo_modules(topology_id,
+ CORE_UNLOAD_TOPOLOGY);
+ if (ret < 0)
+ pr_debug("%s %d unload topology failed\n",
+ __func__, topology_id);
+
+}
+
static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -17065,6 +17125,11 @@
ret = -EINVAL;
goto done;
}
+ /* Pre-load if it is ADM topology */
+ if ((cal_index == ADM_TOPOLOGY_CAL_TYPE_IDX) ||
+ (cal_index == ADM_LSM_TOPOLOGY_CAL_TYPE_IDX)) {
+ msm_routing_load_topology(data_size, data);
+ }
done:
return ret;
}