ASoC: wcd9xxx: Add Q6 support for AANC

Add AANC commands for Q6 Adaptive AANC algorithm. Read
the AANC calibration data from ACDB and send it to DSP.

Change-Id: I59be2ed8cf3667f118adfe5843be14012ccccc2a
Signed-off-by: Damir Didjusto <damird@codeaurora.org>
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index f88c817..f6f44a7 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6505,6 +6505,54 @@
 
 #define AFE_MAX_CDC_REGISTERS_TO_CONFIG			(20)
 
+/* AANC Port Config Specific */
+#define AFE_PARAM_ID_AANC_PORT_CONFIG			(0x00010215)
+#define AFE_API_VERSION_AANC_PORT_CONFIG		(0x1)
+#define AANC_TX_MIC_UNUSED				(0)
+#define AANC_TX_VOICE_MIC				(1)
+#define AANC_TX_ERROR_MIC				(2)
+#define AANC_TX_NOISE_MIC				(3)
+#define AFE_PORT_MAX_CHANNEL_CNT			(8)
+#define AFE_MODULE_AANC					(0x00010214)
+#define AFE_PARAM_ID_CDC_AANC_VERSION			(0x0001023A)
+#define AFE_API_VERSION_CDC_AANC_VERSION		(0x1)
+#define AANC_HW_BLOCK_VERSION_1				(1)
+#define AANC_HW_BLOCK_VERSION_2				(2)
+
+struct afe_param_aanc_port_cfg {
+	/* Minor version used for tracking the version of the module's
+	* source port configuration.
+	*/
+	uint32_t aanc_port_cfg_minor_version;
+
+	/* Sampling rate of the source Tx port. 8k - 192k*/
+	uint32_t tx_port_sample_rate;
+
+	/* Channel mapping for the Tx port signal carrying Noise (X),
+	* Error (E), and Voice (V) signals.
+	*/
+	uint8_t tx_port_channel_map[AFE_PORT_MAX_CHANNEL_CNT];
+
+	/* Number of channels on the source Tx port. */
+	uint16_t tx_port_num_channels;
+
+	/* Port ID of the Rx path reference signal. */
+	uint16_t rx_path_ref_port_id;
+
+	/* Sampling rate of the reference port. 8k - 192k*/
+	uint32_t ref_port_sample_rate;
+} __packed;
+
+struct afe_param_id_cdc_aanc_version {
+	/* Minor version used for tracking the version of the module's
+	* hw version
+	*/
+	uint32_t cdc_aanc_minor_version;
+
+	/* HW version. */
+	uint32_t aanc_hw_version;
+} __packed;
+
 /* ERROR CODES */
 /* Success. The operation completed with no errors. */
 #define ADSP_EOK          0x00000000
@@ -6736,6 +6784,7 @@
 	AFE_SLIMBUS_SLAVE_PORT_CONFIG,
 	AFE_SLIMBUS_SLAVE_CONFIG,
 	AFE_CDC_REGISTERS_CONFIG,
+	AFE_AANC_VERSION,
 	AFE_MAX_CONFIG_TYPES,
 };
 
@@ -6832,4 +6881,26 @@
 	struct afe_param_cdc_slimbus_slave_cfg sb_slave_cfg;
 } __packed;
 
+struct afe_svc_cmd_cdc_aanc_version {
+	struct apr_hdr hdr;
+	struct afe_svc_cmd_set_param param;
+	struct afe_port_param_data_v2 pdata;
+	struct afe_param_id_cdc_aanc_version version;
+} __packed;
+
+struct afe_port_cmd_set_aanc_param {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2 pdata;
+	union {
+		struct afe_param_aanc_port_cfg aanc_port_cfg;
+		struct afe_mod_enable_param    mod_enable;
+	} __packed data;
+} __packed;
+
+struct afe_port_cmd_set_aanc_acdb_table {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+} __packed;
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 22ddbbc..9c86e1d 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -127,6 +127,14 @@
 	uint32_t               mem_map_handle;
 };
 
+struct aanc_data {
+	bool aanc_active;
+	uint16_t aanc_rx_port;
+	uint16_t aanc_tx_port;
+	uint32_t aanc_rx_port_sample_rate;
+	uint32_t aanc_tx_port_sample_rate;
+};
+
 int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
 int afe_close(int port_id);
 int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
@@ -188,4 +196,5 @@
 int afe_set_config(enum afe_config_type config_type, void *config_data,
 		   int arg);
 
+void afe_set_aanc_info(struct aanc_data *aanc_info);
 #endif /* __Q6AFE_V2_H__ */
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index 3551e66..3c644ed 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -19,6 +19,7 @@
 enum {
 	RX_CAL,
 	TX_CAL,
+	AANC_TX_CAL,
 	MAX_AUDPROC_TYPES
 };
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 819512d..594d753 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -56,6 +56,7 @@
 static int fm_pcmrx_switch_enable;
 static int srs_alsa_ctrl_ever_called;
 static int lsm_mux_slim_port;
