ASoc: msm: Add support for adie RX & TX calibration

Add support for adie RX & TX calibration. This calibration
is used for RMC and speaker protection. A non-blocking
function was created for AFE memory map since it is now
being called from an atomic process and the acdb driver
was changed to use to use atomic variables.

Change-Id: Id6c6ca7a303ef5ee5d23a9932e910e6a7a08805d
Signed-off-by: Ben Romberger <bromberg@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index 16751fe..a55dee6 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,9 +28,15 @@
 	uint32_t		cal_paddr;
 };
 
+struct acdb_atomic_cal_block {
+	atomic_t		cal_size;
+	atomic_t		cal_kvaddr;
+	atomic_t		cal_paddr;
+};
+
 struct acdb_cal_data {
-	uint32_t		num_cal_blocks;
-	struct acdb_cal_block	*cal_blocks;
+	uint32_t			num_cal_blocks;
+	struct acdb_atomic_cal_block	*cal_blocks;
 };
 
 uint32_t get_voice_rx_topology(void);
@@ -44,6 +50,7 @@
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block);
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block);
 void get_anc_cal(struct acdb_cal_block *cal_block);
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 37a6900..2e61e90 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -22,43 +22,52 @@
 
 #define MAX_NETWORKS		12
 
+struct sidetone_atomic_cal {
+	atomic_t	enable;
+	atomic_t	gain;
+};
+
+
 struct acdb_data {
 	struct mutex		acdb_mutex;
 
 	/* ANC Cal */
-	struct acdb_cal_block	anc_cal;
+	struct acdb_atomic_cal_block	anc_cal;
 
 	/* AudProc Cal */
-	uint32_t		asm_topology;
-	uint32_t		adm_topology[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
+	atomic_t			asm_topology;
+	atomic_t			adm_topology[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
 
 	/* VocProc Cal */
-	uint32_t                voice_rx_topology;
-	uint32_t                voice_tx_topology;
-	struct acdb_cal_block	vocproc_cal[MAX_NETWORKS];
-	struct acdb_cal_block	vocstrm_cal[MAX_NETWORKS];
-	struct acdb_cal_block	vocvol_cal[MAX_NETWORKS];
+	atomic_t			voice_rx_topology;
+	atomic_t			voice_tx_topology;
+	struct acdb_atomic_cal_block	vocproc_cal[MAX_NETWORKS];
+	struct acdb_atomic_cal_block	vocstrm_cal[MAX_NETWORKS];
+	struct acdb_atomic_cal_block	vocvol_cal[MAX_NETWORKS];
 	/* size of cal block tables above*/
-	uint32_t		vocproc_cal_size;
-	uint32_t		vocstrm_cal_size;
-	uint32_t		vocvol_cal_size;
+	atomic_t			vocproc_cal_size;
+	atomic_t			vocstrm_cal_size;
+	atomic_t			vocvol_cal_size;
 	/* Total size of cal data for all networks */
-	uint32_t		vocproc_total_cal_size;
-	uint32_t		vocstrm_total_cal_size;
-	uint32_t		vocvol_total_cal_size;
+	atomic_t			vocproc_total_cal_size;
+	atomic_t			vocstrm_total_cal_size;
+	atomic_t			vocvol_total_cal_size;
+
+	/* AFE cal */
+	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
 
 	/* Sidetone Cal */
-	struct sidetone_cal	sidetone_cal;
+	struct sidetone_atomic_cal	sidetone_cal;
 
 	/* PMEM information */
-	int			pmem_fd;
-	unsigned long		paddr;
-	unsigned long		kvaddr;
-	unsigned long		pmem_len;
-	struct file		*file;
+	atomic_t			pmem_fd;
+	atomic64_t			paddr;
+	atomic64_t			kvaddr;
+	atomic64_t			pmem_len;
+	struct file			*file;
 
 };
 
@@ -67,90 +76,105 @@
 
 uint32_t get_voice_rx_topology(void)
 {
-	return acdb_data.voice_rx_topology;
+	return atomic_read(&acdb_data.voice_rx_topology);
 }
 
 void store_voice_rx_topology(uint32_t topology)
 {
-	acdb_data.voice_rx_topology = topology;
+	atomic_set(&acdb_data.voice_rx_topology, topology);
 }
 
 uint32_t get_voice_tx_topology(void)
 {
-	return acdb_data.voice_tx_topology;
+	return atomic_read(&acdb_data.voice_tx_topology);
 }
 
 void store_voice_tx_topology(uint32_t topology)
 {
-	acdb_data.voice_tx_topology = topology;
+	atomic_set(&acdb_data.voice_tx_topology, topology);
 }
 
 uint32_t get_adm_rx_topology(void)
 {
-	return acdb_data.adm_topology[RX_CAL];
+	return atomic_read(&acdb_data.adm_topology[RX_CAL]);
 }
 
 void store_adm_rx_topology(uint32_t topology)
 {
-	acdb_data.adm_topology[RX_CAL] = topology;
+	atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
 }
 
 uint32_t get_adm_tx_topology(void)
 {
-	return acdb_data.adm_topology[TX_CAL];
+	return atomic_read(&acdb_data.adm_topology[TX_CAL]);
 }
 
 void store_adm_tx_topology(uint32_t topology)
 {
-	acdb_data.adm_topology[TX_CAL] = topology;
+	atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
 }
 
 uint32_t get_asm_topology(void)
 {
-	return acdb_data.asm_topology;
+	return atomic_read(&acdb_data.asm_topology);
 }
 
 void store_asm_topology(uint32_t topology)
 {
-	acdb_data.asm_topology = topology;
+	atomic_set(&acdb_data.asm_topology, topology);
 }
 
 void get_all_voice_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size +
-				acdb_data.vocstrm_total_cal_size +
-				acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size) +
+		atomic_read(&acdb_data.vocstrm_total_cal_size) +
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_all_cvp_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size +
-				acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size) +
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_all_vocproc_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size);
 }
 
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocstrm_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocstrm_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocstrm_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocstrm_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocstrm_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocstrm_total_cal_size);
 }
 
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocvol_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocvol_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocvol_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocvol_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_anc_cal(struct acdb_cal_block *cal_block)
@@ -162,13 +186,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.anc_cal.cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.anc_cal.cal_paddr;
-	cal_block->cal_size = acdb_data.anc_cal.cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.anc_cal.cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.anc_cal.cal_size);
 done:
 	return;
 }
