Merge "ASoC: msm: qdsp6v2: defer probe if memory allocation fails"
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 5c420ed..071db4e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -617,12 +617,36 @@
 
 static __devinit int msm_pcm_probe(struct platform_device *pdev)
 {
+	int rc;
+
+	if (!is_voc_initialized()) {
+		pr_debug("%s: voice module not initialized yet, deferring probe()\n",
+		       __func__);
+
+		rc = -EPROBE_DEFER;
+		goto done;
+	}
+
+	rc = voc_alloc_cal_shared_memory();
+	if (rc == -EPROBE_DEFER) {
+		pr_debug("%s: memory allocation for calibration deferred %d\n",
+			 __func__, rc);
+
+		goto done;
+	} else if (rc < 0) {
+		pr_err("%s: memory allocation for calibration failed %d\n",
+		       __func__, rc);
+	}
+
 	if (pdev->dev.of_node)
 		dev_set_name(&pdev->dev, "%s", "msm-pcm-voice");
 
 	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
-	return snd_soc_register_platform(&pdev->dev,
-				   &msm_soc_platform);
+	rc = snd_soc_register_platform(&pdev->dev,
+				       &msm_soc_platform);
+
+done:
+	return rc;
 }
 
 static int msm_pcm_remove(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index f17fe5b..ae454a8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -817,8 +817,15 @@
 		}
 		voc_register_mvs_cb(voip_process_ul_pkt,
 					voip_process_dl_pkt, prtd);
-		voc_start_voice_call(voc_get_session_id(VOIP_SESSION_NAME));
+		ret = voc_start_voice_call(
+				voc_get_session_id(VOIP_SESSION_NAME));
 
+		if (ret < 0) {
+			pr_err("%s: voc_start_voice_call() failed err %d",
+			       __func__, ret);
+
+			goto done;
+		}
 		prtd->state = VOIP_STARTED;
 	}
 done:
@@ -1132,12 +1139,42 @@
 
 static __devinit int msm_pcm_probe(struct platform_device *pdev)
 {
+	int rc;
+
+	if (!is_voc_initialized()) {
+		pr_debug("%s: voice module not initialized yet, deferring probe()\n",
+		       __func__);
+
+		rc = -EPROBE_DEFER;
+		goto done;
+	}
+
+	rc = voc_alloc_cal_shared_memory();
+	if (rc == -EPROBE_DEFER) {
+		pr_debug("%s: memory allocation for calibration deferred %d\n",
+			 __func__, rc);
+
+		goto done;
+	} else if (rc < 0) {
+		pr_err("%s: memory allocation for calibration failed %d\n",
+		       __func__, rc);
+	}
+
+	rc = voc_alloc_voip_shared_memory();
+	if (rc < 0) {
+		pr_err("%s: error allocating shared mem err %d\n",
+		       __func__, rc);
+	}
+
 	if (pdev->dev.of_node)
 		dev_set_name(&pdev->dev, "%s", "msm-voip-dsp");
 
 	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
-	return snd_soc_register_platform(&pdev->dev,
-				   &msm_soc_platform);
+	rc = snd_soc_register_platform(&pdev->dev,
+				       &msm_soc_platform);
+
+done:
+	return rc;
 }
 
 static int msm_pcm_remove(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 0735b7a..f268171 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -48,6 +48,7 @@
 };
 
 static struct common_data common;
+static bool module_initialized;
 
 static int voice_send_enable_vocproc_cmd(struct voice_data *v);
 static int voice_send_netid_timing_cmd(struct voice_data *v);
@@ -84,6 +85,14 @@
 
 static int voice_send_set_pp_enable_cmd(struct voice_data *v,
 					uint32_t module_id, int enable);
+static int is_cal_memory_allocated(void);
+static int is_voip_memory_allocated(void);
+static int voice_alloc_cal_mem_map_table(void);
+static int voice_alloc_oob_shared_mem(void);
+static int voice_free_oob_shared_mem(void);
+static int voice_alloc_oob_mem_table(void);
+static int voice_alloc_and_map_cal_mem(struct voice_data *v);
+static int voice_alloc_and_map_oob_mem(struct voice_data *v);
 
 static struct voice_data *voice_get_session_by_idx(int idx);
 static int voice_get_idx_for_session(u32 session_id);
@@ -1238,6 +1247,89 @@
 	return ret;
 }
 
