From b61865d95c7d74150694edf66d11cae3862af64c Mon Sep 17 00:00:00 2001
From: Prabhu Annabathula <prabhu.annabathula@motorola.com>
Date: Thu, 25 Sep 2014 20:32:14 -0500
Subject: [PATCH] ASoC msm: add controls for motorola audio effects appi module

Module used for Loudspeaker Quality Optimizations and Bass Enhancement

Change-Id: I20299f789840380e962c6d35935cd1194576aa3a
Signed-off-by: Prabhu Annabathula <prabhu.annabathula@motorola.com>
---
 include/sound/apr_audio-v2.h                  |  15 +++
 include/sound/q6asm-v2.h                      |   2 +
 include/uapi/sound/audio_effects.h            |  28 +++++
 .../soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c |  59 +++++++++
 .../soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h |   5 +
 sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c    | 112 +++++++++++++++++-
 sound/soc/msm/qdsp6v2/msm-qti-pp-config.c     |  93 ++++++++++++++-
 sound/soc/msm/qdsp6v2/q6asm.c                 |  48 ++++++++
 8 files changed, 357 insertions(+), 5 deletions(-)

diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index f281d54fc027..ed1f80c501f6 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -5045,6 +5045,21 @@ struct Audio_AigParam {
 
 } __packed;
 
+#define AUDPROC_MODULE_ID_MMIFX				(0x1000E0B0)
+#define AUDPROC_PARAM_ID_MMIFX_ENABLE (0x1000E3B0)
+#define AUDPROC_PARAM_ID_MMIFX_PRESET (0x1000E3A0)
+#define AUDPROC_PARAM_ID_MMIFX_TABLE (0x1000E300)
+#define AUDPROC_PARAM_ID_MMIFX_DEVICE (0x1000E310)
+
+struct asm_mmfx_enable_config {
+	struct apr_hdr	hdr;
+	struct asm_stream_cmd_set_pp_params_v2 param;
+	struct asm_stream_param_data_v2 data;
+	uint32_t                  enable_flag;
+/*< Specifies whether mmfx eq is disabled (0) or enabled (nonzero).*/
+
+} __packed;
+
 
 #define ADM_MODULE_ID_EANS                            0x00010C4A
 #define ADM_PARAM_ID_EANS_ENABLE                      0x00010C4B
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 95621de24932..66823366c31e 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -422,4 +422,6 @@ int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples,
 int q6asm_stream_send_meta_data(struct audio_client *ac, uint32_t stream_id,
 		uint32_t initial_samples, uint32_t trailing_samples);
 
+int q6asm_mmfxeq(struct audio_client *ac, uint32_t enable);
+
 #endif /* __Q6_ASM_H__ */
diff --git a/include/uapi/sound/audio_effects.h b/include/uapi/sound/audio_effects.h
index 4071a6e37b6d..0c0ae45328e9 100644
--- a/include/uapi/sound/audio_effects.h
+++ b/include/uapi/sound/audio_effects.h
@@ -280,4 +280,32 @@ struct eq_params {
 	uint32_t freq_millihertz;
 };
 
+#define MMIFX_EQ_MODULE		0x00005000
+#define MMIFX_EQ_ENABLE			0x00005001
+#define MMIFX_EQ_PRESET			0x00005020
+#define MMIFX_EQ_DEVICE			0x00005300
+
+
+
+#define MMIFX_ENABLE_PARAM_LEN 1
+#define MMIFX_ENABLE_PARAM_SZ	\
+			(MMIFX_ENABLE_PARAM_LEN*sizeof(uint32_t))
+#define MMIFX_PARAM_LEN 1
+#define MMIFX_PRESET_PARAM_SZ	\
+			(MMIFX_PARAM_LEN*sizeof(uint32_t))
+#define MMIFX_PARAM_TABLE_LEN 2000
+#define MMIFX_PARAM_TABLE_SZ	\
+			(MMIFX_PARAM_TABLE_LEN*sizeof(uint16_t))
+#define MMIFX_DEVICE_PARAM_SZ	\
+			(MMIFX_PARAM_LEN*sizeof(uint32_t))
+
+
+struct mmi_eq_params {
+	uint32_t device;
+	uint32_t enable_flag;
+	uint32_t preset;
+};
+
+
 #endif /*_MSM_AUDIO_EFFECTS_H*/