+static int slim0_rx_aanc_fb_port;
 
 enum {
 	MADNONE,
@@ -865,6 +866,42 @@
 	return afe_port_set_mad_type(port_id, mad_type);
 }
 
+static int msm_routing_slim_0_rx_aanc_mux_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+
+	mutex_lock(&routing_lock);
+	ucontrol->value.integer.value[0] = slim0_rx_aanc_fb_port;
+	mutex_unlock(&routing_lock);
+	pr_debug("%s: AANC Mux Port %ld\n", __func__,
+		ucontrol->value.integer.value[0]);
+	return 0;
+};
+
+static int msm_routing_slim_0_rx_aanc_mux_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct aanc_data aanc_info;
+
+	mutex_lock(&routing_lock);
+	memset(&aanc_info, 0x00, sizeof(aanc_info));
+	pr_debug("%s: AANC Mux Port %ld\n", __func__,
+		ucontrol->value.integer.value[0]);
+	slim0_rx_aanc_fb_port = ucontrol->value.integer.value[0];
+	if (ucontrol->value.integer.value[0] == 0) {
+		aanc_info.aanc_active = false;
+		aanc_info.aanc_tx_port = 0;
+		aanc_info.aanc_rx_port = 0;
+	} else {
+		aanc_info.aanc_active = true;
+		aanc_info.aanc_rx_port = SLIMBUS_0_RX;
+		aanc_info.aanc_tx_port =
+			(SLIMBUS_0_RX - 1 + (slim0_rx_aanc_fb_port * 2));
+	}
+	afe_set_aanc_info(&aanc_info);
+	mutex_unlock(&routing_lock);
+	return 0;
+};
 static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1895,6 +1932,21 @@
 		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
 };
 
+static const char * const aanc_slim_0_rx_text[] = {
+	"ZERO", "SLIMBUS_0_TX", "SLIMBUS_1_TX", "SLIMBUS_2_TX", "SLIMBUS_3_TX",
+	"SLIMBUS_4_TX", "SLIMBUS_5_TX", "SLIMBUS_6_TX"
+};
+
+static const struct soc_enum aanc_slim_0_rx_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(aanc_slim_0_rx_text),
+				aanc_slim_0_rx_text);
+
+static const struct snd_kcontrol_new aanc_slim_0_rx_mux[] = {
+	SOC_DAPM_ENUM_EXT("AANC_SLIM_0_RX MUX", aanc_slim_0_rx_enum,
+		msm_routing_slim_0_rx_aanc_mux_get,
+		msm_routing_slim_0_rx_aanc_mux_put)
+};
+
 static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
@@ -2348,6 +2400,8 @@
 
 	/* Mux Definitions */
 	SND_SOC_DAPM_MUX("LSM1 MUX", SND_SOC_NOPM, 0, 0, &lsm_mux),
+	SND_SOC_DAPM_MUX("SLIM_0_RX AANC MUX", SND_SOC_NOPM, 0, 0,
+			aanc_slim_0_rx_mux),
 
 	/* Mixer definitions */
 	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -3002,6 +3056,10 @@
 
 	snd_soc_add_platform_controls(platform, lsm_function,
 				      ARRAY_SIZE(lsm_function));
+
+	snd_soc_add_platform_controls(platform,
+				aanc_slim_0_rx_mux,
+				ARRAY_SIZE(aanc_slim_0_rx_mux));
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 97cd3fc..7bb5401 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -45,6 +45,8 @@
 	u16 dtmf_gen_rx_portid;
 	struct afe_spkr_prot_calib_get_resp calib_data;
 	int vi_tx_port;
+	uint32_t afe_sample_rates[AFE_MAX_PORTS];
+	struct aanc_data aanc_info;
 };
 
 static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