+int voc_alloc_cal_shared_memory(void)
+{
+	int rc = 0;
+
+	mutex_lock(&common.common_lock);
+	if (is_cal_memory_allocated()) {
+		pr_debug("%s: Calibration shared buffer already allocated",
+			 __func__);
+	} else {
+		/* Allocate memory for calibration memory map table. */
+		rc = voice_alloc_cal_mem_map_table();
+		if (rc < 0) {
+			pr_err("%s: Failed to allocate cal memory, err=%d",
+			       __func__, rc);
+		}
+	}
+	mutex_unlock(&common.common_lock);
+
+	return rc;
+}
+
+int voc_alloc_voip_shared_memory(void)
+{
+	int rc = 0;
+
+	/* Allocate shared memory for OOB Voip */
+	rc = voice_alloc_oob_shared_mem();
+	if (rc < 0) {
+		pr_err("%s: Failed to alloc shared memory for OOB rc:%d\n",
+			   __func__, rc);
+	} else {
+		/* Allocate mem map table for OOB */
+		rc = voice_alloc_oob_mem_table();
+		if (rc < 0) {
+			pr_err("%s: Failed to alloc mem map talbe rc:%d\n",
+			       __func__, rc);
+
+			voice_free_oob_shared_mem();
+		}
+	}
+
+	return rc;
+}
+
+static int is_cal_memory_allocated(void)
+{
+	bool ret;
+
+	if (common.cal_mem_map_table.client != NULL &&
+	    common.cal_mem_map_table.handle != NULL)
+		ret = true;
+	else
+		ret = false;
+
+	return ret;
+}
+
+static int is_voip_memory_allocated(void)
+{
+	bool ret;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL, session_id:%d\n", __func__,
+		common.voice[VOC_PATH_FULL].session_id);
+
+		ret = false;
+		goto done;
+	}
+
+	mutex_lock(&common.common_lock);
+	if (v->shmem_info.sh_buf.client != NULL &&
+	    v->shmem_info.sh_buf.handle != NULL)
+		ret = true;
+	else
+		ret = false;
+	mutex_unlock(&common.common_lock);
+
+done:
+	return ret;
+}
+
 static int voice_config_cvs_vocoder(struct voice_data *v)
 {
 	int ret = 0;
@@ -1691,26 +1783,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvs) {
 		pr_err("%s: apr_cvs is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVS cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvs_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1739,7 +1833,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVS cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvs_wait,
 				 (v->cvs_state == CMD_STATUS_SUCCESS),
@@ -1747,13 +1841,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v)
@@ -1766,18 +1858,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvs) {
 		pr_err("%s: apr_cvs is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvs_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -1795,7 +1895,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d de-registering CVS cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvs_wait,
 				 (v->cvs_state == CMD_STATUS_SUCCESS),
@@ -1803,13 +1903,11 @@
 	if (!ret) {
 		pr_err("%s: Command  timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 
 }
 
@@ -1823,26 +1921,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocproc_dev_cfg_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_dev_cfg_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1867,7 +1967,7 @@
 		pr_err("%s: Error %d registering CVP dev cfg cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -1875,13 +1975,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_dev_cfg_cmd(struct voice_data *v)
@@ -1894,18 +1992,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
-		pr_err("%s: apr_cvp is NULL.\n", __func__);
+		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocproc_dev_cfg_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_dev_cfg_cmd.hdr.hdr_field =
 				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1926,7 +2032,7 @@
 		pr_err("%s: Error %d de-registering CVP dev cfg cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -1934,13 +2040,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
@@ -1953,26 +2057,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2001,7 +2107,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVP cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2009,13 +2115,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v)
@@ -2028,18 +2132,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL.\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -2057,7 +2169,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d de-registering CVP cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2065,12 +2177,10 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
+done:
 	return -EINVAL;
 }
 
@@ -2084,26 +2194,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
-		pr_err("%s: apr_cvp is NULL.\n", __func__);
+		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP vol cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_vol_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2135,7 +2247,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVP vol cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2143,13 +2255,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v)
@@ -2162,18 +2272,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_vol_cal_cmd.hdr.hdr_field =
 			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2194,7 +2312,7 @@
 		pr_err("%s: Error %d de-registering CVP vol cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2202,13 +2320,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_map_memory_physical_cmd(struct voice_data *v,
@@ -2320,10 +2436,11 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&common.common_lock);
 	if (common.cal_mem_handle != 0) {
 		pr_debug("%s: Cal block already mem mapped\n", __func__);
 
-		return ret;
+		goto done;
 	}
 
 	/* Get the physical address of calibration memory block from ACDB. */
@@ -2332,7 +2449,8 @@
 	if (!cal_block.cal_paddr) {
 		pr_err("%s: Cal block not allocated\n", __func__);
 
-		return -EINVAL;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	ret = voice_map_memory_physical_cmd(v,
@@ -2341,6 +2459,8 @@
 					    cal_block.cal_size,
 					    VOC_CAL_MEM_MAP_TOKEN);
 
+done:
+	mutex_unlock(&common.common_lock);
 	return ret;
 }
 
@@ -2414,7 +2534,6 @@
 	}
 
 	voice_send_cvs_register_cal_cmd(v);
-
 	voice_send_cvp_register_dev_cfg_cmd(v);
 	voice_send_cvp_register_cal_cmd(v);
 	voice_send_cvp_register_vol_cal_cmd(v);
@@ -4157,31 +4276,34 @@
 			goto fail;
 		}
 
