msm: audio: qdsp5: Add support of dynamic re-enable of post proc

DSP can disable the post processing features due to unavailability
of MIPS during video playback. As a result difference in audio
quality is observed after video playback. Add support to re-enable
the post processing features once video playback ends and MIPS are
available.
DSP sends a message whenever post processing features are disabled
due to unavailability of MIPS and sends another message once the
MIPS are available. AUDPP driver broadcasts these messages to all
the relavant clients which keeps track of disabled features and
re-enables them when re-enable message is received from DSP.

Change-Id: Ic4cad4e7b0afe4377006055417ba193b01cce930
Signed-off-by: Sriranjan Srikantam <cssrika@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
index de30c65..93b77f4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -15,7 +15,7 @@
 EXTERNALIZED FUNCTIONS
   None
 
-Copyright(c) 1992-2009, 2012 Code Aurora Forum. All rights reserved.
+Copyright(c) 1992-2009, 2012-2013 The Linux Foundation. All rights reserved.
 
 This software is licensed under the terms of the GNU General Public
 License version 2, as published by the Free Software Foundation, and
@@ -1071,6 +1071,9 @@
 } __packed;
 #define AUDPP_CMD_SAMPLING_FREQUENCY	7
 #define AUDPP_CMD_QRUMBLE		9
+#define AUDPP_CMD_SRS			18
+#define AUDPP_DISABLE_FEATS_LSW		2
+#define AUDPP_DISABLE_FEATS_MSW		3
 
 #endif /* QDSP5AUDPPCMDI_H */
 
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
index fef4c35..664e246 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
@@ -2,29 +2,29 @@
 #define QDSP5AUDPPMSG_H
 
 /*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-*
-*       Q D S P 5  A U D I O   P O S T   P R O C E S S I N G   M S G
-*
-* GENERAL DESCRIPTION
-*   Messages sent by AUDPPTASK to ARM
-*
-* REFERENCES
-*   None
-*
-* EXTERNALIZED FUNCTIONS
-*   None
-*
-* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
+
+       Q D S P 5  A U D I O   P O S T   P R O C E S S I N G   M S G
+
+ GENERAL DESCRIPTION
+   Messages sent by AUDPPTASK to ARM
+
+ REFERENCES
+   None
+
+ EXTERNALIZED FUNCTIONS
+   None
+
+ Copyright (c) 1992-2009, 2012-2013 The Linux Foundation. All rights reserved.
+
+ This software is licensed under the terms of the GNU General Public
+ License version 2, as published by the Free Software Foundation, and
+ may be copied, distributed, and modified under those terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
 *====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
 /*===========================================================================
 
@@ -319,4 +319,18 @@
 #define ADSP_MESSAGE_ID 0xFFFF
 
 #define AUDPP_MSG_FEAT_QUERY_DM_DONE 0x000b
+
+/*
+ * ADSP sends this message when a PP feature is disabled
+ * due to ADSP resource limitation.
+ */
+#define AUDPP_MSG_PP_DISABLE_FEEDBACK 0x000C
+
+/*
+ * This message is sent by ADSP if any PP features is disabled
+ * due to video and audio concurrency due to MIPS limitation and
+ * the video session is ended in ADSP.
+ */
+#define AUDPP_MSG_PP_FEATS_RE_ENABLE 0x000D
+
 #endif /* QDSP5AUDPPMSG_H */
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index 681b41c..7819395 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -97,11 +97,13 @@
 	u32 device_cb_compl;
 	u32 audpp_cb_compl;
 	u32 preproc_cb_compl;
+	u32 audpp_cb_reenable_compl;
 	u8 preproc_stream_id;
 	u8 audrec_applied;
 	u32 multiple_sessions;
 	u32 cur_tx_session;
 	struct acdb_result acdb_result;
+	uint32_t audpp_disabled_features;
 
 	spinlock_t dsp_lock;
 	int dec_id;
@@ -1550,6 +1552,40 @@
 	return result;
 }
 