+
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
index 5e4d9d3209c9..7efde8bbe83a 100644
--- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
@@ -719,3 +719,62 @@ invalid_config:
 	kfree(params);
 	return rc;
 }
+
+int msm_audio_effects_mmifx_send_eq_params(struct audio_client *ac,
+					struct mmi_eq_params *mmifx, uint32_t cmds)
+{
+	char *params;
+	int *updt_params;
+	uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+
+	pr_debug("%s\n", __func__);
+	if (!ac) {
+		pr_err("%s: cannot set audio effects\n", __func__);
+		return -EINVAL;
+	}
+	params = kzalloc(params_length, GFP_KERNEL);
+	if (!params) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+
+	}
+	updt_params = (int *)params;
+	params_length = 0;
+
+	if ((cmds & MMIFX_EQ_ENABLE) == MMIFX_EQ_ENABLE) {
+		pr_debug("%s: MMIFX_EQ_ENABLE %d\n", __func__, mmifx->enable_flag);
+		*updt_params++ = AUDPROC_MODULE_ID_MMIFX;
+		*updt_params++ = AUDPROC_PARAM_ID_MMIFX_ENABLE;
+		*updt_params++ = MMIFX_ENABLE_PARAM_SZ;
+		*updt_params++ = mmifx->enable_flag;
+		params_length += COMMAND_PAYLOAD_SZ +
+						MMIFX_ENABLE_PARAM_SZ;
+	}
+
+	if ((cmds & MMIFX_EQ_PRESET) == MMIFX_EQ_PRESET) {
+		pr_debug("%s: MMIFX_EQ_PRESET %d\n", __func__, mmifx->preset);
+		*updt_params++ = AUDPROC_MODULE_ID_MMIFX;
+		*updt_params++ = AUDPROC_PARAM_ID_MMIFX_ENABLE;
+		*updt_params++ = MMIFX_ENABLE_PARAM_SZ;
+		*updt_params++ = mmifx->preset;
+		params_length += COMMAND_PAYLOAD_SZ +
+						MMIFX_ENABLE_PARAM_SZ;
+	}
+
+	if ((cmds & MMIFX_EQ_DEVICE) == MMIFX_EQ_DEVICE) {
+		pr_debug("%s: MMIFX_EQ_DEVICE %d\n", __func__, mmifx->device);
+		*updt_params++ = AUDPROC_MODULE_ID_MMIFX;
+		*updt_params++ = AUDPROC_PARAM_ID_MMIFX_ENABLE;
+		*updt_params++ = MMIFX_ENABLE_PARAM_SZ;
+		*updt_params++ = mmifx->device;
+		params_length += COMMAND_PAYLOAD_SZ +
+						MMIFX_ENABLE_PARAM_SZ;
+	}
+
+	if (params_length)
+		q6asm_send_audio_effects_params(ac, params,
+						params_length);
+
+	kfree(params);
+	return 0;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h
index 3d2e6d4065c4..687a2b22d12d 100644
--- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h
@@ -30,4 +30,9 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac,
 int msm_audio_effects_popless_eq_handler(struct audio_client *ac,
 					 struct eq_params *eq,
 					 long *values);
+int msm_audio_effects_mmifx_eq_handler(struct audio_client *ac,
+					struct mmi_eq_params *mmifx,
+					long *values);
+int msm_audio_effects_mmifx_send_eq_params(struct audio_client *ac,
+					struct mmi_eq_params *mmifx, uint32_t cmds);
 #endif /*_MSM_AUDIO_EFFECTS_H*/
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index ad0479706324..060b0e1e2af1 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -162,6 +162,14 @@ struct msm_compr_audio_effects {
 	struct eq_params equalizer;
 };
 
+struct mmi_eq_vals {
+	struct mmi_eq_params eq_params;
+	uint32_t num_cmds;
+	uint32_t cmds;
+};
+
+struct mmi_eq_vals mmifx[MSM_FRONTEND_DAI_MAX];
+
 struct msm_compr_dec_params {
 	struct snd_dec_ddp ddp_params;
 };