-		/* Memory map the calibration memory block. */
-		ret = voice_mem_map_cal_block(v);
+		/* Allocate cal mem if not already allocated and memory map
+		 * the calibration memory block.
+		 */
+		ret = voice_alloc_and_map_cal_mem(v);
 		if (ret < 0) {
-			pr_err("%s: Memory map of cal block failed %d\n",
-			       __func__, ret);
-			/* Allow call to continue, call quality will be bad. */
+			pr_debug("%s: Continue without calibration %d\n",
+				 __func__, ret);
 		}
 
 		if (is_voip_session(session_id)) {
-			ret = voice_map_memory_physical_cmd(v,
-			      &v->shmem_info.memtbl,
-			      v->shmem_info.sh_buf.buf[0].phys,
-			      v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
-			      VOIP_MEM_MAP_TOKEN);
-			if (ret) {
-				pr_err("%s: mvm_map_memory_phy failed %d\n",
-					__func__, ret);
+			/* Allocate oob mem if not already allocated and
+			 * memory map the oob memory block.
+			 */
+			ret = voice_alloc_and_map_oob_mem(v);
+			if (ret < 0) {
+				pr_err("%s: voice_alloc_and_map_oob_mem() failed, ret:%d\n",
+				       __func__, ret);
+
 				goto fail;
 			}
+
 			ret = voice_set_packet_exchange_mode_and_config(
 				session_id,
 				VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND);
 			if (ret) {
 				pr_err("%s: Err: exchange_mode_and_config  %d\n",
 					__func__, ret);
+
 				goto fail;
 			}
 		}
@@ -4799,6 +4921,45 @@
 	return 0;
 }
 
+static int voice_free_oob_shared_mem(void)
+{
+	int rc = 0;
+	int cnt = 0;
+	int bufcnt = NUM_OF_BUFFERS;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	mutex_lock(&common.common_lock);
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		rc = -EINVAL;
+		goto done;
+	}
+
+	rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
+				v->shmem_info.sh_buf.handle);
+	if (rc < 0) {
+		pr_err("%s: Error:%d freeing memory\n", __func__, rc);
+
+		goto done;
+	}
+
+
+	while (cnt < bufcnt) {
+		v->shmem_info.sh_buf.buf[cnt].data =  NULL;
+		v->shmem_info.sh_buf.buf[cnt].phys =  0;
+		cnt++;
+	}
+
+	v->shmem_info.sh_buf.client = NULL;
+	v->shmem_info.sh_buf.handle = NULL;
+
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
+}
+
 static int voice_alloc_oob_shared_mem(void)
 {
 	int cnt = 0;
@@ -4811,9 +4972,12 @@
 	struct voice_data *v = voice_get_session(
 				common.voice[VOC_PATH_FULL].session_id);
 
+	mutex_lock(&common.common_lock);
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
+
+		rc = -EINVAL;
+		goto done;
 	}
 
 	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
@@ -4821,10 +4985,11 @@
 			bufsz*bufcnt,
 			(ion_phys_addr_t *)&phys, (size_t *)&len,
 			&mem_addr);
-	if (rc) {
+	if (rc < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		return -EINVAL;
+
+		goto done;
 	}
 
 	while (cnt < bufcnt) {
@@ -4847,7 +5012,9 @@
 
 	memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
 
-	return 0;
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
 }
 
 static int voice_alloc_oob_mem_table(void)
@@ -4857,9 +5024,12 @@
 	struct voice_data *v = voice_get_session(
 				common.voice[VOC_PATH_FULL].session_id);
 
+	mutex_lock(&common.common_lock);
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
+
+		rc = -EINVAL;
+		goto done;
 	}
 
 	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