+static s32 acdb_re_enable_audpp(void)
+{
+	s32	result = 0;
+
+	if ((acdb_data.audpp_disabled_features &
+			(1 << AUDPP_CMD_IIR_TUNING_FILTER))
+			== (1 << AUDPP_CMD_IIR_TUNING_FILTER)) {
+		result = audpp_dsp_set_rx_iir(COMMON_OBJ_ID,
+				acdb_data.pp_iir->active_flag,
+				acdb_data.pp_iir);
+		if (result) {
+			MM_ERR("ACDB=> Failed to send IIR data to postproc\n");
+			result = -EINVAL;
+		} else {
+			MM_DBG("Re-enable IIR parameters");
+		}
+	}
+	if ((acdb_data.audpp_disabled_features & (1 << AUDPP_CMD_MBADRC))
+			== (1 << AUDPP_CMD_MBADRC)) {
+		result = audpp_dsp_set_mbadrc(COMMON_OBJ_ID,
+				acdb_data.pp_mbadrc->enable,
+				acdb_data.pp_mbadrc);
+		if (result) {
+			MM_ERR("ACDB=> Failed to send MBADRC data to"\
+					" postproc\n");
+			result = -EINVAL;
+		} else {
+			MM_DBG("Re-enable MBADRC parameters");
+		}
+	}
+	acdb_data.audpp_disabled_features = 0;
+	return result;
+}
+
 static struct acdb_agc_block *get_audpreproc_agc_block(void)
 {
 	struct header *prs_hdr;
@@ -2311,6 +2347,22 @@
 static void audpp_cb(void *private, u32 id, u16 *msg)
 {
 	MM_DBG("\n");
+
+	if (id == AUDPP_MSG_PP_DISABLE_FEEDBACK) {
+		acdb_data.audpp_disabled_features |=
+			((uint32_t)(msg[AUDPP_DISABLE_FEATS_MSW] << 16) |
+			 msg[AUDPP_DISABLE_FEATS_LSW]);
+		MM_INFO("AUDPP disable feedback: %x",
+				acdb_data.audpp_disabled_features);
+		goto done;
+	} else if (id == AUDPP_MSG_PP_FEATS_RE_ENABLE) {
+		MM_INFO("AUDPP re-enable messaage: %x",
+				acdb_data.audpp_disabled_features);
+		acdb_data.audpp_cb_reenable_compl = 1;
+		wake_up(&acdb_data.wait);
+		return;
+	}
+
 	if (id != AUDPP_MSG_CFG_MSG)
 		goto done;
 
@@ -2504,6 +2556,7 @@
 		wait_event_interruptible(acdb_data.wait,
 					(acdb_data.device_cb_compl
 					| acdb_data.audpp_cb_compl
+					| acdb_data.audpp_cb_reenable_compl
 					| acdb_data.preproc_cb_compl));
 		mutex_lock(&acdb_data.acdb_mutex);
 		if (acdb_data.device_cb_compl) {
@@ -2534,6 +2587,11 @@
 			if (acdb_data.device_info->dev_type.tx_device)
 				handle_tx_device_ready_callback();
 			else {
+				if (acdb_data.audpp_cb_reenable_compl) {
+					MM_INFO("Reset disabled feature flag");
+					acdb_data.audpp_disabled_features = 0;
+					acdb_data.audpp_cb_reenable_compl = 0;
+				}
 				acdb_cache_rx.node_status =\
 						ACDB_VALUES_FILLED;
 				if (acdb_data.acdb_state &
@@ -2546,6 +2604,7 @@
 		}
 
 		if (!(acdb_data.audpp_cb_compl ||
+				acdb_data.audpp_cb_reenable_compl ||
 				acdb_data.preproc_cb_compl)) {
 			MM_DBG("need to wait for either AUDPP / AUDPREPROC "\
 					"Event\n");
@@ -2554,10 +2613,21 @@
 		} else {
 			MM_DBG("got audpp / preproc call back\n");
 			if (acdb_data.audpp_cb_compl) {
+				if (acdb_data.audpp_cb_reenable_compl) {
+					MM_INFO("Reset disabled feature flag");
+					acdb_data.audpp_disabled_features = 0;
+					acdb_data.audpp_cb_reenable_compl = 0;
+				}
 				send_acdb_values_for_active_devices();
 				acdb_data.audpp_cb_compl = 0;
 				mutex_unlock(&acdb_data.acdb_mutex);
 				continue;
+			} else if (acdb_data.audpp_cb_reenable_compl) {
+				acdb_re_enable_audpp();
+				acdb_data.audpp_disabled_features = 0;
+				acdb_data.audpp_cb_reenable_compl = 0;
+				mutex_unlock(&acdb_data.acdb_mutex);
+				continue;
 			} else {
 				result = handle_audpreproc_cb();
 				if (result < 0) {
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index ceb73f0..07f9f4c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -189,6 +189,8 @@
 	int srs_needs_commit;
 	int srs_feature_mask;
 	audpp_cmd_cfg_object_params_qconcert qconcert_plus;
+	int srs_current_feature_mask;
+	uint32_t audpp_disabled_features;
 
 	int status;
 	int opened;
@@ -298,12 +300,75 @@
 		return;
 	}
 
-	if (AUDPP_MSG_CFG_MSG == id && msg[0] == AUDPP_MSG_ENA_DIS)
+	if (AUDPP_MSG_CFG_MSG == id && msg[0] == AUDPP_MSG_ENA_DIS) {
+		audio_copp->audpp_disabled_features = 0;
 		return;
+	}
+	if (AUDPP_MSG_CFG_MSG == id && msg[0] == AUDPP_MSG_ENA_ENA)
+		audio_copp->audpp_disabled_features = 0;
 
 	if (!audio_copp->status)
 		return;
 
+	if (id == AUDPP_MSG_PP_DISABLE_FEEDBACK) {
+		audio_copp->audpp_disabled_features |=
+			((uint32_t)(msg[AUDPP_DISABLE_FEATS_MSW] << 16) |
+			 msg[AUDPP_DISABLE_FEATS_LSW]);
+		MM_DBG("AUDPP disable feedback: %x",
+				audio_copp->audpp_disabled_features);
+		return;
+	} else if (id == AUDPP_MSG_PP_FEATS_RE_ENABLE) {
+		MM_DBG("AUDPP re-enable messaage: %x, acdb_enabled %d",
+			audio_copp->audpp_disabled_features, is_acdb_enabled());
+		if (!is_acdb_enabled()) {
+			if ((audio_copp->audpp_disabled_features &
+				(1 << AUDPP_CMD_MBADRC)) ==
+				(1 << AUDPP_CMD_MBADRC)) {
+				audpp_dsp_set_mbadrc(COMMON_OBJ_ID,
+						audio_copp->mbadrc_enable,
+						&audio_copp->mbadrc);
+			}
+			if ((audio_copp->audpp_disabled_features &
+				(1 << AUDPP_CMD_EQUALIZER)) ==
+				(1 << AUDPP_CMD_EQUALIZER)) {
+				audpp_dsp_set_eq(COMMON_OBJ_ID,
+						audio_copp->eq_enable,
+						&audio_copp->eq);
+			}
+			if ((audio_copp->audpp_disabled_features &
+				(1 << AUDPP_CMD_IIR_TUNING_FILTER)) ==
+				(1 << AUDPP_CMD_IIR_TUNING_FILTER)) {
+				audpp_dsp_set_rx_iir(COMMON_OBJ_ID,
+						audio_copp->rx_iir_enable,
+						&audio_copp->iir);
+			}
+			if ((audio_copp->audpp_disabled_features &
+				(1 << AUDPP_CMD_QCONCERT)) ==
+					(1 << AUDPP_CMD_QCONCERT)) {
+				audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
+					audio_copp->qconcert_plus_enable,
+					&audio_copp->qconcert_plus);
+			}
+		}
+		if ((audio_copp->audpp_disabled_features & (1 << AUDPP_CMD_SRS))
+			== (1 << AUDPP_CMD_SRS)) {
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_W)
+				audpp_dsp_set_rx_srs_trumedia_w(&audio_copp->w);
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_C)
+				audpp_dsp_set_rx_srs_trumedia_c(&audio_copp->c);
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_HP)
+				audpp_dsp_set_rx_srs_trumedia_h(&audio_copp->h);
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_P)
+				audpp_dsp_set_rx_srs_trumedia_p(&audio_copp->p);
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_HL)
+				audpp_dsp_set_rx_srs_trumedia_l(&audio_copp->l);
+			if (audio_copp->srs_current_feature_mask & SRS_MASK_G)
+				audpp_dsp_set_rx_srs_trumedia_g(&audio_copp->g);
+		}
+		audio_copp->audpp_disabled_features = 0;
+		return;
+	}
+
 	if (!is_acdb_enabled()) {
 		audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
 						&audio_copp->mbadrc);