@@ -177,23 +200,69 @@
 {
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.anc_cal.cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.anc_cal.cal_size,
+		cal_block->cal_size);
+done:
+	return;
+}
 
-	acdb_data.anc_cal.cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.anc_cal.cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.anc_cal.cal_size =
-		cal_block->cal_size;
+void store_afe_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_unlock(&acdb_data.acdb_mutex);
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
+		pr_err("%s: offset %d is > pmem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.pmem_len));
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.afe_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.afe_cal[path].cal_size,
+		cal_block->cal_size);
+done:
+	return;
+}
+
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.afe_cal[path].cal_size);
 done:
 	return;
 }
@@ -202,12 +271,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -216,15 +283,13 @@
 		goto done;
 	}
 
-	acdb_data.audproc_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audproc_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audproc_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audproc_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -242,13 +307,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audproc_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audproc_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audproc_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audproc_cal[path].cal_size);
 done:
 	return;
 }
@@ -257,12 +321,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -271,15 +333,13 @@
 		goto done;
 	}
 
-	acdb_data.audstrm_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audstrm_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audstrm_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audstrm_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -297,13 +357,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audstrm_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audstrm_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audstrm_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_size);
 done:
 	return;
 }
@@ -312,12 +371,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -326,15 +383,13 @@
 		goto done;
 	}
 
-	acdb_data.audvol_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audvol_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audvol_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audvol_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -352,13 +407,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audvol_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audvol_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audvol_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audvol_cal[path].cal_size);
 done:
 	return;
 }
@@ -375,31 +429,28 @@
 		goto done;
 	}
 
-
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocproc_total_cal_size = 0;
+	atomic_set(&acdb_data.vocproc_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocproc_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocproc_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocproc_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocproc_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocproc_total_cal_size);
+			atomic_set(&acdb_data.vocproc_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocproc_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocproc_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocproc_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocproc_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocproc_cal_size, len);
 done:
 	return;
 }
