Merge "msm: msm8960-clock: Add the clock mapping for MI2S TX device" into msm-3.0
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index d9999e7..aa3cf23 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,33 +433,6 @@
 	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
-
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
-	.func = GPIOMUX_FUNC_1,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting cyts_resout_sus_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_6MA,
-	.pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_resout_act_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_6MA,
-	.pull = GPIOMUX_PULL_UP,
-};
-
 static struct gpiomux_setting cyts_sleep_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_6MA,
@@ -499,15 +472,23 @@
 			[GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
 		},
 	},
-	{	/* TS RESOUT */
-		.gpio = 7,
-		.settings = {
-			[GPIOMUX_ACTIVE]    = &cyts_resout_act_cfg,
-			[GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
-		},
-	},
 };
 
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+
 static struct msm_gpiomux_config apq8064_hsic_configs[] = {
 	{
 		.gpio = 88,               /*HSIC_STROBE */
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index f8aa9c0..2cab803 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -195,7 +195,7 @@
 			.bus_freq = 0,
 		},
 	},
-	.init_level = 0,
+	.init_level = 1,
 	.num_levels = 4,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/10,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 9bf16c9..0b1eafd 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1123,7 +1123,6 @@
 };
 #endif
 #define CYTTSP_TS_GPIO_IRQ		6
-#define CYTTSP_TS_GPIO_RESOUT		7
 #define CYTTSP_TS_GPIO_SLEEP		33
 
 static ssize_t tma340_vkeys_show(struct kobject *kobj,
@@ -1217,7 +1216,7 @@
 	 */
 	.lp_intrvl = CY_LP_INTRVL_DFLT,
 	.sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
-	.resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+	.resout_gpio = -1,
 	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
 	.regulator_info = cyttsp_regulator_data,
 	.num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
@@ -2128,7 +2127,7 @@
 };
 
 static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
-	.clk_freq = 100000,
+	.clk_freq = 384000,
 	.src_clk_rate = 24000000,
 };
 
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index c952782..9b3d9eb 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -413,14 +413,14 @@
 
 
 static struct i2c_board_info imx074_actuator_i2c_info = {
-	I2C_BOARD_INFO("imx074_act", 0x11),
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
 static struct msm_actuator_info imx074_actuator_info = {
 	.board_info     = &imx074_actuator_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_0,
 	.bus_id         = MSM_GSBI4_QUP_I2C_BUS_ID,
-	.vcm_pwd        = 0,
-	.vcm_enable     = 1,
+	.vcm_enable     = 0,
 };
 
 static struct msm_camera_sensor_flash_data flash_imx074 = {
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
index 1dd90a7..5df976d 100644
--- a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -201,8 +201,8 @@
 	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
 				GFP_KERNEL);
 	if (audio->enc_cfg == NULL) {
-		pr_err("%s: Could not allocate memory for amrwb"
-			"config param\n", __func__);
+		pr_err("%s:session id %d: Could not allocate memory for amrwb"
+			"config param\n", __func__, audio->ac->session);
 		kfree(audio);
 		return -ENOMEM;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 438909a..88189f6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, 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
@@ -274,10 +274,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
index 9618adb..6768f7a 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -138,10 +138,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrnb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
index a15ab28..f95e191 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -140,10 +140,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrwb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
index 5a511c9..12c815d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -144,10 +144,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_evrc_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
index eff41cc..22552c6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -141,10 +141,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_mp3_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index 0f6b5a6..ee32b80 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -275,10 +275,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_multi_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
index 8343beb..7b72c97 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -150,10 +150,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_qcelp_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index ba3129d8..644df2d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1188,19 +1188,21 @@
 	file->private_data = audio;
 	audio->codec_ioctl = audio_aio_ioctl;
 
-	e_node = kmalloc(sizeof(struct audio_aio_event) * AUDIO_EVENT_NUM,
-			GFP_KERNEL);
-	if (e_node) {
-		for (i = 0; i < AUDIO_EVENT_NUM; i++)
-			list_add_tail(&e_node[i].list,
-				&audio->free_event_queue);
-	} else {
-		pr_err("%s[%p]:event pkt alloc failed\n",
-			__func__, audio);
-		rc = -ENOMEM;
-		goto fail;
+	for (i = 0; i < AUDIO_EVENT_NUM; i++) {
+		e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL);
+		if (e_node)
+			list_add_tail(&e_node->list, &audio->free_event_queue);
+		else {
+			pr_err("%s[%p]:event pkt alloc failed\n",
+				__func__, audio);
+			break;
+		}
 	}
+	return 0;
 fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wma.c b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
index 62d4393..bea0485 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, 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
@@ -185,10 +185,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wma_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
index a83fce9..98d1b30 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, 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
@@ -245,10 +245,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wmapro_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index bfd4c48..edb1e7d 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, 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
@@ -249,6 +249,8 @@
 	int len;
 	static int t_len;
 
+	if (count < 0)
+		return 0;
 	len = count > 63 ? 63 : count;
 	if (copy_from_user(l_buf + 20 , buf, len)) {
 		pr_info("Unable to copy data from user space\n");
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 9a7a41c..4ce9b030 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -443,6 +443,7 @@
 
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
+
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -613,6 +614,7 @@
 	}
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
+
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -623,15 +625,17 @@
 			__func__);
 		goto done;
 	}