@@ -4868,21 +5038,22 @@
 				(ion_phys_addr_t *)&v->shmem_info.memtbl.phys,
 				(size_t *)&len,
 				&(v->shmem_info.memtbl.data));
-	if (rc) {
+	if (rc < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		return -EINVAL;
+
+		goto done;
 	}
 
 	v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
-
 	pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
 		 (void *)v->shmem_info.memtbl.data,
 		 (void *)v->shmem_info.memtbl.phys,
 		 (void *)&v->shmem_info.memtbl.phys);
 
-	return 0;
-
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
 }
 
 static int voice_alloc_cal_mem_map_table(void)
@@ -4890,17 +5061,17 @@
 	int ret = 0;
 	int len;
 
-	ret = msm_audio_ion_alloc("voip_client",
+	ret = msm_audio_ion_alloc("voc_cal",
 				&(common.cal_mem_map_table.client),
 				&(common.cal_mem_map_table.handle),
 				sizeof(struct vss_imemory_table_t),
 			      (ion_phys_addr_t *)&common.cal_mem_map_table.phys,
 				(size_t *) &len,
 				&(common.cal_mem_map_table.data));
-	if (ret) {
+	if (ret < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, ret);
-		return -EINVAL;
+		goto done;
 	}
 
 	common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
@@ -4908,7 +5079,78 @@
 		 (unsigned int) common.cal_mem_map_table.data,
 		 common.cal_mem_map_table.phys);
 
-	return 0;
+done:
+	return ret;
+}
+
+static int voice_alloc_and_map_cal_mem(struct voice_data *v)
+{
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		return -EINVAL;
+	}
+
+	ret = voc_alloc_cal_shared_memory();
+	if (ret < 0) {
+		pr_err("%s: Memory allocation of cal block failed %d\n",
+			   __func__, ret);
+
+		goto done;
+	}
+
+	/* Memory map the calibration memory block. */
+	ret = voice_mem_map_cal_block(v);
+	if (ret < 0) {
+		pr_err("%s: Memory map of cal block failed %d\n",
+			   __func__, ret);
+	}
+
+done:
+	return ret;
+}
+
+static int voice_alloc_and_map_oob_mem(struct voice_data *v)
+{
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		return -EINVAL;
+	}
+
+	if (!is_voip_memory_allocated()) {
+		ret = voc_alloc_voip_shared_memory();
+		if (ret < 0) {
+			pr_err("%s: Failed to create voip oob memory %d\n",
+				   __func__, ret);
+
+			goto done;
+		}
+	}
+
+	ret = voice_map_memory_physical_cmd(v,
+			&v->shmem_info.memtbl,
+			v->shmem_info.sh_buf.buf[0].phys,
+			v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
+			VOIP_MEM_MAP_TOKEN);
+	if (ret) {
+		pr_err("%s: mvm_map_memory_phy failed %d\n",
+			   __func__, ret);
+
+		goto done;
+	}
+
+done:
+	return ret;
+}
+
+int is_voc_initialized(void)
+{
+	return module_initialized;
 }
 
 static int __init voice_init(void)
@@ -4954,21 +5196,11 @@
 		mutex_init(&common.voice[i].lock);
 	}
 
-	/* Allocate shared memory for OOB Voip */
-	rc = voice_alloc_oob_shared_mem();
-	if (rc < 0)
-		pr_err("failed to alloc shared memory for OOB %d\n", rc);
-	else {
-		/* Allocate mem map table for OOB */
-		rc = voice_alloc_oob_mem_table();
-		if (rc < 0)
-			pr_err("failed to alloc mem map talbe %d\n", rc);
-	}
+	if (rc == 0)
+		module_initialized = true;
 
-	/* Allocate memory for calibration memory map table. */
-	rc = voice_alloc_cal_mem_map_table();
-
+	pr_debug("%s: rc=%d\n", __func__, rc);
 	return rc;
 }
 
-late_initcall(voice_init);
+device_initcall(voice_init);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 52cf940..b8f7008 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1374,6 +1374,9 @@
 uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir);
 int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable);
 void voc_disable_dtmf_det_on_active_sessions(void);
+int voc_alloc_cal_shared_memory(void);
+int voc_alloc_voip_shared_memory(void);
+int is_voc_initialized(void);
 
 uint32_t voc_get_session_id(char *name);