@@ -57,6 +59,21 @@
 #define SIZEOF_CFG_CMD(y) \
 		(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
 
+void afe_set_aanc_info(struct aanc_data *q6_aanc_info)
+{
+	pr_debug("%s\n", __func__);
+
+	this_afe.aanc_info.aanc_active = q6_aanc_info->aanc_active;
+	this_afe.aanc_info.aanc_rx_port = q6_aanc_info->aanc_rx_port;
+	this_afe.aanc_info.aanc_tx_port = q6_aanc_info->aanc_tx_port;
+
+	pr_debug("aanc active is %d rx port is %d, tx port is %d\n",
+		this_afe.aanc_info.aanc_active,
+		this_afe.aanc_info.aanc_rx_port,
+		this_afe.aanc_info.aanc_tx_port);
+}
+
+
 static int32_t afe_callback(struct apr_client_data *data, void *priv)
 {
 	if (!data) {
@@ -342,7 +359,12 @@
 	struct afe_audioif_config_command_no_payload	afe_cal;
 	pr_debug("%s: path %d\n", __func__, path);
 
-	get_afe_cal(path, &cal_block);
+	if (path == AANC_TX_CAL) {
+		get_aanc_cal(&cal_block);
+	} else {
+		get_afe_cal(path, &cal_block);
+	}
+
 	if (cal_block.cal_size <= 0) {
 		pr_debug("%s: No AFE cal to send!\n", __func__);
 		goto done;
@@ -738,6 +760,166 @@
 	pr_debug("%s: leave %d\n", __func__, ret);
 	return ret;
 }
+static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port)
+{
+	struct afe_port_cmd_set_aanc_param cfg;
+	int ret = 0;
+	int index = 0;
+
+	pr_debug("%s: tx_port %d, rx_port %d\n",
+		__func__, tx_port, rx_port);
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0)
+		return -EINVAL;
+
+	index = q6audio_get_port_index(tx_port);
+	if (q6audio_validate_port(tx_port) < 0) {
+		pr_err("%s: port id: %#x\n", __func__, tx_port);
+		return -EINVAL;
+	}
+
+	cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	cfg.hdr.pkt_size = sizeof(cfg);
+	cfg.hdr.src_port = 0;
+	cfg.hdr.dest_port = 0;
+	cfg.hdr.token = index;
+	cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+
+	cfg.param.port_id = tx_port;
+	cfg.param.payload_size        = sizeof(struct afe_port_param_data_v2) +
+					sizeof(struct afe_param_aanc_port_cfg);
+	cfg.param.payload_address_lsw     = 0;
+	cfg.param.payload_address_msw     = 0;
+	cfg.param.mem_map_handle	  = 0;
+
+	cfg.pdata.module_id = AFE_MODULE_AANC;
+	cfg.pdata.param_id    = AFE_PARAM_ID_AANC_PORT_CONFIG;
+	cfg.pdata.param_size = sizeof(struct afe_param_aanc_port_cfg);
+	cfg.pdata.reserved    = 0;
+
+	cfg.data.aanc_port_cfg.aanc_port_cfg_minor_version =
+		AFE_API_VERSION_AANC_PORT_CONFIG;
+	cfg.data.aanc_port_cfg.tx_port_sample_rate =
+		this_afe.aanc_info.aanc_tx_port_sample_rate;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[0] = AANC_TX_VOICE_MIC;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[1] = AANC_TX_NOISE_MIC;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[2] = AANC_TX_ERROR_MIC;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[3] = AANC_TX_MIC_UNUSED;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[4] = AANC_TX_MIC_UNUSED;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[5] = AANC_TX_MIC_UNUSED;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[6] = AANC_TX_MIC_UNUSED;
+	cfg.data.aanc_port_cfg.tx_port_channel_map[7] = AANC_TX_MIC_UNUSED;
+	cfg.data.aanc_port_cfg.tx_port_num_channels = 3;
+	cfg.data.aanc_port_cfg.rx_path_ref_port_id = rx_port;
+	cfg.data.aanc_port_cfg.ref_port_sample_rate =
+		 this_afe.aanc_info.aanc_rx_port_sample_rate;
+
+	ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
+	if (ret) {
+		pr_err("%s: AFE AANC port config failed for tx_port %d, rx_port %d\n",
+			__func__, tx_port, rx_port);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+	}
+
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
+static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable)
+{
+	struct afe_port_cmd_set_aanc_param cfg;
+	int ret = 0;
+	int index = 0;
+
+	pr_debug("%s: tx_port %d\n",
+		__func__, tx_port);
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0)
+		return -EINVAL;
+
+	index = q6audio_get_port_index(tx_port);
+	if (q6audio_validate_port(tx_port) < 0) {
+		pr_err("%s: port id: %#x\n", __func__, tx_port);
+		return -EINVAL;
+	}
+
+	cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	cfg.hdr.pkt_size = sizeof(cfg);
+	cfg.hdr.src_port = 0;
+	cfg.hdr.dest_port = 0;
+	cfg.hdr.token = index;
+	cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+
+	cfg.param.port_id = tx_port;
+	cfg.param.payload_size        = sizeof(struct afe_port_param_data_v2) +
+					sizeof(struct afe_mod_enable_param);
+	cfg.param.payload_address_lsw     = 0;
+	cfg.param.payload_address_lsw     = 0;
+	cfg.param.mem_map_handle          = 0;
+
+	cfg.pdata.module_id = AFE_MODULE_AANC;
+	cfg.pdata.param_id    = AFE_PARAM_ID_ENABLE;
+	cfg.pdata.param_size = sizeof(struct afe_mod_enable_param);
+	cfg.pdata.reserved    = 0;
+
+	cfg.data.mod_enable.enable = enable;
+	cfg.data.mod_enable.reserved = 0;
+
+	ret = afe_apr_send_pkt((uint32_t *) &cfg, &this_afe.wait[index]);
+	if (ret) {
+		pr_err("%s: AFE AANC enable failed for tx_port %d\n",
+			__func__, tx_port);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+	}
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
+int afe_send_aanc_version(
+	struct afe_param_id_cdc_aanc_version *version_cfg)
+{
+	int ret;
+	struct afe_svc_cmd_cdc_aanc_version config;
+
+	pr_debug("%s: enter\n", __func__);
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = IDX_GLOBAL_CFG;
+	config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
+
+	config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
+				sizeof(struct afe_param_id_cdc_aanc_version);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+
+	config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
+	config.pdata.param_id = AFE_PARAM_ID_CDC_AANC_VERSION;
+	config.pdata.param_size =
+		sizeof(struct afe_param_id_cdc_aanc_version);
+	config.version = *version_cfg;
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret) {
+		pr_err("%s: AFE_PARAM_ID_CDC_AANC_VERSION failed %d\n",
+		__func__, ret);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+	ret = -EINVAL;
+	}
+	pr_debug("%s: leave ret %d\n", __func__, 0);
+	return ret;
+}
 
 int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
 {
@@ -790,6 +972,9 @@
 	case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
 		ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
 		break;
+	case AFE_AANC_VERSION:
+		ret = afe_send_aanc_version(config_data);
+		break;
 	default:
 		pr_err("%s: unknown configuration type", __func__);
 		ret = -EINVAL;
@@ -837,6 +1022,24 @@
 	return ret;
 }
 