-	if (session_id > SESSION_MAX) {
+	if (session_id > (SESSION_MAX + 1)) {
 		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
 		goto done;
 	}
 
 	mutex_lock(&rtac_asm_apr_mutex);
-	if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
-		pr_err("%s: APR not initialized\n", __func__);
-		goto err;
+	if (session_id < SESSION_MAX+1) {
+		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+			pr_err("%s: APR not initialized\n", __func__);
+			goto err;
+		}
 	}
 
 	/* Set globals for copy of returned payload */
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 87f259d..00dba96 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -169,10 +169,9 @@
 
 };
 
-static irqreturn_t adreno_isr(int irq, void *data)
+static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
 {
 	irqreturn_t result;
-	struct kgsl_device *device = data;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	result = adreno_dev->gpudev->irq_handler(adreno_dev);
@@ -490,7 +489,7 @@
 	if (status != 0)
 		goto error;
 
-	status = kgsl_device_platform_probe(device, adreno_isr);
+	status = kgsl_device_platform_probe(device);
 	if (status)
 		goto error_close_rb;
 
@@ -1444,6 +1443,7 @@
 	.irqctrl = adreno_irqctrl,
 	.gpuid = adreno_gpuid,
 	.snapshot = adreno_snapshot,
+	.irq_handler = adreno_irq_handler,
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e38037c..321c59e 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2295,6 +2295,14 @@
 	return 0;
 }
 
+static irqreturn_t kgsl_irq_handler(int irq, void *data)
+{
+	struct kgsl_device *device = data;
+
+	return device->ftbl->irq_handler(device);
+
+}
+
 static const struct file_operations kgsl_fops = {
 	.owner = THIS_MODULE,
 	.release = kgsl_release,
@@ -2455,8 +2463,7 @@
 }
 EXPORT_SYMBOL(kgsl_register_device);
 
-int kgsl_device_platform_probe(struct kgsl_device *device,
-			       irqreturn_t (*dev_isr) (int, void*))
+int kgsl_device_platform_probe(struct kgsl_device *device)
 {
 	int result;
 	int status = -EINVAL;
@@ -2504,7 +2511,7 @@
 		goto error_release_mem;
 	}
 
-	status = request_irq(device->pwrctrl.interrupt_num, dev_isr,
+	status = request_irq(device->pwrctrl.interrupt_num, kgsl_irq_handler,
 			     IRQF_TRIGGER_HIGH, device->name, device);
 	if (status) {
 		KGSL_DRV_ERR(device, "request_irq(%d) failed: %d\n",
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 7d3cfca..b42e606 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -94,6 +94,7 @@
 	unsigned int (*gpuid)(struct kgsl_device *device);
 	void * (*snapshot)(struct kgsl_device *device, void *snapshot,
 		int *remain, int hang);
+	irqreturn_t (*irq_handler)(struct kgsl_device *device);
 	/* Optional functions - these functions are not mandatory.  The
 	   driver will check that the function pointer is not NULL before
 	   calling the hook */
@@ -340,8 +341,8 @@
 int kgsl_unregister_ts_notifier(struct kgsl_device *device,
 				struct notifier_block *nb);
 
-int kgsl_device_platform_probe(struct kgsl_device *device,
-		irqreturn_t (*dev_isr) (int, void*));
+int kgsl_device_platform_probe(struct kgsl_device *device);
+
 void kgsl_device_platform_remove(struct kgsl_device *device);
 
 const char *kgsl_pwrstate_to_str(unsigned int state);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8c29535..5902361 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -206,11 +206,10 @@
 	},
 };
 
-static irqreturn_t z180_isr(int irq, void *data)
+static irqreturn_t z180_irq_handler(struct kgsl_device *device)
 {
 	irqreturn_t result = IRQ_NONE;
 	unsigned int status;
-	struct kgsl_device *device = (struct kgsl_device *) data;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
 	z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status);
@@ -546,7 +545,7 @@
 	if (status != 0)
 		goto error;
 
-	status = kgsl_device_platform_probe(device, z180_isr);
+	status = kgsl_device_platform_probe(device);
 	if (status)
 		goto error_close_ringbuffer;
 
@@ -945,6 +944,7 @@
 	.power_stats = z180_power_stats,
 	.irqctrl = z180_irqctrl,
 	.gpuid = z180_gpuid,
+	.irq_handler = z180_irq_handler,
 	/* Optional functions */
 	.drawctxt_create = NULL,
 	.drawctxt_destroy = z180_drawctxt_destroy,
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index ff4f426..d60f4b7 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -2372,8 +2372,7 @@
 		/* later we need to add check for live snapshot mode. */
 		if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
 			(vfe31_ctrl->snapshot_frame_cnt %
-			vfe31_ctrl->frame_skip_cnt))) {
-			vfe31_ctrl->vfe_capture_count--;
+				vfe31_ctrl->frame_skip_cnt))) {
 			/* if last frame to be captured: */
 			if (vfe31_ctrl->vfe_capture_count == 0) {
 				/* stop the bus output:write master enable = 0*/
@@ -2403,7 +2402,6 @@
 				vfe31_ctrl->frame_skip_pattern = 0xffffffff;
 			} /*if snapshot count is 0*/
 		} /*if frame is not being dropped*/
