Browse Source

Merge "asoc: msm-lsm-client: add support for shared buffer DAM module"

qctecmdr 5 years ago
parent
commit
805c422306
3 changed files with 158 additions and 3 deletions
  1. 72 1
      asoc/msm-lsm-client.c
  2. 80 0
      dsp/q6lsm.c
  3. 6 2
      include/dsp/q6lsm.h

+ 72 - 1
asoc/msm-lsm-client.c

@@ -2425,6 +2425,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct lsm_priv *prtd;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	int ret = 0;
 
 	pr_debug("%s\n", __func__);
@@ -2488,6 +2489,8 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
 	prtd->lsm_client->perf_mode = 0;
 	prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE;
 	prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY;
+	prtd->lsm_client->fe_id = rtd->dai_link->id;
+	prtd->lsm_client->unprocessed_data = 0;
 
 	return 0;
 }
@@ -2958,13 +2961,81 @@ static int msm_lsm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+static int msm_lsm_afe_data_ctl_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	u64 fe_id = kcontrol->private_value;
+	uint16_t afe_data_format = 0;
+	int ret = 0;
+
+	afe_data_format = ucontrol->value.integer.value[0];
+	pr_debug("%s: afe data is %s\n", __func__,
+		 afe_data_format ? "unprocessed" : "processed");
+
+	ret = q6lsm_set_afe_data_format(fe_id, afe_data_format);
+	if (ret)
+		pr_err("%s: q6lsm_set_afe_data_format failed, ret = %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static int msm_lsm_afe_data_ctl_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	u64 fe_id = kcontrol->private_value;
+	uint16_t afe_data_format = 0;
+	int ret = 0;
+
+	q6lsm_get_afe_data_format(fe_id, &afe_data_format);
+	ucontrol->value.integer.value[0] = afe_data_format;
+	pr_debug("%s: afe data is %s\n", __func__,
+		 afe_data_format ? "unprocessed" : "processed");
+
+	return ret;
+}
+
+static int msm_lsm_add_afe_data_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_pcm *pcm = rtd->pcm;
+	struct snd_pcm_usr *afe_data_info;
+	struct snd_kcontrol *kctl;
+	const char *mixer_ctl_name	= "Listen Stream";
+	const char *deviceNo		= "NN";
+	const char *suffix		= "Unprocessed Data";
+	int ctl_len, ret = 0;
+
+	ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
+		  strlen(suffix) + 1;
+	pr_debug("%s: Adding Listen afe data cntrls\n", __func__);
+	ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				   NULL, 1, ctl_len, rtd->dai_link->id,
+				   &afe_data_info);
+	if (ret < 0) {
+		pr_err("%s: Adding Listen afe data cntrls failed: %d\n",
+		       __func__, ret);
+		return ret;
+	}
+	kctl = afe_data_info->kctl;
+	snprintf(kctl->id.name, ctl_len, "%s %d %s",
+		 mixer_ctl_name, rtd->pcm->device, suffix);
+	kctl->put = msm_lsm_afe_data_ctl_put;
+	kctl->get = msm_lsm_afe_data_ctl_get;
+
+	return 0;
+}
+
 static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd)
 {
 	int ret = 0;
 
 	ret = msm_lsm_add_app_type_controls(rtd);
 	if (ret)
-		pr_err("%s, add  app type controls failed:%d\n", __func__, ret);
+		pr_err("%s, add app type controls failed:%d\n", __func__, ret);
+
+	ret = msm_lsm_add_afe_data_controls(rtd);
+	if (ret)
+		pr_err("%s, add afe data controls failed:%d\n", __func__, ret);
 
 	return ret;
 }

+ 80 - 0
dsp/q6lsm.c

@@ -89,6 +89,13 @@ static int q6lsm_memory_map_regions(struct lsm_client *client,
 static int q6lsm_memory_unmap_regions(struct lsm_client *client,
 				      uint32_t handle);
 
+struct lsm_client_afe_data {
+	uint64_t fe_id;
+	uint16_t unprocessed_data;
+};
+
+static struct lsm_client_afe_data lsm_client_afe_data[LSM_MAX_SESSION_ID + 1];
+
 static int q6lsm_get_session_id_from_lsm_client(struct lsm_client *client)
 {
 	int n;
@@ -255,6 +262,8 @@ static void q6lsm_session_free(struct lsm_client *client)
 	pr_debug("%s: Freeing session ID %d\n", __func__, client->session);
 	spin_lock_irqsave(&lsm_session_lock, flags);
 	lsm_session[client->session] = NULL;
+	lsm_client_afe_data[client->session].fe_id = 0;
+	lsm_client_afe_data[client->session].unprocessed_data = 0;
 	spin_unlock_irqrestore(&lsm_session_lock, flags);
 	client->session = LSM_INVALID_SESSION_ID;
 }
@@ -1062,6 +1071,72 @@ int get_lsm_port(void)
 	return lsm_afe_port;
 }
 
