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>
This commit is contained in:
Vikram Panduranga 2018-03-14 13:56:18 -07:00
parent 87f926a612
commit 6e55ad86b2
4 changed files with 193 additions and 1 deletions

View File

@ -147,6 +147,9 @@ static struct msm_pcm_route_bdai_name be_dai_name_table[MSM_BACKEND_DAI_MAX];
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 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
}
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 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
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 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream)
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 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx,
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 @@ static int msm_routing_set_cal(int32_t cal_type,
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;
}

View File

@ -184,6 +184,17 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
q6core_lcl.avcs_fwk_ver_resp_received = 1;
wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
break;
case AVCS_CMD_LOAD_TOPO_MODULES:
case AVCS_CMD_UNLOAD_TOPO_MODULES:
pr_debug("%s: Cmd = %s status[%s]\n",
__func__,
(payload1[0] == AVCS_CMD_LOAD_TOPO_MODULES) ?
"AVCS_CMD_LOAD_TOPO_MODULES" :
"AVCS_CMD_UNLOAD_TOPO_MODULES",
adsp_err_get_err_str(payload1[1]));
q6core_lcl.bus_bw_resp_received = 1;
wake_up(&q6core_lcl.bus_bw_req_wait);
break;
default:
pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
__func__,
@ -655,6 +666,64 @@ uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
}
EXPORT_SYMBOL(core_set_dolby_manufacturer_id);
int32_t q6core_load_unload_topo_modules(uint32_t topo_id,
bool preload_type)
{
struct avcs_cmd_load_unload_topo_modules load_unload_topo_modules;
int ret = 0;
mutex_lock(&(q6core_lcl.cmd_lock));
ocm_core_open();
if (q6core_lcl.core_handle_q == NULL) {
pr_err("%s: apr registration for CORE failed\n", __func__);
ret = -ENODEV;
goto done;
}
memset(&load_unload_topo_modules, 0, sizeof(load_unload_topo_modules));
load_unload_topo_modules.hdr.hdr_field =
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
load_unload_topo_modules.hdr.pkt_size =
sizeof(struct avcs_cmd_load_unload_topo_modules);
load_unload_topo_modules.hdr.src_port = 0;
load_unload_topo_modules.hdr.dest_port = 0;
load_unload_topo_modules.hdr.token = 0;
if (preload_type == CORE_LOAD_TOPOLOGY)
load_unload_topo_modules.hdr.opcode =
AVCS_CMD_LOAD_TOPO_MODULES;
else
load_unload_topo_modules.hdr.opcode =
AVCS_CMD_UNLOAD_TOPO_MODULES;
load_unload_topo_modules.topology_id = topo_id;
q6core_lcl.bus_bw_resp_received = 0;
ret = apr_send_pkt(q6core_lcl.core_handle_q,
(uint32_t *) &load_unload_topo_modules);
if (ret < 0) {
pr_err("%s: Load/unload topo modules failed for topology = %d ret = %d\n",
__func__, topo_id, ret);
ret = -EINVAL;
goto done;
}
ret = wait_event_timeout(q6core_lcl.bus_bw_req_wait,
(q6core_lcl.bus_bw_resp_received == 1),
msecs_to_jiffies(TIMEOUT_MS));
if (!ret) {
pr_err("%s: wait_event timeout for load/unload topo modules\n",
__func__);
ret = -ETIME;
goto done;
}
done:
mutex_unlock(&(q6core_lcl.cmd_lock));
return ret;
}
EXPORT_SYMBOL(q6core_load_unload_topo_modules);
/**
* q6core_is_adsp_ready - check adsp ready status
*

View File

@ -96,6 +96,8 @@ static int voice_send_cvp_channel_info_v2(struct voice_data *v,
uint32_t param_type);
static int voice_get_avcs_version_per_service(uint32_t service_id);
static void voice_load_topo_modules(int cal_index);
static void voice_unload_topo_modules(void);
static int voice_cvs_stop_playback(struct voice_data *v);
static int voice_cvs_start_playback(struct voice_data *v);
@ -2698,6 +2700,35 @@ done:
}
static void voice_load_topo_modules(int cal_index)
{
uint32_t topology_id;
int ret;
topology_id = voice_get_topology(cal_index);
ret = q6core_load_unload_topo_modules(topology_id, CORE_LOAD_TOPOLOGY);
if (ret < 0)
pr_debug("%s ret:%d load topo modules %d failed\n",
__func__, ret, topology_id);
}
static void voice_unload_topo_modules(void)
{
uint32_t topology_id;
int i, ret;
for (i = CVP_VOC_RX_TOPOLOGY_CAL; i <= CVP_VOC_TX_TOPOLOGY_CAL; i++) {
topology_id = voice_get_topology(i);
ret = q6core_load_unload_topo_modules(topology_id,
CORE_UNLOAD_TOPOLOGY);
if (ret < 0) {
pr_debug("%s ret:%d unload topo modules %d failed\n",
__func__, ret, topology_id);
}
}
}
static int voice_send_cvp_create_cmd(struct voice_data *v)
{
struct cvp_create_full_ctl_session_cmd cvp_session_cmd;
@ -5000,6 +5031,9 @@ static int voice_destroy_vocproc(struct voice_data *v)
voice_send_cvp_deregister_dev_cfg_cmd(v);
voice_send_cvs_deregister_cal_cmd(v);
/* Unload topology modules */
voice_unload_topo_modules();
/* destrop cvp session */
cvp_destroy_session_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@ -6728,6 +6762,9 @@ int voc_disable_device(uint32_t session_id)
voice_send_cvp_deregister_cal_cmd(v);
voice_send_cvp_deregister_dev_cfg_cmd(v);
/* Unload topology modules */
voice_unload_topo_modules();
v->voc_state = VOC_CHANGE;
} else {
pr_debug("%s: called in voc state=%d, No_OP\n",
@ -8721,6 +8758,11 @@ static int voice_set_cal(int32_t cal_type,
ret = -EINVAL;
goto done;
}
/* Pre-load if it is voice Rx or Tx topology */
if ((cal_index == CVP_VOC_RX_TOPOLOGY_CAL) ||
(cal_index == CVP_VOC_TX_TOPOLOGY_CAL)) {
voice_load_topo_modules(cal_index);
}
done:
return ret;
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -158,8 +158,24 @@ struct avcs_cmd_deregister_topologies {
#define AVCS_MODE_DEREGISTER_ALL_CUSTOM_TOPOLOGIES 2
#define AVCS_CMD_LOAD_TOPO_MODULES 0x0001296C
#define AVCS_CMD_UNLOAD_TOPO_MODULES 0x0001296D
#define CORE_LOAD_TOPOLOGY 0
#define CORE_UNLOAD_TOPOLOGY 1
struct avcs_cmd_load_unload_topo_modules {
struct apr_hdr hdr;
uint32_t topology_id;
} __packed;
int32_t core_set_license(uint32_t key, uint32_t module_id);
int32_t core_get_license_status(uint32_t module_id);
int32_t q6core_load_unload_topo_modules(uint32_t topology_id,
bool preload_type);
#endif /* __Q6CORE_H__ */