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:
parent
87f926a612
commit
6e55ad86b2
@ -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;
|
||||
}
|
||||
|
69
dsp/q6core.c
69
dsp/q6core.c
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user