Merge "msm: ipa: fix unclocked IPA register access"
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index 3c3a242..af5cbc6 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -11,6 +11,8 @@
 - qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
 - qcom,iommu-pmu-ncounters: Number of PMU counters per group.
 - qcom,iommu-pmu-event-classes: List of event classes supported.
+- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
+  access to the IOMMU configuration registers
 
 - List of sub nodes, one for each of the translation context banks supported.
     Required properties for each sub-node:
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_router.h b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
index c68c783..894379e 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_router.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -31,6 +31,11 @@
 	MSM_IPC_ROUTER_WRITE_DONE,
 };
 
+struct comm_mode_info {
+	int mode;
+	void *xprt_info;
+};
+
 struct msm_ipc_port {
 	struct list_head list;
 
@@ -39,6 +44,7 @@
 	uint32_t type;
 	unsigned flags;
 	spinlock_t port_lock;
+	struct comm_mode_info mode_info;
 
 	struct list_head incomplete;
 	struct mutex incomplete_lock;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index c31c969..a328b2b 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1245,6 +1245,67 @@
 	return 0;
 }
 
+static int msm_ipc_router_send_remove_client(struct comm_mode_info *mode_info,
+					uint32_t node_id, uint32_t port_id)
+{
+	union rr_control_msg msg;
+	struct msm_ipc_router_xprt_info *tmp_xprt_info;
+	int mode;
+	void *xprt_info;
+	int rc = 0;
+
+	if (!mode_info) {
+		pr_err("%s: NULL mode_info\n", __func__);
+		return -EINVAL;
+	}
+	mode = mode_info->mode;
+	xprt_info = mode_info->xprt_info;
+
+	msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
+	msg.cli.node_id = node_id;
+	msg.cli.port_id = port_id;
+
+	if ((mode == SINGLE_LINK_MODE) && xprt_info) {
+		mutex_lock(&xprt_info_list_lock);
+		list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
+			if (tmp_xprt_info != xprt_info)
+				continue;
+			msm_ipc_router_send_control_msg(tmp_xprt_info, &msg);
+			break;
+		}
+		mutex_unlock(&xprt_info_list_lock);
+	} else if ((mode == SINGLE_LINK_MODE) && !xprt_info) {
+		broadcast_ctl_msg_locally(&msg);
+	} else if (mode == MULTI_LINK_MODE) {
+		broadcast_ctl_msg(&msg);
+		broadcast_ctl_msg_locally(&msg);
+	} else if (mode != NULL_MODE) {
+		pr_err("%s: Invalid mode(%d) + xprt_inf(%p) for %08x:%08x\n",
+			__func__, mode, xprt_info, node_id, port_id);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static void update_comm_mode_info(struct comm_mode_info *mode_info,
+				  struct msm_ipc_router_xprt_info *xprt_info)
+{
+	if (!mode_info) {
+		pr_err("%s: NULL mode_info\n", __func__);
+		return;
+	}
+
+	if (mode_info->mode == NULL_MODE) {
+		mode_info->xprt_info = xprt_info;
+		mode_info->mode = SINGLE_LINK_MODE;
+	} else if (mode_info->mode == SINGLE_LINK_MODE &&
+		   mode_info->xprt_info != xprt_info) {
+		mode_info->mode = MULTI_LINK_MODE;
+	}
+
+	return;
+}
+
 static void reset_remote_port_info(uint32_t node_id, uint32_t port_id)
 {
 	struct msm_ipc_router_remote_port *rport_ptr;
@@ -1915,6 +1976,7 @@
 	broadcast_ctl_msg(&ctl);
 	spin_lock_irqsave(&port_ptr->port_lock, flags);
 	port_ptr->type = SERVER_PORT;
+	port_ptr->mode_info.mode = MULTI_LINK_MODE;
 	port_ptr->port_name.service = server->name.service;
 	port_ptr->port_name.instance = server->name.instance;
 	spin_unlock_irqrestore(&port_ptr->port_lock, flags);
@@ -2026,6 +2088,7 @@
 	ret_len = pkt->length;
 	wake_up(&port_ptr->port_rx_wait_q);
 	mutex_unlock(&port_ptr->port_rx_q_lock);
+	update_comm_mode_info(&src->mode_info, NULL);
 	mutex_unlock(&local_ports_lock);
 
 	return ret_len;
@@ -2118,6 +2181,7 @@
 		pr_err("%s: Write on XPRT failed\n", __func__);
 		return ret;
 	}
+	update_comm_mode_info(&src->mode_info, xprt_info);
 
 	RAW_HDR("[w rr_h] "
 		"ver=%i,type=%s,src_nid=%08x,src_port_id=%08x,"
@@ -2407,13 +2471,11 @@
 		 * Server port could have been a client port earlier.
 		 * Send REMOVE_CLIENT message in either case.
 		 */
-		msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
-		msg.cli.node_id = port_ptr->this_port.node_id;
-		msg.cli.port_id = port_ptr->this_port.port_id;
 		RR("x REMOVE_CLIENT id=%d:%08x\n",
-		   msg.cli.node_id, msg.cli.port_id);
-		broadcast_ctl_msg(&msg);
-		broadcast_ctl_msg_locally(&msg);
+		   port_ptr->this_port.node_id, port_ptr->this_port.port_id);
+		msm_ipc_router_send_remove_client(&port_ptr->mode_info,
+			port_ptr->this_port.node_id,
+			port_ptr->this_port.port_id);
 	} else if (port_ptr->type == CONTROL_PORT) {
 		mutex_lock(&control_ports_lock);
 		list_del(&port_ptr->list);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index cafcdd2..32832dd 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -62,6 +62,12 @@
 	IRSC_PORT,
 };
 