+/**
+ * q6lsm_set_afe_data_format -
+ * command to set afe data format
+ *
+ * @fe_id: FrontEnd DAI link ID
+ * @afe_data_format: afe data format
+ *
+ * Returns 0 on success or -EINVAL on failure
+ */
+int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format)
+{
+	int n = 0;
+
+	if (0 != afe_data_format && 1 != afe_data_format)
+		goto done;
+
+	pr_debug("%s: afe data is %s\n", __func__,
+		 afe_data_format ? "unprocessed" : "processed");
+
+	for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) {
+		if (0 == lsm_client_afe_data[n].fe_id) {
+			lsm_client_afe_data[n].fe_id = fe_id;
+			lsm_client_afe_data[n].unprocessed_data =
+							afe_data_format;
+			pr_debug("%s: session ID is %d, fe_id is %d\n",
+				 __func__, n, fe_id);
+			return 0;
+		}
+	}
+
+	pr_err("%s: all lsm sessions are taken\n", __func__);
+done:
+	return -EINVAL;
+}
+EXPORT_SYMBOL(q6lsm_set_afe_data_format);
+
+/**
+ * q6lsm_get_afe_data_format -
+ * command to get afe data format
+ *
+ * @fe_id: FrontEnd DAI link ID
+ * @afe_data_format: afe data format
+ *
+ */
+void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format)
+{
+	int n = 0;
+
+	if (NULL == afe_data_format) {
+		pr_err("%s: Pointer afe_data_format is NULL\n", __func__);
+		return;
+	}
+
+	for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) {
+		if (fe_id == lsm_client_afe_data[n].fe_id) {
+			*afe_data_format =
+				lsm_client_afe_data[n].unprocessed_data;
+			pr_debug("%s: session: %d, fe_id: %d, afe data: %s\n",
+				__func__, n, fe_id,
+				*afe_data_format ? "unprocessed" : "processed");
+			return;
+		}
+	}
+}
+EXPORT_SYMBOL(q6lsm_get_afe_data_format);
+
 /**
  * q6lsm_set_port_connected -
  *       command to set LSM port connected
@@ -1092,14 +1167,19 @@ int q6lsm_set_port_connected(struct lsm_client *client)
 	connectport_hdr.param_size = sizeof(connect_port);
 
 	client->connect_to_port = get_lsm_port();
+	if (ADM_LSM_PORT_ID != client->connect_to_port)
+		q6lsm_get_afe_data_format(client->fe_id,
+					  &client->unprocessed_data);
 	connect_port.minor_version = QLSM_PARAM_ID_MINOR_VERSION;
 	connect_port.port_id = client->connect_to_port;
+	connect_port.unprocessed_data = client->unprocessed_data;
 
 	rc = q6lsm_pack_and_set_params(client, &connectport_hdr,
 				       (uint8_t *) &connect_port,
 				       set_param_opcode);
 	if (rc)
 		pr_err("%s: Failed set_params, rc %d\n", __func__, rc);
+
 	return rc;
 }
 EXPORT_SYMBOL(q6lsm_set_port_connected);

+ 6 - 2
include/dsp/q6lsm.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
  */
 #ifndef __Q6LSM_H__
 #define __Q6LSM_H__
@@ -102,6 +102,8 @@ struct lsm_client {
 	uint32_t	event_type;
 	uint32_t	num_stages;
 	struct lsm_stage_config	stage_cfg[LSM_MAX_STAGES_PER_SESSION];
+	uint64_t	fe_id;
+	uint16_t	unprocessed_data;
 };
 
 struct lsm_stream_cmd_open_tx {
@@ -159,7 +161,7 @@ struct lsm_param_connect_to_port {
 	uint32_t	minor_version;
 	/* AFE port id that receives voice wake up data */
 	uint16_t	port_id;
-	uint16_t	reserved;
+	uint16_t	unprocessed_data;
 } __packed;
 
 struct lsm_param_poll_enable {
@@ -295,4 +297,6 @@ int q6lsm_set_media_fmt_v2_params(struct lsm_client *client);
 int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map,
 		struct lsm_params_info_v2 *p_info);
 bool q6lsm_adsp_supports_multi_stage_detection(void);
+int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format);
+void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format);
 #endif /* __Q6LSM_H__ */