@@ -513,6 +578,8 @@
 		if (audio_copp->srs_feature_mask & SRS_MASK_G)
 			audpp_dsp_set_rx_srs_trumedia_g(&audio_copp->g);
 
+		audio_copp->srs_current_feature_mask =
+			audio_copp->srs_feature_mask;
 		audio_copp->srs_needs_commit = 0;
 		audio_copp->srs_feature_mask = 0;
 	}
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index 2a83238..bcc00a4 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -211,9 +211,13 @@
 			    uint16_t *msg)
 {
 	unsigned n;
-	for (n = 0; n < AUDPP_CLNT_MAX_COUNT; n++) {
-		if (audpp->func[n])
-			audpp->func[n] (audpp->private[n], id, msg);
+
+	if ((id != AUDPP_MSG_PP_DISABLE_FEEDBACK) &&
+		(id != AUDPP_MSG_PP_FEATS_RE_ENABLE)) {
+		for (n = 0; n < AUDPP_CLNT_MAX_COUNT; n++) {
+			if (audpp->func[n])
+				audpp->func[n] (audpp->private[n], id, msg);
+		}
 	}
 
 	for (n = 0; n < MAX_EVENT_CALLBACK_CLIENTS; ++n)
@@ -337,6 +341,14 @@
 			msg[1], msg[2]);
 		acdb_rtc_set_err(msg[2]);
 		break;
+	case AUDPP_MSG_PP_DISABLE_FEEDBACK:
+		MM_DBG("PP Disable feedback due to mips limitation");
+		audpp_broadcast(audpp, id, msg);
+		break;
+	case AUDPP_MSG_PP_FEATS_RE_ENABLE:
+		MM_DBG("Re-enable the disabled PP features");
+		audpp_broadcast(audpp, id, msg);
+		break;
 	default:
 		MM_ERR("unhandled msg id %x\n", id);
 	}