+enum {
+	NULL_MODE,
+	SINGLE_LINK_MODE,
+	MULTI_LINK_MODE,
+};
+
 union rr_control_msg {
 	uint32_t cmd;
 	struct {
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 12a3ceb..d316496 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -279,6 +279,8 @@
 	/* 8974 IDs */
 	[126] = MSM_CPU_8974,
 	[184] = MSM_CPU_8974,
+	[185] = MSM_CPU_8974,
+	[186] = MSM_CPU_8974,
 
 	/* 8625 IDs */
 	[127] = MSM_CPU_8625,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7cd9943..2b674ab 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -308,16 +308,28 @@
 
 static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
 {
+	bool had_gpuaddr = false;
+
 	if (entry == NULL)
 		return;
 
+	/*
+	 * Unmap the entry first so that there isn't a period of
+	 * time where kgsl doesn't know about the address range
+	 * but it is still present in the pagetable. Unmapping will
+	 * clear the gpuaddr field, so remember if we had a mapping,
+	 * and an rbtree entry for later.
+	 */
+	had_gpuaddr = entry->memdesc.gpuaddr != 0;
+	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+
 	spin_lock(&entry->priv->mem_lock);
 
 	if (entry->id != 0)
 		idr_remove(&entry->priv->mem_idr, entry->id);
 	entry->id = 0;
 
-	if (entry->memdesc.gpuaddr != 0)
+	if (had_gpuaddr)
 		rb_erase(&entry->node, &entry->priv->mem_rb);
 
 	spin_unlock(&entry->priv->mem_lock);
@@ -325,7 +337,6 @@
 	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	entry->priv = NULL;
 
-	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
 
 	kgsl_mem_entry_put(entry);
 }
@@ -1346,6 +1357,12 @@
 				"invalid gpuaddr %08x\n", gpuaddr);
 		return -EINVAL;
 	}
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+	entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
+
 	trace_kgsl_mem_timestamp_queue(device, entry, context_id,
 				       kgsl_readtimestamp(device, context,
 						  KGSL_TIMESTAMP_RETIRED),
@@ -1445,6 +1462,11 @@
 		return -EINVAL;
 	}
 
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+
 	trace_kgsl_mem_free(entry);
 
 	kgsl_memfree_hist_set_event(entry->priv->pid,
@@ -1470,6 +1492,12 @@
 		KGSL_MEM_INFO(dev_priv->device, "invalid id %d\n", param->id);
 		return -EINVAL;
 	}
+
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+
 	trace_kgsl_mem_free(entry);
 
 	kgsl_memfree_hist_set_event(entry->priv->pid,
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index d63aa79..debba18 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -151,6 +151,8 @@
 #define KGSL_MEMDESC_GLOBAL BIT(1)
 /* The memdesc is frozen during a snapshot */
 #define KGSL_MEMDESC_FROZEN BIT(2)
+/* The memdesc is scheduled to be freed on a timestamp */
+#define KGSL_MEMDESC_FREE_PENDING BIT(3)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index b1960c6..b92ec7f 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -148,12 +148,26 @@
 		if (ret)
 			clk_disable_unprepare(drvdata->pclk);
 	}
+
+	if (ret)
+		goto fail;
+
+	if (drvdata->aclk) {
+		ret = clk_prepare_enable(drvdata->aclk);
+		if (ret) {
+			clk_disable_unprepare(drvdata->clk);
+			clk_disable_unprepare(drvdata->pclk);
+		}
+	}
+
 fail:
 	return ret;
 }
 
 static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
 {
+	if (drvdata->aclk)
+		clk_disable_unprepare(drvdata->aclk);
 	if (drvdata->clk)
 		clk_disable_unprepare(drvdata->clk);
 	clk_disable_unprepare(drvdata->pclk);
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 7ae0b21..059216e 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -129,7 +129,8 @@
 }
 
 static int msm_iommu_parse_dt(struct platform_device *pdev,
-				struct msm_iommu_drvdata *drvdata)
+				struct msm_iommu_drvdata *drvdata,
+				int *needs_alt_core_clk)
 {
 #ifdef CONFIG_OF_DEVICE
 	struct device_node *child;
@@ -169,6 +170,10 @@
 		pr_err("%s: Missing property label\n", __func__);
 		return -EINVAL;
 	}
+
+	*needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node,
+						   "qcom,needs-alt-core-clk");
+
 	drvdata->sec_id = -1;
 	drvdata->ttbr_split = 0;
 #endif
@@ -176,7 +181,8 @@
 }
 
 static int __get_clocks(struct platform_device *pdev,
-				 struct msm_iommu_drvdata *drvdata)
+			struct msm_iommu_drvdata *drvdata,
+			int needs_alt_core_clk)
 {
 	int ret = 0;
 
@@ -199,6 +205,18 @@
 	} else {
 		drvdata->clk = NULL;
 	}
+
+	if (needs_alt_core_clk) {
+		drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk");
+		if (IS_ERR(drvdata->aclk))
+			return PTR_ERR(drvdata->aclk);
+	}
+
+	if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) {
+		ret = clk_round_rate(drvdata->aclk, 1000);
+		clk_set_rate(drvdata->aclk, ret);
+	}
+
 	return 0;
 fail:
 	return ret;