-		vfe31_ctrl->snapshot_frame_cnt++;
 		/* then do reg_update. */
 		msm_camera_io_w(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	} /* if snapshot mode. */
@@ -2503,6 +2501,17 @@
 		else
 			vfe31_ctrl->sync_timer_repeat_count--;
 	}
+	if ((vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+		if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
+			(vfe31_ctrl->snapshot_frame_cnt %
+				vfe31_ctrl->frame_skip_cnt))) {
+			vfe31_ctrl->vfe_capture_count--;
+		}
+		vfe31_ctrl->snapshot_frame_cnt++;
+	}
 }
 
 static void vfe31_process_error_irq(uint32_t errStatus)
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 77ad02e..a027a2d 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -73,7 +73,7 @@
 	u32 i;
 	u32 found = false;
 
-	for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+	for (i = 0; i < VID_ENC_MAX_ENCODER_CLIENTS; i++) {
 		if (!venc_p.venc_clients[i].venc_client.vcd_handle) {
 			found = true;
 			break;
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index fb586be..c12636c 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -1341,10 +1341,10 @@
 		if (rc)
 			WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
 
+		wfd_stats_deinit(&inst->stats);
 		kfree(inst);
 	}
 
-	wfd_stats_deinit(&inst->stats);
 	WFD_MSG_DBG("wfd_close: X\n");
 	return 0;
 }
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 1d3cf17..420fc19 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -869,7 +869,7 @@
 		client_ctx->h264_mv_ion_handle = ion_import_fd(
 					client_ctx->user_ion_client,
 					vcd_h264_mv_buffer->pmem_fd);
-		if (!client_ctx->h264_mv_ion_handle) {
+		if (IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 			ERR("%s(): get_ION_handle failed\n", __func__);
 			goto import_ion_error;
 		}
@@ -916,12 +916,16 @@
 	else
 		return true;
 ion_map_error:
-	if (vcd_h264_mv_buffer->kernel_virtual_addr)
+	if (vcd_h264_mv_buffer->kernel_virtual_addr) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 				client_ctx->h264_mv_ion_handle);
-	if (client_ctx->h264_mv_ion_handle)
+		vcd_h264_mv_buffer->kernel_virtual_addr = NULL;
+	}
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		ion_free(client_ctx->user_ion_client,
 			client_ctx->h264_mv_ion_handle);
+		 client_ctx->h264_mv_ion_handle = NULL;
+	}
 import_ion_error:
 	return false;
 }
@@ -990,7 +994,7 @@
 	vcd_status = vcd_set_property(client_ctx->vcd_handle,
 				      &vcd_property_hdr, &h264_mv_buffer_size);
 
-	if (client_ctx->h264_mv_ion_handle != NULL) {
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
 		ion_unmap_iommu(client_ctx->user_ion_client,
@@ -999,6 +1003,7 @@
 				VIDEO_MAIN_POOL);
 		ion_free(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
+		 client_ctx->h264_mv_ion_handle = NULL;
 	}
 
 	if (vcd_status)
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index dda81ed..f633235 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -417,16 +417,21 @@
 			buf_addr_table[i].client_data);
 			buf_addr_table[i].client_data = NULL;
 		}
