ASoC: msm: qdsp6: add support to query RMS during recording

Recorder app requires RMS value of the recording when using
tunnel mode AMR-WB encoding. Add mixer control so app can query
the RMS value from DSP

Change-Id: I84127ad35b916d257b0edee260141c34b92742f2
Signed-off-by: Jitendra Singh Naruka <jnaruk@codeaurora.org>
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 364de9a..88fcf61 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6924,6 +6924,11 @@
 /* Dolby DAP topology */
 #define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
 
+/* RMS value from DSP */
+#define RMS_MODULEID_APPI_PASSTHRU  0x10009011
+#define RMS_PARAM_FIRST_SAMPLE 0x10009012
+#define RMS_PAYLOAD_LEN 4
+
 struct afe_svc_cmd_set_clip_bank_selection {
 	struct apr_hdr hdr;
 	struct afe_svc_cmd_set_param param;
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 795bb99..e07f634 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,7 +32,7 @@
 int adm_open(int port, int path, int rate, int mode, int topology,
 				bool perf_mode, uint16_t bits_per_sample);
 
-int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
 			uint32_t params_length, char *params);
 
 int adm_dolby_dap_send_params(int port_id, char *params,
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index ca2afaf..cd08b39 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -557,7 +557,7 @@
 		return -ENOMEM;
 	}
 	if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
-		rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+		rc = adm_get_params(dolby_dap_params_get.port_id,
 						DOLBY_BUNDLE_MODULE_ID,
 						DOLBY_PARAM_ID_VER,
 						params_length +
@@ -575,7 +575,7 @@
 			params_length = (dolby_dap_params_length[i] +
 						DOLBY_PARAM_PAYLOAD_SIZE) *
 						sizeof(uint32_t);
-			rc = adm_dolby_dap_get_params(
+			rc = adm_get_params(
 						dolby_dap_params_get.port_id,
 						DOLBY_BUNDLE_MODULE_ID,
 						dolby_dap_params_id[i],
@@ -652,7 +652,7 @@
 	}
 	offset = 0;
 	params_length = length * sizeof(uint32_t);
-	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+	rc = adm_get_params(dolby_dap_params_states.port_id,
 					DOLBY_BUNDLE_MODULE_ID,
 					DOLBY_PARAM_ID_VCBG,
 					params_length + param_payload_len,
@@ -664,7 +664,7 @@
 	}
 
 	offset = length * sizeof(uint32_t);
-	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+	rc = adm_get_params(dolby_dap_params_states.port_id,
 					DOLBY_BUNDLE_MODULE_ID,
 					DOLBY_PARAM_ID_VCBE,
 					params_length + param_payload_len,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index d02713a..df28cee 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -30,6 +30,7 @@
 #include <sound/tlv.h>
 #include <sound/asound.h>
 #include <sound/pcm_params.h>
+#include <linux/slab.h>
 
 #include "msm-pcm-routing-v2.h"
 #include "msm-dolby-dap-config.h"
@@ -2526,6 +2527,49 @@
 	msm_routing_put_dolby_dap_endpoint_control),
 };
 
+int msm_routing_get_rms_value_control(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0;
+	char *param_value;
+	int *update_param_value;
+	uint32_t param_length = sizeof(uint32_t);
+	uint32_t param_payload_len = RMS_PAYLOAD_LEN * sizeof(uint32_t);
+	param_value = kzalloc(param_length, GFP_KERNEL);
+	if (!param_value) {
+		pr_err("%s, param memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	rc = adm_get_params(SLIMBUS_0_TX,
+			RMS_MODULEID_APPI_PASSTHRU,
+			RMS_PARAM_FIRST_SAMPLE,
+			param_length + param_payload_len,
+			param_value);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(param_value);
+		return -EINVAL;
+	}
+	update_param_value = (int *)param_value;
+	ucontrol->value.integer.value[0] = update_param_value[0];
+
+	pr_debug("%s: FROM DSP value[0] 0x%x\n",
+		__func__, update_param_value[0]);
+	kfree(param_value);
+	return 0;
+}
+
+int msm_routing_put_rms_value_control(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used */
+	return 0;
+}
+
+static const struct snd_kcontrol_new get_rms_controls[] = {
+	SOC_SINGLE_EXT("Get RMS", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, msm_routing_get_rms_value_control,
+	msm_routing_put_rms_value_control),
+};
+
 static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -3773,6 +3817,10 @@
 	snd_soc_add_platform_controls(platform,
 				ec_ref_rx_mixer_controls,
 			ARRAY_SIZE(ec_ref_rx_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				get_rms_controls,
+			ARRAY_SIZE(get_rms_controls));
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index a6ae357..df0fa6a 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -69,7 +69,7 @@
 						{0, 0, 0, 0, 0, 0, 0, 0}
 					      };
 
-static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+static int adm_get_parameters[ADM_GET_PARAMETER_LENGTH];
 
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
 {
@@ -333,10 +333,10 @@
 	return rc;
 }
 
-int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
-				uint32_t params_length, char *params)
+int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+		uint32_t params_length, char *params)
 {
-	struct adm_cmd_get_pp_params_v5	*adm_params = NULL;
+	struct adm_cmd_get_pp_params_v5 *adm_params = NULL;
 	int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
 	int *params_data = (int *)params;
 
@@ -345,17 +345,17 @@
 			__func__, index, port_id);
 		return -EINVAL;
 	}