@@ -206,35 +224,13 @@
 
 static void __put_clocks(struct msm_iommu_drvdata *drvdata)
 {
+	if (drvdata->aclk)
+		clk_put(drvdata->aclk);
 	if (drvdata->clk)
 		clk_put(drvdata->clk);
 	clk_put(drvdata->pclk);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	int ret;
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret)
-			clk_disable_unprepare(drvdata->pclk);
-	}
-fail:
-	return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	if (drvdata->clk)
-		clk_disable_unprepare(drvdata->clk);
-	clk_disable_unprepare(drvdata->pclk);
-}
-
 /*
  * Do a basic check of the IOMMU by performing an ATS operation
  * on context bank 0.
@@ -326,6 +322,7 @@
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	int ret;
+	int needs_alt_core_clk = 0;
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
 
@@ -335,7 +332,7 @@
 	}
 
 	if (pdev->dev.of_node) {
-		ret = msm_iommu_parse_dt(pdev, drvdata);
+		ret = msm_iommu_parse_dt(pdev, drvdata, &needs_alt_core_clk);
 		if (ret)
 			goto fail;
 	} else if (pdev->dev.platform_data) {
@@ -382,12 +379,12 @@
 
 	drvdata->dev = &pdev->dev;
 
-	ret = __get_clocks(pdev, drvdata);
+	ret = __get_clocks(pdev, drvdata, needs_alt_core_clk);
 
 	if (ret)
 		goto fail;
 
-	__enable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_on(drvdata);
 
 	msm_iommu_reset(drvdata->base, drvdata->glb_base, drvdata->ncb);
 
@@ -401,7 +398,7 @@
 	msm_iommu_add_drv(drvdata);
 	platform_set_drvdata(pdev, drvdata);
 
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 
 	pmon_info = msm_iommu_pm_alloc(&pdev->dev);
 	if (pmon_info != NULL) {
@@ -430,7 +427,7 @@
 	return 0;
 
 fail_clk:
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 	__put_clocks(drvdata);
 fail:
 	return ret;
@@ -618,9 +615,9 @@
 		goto fail;
 	}
 
-	__enable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_on(drvdata);
 	__program_m2v_tables(drvdata, ctx_drvdata);
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 
 	dev_info(&pdev->dev, "context %s using bank %d\n", ctx_drvdata->name,
 							   ctx_drvdata->num);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 7fc8810..82a4f3c 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -316,6 +316,9 @@
 	case HAL_EXTRADATA_ASPECT_RATIO:
 		ret = HFI_PROPERTY_PARAM_INDEX_EXTRADATA;
 		break;
+	case HAL_EXTRADATA_MPEG2_SEQDISP:
+		ret = HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index bf646a2..511a478 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -66,6 +66,7 @@
 	"Extradata input crop",
 	"Extradata digital zoom",
 	"Extradata aspect ratio",
+	"Extradata mpeg2 seqdisp",
 };
 
 static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
@@ -203,7 +204,7 @@
 		.name = "Extradata Type",
 		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
-		.maximum = V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+		.maximum = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP,
 		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
 		.menu_skip_mask = ~(
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -223,7 +224,8 @@
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
-			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO)
+			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP)
 			),
 		.qmenu = mpeg_video_vidc_extradata,
 		.step = 0,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 4fc7518..17f4590 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2276,6 +2276,9 @@
 	case V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO:
 		ret = HAL_EXTRADATA_ASPECT_RATIO;
 		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
+		ret = HAL_EXTRADATA_MPEG2_SEQDISP;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
 		break;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 1311752..bb72da7 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -75,7 +75,8 @@
 #define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
 #define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
 #define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
-#define HFI_EXTRADATA_AFD_UD				0x0000000B
+#define HFI_EXTRADATA_AFD_UD			0x0000000B
+#define HFI_EXTRADATA_MPEG2_SEQDISP		0x0000000D
 #define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
 #define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
 #define HFI_EXTRADATA_INDEX					0x7F100002
@@ -191,6 +192,8 @@
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
 #define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
+#define HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x016)
 
 #define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
 	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 6672d7b..bf1c70b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -95,6 +95,7 @@
 	HAL_EXTRADATA_NUM_CONCEALED_MB,
 	HAL_EXTRADATA_METADATA_FILLER,
 	HAL_EXTRADATA_ASPECT_RATIO,
+	HAL_EXTRADATA_MPEG2_SEQDISP
 };
 
 enum hal_property {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e12b9b4..c8fdc6b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1384,17 +1384,17 @@
 			 *  The result is saved with the response so that
 			 *  the ufs_core layer will handle it.
 			 */
-			result |= DID_OK << 16;
+			result = DID_OK << 16;
 			ufshcd_copy_query_response(hba, lrbp);
 			break;
 		case UPIU_TRANSACTION_REJECT_UPIU:
 			/* TODO: handle Reject UPIU Response */
-			result |= DID_ERROR << 16;
+			result = DID_ERROR << 16;
 			dev_err(hba->dev,
 				"Reject UPIU not fully implemented\n");
 			break;
 		default:
-			result |= DID_ERROR << 16;
+			result = DID_ERROR << 16;
 			dev_err(hba->dev,
 				"Unexpected request response code = %x\n",
 				result);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index b89f608..c5aa7e5 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2280,7 +2280,7 @@
 		bam_props.phys_addr = dd->bam.phys_addr;
 		bam_props.virt_addr = dd->bam.base;
 		bam_props.irq       = dd->bam.irq;
-		bam_props.manage    = SPS_BAM_MGR_LOCAL;
+		bam_props.manage    = SPS_BAM_MGR_DEVICE_REMOTE;
 		bam_props.summing_threshold = 0x10;
 
 		rc = sps_register_bam_device(&bam_props, &bam_handle);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 991cf2e..f01a078 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -199,8 +199,8 @@
 #define TSENS0_8X10_POINT1_SHIFT	16
 #define TSENS0_8X10_POINT2_SHIFT	22
 #define TSENS1_8X10_POINT2_SHIFT	6