-		if (buf_addr_table[i].buff_ion_handle) {
-			ion_unmap_kernel(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle);
-			ion_unmap_iommu(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle,
-					VIDEO_DOMAIN,
-					VIDEO_MAIN_POOL);
-			ion_free(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle);
-			buf_addr_table[i].buff_ion_handle = NULL;
+		if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
+			if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+				ion_unmap_kernel(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle);
+				ion_unmap_iommu(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle,
+						VIDEO_DOMAIN,
+						VIDEO_MAIN_POOL);
+				ion_free(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle);
+				buf_addr_table[i].buff_ion_handle = NULL;
+			}
 		}
 	}
 	if (client_ctx->vcd_h264_mv_buffer.client_data) {
@@ -434,16 +439,18 @@
 		client_ctx->vcd_h264_mv_buffer.client_data);
 		client_ctx->vcd_h264_mv_buffer.client_data = NULL;
 	}
-	if (client_ctx->h264_mv_ion_handle) {
-		ion_unmap_kernel(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle);
-		ion_unmap_iommu(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle,
-				VIDEO_DOMAIN,
-				VIDEO_MAIN_POOL);
-		ion_free(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle);
-		client_ctx->h264_mv_ion_handle = NULL;
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+		if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+			ion_unmap_kernel(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+			ion_unmap_iommu(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle,
+					VIDEO_DOMAIN,
+					VIDEO_MAIN_POOL);
+			ion_free(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+			client_ctx->h264_mv_ion_handle = NULL;
+		}
 	}
 bail_out_cleanup:
 	return;
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
new file mode 100644
index 0000000..0104abc
--- /dev/null
+++ b/include/linux/iopoll.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_IOPOLL_H
+#define _LINUX_IOPOLL_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+
+/**
+ * readl_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
+({ \
+	unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \
+	might_sleep_if(timeout_us); \
+	for (;;) { \
+		(val) = readl(addr); \
+		if ((cond) || (timeout_us && time_after(jiffies, timeout))) \
+			break; \
+		if (sleep_us) \
+			usleep_range(1, sleep_us); \
+	} \
+	(cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
+ * readl_poll - Periodically poll an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ *
+ * Must not be called from atomic context if sleep_us is used.
+ */
+#define readl_poll(addr, val, cond, sleep_us) \
+	readl_poll_timeout(addr, val, cond, sleep_us, 0)
+
+/**
+ * readl_tight_poll_timeout - Tight-loop on an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if timeout_us is used.
+ */
+#define readl_tight_poll_timeout(addr, val, cond, timeout_us) \
+	readl_poll_timeout(addr, val, cond, 0, timeout_us)
+
+/**
+ * readl_tight_poll - Tight-loop on an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ *
+ * May be called from atomic context.
+ */
+#define readl_tight_poll(addr, val, cond) \
+	readl_poll_timeout(addr, val, cond, 0, 0)
+
+#endif /* _LINUX_IOPOLL_H */
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
index 65e4728..70902bc 100644
--- a/include/linux/mfd/wcd9xxx/wcd9304_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -517,7 +517,7 @@
 #define SITAR_A_CDC_CLK_TX_I2S_CTL			(0x306)
 #define SITAR_A_CDC_CLK_TX_I2S_CTL__POR			(0x00000003)
 #define SITAR_A_CDC_CLK_OTHR_RESET_CTL			(0x307)
-#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR			(0x00000010)
 #define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL			(0x308)
 #define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR			(0x00000000)
 #define SITAR_A_CDC_CLK_OTHR_CTL			(0x30A)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3b5ad95..37ee9b1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5371,7 +5371,7 @@
 	release_sock(sk);
 }
 
-int l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
+static void l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
 {
 	struct l2cap_pinfo *pi;
 	struct sock *sk;
@@ -5385,11 +5385,14 @@
 
 	BT_DBG("sk %p", sk);
 
+	if (!sk)
+		return;
+
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_CONNECTED && !l2cap_pi(sk)->amp_id) {
 		release_sock(sk);
-		return 0;
+		return;
 	}
 
 	pi = l2cap_pi(sk);
@@ -5516,7 +5519,6 @@
 	}
 
 	release_sock(sk);
-	return 0;
 }
 
 static void l2cap_logical_link_worker(struct work_struct *work)
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 3229bce..1fe28a2 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1474,6 +1474,8 @@
 	pr_err("%s %d\n", __func__, event);
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+			0x00);
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
 			0x01);
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x08);
@@ -1996,7 +1998,6 @@
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
 	usleep_range(50, 50);
 	sitar->clock_active = true;
 	return 0;