+static int afe_aanc_start(uint16_t tx_port_id, uint16_t rx_port_id)
+{
+	int ret;
+
+	pr_debug("%s Tx port is %d, Rx port is %d\n",
+		 __func__, tx_port_id, rx_port_id);
+	ret = afe_aanc_port_cfg(this_afe.apr, tx_port_id, rx_port_id);
+	if (ret) {
+		pr_err("%s Send AANC Port Config failed %d\n",
+			__func__, ret);
+		goto fail_cmd;
+	}
+	afe_send_cal_block(AANC_TX_CAL, tx_port_id);
+
+fail_cmd:
+	return ret;
+}
+
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate) /* This function is no blocking */
 {
@@ -845,6 +1048,7 @@
 	int cfg_type;
 	int index = 0;
 	enum afe_mad_type mad_type;
+	uint16_t port_index;
 
 	if (!afe_config) {
 		pr_err("%s: Error, no configuration data\n", __func__);
@@ -886,6 +1090,22 @@
 		}
 	}
 
+	if ((this_afe.aanc_info.aanc_active) &&
+	    (this_afe.aanc_info.aanc_tx_port == port_id)) {
+		this_afe.aanc_info.aanc_tx_port_sample_rate = rate;
+		port_index =
+			afe_get_port_index(this_afe.aanc_info.aanc_rx_port);
+		if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
+			this_afe.aanc_info.aanc_rx_port_sample_rate =
+				this_afe.afe_sample_rates[port_index];
+		} else {
+			ret = -EINVAL;
+			goto fail_cmd;
+		}
+		ret = afe_aanc_start(this_afe.aanc_info.aanc_tx_port,
+				this_afe.aanc_info.aanc_rx_port);
+		pr_debug("%s afe_aanc_start ret %d\n", __func__, ret);
+	}
 	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	config.hdr.pkt_size = sizeof(config);
@@ -974,6 +1194,14 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
+
+	port_index = afe_get_port_index(port_id);
+	if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
+		this_afe.afe_sample_rates[port_index] = rate;
+	} else {
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
 	return afe_send_cmd_port_start(port_id);
 
 fail_cmd:
@@ -2392,6 +2620,7 @@
 	enum afe_mad_type mad_type;
 	int ret = 0;
 	int index = 0;
+	uint16_t port_index;
 
 	if (this_afe.apr == NULL) {
 		pr_err("AFE is already closed\n");
@@ -2422,6 +2651,23 @@
 		pr_debug("%s: Not a MAD port\n", __func__);
 	}
 
+	port_index = afe_get_port_index(port_id);
+	if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
+		this_afe.afe_sample_rates[port_index] = 0;
+	} else {
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if ((port_id == this_afe.aanc_info.aanc_tx_port) &&
+	    (this_afe.aanc_info.aanc_active)) {
+		memset(&this_afe.aanc_info, 0x00, sizeof(this_afe.aanc_info));
+		ret = afe_aanc_mod_enable(this_afe.apr, port_id, 0);
+		if (ret)
+			pr_err("%s: AFE mod disable failed %d\n",
+				__func__, ret);
+	}
+
 	stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	stop.hdr.pkt_size = sizeof(stop);