-#define TSENS_8X10_BASE0_MASK		0xf
-#define TSENS_8X10_BASE1_MASK		0xf0
+#define TSENS_8X10_BASE0_MASK		0xff
+#define TSENS_8X10_BASE1_MASK		0xff00
 #define TSENS0_8X10_POINT1_MASK		0x3f0000
 #define TSENS0_8X10_POINT2_MASK		0xfc00000
 #define TSENS_8X10_TSENS_CAL_SEL	0x70000000
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f672bd4..290e317 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -32,6 +32,8 @@
 #include <linux/spinlock.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/msm_kgsl.h>
 
 #include <mach/board.h>
 #include <mach/clk.h>
@@ -125,7 +127,7 @@
 	pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
 
 	spin_lock(&mdata->irq_lock);
-	mdp_interrupt &= mdata->irqMask;
+	mdp_interrupt &= mdata->irq_mask;
 
 	while (mdp_interrupt && i < MDP3_MAX_INTR) {
 		if ((mdp_interrupt & 0x1) && mdata->callbacks[i].cb)
@@ -145,14 +147,15 @@
 
 	pr_debug("mdp3_irq_enable type=%d\n", type);
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
-	if (mdp3_res->irqMask & BIT(type)) {
+	mdp3_res->irq_ref_count[type] += 1;
+	if (mdp3_res->irq_ref_count[type] > 1) {
 		pr_debug("interrupt %d already enabled\n", type);
 		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 		return;
 	}
-	irqEnabled = mdp3_res->irqMask;
-	mdp3_res->irqMask |= BIT(type);
-	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+	irqEnabled = mdp3_res->irq_mask;
+	mdp3_res->irq_mask |= BIT(type);
+	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
 	if (!irqEnabled)
 		enable_irq(mdp3_res->irq);
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
@@ -163,26 +166,33 @@
 	unsigned long flag;
 
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
-	if (mdp3_res->irqMask & BIT(type)) {
-		mdp3_res->irqMask &= ~BIT(type);
-		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
-		if (!mdp3_res->irqMask)
-			disable_irq(mdp3_res->irq);
-	} else {
+	if (mdp3_res->irq_ref_count[type] <= 0) {
 		pr_debug("interrupt %d not enabled\n", type);
+		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+		return;
+	}
+	mdp3_res->irq_ref_count[type] -= 1;
+	if (mdp3_res->irq_ref_count[type] == 0) {
+		mdp3_res->irq_mask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+		if (!mdp3_res->irq_mask)
+			disable_irq(mdp3_res->irq);
 	}
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 }
 
 void mdp3_irq_disable_nosync(int type)
 {
-	if (mdp3_res->irqMask & BIT(type)) {
-		mdp3_res->irqMask &= ~BIT(type);
-		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
-		if (!mdp3_res->irqMask)
-			disable_irq_nosync(mdp3_res->irq);
-	} else {
+	if (mdp3_res->irq_ref_count[type] <= 0) {
 		pr_debug("interrupt %d not enabled\n", type);
+		return;
+	}
+	mdp3_res->irq_ref_count[type] -= 1;
+	if (mdp3_res->irq_ref_count[type] == 0) {
+		mdp3_res->irq_mask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+		if (!mdp3_res->irq_mask)
+			disable_irq_nosync(mdp3_res->irq);
 	}
 }
 
@@ -688,6 +698,108 @@
 	return 0;
 }
 
+int mdp3_put_img(struct mdp3_img_data *data)
+{
+	struct ion_client *iclient = mdp3_res->ion_client;
+	int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+	if (!data->srcp_file) {
+		pr_debug("No img to put\n");
+		return 0;
+	}
+	if (data->flags & MDP_BLIT_SRC_GEM) {
+		pr_debug("memory source MDP_BLIT_SRC_GEM\n");
+	} else if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
+		pr_debug("fb mem buf=0x%x\n", data->addr);
+		fput_light(data->srcp_file, data->p_need);
+		data->srcp_file = NULL;
+	} else {
+		ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+		ion_free(iclient, data->srcp_ihdl);
+		data->srcp_ihdl = NULL;
+	}
+	return 0;
+}
+
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data)
+{
+	struct file *file;
+	int ret = -EINVAL;
+	int fb_num;
+	unsigned long *start, *len;
+	struct ion_client *iclient = mdp3_res->ion_client;
+	int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+	start = (unsigned long *) &data->addr;
+	len = (unsigned long *) &data->len;
+	data->flags |= img->flags;
+	data->p_need = 0;
+
+	if (img->flags & MDP_BLIT_SRC_GEM) {
+		data->srcp_file = NULL;
+		ret = kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+					&data->addr, &data->len);
+		if (!ret)
+			goto done;
+	}
+	if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+		file = fget_light(img->memory_id, &data->p_need);
+		if (file == NULL) {
+			pr_err("invalid framebuffer file (%d)\n",
+					img->memory_id);
+			return -EINVAL;
+		}
+		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+			ret = mdss_fb_get_phys_info(start, len, fb_num);
+			if (ret) {
+				pr_err("mdss_fb_get_phys_info() failed\n");
+				fput_light(file, data->p_need);
+				file = NULL;
+			}
+		} else {
+			pr_err("invalid FB_MAJOR\n");
+			fput_light(file, data->p_need);
+			file = NULL;
+			ret = -EINVAL;
+		}
+		data->srcp_file = file;
+		if (!ret)
+			goto done;
+	}
+	if (iclient) {
+		data->srcp_ihdl = ion_import_dma_buf(iclient, img->memory_id);
+		if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+			pr_err("error on ion_import_fd\n");
+			ret = PTR_ERR(data->srcp_ihdl);
+			data->srcp_ihdl = NULL;
+			return ret;
+		}
+
+		ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
+		    0, SZ_4K, 0, start, len, 0, 0);
+
+		if (IS_ERR_VALUE(ret)) {
+			ion_free(iclient, data->srcp_ihdl);
+			pr_err("failed to map ion handle (%d)\n", ret);
+			return ret;
+		}
+	}
+done:
+	if (!ret && (img->offset < data->len)) {
+		data->addr += img->offset;
+		data->len -= img->offset;
+
+		pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
+			 data->srcp_ihdl, data->addr, data->len);
+	} else {
+		mdp3_put_img(data);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
 static int mdp3_init(struct msm_fb_data_type *mfd)
 {
 	return mdp3_ctrl_init(mfd);
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 5774e5a..7e395e1 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -23,6 +23,7 @@
 #include <mach/iommu_domains.h>
 
 #include "mdp3_dma.h"
+#include "mdss_fb.h"
 
 enum  {
 	MDP3_CLK_AHB,
@@ -100,12 +101,22 @@
 	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
 
 	spinlock_t irq_lock;
-	u32 irqMask;
+	u32 irq_ref_count[MDP3_MAX_INTR];
+	u32 irq_mask;
 	struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
 
 	struct early_suspend suspend_handler;
 };
 
+struct mdp3_img_data {
+	u32 addr;
+	u32 len;
+	u32 flags;
+	int p_need;
+	struct file *srcp_file;
+	struct ion_handle *srcp_ihdl;
+};
+
 extern struct mdp3_hw_resource *mdp3_res;
 
 struct mdp3_dma *mdp3_get_dma_pipe(int capability);
@@ -117,6 +128,8 @@
 int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
 int mdp3_clk_enable(int enable);
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
+int mdp3_put_img(struct mdp3_img_data *data);
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
 
 #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
 #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 929e5f8..f5ac5e9 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -26,37 +26,108 @@
 #define MDP_VSYNC_CLK_RATE	19200000
 #define VSYNC_PERIOD 16
 
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
+
+static void mdp3_bufq_init(struct mdp3_buffer_queue *bufq)
+{
+	bufq->count = 0;
+	bufq->push_idx = 0;
+	bufq->pop_idx = 0;
+}
+
+static void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
+{
+	int count = bufq->count;
+
+	if (!count)
+		return;
+
+	while (count--) {
+		struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
+		bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+		mdp3_put_img(data);
+	}
+	bufq->count = 0;
+	bufq->push_idx = 0;
+	bufq->pop_idx = 0;
+}
+
+static int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
+			struct mdp3_img_data *data)
+{
+	if (bufq->count >= MDP3_MAX_BUF_QUEUE) {
+		pr_err("bufq full\n");
+		return -EPERM;
+	}
+
+	bufq->img_data[bufq->push_idx] = *data;
+	bufq->push_idx = (bufq->push_idx + 1) % MDP3_MAX_BUF_QUEUE;
+	bufq->count++;
+	return 0;
+}
+
+static struct mdp3_img_data *mdp3_bufq_pop(struct mdp3_buffer_queue *bufq)
+{
+	struct mdp3_img_data *data;
+	if (bufq->count == 0)
+		return NULL;
+
+	data = &bufq->img_data[bufq->pop_idx];
+	bufq->count--;
+	bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+	return data;
+}
+
+static int mdp3_bufq_count(struct mdp3_buffer_queue *bufq)
+{
+	return bufq->count;
+}
+
 void vsync_notify_handler(void *arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+	spin_lock(&session->vsync_lock);
+	session->vsync_time = ktime_get();
 	complete(&session->vsync_comp);
+	spin_unlock(&session->vsync_lock);
 }
 
 static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
 {
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_vsync_notification *arg = NULL;
+	unsigned long flag;
 
+	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
 		!mdp3_session->intf)
 		return -ENODEV;
 
-	vsync_client.handler = vsync_notify_handler;
-	vsync_client.arg = mdp3_session;
-
-	mutex_lock(&mdp3_session->lock);
 	if (!mdp3_session->status) {
 		pr_debug("fb%d is not on yet", mfd->index);
-		mutex_unlock(&mdp3_session->lock);
 		return -EINVAL;
 	}
+	if (enable) {
+		vsync_client.handler = vsync_notify_handler;
+		vsync_client.arg = mdp3_session;
+		arg = &vsync_client;
+	}
 
-	mdp3_session->dma->vsync_enable(mdp3_session->dma, &vsync_client);
+	mutex_lock(&mdp3_session->lock);
+	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
 	mutex_unlock(&mdp3_session->lock);
+	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+	if (enable)
+		INIT_COMPLETION(mdp3_session->vsync_comp);
+	else
+		complete_all(&mdp3_session->vsync_comp);
+	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 	return 0;
 }
 