@@ -2005,7 +2006,6 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	pr_err("%s\n", __func__);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
 	ndelay(160);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -3962,6 +3962,9 @@
 	/*enable HPF filter for TX paths */
 	{SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
 	{SITAR_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+
+	/*enable External clock select*/
+	{SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01},
 };
 
 static void sitar_codec_init_reg(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 4c9cef9..3f86962 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -293,6 +293,28 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "VOICE_STUB",
 	},
+	{
+		.playback = {
+			.stream_name = "VoLTE Playback",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.capture = {
+			.stream_name = "VoLTE Capture",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "VoLTE",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 18f95f6..0f74afb 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -441,6 +441,8 @@
 
 	if (val == MSM_FRONTEND_DAI_CS_VOICE)
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
+	else if (val == MSM_FRONTEND_DAI_VOLTE)
+		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOIP_SESSION_NAME);
 
@@ -1060,6 +1062,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1069,6 +1074,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1078,6 +1086,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1090,6 +1101,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -1102,6 +1116,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -1114,6 +1131,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -1123,6 +1143,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -1155,6 +1178,24 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_TX_VoLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX_VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_VoLTE",
+	MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOLTE, 1, 0,
+	msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX_VoLTE", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
@@ -1446,6 +1487,8 @@
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
 		0, 0, 0, 0),
@@ -1568,6 +1611,9 @@
 	SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
 				ARRAY_SIZE(tx_voip_mixer_controls)),
+	SND_SOC_DAPM_MIXER("VoLTE_Tx Mixer",
+				SND_SOC_NOPM, 0, 0, tx_volte_mixer_controls,
+				ARRAY_SIZE(tx_volte_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -1676,30 +1722,37 @@
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
 	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
 	{"HDMI", NULL, "HDMI_DL_HL"},
@@ -1710,6 +1763,12 @@
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
 	{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
+	{"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
+	{"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
+	{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
+	{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
+	{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+	{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
 	{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
 	{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
 	{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index b254381..e5d8638 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -56,6 +56,7 @@
 	MSM_FRONTEND_DAI_AFE_RX,
 	MSM_FRONTEND_DAI_AFE_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB,
+	MSM_FRONTEND_DAI_VOLTE,
 	MSM_FRONTEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 5a0f27a..59b8bbd 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -29,7 +29,7 @@
 #include "msm-pcm-voice.h"
 #include "qdsp6/q6voice.h"
 
-static struct msm_voice voice_info;
+static struct msm_voice voice_info[VOICE_SESSION_INDEX_MAX];
 
 static struct snd_pcm_hardware msm_pcm_hardware = {
 
@@ -49,6 +49,13 @@
 
 	.fifo_size =            0,
 };
+static int is_volte(struct msm_voice *pvolte)
+{
+	if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
+		return true;
+	else
+		return false;
+}
 
 static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
@@ -78,8 +85,17 @@
 static int msm_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct msm_voice *voice = &voice_info;
+	struct msm_voice *voice;
 
+	if (!strncmp("VoLTE", substream->pcm->id, 5)) {
+		voice = &voice_info[VOLTE_SESSION_INDEX];
+		pr_debug("%s: Open VoLTE Substream Id=%s\n",
+				__func__, substream->pcm->id);
+	} else {
+		voice = &voice_info[VOICE_SESSION_INDEX];
+		pr_debug("%s: Open VOICE Substream Id=%s\n",
+				__func__, substream->pcm->id);
+	}
 	mutex_lock(&voice->lock);
 
 	runtime->hw = msm_pcm_hardware;
@@ -90,7 +106,8 @@
 		voice->capture_substream = substream;
 
 	voice->instance++;
-	pr_debug(" %s: instance: %d\n", __func__ , voice->instance);
+	pr_debug("%s: Instance = %d, Stream ID = %s\n",
+			__func__ , voice->instance, substream->pcm->id);
 	runtime->private_data = voice;
 
 	mutex_unlock(&voice->lock);
@@ -129,6 +146,7 @@
 
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *prtd = runtime->private_data;
+	uint16_t session_id = 0;
 	int ret = 0;
 
 	mutex_lock(&prtd->lock);
@@ -140,7 +158,11 @@
 	prtd->instance--;
 	if (!prtd->playback_start && !prtd->capture_start) {
 		pr_debug("end voice call\n");
-		voc_end_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
+		if (is_volte(prtd))
+			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else
+			session_id = voc_get_session_id(VOICE_SESSION_NAME);
+		voc_end_voice_call(session_id);
 	}
 	mutex_unlock(&prtd->lock);
 
@@ -151,6 +173,7 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *prtd = runtime->private_data;
+	uint16_t session_id = 0;
 
 	mutex_lock(&prtd->lock);
 
@@ -159,9 +182,13 @@
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		ret = msm_pcm_capture_prepare(substream);
 
-	if (prtd->playback_start && prtd->capture_start)
-		voc_start_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
-
+	if (prtd->playback_start && prtd->capture_start) {
+		if (is_volte(prtd))
+			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else
+			session_id = voc_get_session_id(VOICE_SESSION_NAME);
+		voc_start_voice_call(session_id);
+	}
 	mutex_unlock(&prtd->lock);
 
 	return ret;
@@ -189,12 +216,26 @@
 				struct snd_ctl_elem_value *ucontrol)
 {
 	int volume = ucontrol->value.integer.value[0];
-
 	pr_debug("%s: volume: %d\n", __func__, volume);
-
 	voc_set_rx_vol_index(voc_get_session_id(VOICE_SESSION_NAME),
-			     RX_PATH,
-			     volume);
+						RX_PATH, volume);
+	return 0;
+}
+
+static int msm_volte_volume_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_volte_volume_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int volume = ucontrol->value.integer.value[0];
+	pr_debug("%s: volume: %d\n", __func__, volume);
+	voc_set_rx_vol_index(voc_get_session_id(VOLTE_SESSION_NAME),
+						RX_PATH, volume);
 	return 0;
 }
 
@@ -217,6 +258,25 @@
 	return 0;
 }
 
+static int msm_volte_mute_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_volte_mute_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_tx_mute(voc_get_session_id(VOLTE_SESSION_NAME), TX_PATH, mute);
+
+	return 0;
+}
+
 static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -237,6 +297,26 @@
 	return 0;
 }
 
+static int msm_volte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] =
+		voc_get_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME));
+	return 0;
+}
+
+static int msm_volte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME), mute);
+
+	return 0;
+}
+
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
 		SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -343,6 +423,13 @@
 				msm_voice_slowtalk_get, msm_voice_slowtalk_put),
 	SOC_SINGLE_EXT("FENS Enable", SND_SOC_NOPM, 0, 1, 0,
 				msm_voice_fens_get, msm_voice_fens_put),