@@ -734,7 +742,8 @@ static int msm_compr_open(struct snd_compr_stream *cstream)
 	prtd->cstream = cstream;
 	pdata->cstream[rtd->dai_link->be_id] = cstream;
 	pdata->audio_effects[rtd->dai_link->be_id] =
-		 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
+		kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
+
 	if (!pdata->audio_effects[rtd->dai_link->be_id]) {
 		pr_err("%s: Could not allocate memory for effects\n", __func__);
 		pdata->cstream[rtd->dai_link->be_id] = NULL;
@@ -1119,6 +1128,15 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 		if (rc)
 			pr_err("%s : Set Volume failed : %d\n",
 				__func__, rc);
+
+		if (mmifx[fe_id].cmds != 0) {
+			pr_debug("%s: Update MMIFX EQ Module params send\n", __func__);
+			msm_audio_effects_mmifx_send_eq_params(prtd->audio_client,
+								&(mmifx[fe_id].eq_params),
+								mmifx[fe_id].cmds);
+			mmifx[fe_id].cmds = 0;
+		}
+
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		spin_lock_irqsave(&prtd->lock, flags);
@@ -1793,6 +1811,70 @@ static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int msm_audio_effects_mmifx_params(struct mmi_eq_vals *mmifx_eq,
+					long *values)
+{
+	int devices = *values++;
+	int num_commands = *values++;
+	uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+	int rc = 0;
+	int i;
+	struct mmi_eq_params *mmifx = &(mmifx_eq->eq_params);
+
+	pr_debug("%s: device: %d num commands %d\n", __func__, devices, num_commands);
+	mmifx_eq->num_cmds = num_commands;
+	params_length = 0;
+	for (i = 0; i < num_commands; i++) {
+		uint32_t command_id = *values++;
+		/*command_config_state */
+		uint32_t command_config_state = *values++;
+		uint32_t index_offset = *values++;
+		uint32_t length = *values++;
+		switch (command_id) {
+		case MMIFX_EQ_ENABLE:
+			pr_debug("%s: MMIFX_EQ_ENABLE\n", __func__);
+			if (length != 1 || index_offset != 0) {
+				pr_err("no valid params\n");
+				rc = -EINVAL;
+				goto invalid_config;
+			}
+			mmifx->enable_flag = *values++;
+			mmifx_eq->cmds |= command_id;
+			break;
+		case MMIFX_EQ_DEVICE:
+			pr_debug("%s: MMIFX_DEVICE\n", __func__);
+			if (length != 1 || index_offset != 0) {
+				pr_err("no valid params\n");
+				rc = -EINVAL;
+				goto invalid_config;
+			}
+			if (command_config_state == CONFIG_SET) {
+				mmifx->device = devices;
+				mmifx_eq->cmds |= command_id;
+			}
+			break;
+		case MMIFX_EQ_PRESET:
+			pr_debug("%s: MMIFX_EQ_PRESET\n", __func__);
+			if (length != 1 || index_offset != 0) {
+				pr_err("no valid params\n");
+				rc = -EINVAL;
+				goto invalid_config;
+			}
+			if (command_config_state == CONFIG_SET) {
+				mmifx->preset= *values++;
+				mmifx_eq->cmds |= command_id;
+			}
+			break;
+		default:
+			pr_err("%s: Invalid command to set config\n", __func__);
+			break;
+		}
+	}
+
+invalid_config:
+	return rc;
+}
+
 static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
 					   struct snd_ctl_elem_value *ucontrol)
 {
@@ -1807,6 +1889,7 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
 	int effects_module;
 
 	pr_debug("%s\n", __func__);
+	effects_module = *values++;
 	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
 		pr_err("%s Received out of bounds fe_id %lu\n",
 			__func__, fe_id);
@@ -1814,13 +1897,23 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
 	}
 	cstream = pdata->cstream[fe_id];
 	audio_effects = pdata->audio_effects[fe_id];
