Browse Source

Merge "dsp: preload voice and copp topologies"

Linux Build Service Account 6 years ago
parent
commit
ec7e65b420
4 changed files with 192 additions and 0 deletions
  1. 65 0
      asoc/msm-pcm-routing-v2.c
  2. 69 0
      dsp/q6core.c
  3. 42 0
      dsp/q6voice.c
  4. 16 0
      include/dsp/q6core.h

+ 65 - 0
asoc/msm-pcm-routing-v2.c

@@ -150,6 +150,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;
@@ -1683,6 +1686,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);
@@ -1881,6 +1885,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",
@@ -19908,6 +19913,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,
@@ -20200,6 +20206,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)
 {
@@ -20665,6 +20725,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 - 0
dsp/q6core.c

@@ -291,6 +291,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__,
@@ -805,6 +816,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
  *

+ 42 - 0
dsp/q6voice.c

@@ -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;
 }

+ 16 - 0
include/dsp/q6core.h

@@ -168,8 +168,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__ */