+	SOC_SINGLE_EXT("VoLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+			msm_volte_rx_device_mute_get,
+			msm_volte_rx_device_mute_put),
+	SOC_SINGLE_EXT("VoLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+				msm_volte_mute_get, msm_volte_mute_put),
+	SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+				msm_volte_volume_get, msm_volte_volume_put),
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
@@ -402,7 +489,8 @@
 static int __init msm_soc_platform_init(void)
 {
 	memset(&voice_info, 0, sizeof(voice_info));
-	mutex_init(&voice_info.lock);
+	mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
+	mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
 
 	return platform_driver_register(&msm_pcm_driver);
 }
diff --git a/sound/soc/msm/msm-pcm-voice.h b/sound/soc/msm/msm-pcm-voice.h
index 71bdbc1..aa00577 100644
--- a/sound/soc/msm/msm-pcm-voice.h
+++ b/sound/soc/msm/msm-pcm-voice.h
@@ -13,6 +13,11 @@
 #define _MSM_PCM_VOICE_H
 #include <sound/apr_audio.h>
 
+enum {
+	VOICE_SESSION_INDEX,
+	VOLTE_SESSION_INDEX,
+	VOICE_SESSION_INDEX_MAX,
+};
 
 struct msm_voice {
 	struct snd_pcm_substream *playback_substream;
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index aec1bb2..2301472 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -691,7 +691,7 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
-	int32_t media_type = 0;
+	uint32_t media_type = 0;
 	uint32_t rate_type = 0;
 
 	mutex_lock(&prtd->lock);
@@ -988,7 +988,7 @@
 static int voip_get_media_type(uint32_t mode,
 				unsigned int samp_rate)
 {
-	int32_t media_type;
+	uint32_t media_type;
 
 	pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
 		mode, samp_rate);
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 9dad1bb..04b0fb0 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -129,8 +129,8 @@
 		if (!clk_users) {
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			clk_disable_unprepare(codec_clk);
 			sitar_mclk_enable(codec, 0);
+			clk_disable_unprepare(codec_clk);
 		}
 	}
 	return 0;
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 3745b17..676ecf1 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -143,14 +143,14 @@
 	s32				result = 0;
 	struct adm_set_params_command	adm_params;
 	int index = afe_get_port_index(port_id);