+
 static ssize_t mdp3_vsync_show_event(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -64,8 +135,8 @@
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
 	struct mdp3_session_data *mdp3_session = NULL;
 	u64 vsync_ticks;
-	ktime_t vsync_time;
 	int rc;
+	unsigned long flag;
 
 	if (!mfd || !mfd->mdp.private1)
 		return 0;
@@ -78,11 +149,11 @@
 	if (rc <= 0) {
 		pr_warn("vsync wait on fb%d interrupted (%d)\n",
 			mfd->index, rc);
-		return -EBUSY;
 	}
 
-	vsync_time = mdp3_session->dma->get_vsync_time(mdp3_session->dma);
-	vsync_ticks = ktime_to_ns(vsync_time);
+	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+	vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
+	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 
 	pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
 	rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
@@ -395,6 +466,148 @@
 	return 0;
 }
 
+static int mdp3_overlay_get(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == req->id)
+		*req = mdp3_session->overlay;
+	else
+		rc = -EINVAL;
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_set(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == req->id) {
+		mdp3_session->overlay = *req;
+		if (req->id == MSMFB_NEW_REQUEST) {
+			mdp3_session->overlay.id = 1;
+			req->id = 1;
+		}
+	} else {
+		rc = -EINVAL;
+	}
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mdp3_ctrl_pan_display(mfd);
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == ndx && ndx == 1) {
+		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+		mdp3_bufq_deinit(&mdp3_session->bufq_in);
+		mdp3_bufq_deinit(&mdp3_session->bufq_out);
+	} else {
+		rc = -EINVAL;
+	}
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_queue_buffer(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_data *req)
+{
+	int rc;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+	struct msmfb_data *img = &req->data;
+	struct mdp3_img_data data;
+
+	rc = mdp3_get_img(img, &data);
+	if (rc) {
+		pr_err("fail to get overlay buffer\n");
+		return rc;
+	}
+
+	rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
+	if (rc) {
+		pr_err("fail to queue the overlay buffer, buffer drop\n");
+		mdp3_put_img(&data);
+		return rc;
+	}
+	return 0;
+}
+
+static int mdp3_overlay_play(struct msm_fb_data_type *mfd,
+				 struct msmfb_overlay_data *req)
+{
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+	int rc = 0;
+
+	pr_debug("mdp3_overlay_play req id=%x mem_id=%d\n",
+		req->id, req->data.memory_id);
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mfd->panel_power_on)
+		rc = mdp3_overlay_queue_buffer(mfd, req);
+	else
+		rc = -EPERM;
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd)
+{
+	struct mdp3_session_data *mdp3_session;
+	struct mdp3_img_data *data;
+	int rc = 0;
+
+	if (!mfd || !mfd->mdp.private1)
+		return -EINVAL;
+
+	mdp3_session = mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->dma)
+		return -EINVAL;
+
+	if (!mdp3_session->status) {
+		pr_err("%s, display off!\n", __func__);
+		return -EPERM;
+	}
+
+	mutex_lock(&mdp3_session->lock);
+
+	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
+	if (data) {
+		mdp3_session->dma->update(mdp3_session->dma,
+			(void *)data->addr);
+		mdp3_bufq_push(&mdp3_session->bufq_out, data);
+	}
+
+	if (mdp3_bufq_count(&mdp3_session->bufq_out) > 1) {
+		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
+		mdp3_put_img(data);
+	}
+
+	mutex_unlock(&mdp3_session->lock);
+	return rc;
+}
+
 static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
 {
 	struct fb_info *fbi;
@@ -445,6 +658,9 @@
 		break;
 	case metadata_op_get_caps:
 		metadata->data.caps.mdp_rev = 304;
+		metadata->data.caps.rgb_pipes = 0;
+		metadata->data.caps.vig_pipes = 0;
+		metadata->data.caps.dma_pipes = 1;
 		break;
 	default:
 		pr_warn("Unsupported request to MDP META IOCTL.\n");
@@ -460,6 +676,8 @@
 	int rc = -EINVAL;
 	struct mdp3_session_data *mdp3_session;
 	struct msmfb_metadata metadata;
+	struct mdp_overlay req;
+	struct msmfb_overlay_data ov_data;
 	int val;
 
 	pr_debug("mdp3_ctrl_ioctl_handler\n");
@@ -478,8 +696,6 @@
 	case MSMFB_OVERLAY_VSYNC_CTRL:
 		if (!copy_from_user(&val, argp, sizeof(val))) {
 			rc = mdp3_ctrl_vsync_enable(mfd, val);
-			if (!val)
-				init_completion(&mdp3_session->vsync_comp);
 		} else {
 			pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
 			rc = -EFAULT;
@@ -493,10 +709,42 @@
 		if (!rc)
 			rc = copy_to_user(argp, &metadata, sizeof(metadata));
 		break;
+	case MSMFB_OVERLAY_GET:
+		rc = copy_from_user(&req, argp, sizeof(req));
+		if (!rc) {
+			rc = mdp3_overlay_get(mfd, &req);
+
+		if (!IS_ERR_VALUE(rc))
+			rc = copy_to_user(argp, &req, sizeof(req));
+		}
+		if (rc)
+			pr_err("OVERLAY_GET failed (%d)\n", rc);
+		break;
+	case MSMFB_OVERLAY_SET:
+		rc = copy_from_user(&req, argp, sizeof(req));
+		if (!rc) {
+			rc = mdp3_overlay_set(mfd, &req);
+
+		if (!IS_ERR_VALUE(rc))
+			rc = copy_to_user(argp, &req, sizeof(req));
+		}
+		if (rc)
+			pr_err("OVERLAY_SET failed (%d)\n", rc);
+		break;
+	case MSMFB_OVERLAY_UNSET:
+		if (!IS_ERR_VALUE(copy_from_user(&val, argp, sizeof(val))))
+			rc = mdp3_overlay_unset(mfd, val);
+		break;
+	case MSMFB_OVERLAY_PLAY:
+		rc = copy_from_user(&ov_data, argp, sizeof(ov_data));
+		if (!rc)
+			rc = mdp3_overlay_play(mfd, &ov_data);
+		if (rc)
+			pr_err("OVERLAY_PLAY failed (%d)\n", rc);
+		break;
 	default:
 		break;
 	}
-
 	return rc;
 }
 