-	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	sz = sizeof(struct adm_cmd_get_pp_params_v5) + params_length;
 	adm_params = kzalloc(sz, GFP_KERNEL);
 	if (!adm_params) {
 		pr_err("%s, adm params memory alloc failed", __func__);
 		return -ENOMEM;
 	}
 
-	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
-			params, params_length);
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_get_pp_params_v5)),
+		params, params_length);
 	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	adm_params->hdr.pkt_size = sz;
 	adm_params->hdr.src_svc = APR_SVC_ADM;
 	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
@@ -376,31 +376,33 @@
 	atomic_set(&this_adm.copp_stat[index], 0);
 	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
 	if (rc < 0) {
-		pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+		pr_err("%s: Failed to Get Params on port %d\n", __func__,
 			port_id);
 		rc = -EINVAL;
-		goto dolby_dap_get_param_return;
+		goto adm_get_param_return;
 	}
 	/* Wait for the callback with copp id */
 	rc = wait_event_timeout(this_adm.wait[index],
-			atomic_read(&this_adm.copp_stat[index]),
-			msecs_to_jiffies(TIMEOUT_MS));
+	atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
 	if (!rc) {
-		pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+		pr_err("%s: get params timed out port = %d\n", __func__,
 			port_id);
 		rc = -EINVAL;
-		goto dolby_dap_get_param_return;
+		goto adm_get_param_return;
 	}
 	if (params_data) {
-		for (i = 0; i < adm_dolby_get_parameters[0]; i++)
-			params_data[i] = adm_dolby_get_parameters[1+i];
+		for (i = 0; i < adm_get_parameters[0]; i++)
+			params_data[i] = adm_get_parameters[1+i];
 	}
 	rc = 0;
-dolby_dap_get_param_return:
+adm_get_param_return:
 	kfree(adm_params);
+
 	return rc;
 }
 
+
 static void adm_callback_debug_print(struct apr_client_data *data)
 {
 	uint32_t *payload;
@@ -574,11 +576,11 @@
 					__func__, payload[0]);
 			rtac_make_adm_callback(payload,
 				data->payload_size);
-			adm_dolby_get_parameters[0] = payload[3];
+			adm_get_parameters[0] = payload[3];
 			pr_debug("GET_PP PARAM:received parameter length: %x\n",
-					adm_dolby_get_parameters[0]);
+					adm_get_parameters[0]);
 			for (i = 0; i < payload[3]; i++)
-				adm_dolby_get_parameters[1+i] = payload[4+i];
+				adm_get_parameters[1+i] = payload[4+i];
 			atomic_set(&this_adm.copp_stat[index], 1);
 			wake_up(&this_adm.wait[index]);
 			break;