-
-	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
-
 	if (index < 0 || index >= AFE_MAX_PORTS) {
 		pr_err("%s: invalid port idx %d portid %d\n",
 				__func__, index, port_id);
-		goto done;
+		return 0;
 	}
+
+	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
+
 	if (!aud_cal || aud_cal->cal_size == 0) {
 		pr_debug("%s: No ADM cal to send for port_id = %d!\n",
 			__func__, port_id);
@@ -580,16 +580,15 @@
 	int ret = 0, i = 0;
 	/* Assumes port_ids have already been validated during adm_open */
 	int index = afe_get_port_index(copp_id);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d token %d\n",
+					__func__, index, copp_id);
+		return 0;
+	}
 
 	pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
 		 __func__, session_id, path, num_copps, port_id[0]);
 
-	if (index < 0 || index >= AFE_MAX_PORTS) {
-		pr_err("%s: invalid port idx %d token %d\n",
-					__func__, index, copp_id);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
 	route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	route.hdr.pkt_size = sizeof(route);
@@ -614,7 +613,7 @@
 		pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
 			 port_id[i], tmp);
 
-		if ((tmp >= 0) && (tmp < AFE_MAX_PORTS))
+		if (tmp >= 0 && tmp < AFE_MAX_PORTS)
 			route.session[0].copp_id[i] =
 					atomic_read(&this_adm.copp_id[tmp]);
 	}
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 6050929..f4b4dd1 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -33,6 +33,7 @@
 
 #define VOC_PATH_PASSIVE 0
 #define VOC_PATH_FULL 1
+#define VOC_PATH_VOLTE_PASSIVE 2
 
 /* CVP CAL Size: 245760 = 240 * 1024 */
 #define CVP_CAL_SIZE 245760
@@ -145,6 +146,9 @@
 	if (name != NULL) {
 		if (!strncmp(name, "Voice session", 13))
 			session_id = common.voice[VOC_PATH_PASSIVE].session_id;
+		else if (!strncmp(name, "VoLTE session", 13))
+			session_id =
+			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
 		else
 			session_id = common.voice[VOC_PATH_FULL].session_id;
 
@@ -180,6 +184,11 @@
 	return (session_id == common.voice[VOC_PATH_FULL].session_id);
 }
 
+static bool is_volte_session(u16 session_id)
+{
+	return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
+}
+
 static int voice_apr_register(void)
 {
 	pr_debug("%s\n", __func__);
@@ -250,6 +259,65 @@
 	return -ENODEV;
 }
 