@@ -515,7 +763,7 @@
 	mdp3_interface->cursor_update = NULL;
 	mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
 	mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
-	mdp3_interface->kickoff_fnc = NULL;
+	mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff;
 
 	mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
 	if (!mdp3_session) {
@@ -525,6 +773,7 @@
 	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
 	mutex_init(&mdp3_session->lock);
 	init_completion(&mdp3_session->vsync_comp);
+	spin_lock_init(&mdp3_session->vsync_lock);
 	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
 	if (!mdp3_session->dma) {
 		rc = -ENODEV;
@@ -540,6 +789,9 @@
 
 	mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
 	mdp3_session->status = 0;
+	mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+	mdp3_bufq_init(&mdp3_session->bufq_in);
+	mdp3_bufq_init(&mdp3_session->bufq_out);
 
 	mfd->mdp.private1 = mdp3_session;
 
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index d42ece7..fb3bd36 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -18,10 +18,20 @@
 #include <linux/mutex.h>
 #include <linux/completion.h>
 
+#include "mdp3.h"
 #include "mdp3_dma.h"
 #include "mdss_fb.h"
 #include "mdss_panel.h"
 
+#define MDP3_MAX_BUF_QUEUE 8
+
+struct mdp3_buffer_queue {
+	struct mdp3_img_data img_data[MDP3_MAX_BUF_QUEUE];
+	int count;
+	int push_idx;
+	int pop_idx;
+};
+
 struct mdp3_session_data {
 	struct mutex lock;
 	int status;
@@ -29,7 +39,12 @@
 	struct mdss_panel_data *panel;
 	struct mdp3_intf *intf;
 	struct msm_fb_data_type *mfd;
+	ktime_t vsync_time;
+	spinlock_t vsync_lock;
 	struct completion vsync_comp;
+	struct mdp_overlay overlay;
+	struct mdp3_buffer_queue bufq_in;
+	struct mdp3_buffer_queue bufq_out;
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 69e3d7e..a09f503 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -20,17 +20,6 @@
 #define DMA_STOP_POLL_SLEEP_US 1000
 #define DMA_STOP_POLL_TIMEOUT_US 16000
 
-static ktime_t mdp3_get_vsync_time(struct mdp3_dma *dma)
-{
-	unsigned long flag;
-	ktime_t time;
-
-	spin_lock_irqsave(&dma->dma_lock, flag);
-	time = dma->vsync_time;
-	spin_unlock_irqrestore(&dma->dma_lock, flag);
-	return time;
-}
-
 static void mdp3_vsync_intr_handler(int type, void *arg)
 {
 	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
@@ -41,13 +30,11 @@
 	vsync_client = dma->vsync_client;
 	if (!vsync_client.handler)
 		dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_VSYNC;
-	dma->vsync_time = ktime_get();
 	complete(&dma->vsync_comp);
+	spin_unlock(&dma->dma_lock);
 	if (vsync_client.handler)
 		vsync_client.handler(vsync_client.arg);
-	spin_unlock(&dma->dma_lock);
-
-	if (!vsync_client.handler)
+	else
 		mdp3_irq_disable_nosync(type);
 }
 
@@ -186,7 +173,7 @@
 			updated = 1;
 		}
 	} else {
-		if (!dma->vsync_client.handler) {
+		if (dma->vsync_client.handler) {
 			dma->vsync_client.handler = NULL;
 			dma->vsync_client.arg = NULL;
 			updated = 1;
@@ -696,7 +683,6 @@
 		dma->histo_intr_enable = mdp3_dmap_histo_intr_enable;
 		dma->histo_intr_clear = mdp3_dmap_histo_intr_clear;
 		dma->vsync_enable = mdp3_dma_vsync_enable;
-		dma->get_vsync_time = mdp3_get_vsync_time;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
 		break;
@@ -717,7 +703,6 @@
 		dma->histo_intr_enable = NULL;
 		dma->histo_intr_clear = NULL;
 		dma->vsync_enable = mdp3_dma_vsync_enable;
-		dma->get_vsync_time = mdp3_get_vsync_time;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
 		break;
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 2fb8427..cef749b 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -231,7 +231,6 @@
 	spinlock_t dma_lock;
 	struct completion vsync_comp;
 	struct completion dma_comp;
-	ktime_t vsync_time;
 	struct mdp3_vsync_notification vsync_client;
 	u32 cb_type;
 
@@ -275,9 +274,6 @@
 
 	void (*vsync_enable)(struct mdp3_dma *dma,
 			struct mdp3_vsync_notification *vsync_client);
-
-	ktime_t (*get_vsync_time)(struct mdp3_dma *dma);
-
 };
 
 struct mdp3_video_intf_cfg {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index ef8323e..26d4ada 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1839,6 +1839,7 @@
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+	V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP
 };
 #define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
 		(V4L2_CID_MPEG_MSM_VIDC_BASE + 23)
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index f632ad6..2164275 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -73,6 +73,16 @@
 	unsigned int aspect_height;
 };
 
+struct msm_vidc_mpeg2_seqdisp_payload {
+	unsigned int video_format;
+	bool color_descp;
+	unsigned int color_primaries;
+	unsigned int transfer_char;
+	unsigned int matrix_coeffs;
+	unsigned int disp_width;
+	unsigned int disp_height;
+};
+
 struct msm_vidc_panscan_window {
 	unsigned int panscan_height_offset;
 	unsigned int panscan_width_offset;
@@ -94,6 +104,7 @@
 	EXTRADATA_FRAME_RATE = 0x00000007,
 	EXTRADATA_PANSCAN_WINDOW = 0x00000008,
 	EXTRADATA_RECOVERY_POINT_SEI = 0x00000009,
+	EXTRADATA_MPEG2_SEQDISP = 0x0000000D,
 	EXTRADATA_MULTISLICE_INFO = 0x7F100000,
 	EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
 	EXTRADATA_INDEX = 0x7F100002,
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0dd14e6..2d34d70 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -70,7 +70,6 @@
 #define COMPRESSED_IO	0x0040
 #define NT_MODE        0x0400
 
-
 #define NO_TIMESTAMP    0xFF00
 #define SET_TIMESTAMP   0x0000
 
@@ -79,6 +78,19 @@
 
 #define SESSION_MAX	0x08
 
+/* payload structure bytes */
+#define READDONE_IDX_STATUS 0
+#define READDONE_IDX_BUFADD_LSW 1
+#define READDONE_IDX_BUFADD_MSW 2
+#define READDONE_IDX_MEMMAP_HDL 3
+#define READDONE_IDX_SIZE 4
+#define READDONE_IDX_OFFSET 5
+#define READDONE_IDX_LSW_TS 6
+#define READDONE_IDX_MSW_TS 7
+#define READDONE_IDX_FLAGS 8
+#define READDONE_IDX_NUMFRAMES 9
+#define READDONE_IDX_SEQ_ID 10
+
 #define SOFT_PAUSE_PERIOD       30   /* ramp up/down for 30ms    */
 #define SOFT_PAUSE_STEP         2000 /* Step value 2ms or 2000us */
 enum {
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index b140b5b..c3967dc 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -2336,6 +2336,9 @@
 {
 	int ret;
 
+	/* Set GPIO headset detection by default */
+	hs_detect_use_gpio = true;
+
 	if (!cpu_is_msm9615()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
@@ -2413,8 +2416,6 @@
 	sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
 	secpcm_portslc_virt_addr = ioremap(SEC_PCM_PORT_SLC_ADDR, 4);
 
-	hs_detect_use_gpio = true;
-
 	return ret;
 }
 module_init(mdm9615_audio_init);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9359ed7..9dbbf20 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -39,7 +39,10 @@
 #define COMPRE_CAPTURE_NUM_PERIODS	16
 /* Allocate the worst case frame size for compressed audio */
 #define COMPRE_CAPTURE_HEADER_SIZE	(sizeof(struct snd_compr_audio_info))
-#define COMPRE_CAPTURE_MAX_FRAME_SIZE	(6144)
+/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE
+ * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1
+ */
+#define COMPRE_CAPTURE_MAX_FRAME_SIZE	(4032)
 #define COMPRE_CAPTURE_PERIOD_SIZE	((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
 					  COMPRE_CAPTURE_HEADER_SIZE) * \
 					  MAX_NUM_FRAMES_PER_BUFFER)
@@ -226,7 +229,7 @@
 				prtd->pcm_irq_pos);
 
 		memcpy(prtd->audio_client->port[OUT].buf->data +
-			   prtd->pcm_irq_pos, (ptrmem + 2),
+			   prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE),
 			   COMPRE_CAPTURE_HEADER_SIZE);
 		pr_debug("buf = %p, updated data = 0x%X, *data = %p\n",
 				prtd->audio_client->port[OUT].buf,
@@ -235,9 +238,10 @@
 				prtd->audio_client->port[OUT].buf->data);
 		if (!atomic_read(&prtd->start))
 			break;
-		pr_debug("frame size=%d, buffer = 0x%X\n", ptrmem[2],
-				ptrmem[1]);
-		if (ptrmem[2] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
+		pr_debug("frame size=%d, buffer = 0x%X\n",
+				ptrmem[READDONE_IDX_SIZE],
+				ptrmem[READDONE_IDX_BUFADD_LSW]);
+		if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
 			pr_err("Frame length exceeded the max length");
 			break;
 		}
@@ -546,7 +550,7 @@
 {
 	pr_debug("%s\n", __func__);
 	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 4;
+	compr->info.compr_cap.num_codecs = 5;
 	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
 	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -555,6 +559,7 @@
 	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
 	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
 	compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
+	compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB;
 	/* Add new codecs here */
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 59d4de2..af8e873 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -45,17 +45,6 @@
 
 #define TRUE        0x01
 #define FALSE       0x00
-#define READDONE_IDX_STATUS 0
-#define READDONE_IDX_BUFADD_LSW 1
-#define READDONE_IDX_BUFADD_MSW 2
-#define READDONE_IDX_MEMMAP_HDL 3
-#define READDONE_IDX_SIZE 4
-#define READDONE_IDX_OFFSET 5
-#define READDONE_IDX_LSW_TS 6
-#define READDONE_IDX_MSW_TS 7
-#define READDONE_IDX_FLAGS 8
-#define READDONE_IDX_NUMFRAMES 9
-#define READDONE_IDX_SEQ_ID 10
 
 /* TODO, combine them together */
 static DEFINE_MUTEX(session_lock);
@@ -3371,6 +3360,7 @@
 	struct list_head *ptr, *next;
 	u32 lbuf_addr_lsw;
 	u32 liomode;
+	u32 io_compressed;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3387,12 +3377,15 @@
 	read.buf_size = param->len;
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
+	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
 	if (ac->io_mode == liomode)
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
+	else if (ac->io_mode == io_compressed)
+		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
 	else
 		lbuf_addr_lsw = read.buf_addr_lsw;
 
-	list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
 		buf_node = list_entry(ptr, struct asm_buffer_node, list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;