@@ -413,12 +464,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocproc_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocproc_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocproc_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -434,30 +481,28 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocstrm_total_cal_size = 0;
+	atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocstrm_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocstrm_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocstrm_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocstrm_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocstrm_total_cal_size);
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocstrm_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocstrm_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocstrm_cal_size, len);
 done:
 	return;
 }
@@ -471,12 +516,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocstrm_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocstrm_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocstrm_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -492,30 +533,28 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocvol_total_cal_size = 0;
+	atomic_set(&acdb_data.vocvol_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocvol_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocvol_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocvol_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocvol_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocvol_total_cal_size);
+			atomic_set(&acdb_data.vocvol_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocvol_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocvol_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocvol_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocvol_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocvol_cal_size, len);
 done:
 	return;
 }
@@ -529,12 +568,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocvol_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocvol_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocvol_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -543,12 +578,8 @@
 {
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.sidetone_cal.enable = cal_data->enable;
-	acdb_data.sidetone_cal.gain = cal_data->gain;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
+	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
 }
 
 
@@ -561,12 +592,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->enable = acdb_data.sidetone_cal.enable;
-	cal_data->gain = acdb_data.sidetone_cal.gain;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
+	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
 done:
 	return;
 }