-	if (!cstream || !audio_effects) {
-		pr_err("%s: stream or effects inactive\n", __func__);
+	if (!cstream || !audio_effects || !cstream->runtime) {
+		pr_err("%s: stream or effects inactive %ld\n", __func__, fe_id);
+		if (effects_module == MMIFX_EQ_MODULE)
+			/* update mmfx params, will be set when compr
+			 * session is started
+			 */
+			msm_audio_effects_mmifx_params(&(mmifx[fe_id]),
+						     values);
 		return -EINVAL;
 	}
+
 	prtd = cstream->runtime->private_data;
 	if (!prtd) {
 		pr_err("%s: cannot set audio effects\n", __func__);
+		if (effects_module == MMIFX_EQ_MODULE)
+			msm_audio_effects_mmifx_params(&(mmifx[fe_id]),
+						     values);
 		return -EINVAL;
 	}
 	if (prtd->compr_passthr != LEGACY_PCM) {
@@ -1831,7 +1924,7 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
 		pr_debug("%s: Effects supported for compr_type[%d]\n",
 			 __func__, prtd->compr_passthr);
 	}
-	effects_module = *values++;
+
 	switch (effects_module) {
 	case VIRTUALIZER_MODULE:
 		pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
@@ -1857,6 +1950,17 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
 						    &(audio_effects->equalizer),
 						     values);
 		break;
+	case MMIFX_EQ_MODULE:
+		pr_debug("%s: MMIFX EQ Module\n", __func__);
+		msm_audio_effects_mmifx_params(&(mmifx[fe_id]),
+						     values);
+		if (atomic_read(&prtd->start)) {
+			msm_audio_effects_mmifx_send_eq_params(prtd->audio_client,
+							   &(mmifx[fe_id].eq_params),
+								mmifx[fe_id].cmds);
+			mmifx[fe_id].cmds = 0;
+		}
+		break;
 	default:
 		pr_err("%s Invalid effects config module\n", __func__);
 		return -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
index 9bff9b113daa..d1ab17975b91 100644
--- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
@@ -62,6 +62,8 @@ struct msm_audio_eq_stream_config {
 
 struct msm_audio_eq_stream_config	eq_data[MAX_EQ_SESSIONS];
 
+static uint32_t mmfx_enable[MAX_EQ_SESSIONS];
+
 static void msm_qti_pp_send_eq_values_(int eq_idx)
 {
 	int result;
@@ -88,6 +90,32 @@ done:
 	return;
 }
 
+static void msm_pcm_mmfx_enable_send(int eq_idx)
+{
+	int result;
+	struct msm_pcm_routing_fdai_data fe_dai;
+	int fe_dai_perf_mode;
+	struct audio_client *ac = NULL;
+
+	msm_pcm_routing_get_fedai_info(eq_idx, SESSION_TYPE_RX, &fe_dai,
+				       &fe_dai_perf_mode);
+	ac = q6asm_get_audio_client(fe_dai.strm_id);
+
+	if (ac == NULL) {
+		pr_err("%s: Could not get audio client for session: %d\n",
+		      __func__, fe_dai.strm_id);
+		goto done;
+	}
+
+	result = q6asm_mmfxeq(ac, mmfx_enable[eq_idx]);
+
+	if (result < 0)
+		pr_err("%s: Call to ASM equalizer failed, returned = %d\n",
+		      __func__, result);
+done:
+	return;
+}
+
 static int msm_qti_pp_get_eq_enable_mixer(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_value *ucontrol)
 {
@@ -116,8 +144,47 @@ static int msm_qti_pp_put_eq_enable_mixer(struct snd_kcontrol *kcontrol,
 	pr_debug("%s: EQ #%d enable %d\n", __func__,
 		eq_idx, value);
 	eq_data[eq_idx].enable = value;
+
+	msm_pcm_routing_acquire_lock();
+	msm_pcm_mmfx_enable_send(eq_idx);
+	msm_pcm_routing_release_lock();
+	return 0;
+}
+
+static int msm_qti_pp_get_mmfx_eq_enable_mixer(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	if ((eq_idx < 0) || (eq_idx >= MAX_EQ_SESSIONS)) {
+		pr_debug("%s : return einval\n", __func__);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = mmfx_enable[eq_idx];
+
+	pr_debug("%s: EQ #%d enable %d\n", __func__,
+		eq_idx, mmfx_enable[eq_idx]);
+	return 0;
+}
+
+static int msm_qti_pp_put_mmfx_eq_enable_mixer(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	pr_debug("%s: enter EQ #%d enable %d\n", __func__,
+		eq_idx, value);
+	if ((eq_idx < 0) || (eq_idx >= MAX_EQ_SESSIONS))
+		return -EINVAL;
+	pr_debug("%s: EQ #%d enable %d\n", __func__,
+		eq_idx, value);
+	mmfx_enable[eq_idx] = value;
 	msm_pcm_routing_acquire_lock();
-	msm_qti_pp_send_eq_values_(eq_idx);
+	msm_pcm_mmfx_enable_send(eq_idx);
+
 	msm_pcm_routing_release_lock();
 	return 0;
 }
@@ -222,6 +289,13 @@ void msm_qti_pp_send_eq_values(int fedai_id)
 		msm_qti_pp_send_eq_values_(fedai_id);
 }
 
+
+void msm_qti_pp_mmfx_eq_send_eq_values(int fedai_id)
+{
+	if (eq_data[fedai_id].enable)
+		msm_qti_pp_send_eq_values_(fedai_id);
+}
+
 /* CUSTOM MIXING */
 int msm_qti_pp_send_stereo_to_custom_stereo_cmd(int port_id,
 						unsigned int session_id,
@@ -510,6 +584,19 @@ static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	msm_qti_pp_put_eq_enable_mixer),
 };
 
+
+static const struct snd_kcontrol_new mmfx_eq_enable_mixer_controls[] = {
+	SOC_SINGLE_EXT("MMFX MultiMedia1 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_qti_pp_get_mmfx_eq_enable_mixer,
+	msm_qti_pp_put_mmfx_eq_enable_mixer),
+	SOC_SINGLE_EXT("MMFX MultiMedia2 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_qti_pp_get_mmfx_eq_enable_mixer,
+	msm_qti_pp_put_mmfx_eq_enable_mixer),
+	SOC_SINGLE_EXT("MMFX MultiMedia3 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_qti_pp_get_mmfx_eq_enable_mixer,
+	msm_qti_pp_put_mmfx_eq_enable_mixer),
+};
+
 static const struct snd_kcontrol_new eq_band_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Band Count", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 11, 0,
@@ -657,6 +744,10 @@ void msm_qti_pp_add_controls(struct snd_soc_platform *platform)
 	snd_soc_add_platform_controls(platform, eq_enable_mixer_controls,
 			ARRAY_SIZE(eq_enable_mixer_controls));
 
+
+	snd_soc_add_platform_controls(platform, mmfx_eq_enable_mixer_controls,
+			ARRAY_SIZE(mmfx_eq_enable_mixer_controls));
+
 	snd_soc_add_platform_controls(platform, eq_band_mixer_controls,
 			ARRAY_SIZE(eq_band_mixer_controls));
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 194ec99dbdfc..eaf644eac2e9 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -3695,6 +3695,54 @@ fail_cmd:
 	return rc;
 }
 
+int q6asm_mmfxeq(struct audio_client *ac, uint32_t enable)
+{
+	struct asm_mmfx_enable_config cfg;
+	int sz = 0;
+	int rc  = 0;
+
+	if (!ac || ac->apr == NULL) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	pr_info("%s: value %d\n", __func__, enable);
+	sz = sizeof(struct asm_mmfx_enable_config);
+	q6asm_add_hdr_async(ac, &cfg.hdr, sz, TRUE);
+	atomic_set(&ac->cmd_state, 1);
+	cfg.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
+	cfg.param.data_payload_addr_lsw = 0;
+	cfg.param.data_payload_addr_msw = 0;
+	cfg.param.mem_map_handle = 0;
+	cfg.param.data_payload_size = sizeof(cfg) -
+				sizeof(cfg.hdr) - sizeof(cfg.param);
+	cfg.data.module_id = AUDPROC_MODULE_ID_MMIFX;
+	cfg.data.param_id = AUDPROC_PARAM_ID_MMIFX_ENABLE;
+	cfg.data.param_size = cfg.param.data_payload_size - sizeof(cfg.data);
+	cfg.data.reserved = 0;
+	cfg.enable_flag = enable;
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &cfg);
+	if (rc < 0) {
+		pr_err("%s: set-params send failed paramid[0x%x]\n", __func__,
+						cfg.data.param_id);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
+						cfg.data.param_id);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = 0;
+fail_cmd:
+	return rc;
+}
+
 int q6asm_set_softpause(struct audio_client *ac,
 			struct asm_softpause_params *pause_param)
 {
-- 
GitLab