+static int voice_send_dual_control_cmd(struct voice_data *v)
+{
+	int ret = 0;
+	struct mvm_modem_dual_control_session_cmd mvm_voice_ctl_cmd;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_mvm = common.apr_q6_mvm;
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: VoLTE command to MVM\n", __func__);
+	if (is_volte_session(v->session_id)) {
+		mvm_handle = voice_get_mvm_handle(v);
+		mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
+						APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+		mvm_voice_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE(
+						APR_HDR_SIZE,
+						sizeof(mvm_voice_ctl_cmd) -
+						APR_HDR_SIZE);
+		pr_debug("%s: send mvm Voice Ctl pkt size = %d\n",
+			__func__, mvm_voice_ctl_cmd.hdr.pkt_size);
+		mvm_voice_ctl_cmd.hdr.src_port = v->session_id;
+		mvm_voice_ctl_cmd.hdr.dest_port = mvm_handle;
+		mvm_voice_ctl_cmd.hdr.token = 0;
+		mvm_voice_ctl_cmd.hdr.opcode =
+					VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL;
+		mvm_voice_ctl_cmd.voice_ctl.enable_flag = true;
+		v->mvm_state = CMD_STATUS_FAIL;
+
+		ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_voice_ctl_cmd);
+		if (ret < 0) {
+			pr_err("%s: Error sending MVM Voice CTL CMD\n",
+							__func__);
+			ret = -EINVAL;
+			goto fail;
+		}
+		ret = wait_event_timeout(v->mvm_wait,
+				(v->mvm_state == CMD_STATUS_SUCCESS),
+				msecs_to_jiffies(TIMEOUT_MS));
+		if (!ret) {
+			pr_err("%s: wait_event timeout\n", __func__);
+			ret = -EINVAL;
+			goto fail;
+		}
+	}
+	ret = 0;
+fail:
+	return ret;
+}
+
+
 static int voice_create_mvm_cvs_session(struct voice_data *v)
 {
 	int ret = 0;
@@ -281,7 +349,8 @@
 	/* send cmd to create mvm session and wait for response */
 
 	if (!mvm_handle) {
-		if (is_voice_session(v->session_id)) {
+		if (is_voice_session(v->session_id) ||
+				is_volte_session(v->session_id)) {
 			mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -297,9 +366,15 @@
 			mvm_session_cmd.hdr.token = 0;
 			mvm_session_cmd.hdr.opcode =
 				VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+			if (is_volte_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				"default volte voice",
+				sizeof(mvm_session_cmd.mvm_session.name));
+			} else {
 			strlcpy(mvm_session_cmd.mvm_session.name,
 				"default modem voice",
 				sizeof(mvm_session_cmd.mvm_session.name));
+			}
 
 			v->mvm_state = CMD_STATUS_FAIL;
 
@@ -356,7 +431,8 @@
 	}
 	/* send cmd to create cvs session */
 	if (!cvs_handle) {
-		if (is_voice_session(v->session_id)) {
+		if (is_voice_session(v->session_id) ||
+			is_volte_session(v->session_id)) {
 			pr_debug("%s: creating CVS passive session\n",
 				 __func__);
 
@@ -373,10 +449,15 @@
 			cvs_session_cmd.hdr.token = 0;
 			cvs_session_cmd.hdr.opcode =
 				VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+			if (is_volte_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				"default volte voice",
+				sizeof(mvm_session_cmd.mvm_session.name));
+			} else {
 			strlcpy(cvs_session_cmd.cvs_session.name,
 				"default modem voice",
 				sizeof(cvs_session_cmd.cvs_session.name));
-
+			}
 			v->cvs_state = CMD_STATUS_FAIL;
 
 			ret = apr_send_pkt(apr_cvs,
@@ -3350,6 +3431,11 @@
 			pr_err("create mvm and cvs failed\n");
 			goto fail;
 		}
+		ret = voice_send_dual_control_cmd(v);
+		if (ret < 0) {
+			pr_err("Err Dual command failed\n");
+			goto fail;
+		}
 		ret = voice_setup_vocproc(v);
 		if (ret < 0) {
 			pr_err("setup voice failed\n");
@@ -3373,7 +3459,6 @@
 
 		v->voc_state = VOC_RUN;
 	}
-
 fail:	mutex_unlock(&v->lock);
 	return ret;
 }
@@ -3471,6 +3556,7 @@
 			case VSS_ICOMMON_CMD_SET_NETWORK:
 			case VSS_ICOMMON_CMD_SET_VOICE_TIMING:
 			case VSS_IWIDEVOICE_CMD_SET_WIDEVOICE:
+			case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				v->mvm_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->mvm_wait);
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 0fc7a01..3310abd 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -107,6 +107,15 @@
 #define VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION	0x000110FF
 /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
 
+#define VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL	0x00011327
+/*
+ * VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL
+ * Description: This command is required to let MVM know
+ * who is in control of session.
+ * Payload: Defined by vss_imvm_cmd_set_policy_dual_control_t.
+ * Result: Wait for APRV2_IBASIC_RSP_RESULT response.
+ */
+
 #define VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION	0x000110FE
 /* Create a new full control MVM session. */
 
@@ -228,6 +237,12 @@
 	*/
 } __packed;
 
+
+struct vss_imvm_cmd_set_policy_dual_control_t {
+	bool enable_flag;
+	/* Set to TRUE to enable modem state machine control */
+} __packed;
+
 struct vss_iwidevoice_cmd_set_widevoice_t {
 	uint32_t enable;
 	/* WideVoice enable/disable; possible values:
@@ -251,6 +266,11 @@
 	struct vss_imvm_cmd_create_control_session_t mvm_session;
 } __packed;
 
+struct mvm_modem_dual_control_session_cmd {
+	struct apr_hdr hdr;
+	struct vss_imvm_cmd_set_policy_dual_control_t voice_ctl;
+} __packed;
+
 struct mvm_set_tty_mode_cmd {
 	struct apr_hdr hdr;
 	struct vss_istream_cmd_set_tty_mode_t tty_mode;
@@ -878,7 +898,7 @@
 	void *buf;
 };
 
-#define MAX_VOC_SESSIONS 2
+#define MAX_VOC_SESSIONS 3
 #define SESSION_ID_BASE 0xFFF0
 
 struct common_data {
@@ -947,6 +967,7 @@
 
 #define VOICE_SESSION_NAME "Voice session"
 #define VOIP_SESSION_NAME "VoIP session"
+#define VOLTE_SESSION_NAME "VoLTE session"
 uint16_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set);