@@ -574,14 +601,12 @@
 static int acdb_open(struct inode *inode, struct file *f)
 {
 	s32 result = 0;
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	if (acdb_data.pmem_fd) {
-		pr_info("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
 			__func__);
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
 
 	atomic_inc(&usage_count);
 	return result;
@@ -589,9 +614,11 @@
 
 static int deregister_pmem(void)
 {
-	if (acdb_data.pmem_fd) {
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		mutex_lock(&acdb_data.acdb_mutex);
 		put_pmem_file(acdb_data.file);
-		acdb_data.pmem_fd = 0;
+		mutex_unlock(&acdb_data.acdb_mutex);
+		atomic_set(&acdb_data.pmem_fd, 0);
 	}
 	return 0;
 }
@@ -599,19 +626,30 @@
 static int register_pmem(void)
 {
 	int result;
+	unsigned long paddr;
+	unsigned long kvaddr;
+	unsigned long pmem_len;
 
-	result = get_pmem_file(acdb_data.pmem_fd, &acdb_data.paddr,
-				&acdb_data.kvaddr, &acdb_data.pmem_len,
+	mutex_lock(&acdb_data.acdb_mutex);
+	result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
+				&paddr, &kvaddr, &pmem_len,
 				&acdb_data.file);
+	mutex_unlock(&acdb_data.acdb_mutex);
 	if (result != 0) {
-		acdb_data.pmem_fd = 0;
+		atomic_set(&acdb_data.pmem_fd, 0);
+		atomic64_set(&acdb_data.pmem_len, 0);
 		pr_err("%s: Could not register PMEM!!!\n", __func__);
 		goto done;
 	}
 
+	atomic64_set(&acdb_data.paddr, paddr);
+	atomic64_set(&acdb_data.kvaddr, kvaddr);
+	atomic64_set(&acdb_data.pmem_len, pmem_len);
 	pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
-		"kvaddr = 0x%lx, len = x%lx\n", acdb_data.paddr,
-		acdb_data.kvaddr, acdb_data.pmem_len);
+		"kvaddr = 0x%lx, len = x%lx\n",
+		(long)atomic64_read(&acdb_data.paddr),
+		(long)atomic64_read(&acdb_data.kvaddr),
+		(long)atomic64_read(&acdb_data.pmem_len));
 
 done:
 	return result;
@@ -619,37 +657,33 @@
 static long acdb_ioctl(struct file *f,
 		unsigned int cmd, unsigned long arg)
 {
-	s32			result = 0;
-	s32			audproc_path;
-	s32			size;
-	u32			topology;
+	int32_t			result = 0;
+	int32_t			size;
+	int32_t			pmem_fd;
+	uint32_t		topology;
 	struct cal_block	data[MAX_NETWORKS];
 	pr_debug("%s\n", __func__);
 
 	switch (cmd) {
 	case AUDIO_REGISTER_PMEM:
 		pr_debug("AUDIO_REGISTER_PMEM\n");
-		mutex_lock(&acdb_data.acdb_mutex);
-		if (acdb_data.pmem_fd) {
+		if (atomic_read(&acdb_data.pmem_fd)) {
 			deregister_pmem();
-			pr_info("Remove the existing PMEM\n");
+			pr_debug("Remove the existing PMEM\n");
 		}
 
-		if (copy_from_user(&acdb_data.pmem_fd, (void *)arg,
-					sizeof(acdb_data.pmem_fd))) {
+		if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
 			pr_err("%s: fail to copy pmem handle!\n", __func__);
 			result = -EFAULT;
 		} else {
+			atomic_set(&acdb_data.pmem_fd, pmem_fd);
 			result = register_pmem();
 		}
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 
 	case AUDIO_DEREGISTER_PMEM:
 		pr_debug("AUDIO_DEREGISTER_PMEM\n");
-		mutex_lock(&acdb_data.acdb_mutex);
 		deregister_pmem();
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 	case AUDIO_SET_VOICE_RX_TOPOLOGY:
 		if (copy_from_user(&topology, (void *)arg,
@@ -721,45 +755,51 @@
 
 	switch (cmd) {
 	case AUDIO_SET_AUDPROC_TX_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(audproc_path, data);
+		store_audproc_cal(TX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(audproc_path, data);
+		store_audproc_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(audproc_path, data);
+		store_audstrm_cal(TX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(audproc_path, data);
+		store_audstrm_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(audproc_path, data);
+		store_audvol_cal(TX_CAL, data);
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(audproc_path, data);
+		store_audvol_cal(RX_CAL, data);
+		break;
+	case AUDIO_SET_AFE_TX_CAL:
+		if (size > sizeof(struct cal_block))
+			pr_err("%s: More AFE Cal then expected, "
+				"size received: %d\n", __func__, size);
+		store_afe_cal(TX_CAL, data);
+		break;
+	case AUDIO_SET_AFE_RX_CAL:
+		if (size > sizeof(struct cal_block))
+			pr_err("%s: More AFE Cal then expected, "
+				"size received: %d\n", __func__, size);
+		store_afe_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_VOCPROC_CAL:
 		store_vocproc_cal(size / sizeof(struct cal_block), data);
@@ -794,14 +834,13 @@
 
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	if (acdb_data.pmem_fd) {
-		if (size <= acdb_data.pmem_len) {
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		if (size <= atomic64_read(&acdb_data.pmem_len)) {
 			vma->vm_page_prot = pgprot_noncached(
 						vma->vm_page_prot);
 			result = remap_pfn_range(vma,
 				vma->vm_start,
-				acdb_data.paddr >> PAGE_SHIFT,
+				atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
 				size,
 				vma->vm_page_prot);
 		} else {
@@ -812,7 +851,6 @@
 		pr_err("%s: PMEM is not allocated, yet!\n", __func__);
 		result = -ENODEV;
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
 
 	return result;
 }
@@ -824,16 +862,13 @@
 	atomic_dec(&usage_count);
 	atomic_read(&usage_count);
 
-	pr_info("%s: ref count %d!\n", __func__,
+	pr_debug("%s: ref count %d!\n", __func__,
 		atomic_read(&usage_count));
 
-	if (atomic_read(&usage_count) >= 1) {
+	if (atomic_read(&usage_count) >= 1)
 		result = -EBUSY;
-	} else {
-		mutex_lock(&acdb_data.acdb_mutex);
+	else
 		result = deregister_pmem();
-		mutex_unlock(&acdb_data.acdb_mutex);
-	}
 
 	return result;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index d0fec7c..12a02c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -791,7 +791,7 @@
 	struct apr_hdr cvs_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
 	int index = 0;
@@ -830,11 +830,12 @@
 	pr_debug("cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
 		pr_debug(" cal size =%d\n", cal_size_per_network);
 		if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
 			pr_err("Cal size is too big\n");
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 		pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
 		cvs_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
 			cal_size_per_network);
@@ -868,7 +869,7 @@
 	struct apr_hdr cvp_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
 	int index = 0;
@@ -907,11 +908,12 @@
 	pr_debug(" cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
 		if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
 			pr_err("Cal size is too big\n");
 		pr_debug(" cal size =%d\n", cal_size_per_network);
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 		pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
 
 		cvp_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
@@ -945,7 +947,7 @@
 	struct apr_hdr cvp_vol_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
 	int index = 0;
@@ -984,8 +986,9 @@
 	pr_debug("Cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 
 		pr_debug("Cal size =%d, index=%d\n", cal_size_per_network,
 			index);
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index 3d756c2..e7f06b5 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -35,6 +35,13 @@
 			(AUDIO_MAX_COMMON_IOCTL_NUM+14), unsigned)
 #define AUDIO_SET_ASM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+15), unsigned)
+#define AUDIO_SET_AFE_TX_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+#define AUDIO_SET_AFE_RX_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+
+
+#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
 
 /* ACDB structures */
 struct cal_block {
@@ -49,25 +56,26 @@
 
 /* For Real-Time Audio Calibration */
 #define AUDIO_GET_RTAC_ADM_INFO		_IOR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+1), unsigned)
 #define AUDIO_GET_RTAC_VOICE_INFO	_IOR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+2), unsigned)
 #define AUDIO_GET_RTAC_ADM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+18), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+3), unsigned)
 #define AUDIO_SET_RTAC_ADM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+19), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+4), unsigned)
 #define AUDIO_GET_RTAC_ASM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+20), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+5), unsigned)
 #define AUDIO_SET_RTAC_ASM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+21), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+6), unsigned)
 #define AUDIO_GET_RTAC_CVS_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+22), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+7), unsigned)
 #define AUDIO_SET_RTAC_CVS_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+23), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+8), unsigned)
 #define AUDIO_GET_RTAC_CVP_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+9), unsigned)
 #define AUDIO_SET_RTAC_CVP_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+25), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+10), unsigned)
 
+#define	AUDIO_MAX_RTAC_IOCTL	(AUDIO_MAX_ACDB_IOCTL+20)
 
 #endif /* __MSM_AUDIO_ACDB_H */
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 798ed89..30f1a7c 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1,7 +1,6 @@
-
 /*
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -353,6 +352,12 @@
 	struct afe_param_payload payload;
 } __attribute__ ((packed));
 
+struct afe_port_cmd_set_param_no_payload {
+	struct apr_hdr hdr;
+	u16 port_id;
+	u16 payload_size;
+	u32 payload_address;
+} __packed;
 
 #define AFE_EVENT_GET_ACTIVE_PORTS 0x00010100
 struct afe_get_active_ports_rsp {
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 6206838..2d0f53f 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -76,7 +76,9 @@
 int afe_start_pseudo_port(u16 port_id);
 int afe_stop_pseudo_port(u16 port_id);
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_unmap(u32 dma_addr_p);
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p);
 
 int afe_register_get_events(u16 port_id,
 		void (*cb) (uint32_t opcode,
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 18dfc01..d8d9c64 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -457,7 +457,7 @@
 	int     i = 0;
 	int     cmd_size = 0;
 
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 	if (this_adm.apr == NULL) {
 		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
 						0xFFFFFFFF, &this_adm);
@@ -532,7 +532,7 @@
 	int     i = 0;
 	int     cmd_size = 0;
 
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 
 	if (this_adm.apr == NULL) {
 		pr_err("%s APR handle NULL\n", __func__);
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 74a66945..a214529 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
 #include <linux/wait.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
+#include <mach/qdsp6v2/audio_acdb.h>
 #include <sound/apr_audio.h>
 #include <sound/q6afe.h>
 
@@ -36,6 +37,8 @@
 
 static struct afe_ctl this_afe;
 
+static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
+
 #define TIMEOUT_MS 1000
 #define Q6AFE_MAX_VOLUME 0x3FFF
 
@@ -314,6 +317,63 @@
 	return ret;
 }
 
+static void afe_send_cal_block(int32_t path, u16 port_id)
+{
+	int						result = 0;
+	struct acdb_cal_block				cal_block;
+	struct afe_port_cmd_set_param_no_payload	afe_cal;
+	pr_debug("%s: path %d\n", __func__, path);
+
+	get_afe_cal(path, &cal_block);
+	if (cal_block.cal_size <= 0) {
+		pr_debug("%s: No AFE cal to send!\n", __func__);
+		goto done;
+	}
+
+	if (afe_cal_addr[path] != cal_block.cal_paddr) {
+		if (afe_cal_addr[path] != 0)
+			afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
+		afe_cmd_memory_map_nowait(cal_block.cal_paddr,
+						cal_block.cal_size);
+		afe_cal_addr[path] = cal_block.cal_paddr;
+	}
+
+	afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	afe_cal.hdr.pkt_size = sizeof(afe_cal);
+	afe_cal.hdr.src_port = 0;
+	afe_cal.hdr.dest_port = 0;
+	afe_cal.hdr.token = 0;
+	afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
+	afe_cal.port_id = port_id;
+	afe_cal.payload_size = cal_block.cal_size;
+	afe_cal.payload_address = cal_block.cal_paddr;
+
+	pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
+		"cal size = %d, cal addr = 0x%x\n", __func__,
+		port_id, path, cal_block.cal_size, cal_block.cal_paddr);
+
+	result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
+	if (result < 0) {
+		pr_err("%s: AFE cal for port %d failed\n",
+			__func__, port_id);
+	}
+
+	pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
+done:
+	return;
+}
+
+void afe_send_cal(u16 port_id)
+{
+	pr_debug("%s\n", __func__);
+
+	if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
+		afe_send_cal_block(TX_CAL, port_id);
+	else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
+		afe_send_cal_block(RX_CAL, port_id);
+}
+
 int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
 	u32 rate) /* This function is no blocking */
 {
@@ -365,6 +425,10 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
+
+	/* send AFE cal */
+	afe_send_cal(port_id);
+
 	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	start.hdr.pkt_size = sizeof(start);
@@ -875,6 +939,45 @@
 	return 0;
 }
 
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
+{
+	int ret = 0;
+	struct afe_cmd_memory_map mregion;
+
+	pr_debug("%s:\n", __func__);
+
+	if (this_afe.apr == NULL) {
+		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+					0xFFFFFFFF, &this_afe);
+		pr_debug("%s: Register AFE\n", __func__);
+		if (this_afe.apr == NULL) {
+			pr_err("%s: Unable to register AFE\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+	}
+
+	mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mregion.hdr.pkt_size = sizeof(mregion);
+	mregion.hdr.src_port = 0;
+	mregion.hdr.dest_port = 0;
+	mregion.hdr.token = 0;
+	mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
+	mregion.phy_addr = dma_addr_p;
+	mregion.mem_sz = dma_buf_sz;
+	mregion.mem_id = 0;
+	mregion.rsvd = 0;
+
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+	if (ret < 0) {
+		pr_err("%s: AFE memory map cmd failed %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+	}
+	return 0;
+}
+
 int afe_cmd_memory_unmap(u32 dma_addr_p)
 {
 	int ret = 0;
@@ -905,7 +1008,7 @@
 	atomic_set(&this_afe.state, 1);
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
 	if (ret < 0) {
-		pr_err("%s: AFE memory map cmd failed %d\n",
+		pr_err("%s: AFE memory unmap cmd failed %d\n",
 		       __func__, ret);
 		ret = -EINVAL;
 		return ret;
@@ -919,7 +1022,42 @@
 		ret = -EINVAL;
 		return ret;
 	}
+	return 0;
+}
 
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
+{
+	int ret = 0;
+	struct afe_cmd_memory_unmap mregion;
+
+	pr_debug("%s:\n", __func__);
+
+	if (this_afe.apr == NULL) {
+		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+					0xFFFFFFFF, &this_afe);
+		pr_debug("%s: Register AFE\n", __func__);
+		if (this_afe.apr == NULL) {
+			pr_err("%s: Unable to register AFE\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+	}
+
+	mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mregion.hdr.pkt_size = sizeof(mregion);
+	mregion.hdr.src_port = 0;
+	mregion.hdr.dest_port = 0;
+	mregion.hdr.token = 0;
+	mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
+	mregion.phy_addr = dma_addr_p;
+
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+	if (ret < 0) {
+		pr_err("%s: AFE memory unmap cmd failed %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+	}
 	return 0;
 }
 
@@ -1389,12 +1527,17 @@
 
 static void __exit afe_exit(void)
 {
+	int i;
 #ifdef CONFIG_DEBUG_FS
 	if (debugfs_afelb)
 		debugfs_remove(debugfs_afelb);
 	if (debugfs_afelb_gain)
 		debugfs_remove(debugfs_afelb_gain);
 #endif
+	for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+		if (afe_cal_addr[i] != 0)
+			afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
+	}
 }
 
 device_initcall(afe_init);