Merge "msm: clock: Delete obsolete dummy clock tables for 8960 and 8064" into msm-3.0
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index cd8fba5..275c893 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -196,6 +196,9 @@
 	},
 };
 
+#define MSM_MPM_PIN_SDC1_DAT1	17
+#define MSM_MPM_PIN_SDC3_DAT1	21
+
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
 static unsigned int sdc1_sup_clk_rates[] = {
 	400000, 24000000, 48000000, 96000000
@@ -215,6 +218,7 @@
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.uhs_caps	= MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50,
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
 };
 static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
 #else
@@ -244,6 +248,7 @@
 	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
 			MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
 			MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
 };
 static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
 #else
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index 679c2fc..ecebfa9 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -207,6 +207,9 @@
 	},
 };
 
+#define MSM_MPM_PIN_SDC1_DAT1	17
+#define MSM_MPM_PIN_SDC3_DAT1	21
+
 static unsigned int sdc1_sup_clk_rates[] = {
 	400000, 24000000, 48000000,
 };
@@ -230,7 +233,8 @@
 	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
-	.pin_data	= &mmc_slot_pin_data[SDCC1]
+	.pin_data	= &mmc_slot_pin_data[SDCC1],
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
 };
 #endif
 
@@ -268,6 +272,7 @@
 	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
 			MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
 			MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
 };
 #endif
 
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 6859b9f..8bbb596 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1378,7 +1378,7 @@
 	/* T6 Object */
 	 0, 0, 0, 0, 0, 0,
 	/* T38 Object */
-	 15, 1, 0, 15, 12, 11, 0, 0,
+	 15, 2, 0, 15, 12, 11, 0, 0,
 	/* T7 Object */
 	 48, 255, 25,
 	/* T8 Object */
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 22f8fb5..cd53f83 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -206,6 +206,9 @@
 	},
 };
 
+#define MSM_MPM_PIN_SDC1_DAT1	17
+#define MSM_MPM_PIN_SDC3_DAT1	21
+
 static unsigned int sdc1_sup_clk_rates[] = {
 	400000, 24000000, 48000000
 };
@@ -230,6 +233,7 @@
 	.nonremovable	= 1,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
 };
 #endif
 
@@ -255,6 +259,7 @@
 	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
 			MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
 			MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_600),
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
 };
 #endif
 
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index c73e5a9..6bf7c69 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -163,6 +163,8 @@
 #endif
 };
 
+#define MSM_MPM_PIN_SDC1_DAT1	17
+
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
 static unsigned int sdc1_sup_clk_rates[] = {
 	400000, 24000000, 48000000
@@ -183,7 +185,8 @@
 #endif
 	.xpc_cap	= 1,
 	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
-			   MMC_CAP_MAX_CURRENT_400)
+			   MMC_CAP_MAX_CURRENT_400),
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
 };
 static struct mmc_platform_data *msm9615_sdc1_pdata = &sdc1_data;
 #else
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7832b878..da362a0 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -8368,6 +8368,7 @@
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 0,
 	.pclk_src_dfab  = 1,
+	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
 };
 #endif
 
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 6c23c50..53dbebe 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3576,7 +3576,7 @@
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		"qup_i2c.5"),
-	CLK_LOOKUP("ppss_pclk",		ppss_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		ppss_p_clk.c,		"msm_dsps"),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		"msm_tsif.0"),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		"msm_tsif.1"),
 	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	""),
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 608ca27..614f6ff 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -1591,7 +1591,7 @@
 
 static struct dsps_clk_info dsps_clks[] = {
 	{
-		.name = "ppss_pclk",
+		.name = "iface_clk",
 		.rate =	0, /* no rate just on/off */
 	},
 	{
diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
index d1766a3..4e21a86 100644
--- a/arch/arm/mach-msm/gpio-v2.c
+++ b/arch/arm/mach-msm/gpio-v2.c
@@ -490,6 +490,12 @@
 	.irq_disable	= msm_gpio_irq_disable,
 };
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key msm_gpio_lock_class;
+
 static int __devinit msm_gpio_probe(void)
 {
 	int i, irq, ret;
@@ -504,6 +510,7 @@
 
 	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
 		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
 		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
 					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index c62b7fd..3181d29 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_DIAG_CHAR) := diagchar.o
 obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
 obj-$(CONFIG_DIAG_HSIC_PIPE) += diagfwd_hsic.o
-diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o
+diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
new file mode 100644
index 0000000..5cbf888
--- /dev/null
+++ b/drivers/char/diag/diag_dci.c
@@ -0,0 +1,335 @@
+/* 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.
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/diagchar.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <asm/current.h>
+#ifdef CONFIG_DIAG_OVER_USB
+#include <mach/usbdiag.h>
+#endif
+#include "diagchar_hdlc.h"
+#include "diagmem.h"
+#include "diagchar.h"
+#include "diagfwd.h"
+#include "diag_dci.h"
+
+unsigned int dci_max_reg = 100;
+unsigned int dci_max_clients = 10;
+
+static void diag_smd_dci_send_req(int proc_num)
+{
+	void *buf = NULL;
+	smd_channel_t *smd_ch = NULL;
+	int i, r, found = 1;
+	int cmd_code_len = 1;
+
+	if (driver->in_busy_dci)
+		return;
+
+	if (proc_num == MODEM_PROC) {
+		buf = driver->buf_in_dci;
+		smd_ch = driver->ch_dci;
+	}
+
+	if (!smd_ch || !buf)
+		return;
+
+	r = smd_read_avail(smd_ch);
+	if (r > IN_BUF_SIZE) {
+		if (r < MAX_IN_BUF_SIZE) {
+			pr_err("diag: SMD DCI sending pkt upto %d bytes", r);
+			buf = krealloc(buf, r, GFP_KERNEL);
+		} else {
+			pr_err("diag: DCI pkt > %d bytes", MAX_IN_BUF_SIZE);
+			return;
+		}
+	}
+	if (buf && r > 0) {
+		smd_read(smd_ch, buf, r);
+		pr_debug("diag: data received ---\n");
+		for (i = 0; i < r; i++)
+			pr_debug("\t %x \t", *(((unsigned char *)buf)+i));
+
+		if (*(uint8_t *)(buf+4) != DCI_CMD_CODE)
+			cmd_code_len = 4; /* delayed response */
+		driver->write_ptr_dci->length =
+			 (int)(*(uint16_t *)(buf+2)) - (4+cmd_code_len);
+		pr_debug("diag: len = %d\n", (int)(*(uint16_t *)(buf+2))
+							 - (4+cmd_code_len));
+		/* look up DCI client with tag */
+		for (i = 0; i < dci_max_reg; i++) {
+			if (driver->dci_tbl[i].tag ==
+			    *(int *)(buf+(4+cmd_code_len))) {
+				found = 0;
+				break;
+			}
+		}
+		if (found)
+			pr_alert("diag: No matching PID for DCI data\n");
+		pr_debug("\n diag PID = %d", driver->dci_tbl[i].pid);
+		if (driver->dci_tbl[i].pid == 0)
+			pr_alert("diag: Receiving DCI process deleted\n");
+		*(int *)(buf+4+cmd_code_len) = driver->dci_tbl[i].uid;
+		/* update len after adding UID */
+		driver->write_ptr_dci->length =
+			driver->write_ptr_dci->length + 4;
+		pr_debug("diag: data receivd, wake process\n");
+		driver->in_busy_dci = 1;
+		diag_update_sleeping_process(driver->dci_tbl[i].pid,
+							DCI_DATA_TYPE);
+		/* delete immediate response entry */
+		if (driver->buf_in_dci[8+cmd_code_len] != 0x80)
+			driver->dci_tbl[i].pid = 0;
+		for (i = 0; i < dci_max_reg; i++)
+			if (driver->dci_tbl[i].pid != 0)
+				pr_debug("diag: PID = %d, UID = %d, tag = %d\n",
+				driver->dci_tbl[i].pid, driver->dci_tbl[i].uid,
+				 driver->dci_tbl[i].tag);
+		pr_debug("diag: completed clearing table\n");
+	}
+}
+
+void diag_read_smd_dci_work_fn(struct work_struct *work)
+{
+	diag_smd_dci_send_req(MODEM_PROC);
+}
+
+static void diag_smd_dci_notify(void *ctxt, unsigned event)
+{
+	queue_work(driver->diag_wq, &(driver->diag_read_smd_dci_work));
+}
+
+static int diag_dci_probe(struct platform_device *pdev)
+{
+	int err = 0;
+
+	if (pdev->id == SMD_APPS_MODEM) {
+		err = smd_open("DIAG_2", &driver->ch_dci, driver,
+					    diag_smd_dci_notify);
+		if (err)
+			pr_err("diag: cannot open DCI port, Id = %d, err ="
+				" %d\n", pdev->id, err);
+	}
+	return err;
+}
+
+
+int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf,
+					 int len, int index)
+{
+	int i;
+
+	/* remove UID from user space pkt before sending to peripheral */
+	buf = buf + 4;
+	len = len - 4;
+	mutex_lock(&driver->dci_mutex);
+	/* prepare DCI packet */
+	driver->apps_dci_buf[0] = CONTROL_CHAR; /* start */
+	driver->apps_dci_buf[1] = 1; /* version */
+	*(uint16_t *)(driver->apps_dci_buf + 2) = len + 4 + 1; /* length */
+	driver->apps_dci_buf[4] = DCI_CMD_CODE; /* DCI ID */
+	*(int *)(driver->apps_dci_buf + 5) = driver->dci_tbl[index].tag;
+	for (i = 0; i < len; i++)
+		driver->apps_dci_buf[i+9] = *(buf+i);
+	driver->apps_dci_buf[9+len] = CONTROL_CHAR; /* end */
+
+	if (entry.client_id == MODEM_PROC && driver->ch_dci) {
+		smd_write(driver->ch_dci, driver->apps_dci_buf, len + 10);
+		i = DIAG_DCI_NO_ERROR;
+	} else {
+		pr_alert("diag: check DCI channel\n");
+		i = DIAG_DCI_SEND_DATA_FAIL;
+	}
+	mutex_unlock(&driver->dci_mutex);
+	return i;
+}
+
+int diag_register_dci_transaction(int uid)
+{
+	int i, new_dci_client = 1, ret = -1;
+
+	for (i = 0; i < dci_max_reg; i++) {
+		if (driver->dci_tbl[i].pid == current->tgid) {
+			new_dci_client = 0;
+			break;
+		}
+	}
+	mutex_lock(&driver->dci_mutex);
+	if (new_dci_client)
+		driver->num_dci_client++;
+	if (driver->num_dci_client > MAX_DCI_CLIENT) {
+		pr_info("diag: Max DCI Client limit reached\n");
+		driver->num_dci_client--;
+		mutex_unlock(&driver->dci_mutex);
+		return ret;
+	}
+	/* Make an entry in kernel DCI table */
+	driver->dci_tag++;
+	for (i = 0; i < dci_max_reg; i++) {
+		if (driver->dci_tbl[i].pid == 0) {
+			driver->dci_tbl[i].pid = current->tgid;
+			driver->dci_tbl[i].uid = uid;
+			driver->dci_tbl[i].tag = driver->dci_tag;
+			ret = i;
+			break;
+		}
+	}
+	mutex_unlock(&driver->dci_mutex);
+	return ret;
+}
+
+int diag_process_dci_client(unsigned char *buf, int len)
+{
+	unsigned char *temp = buf;
+	uint16_t subsys_cmd_code;
+	int subsys_id, cmd_code, i, ret = -1, index = -1;
+	struct diag_master_table entry;
+
+	/* enter this UID into kernel table and return index */
+	index = diag_register_dci_transaction(*(int *)temp);
+	if (index < 0) {
+		pr_alert("diag: registering new DCI transaction failed\n");
+		return DIAG_DCI_NO_REG;
+	}
+	temp += 4;
+	/* Check for registered peripheral and fwd pkt to apropriate proc */
+	cmd_code = (int)(*(char *)buf);
+	temp++;
+	subsys_id = (int)(*(char *)temp);
+	temp++;
+	subsys_cmd_code = *(uint16_t *)temp;
+	temp += 2;
+	pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
+	for (i = 0; i < diag_max_reg; i++) {
+		entry = driver->table[i];
+		if (entry.process_id != NO_PROCESS) {
+			if (entry.cmd_code == cmd_code && entry.subsys_id ==
+				 subsys_id && entry.cmd_code_lo <=
+							 subsys_cmd_code &&
+				  entry.cmd_code_hi >= subsys_cmd_code) {
+				ret = diag_send_dci_pkt(entry, buf, len, index);
+			} else if (entry.cmd_code == 255
+				  && cmd_code == 75) {
+				if (entry.subsys_id ==
+					subsys_id &&
+				   entry.cmd_code_lo <=
+					subsys_cmd_code &&
+					 entry.cmd_code_hi >=
+					subsys_cmd_code) {
+					ret = diag_send_dci_pkt(entry, buf, len,
+								 index);
+				}
+			} else if (entry.cmd_code == 255 &&
+				  entry.subsys_id == 255) {
+				if (entry.cmd_code_lo <=
+						 cmd_code &&
+						 entry.
+						cmd_code_hi >= cmd_code) {
+					ret = diag_send_dci_pkt(entry, buf, len,
+								 index);
+				}
+			}
+		}
+	}
+	return ret;
+}
+
+static int diag_dci_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int diag_dci_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...\n");
+	return 0;
+}
+
+static const struct dev_pm_ops diag_dci_dev_pm_ops = {
+	.runtime_suspend = diag_dci_runtime_suspend,
+	.runtime_resume = diag_dci_runtime_resume,
+};
+
+struct platform_driver msm_diag_dci_driver = {
+	.probe = diag_dci_probe,
+	.driver = {
+		   .name = "DIAG_2",
+		   .owner = THIS_MODULE,
+		   .pm   = &diag_dci_dev_pm_ops,
+		   },
+};
+
+int diag_dci_init(void)
+{
+	int success = 0;
+
+	driver->dci_tag = 0;
+	driver->dci_client_id = 0;
+	driver->num_dci_client = 0;
+	driver->in_busy_dci = 0;
+	mutex_init(&driver->dci_mutex);
+	if (driver->buf_in_dci == NULL) {
+		driver->buf_in_dci = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+		if (driver->buf_in_dci == NULL)
+			goto err;
+	}
+	if (driver->write_ptr_dci == NULL) {
+		driver->write_ptr_dci = kzalloc(
+			sizeof(struct diag_write_device), GFP_KERNEL);
+		if (driver->write_ptr_dci == NULL)
+			goto err;
+	}
+	if (driver->dci_tbl == NULL) {
+		driver->dci_tbl = kzalloc(dci_max_reg *
+			sizeof(struct diag_dci_tbl), GFP_KERNEL);
+		if (driver->dci_tbl == NULL)
+			goto err;
+	}
+	if (driver->apps_dci_buf == NULL) {
+		driver->apps_dci_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
+		if (driver->apps_dci_buf == NULL)
+			goto err;
+	}
+	success = platform_driver_register(&msm_diag_dci_driver);
+	if (success) {
+		pr_err("diag: Could not register DCI driver\n");
+		goto err;
+	}
+	return DIAG_DCI_NO_ERROR;
+err:
+	pr_err("diag: Could not initialize diag DCI buffers");
+	kfree(driver->dci_tbl);
+	kfree(driver->apps_dci_buf);
+	kfree(driver->buf_in_dci);
+	kfree(driver->write_ptr_dci);
+	return DIAG_DCI_NO_REG;
+}
+
+void diag_dci_exit(void)
+{
+	smd_close(driver->ch_dci);
+	driver->ch_dci = 0;
+	platform_driver_unregister(&msm_diag_dci_driver);
+	kfree(driver->dci_tbl);
+	kfree(driver->apps_dci_buf);
+	kfree(driver->buf_in_dci);
+	kfree(driver->write_ptr_dci);
+}
+
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
new file mode 100644
index 0000000..cc6e0cf
--- /dev/null
+++ b/drivers/char/diag/diag_dci.h
@@ -0,0 +1,46 @@
+/* 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 DIAG_DCI_H
+#define DIAG_DCI_H
+#define MAX_DCI_CLIENT 10
+#define DCI_CMD_CODE 0x93
+
+extern unsigned int dci_max_reg;
+extern unsigned int dci_max_clients;
+struct diag_dci_tbl {
+	int pid;
+	int uid;
+	int tag;
+};
+
+#define DIAG_CON_APSS (0x0001)	/* Bit mask for APSS */
+#define DIAG_CON_MPSS (0x0002)	/* Bit mask for MPSS */
+#define DIAG_CON_LPASS (0x0004)	/* Bit mask for LPASS */
+#define DIAG_CON_WCNSS (0x0008)	/* Bit mask for WCNSS */
+
+enum {
+	DIAG_DCI_NO_ERROR = 1001,	/* No error */
+	DIAG_DCI_NO_REG,		/* Could not register */
+	DIAG_DCI_NO_MEM,		/* Failed memory allocation */
+	DIAG_DCI_NOT_SUPPORTED,	/* This particular client is not supported */
+	DIAG_DCI_HUGE_PACKET,	/* Request/Response Packet too huge */
+	DIAG_DCI_SEND_DATA_FAIL,/* writing to kernel or peripheral fails */
+	DIAG_DCI_TABLE_ERR	/* Error dealing with registration tables */
+};
+
+int diag_dci_init(void);
+void diag_dci_exit(void);
+void diag_read_smd_dci_work_fn(struct work_struct *);
+int diag_process_dci_client(unsigned char *buf, int len);
+int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf,
+							 int len, int index);
+#endif
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 7b63610..d547121 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -54,6 +54,7 @@
 #define DIAG_CTRL_MSG_LOG_MASK	9
 #define DIAG_CTRL_MSG_EVENT_MASK	10
 #define DIAG_CTRL_MSG_F3_MASK	11
+#define CONTROL_CHAR	0x7E
 
 /* Maximum number of pkt reg supported at initialization*/
 extern unsigned int diag_max_reg;
@@ -135,7 +136,14 @@
 	int polling_reg_flag;
 	struct diag_write_device *buf_tbl;
 	int use_device_tree;
-
+	/* DCI related variables */
+	struct diag_dci_tbl *dci_tbl;
+	int dci_tag;
+	int dci_client_id;
+	struct mutex dci_mutex;
+	int num_dci_client;
+	unsigned char *apps_dci_buf;
+	int dci_state;
 	/* Memory pool parameters */
 	unsigned int itemsize;
 	unsigned int poolsize;
@@ -167,6 +175,7 @@
 	unsigned char *buf_in_wcnss_1;
 	unsigned char *buf_in_wcnss_2;
 	unsigned char *buf_in_wcnss_cntl;
+	unsigned char *buf_in_dci;
 	unsigned char *usb_buf_out;
 	unsigned char *apps_rsp_buf;
 	unsigned char *user_space_data;
@@ -176,6 +185,7 @@
 	unsigned char *buf_event_mask_update;
 	smd_channel_t *ch;
 	smd_channel_t *ch_cntl;
+	smd_channel_t *ch_dci;
 	smd_channel_t *chqdsp;
 	smd_channel_t *chqdsp_cntl;
 	smd_channel_t *ch_wcnss;
@@ -186,6 +196,7 @@
 	int in_busy_qdsp_2;
 	int in_busy_wcnss_1;
 	int in_busy_wcnss_2;
+	int in_busy_dci;
 	int read_len_legacy;
 	unsigned char *hdlc_buf;
 	unsigned hdlc_count;
@@ -208,6 +219,7 @@
 	struct work_struct diag_modem_mask_update_work;
 	struct work_struct diag_qdsp_mask_update_work;
 	struct work_struct diag_wcnss_mask_update_work;
+	struct work_struct diag_read_smd_dci_work;
 	uint8_t *msg_masks;
 	uint8_t *log_masks;
 	int log_masks_length;
@@ -223,6 +235,7 @@
 	struct diag_request *write_ptr_qdsp_2;
 	struct diag_request *write_ptr_wcnss_1;
 	struct diag_request *write_ptr_wcnss_2;
+	struct diag_write_device *write_ptr_dci;
 	int logging_mode;
 	int mask_check;
 	int logging_process_id;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7e2333a..0a156de 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -28,6 +28,7 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
+#include "diag_dci.h"
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
 #endif
@@ -222,6 +223,11 @@
 		return -ENOMEM;
 	}
 
+	/* clean up any DCI registrations for this client
+	* This will specially help in case of ungraceful exit of any DCI client
+	* This call will remove any pending registrations of such client
+	*/
+	diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
 #ifdef CONFIG_DIAG_OVER_USB
 	/* If the SD logging process exits, change logging to USB mode */
 	if (driver->logging_process_id == current->tgid) {
@@ -330,6 +336,7 @@
 	int i, j, count_entries = 0, temp;
 	int success = -1;
 	void *temp_buf;
+	uint16_t support_list = 0;
 
 	if (iocmd == DIAG_IOCTL_COMMAND_REG) {
 		struct bindpkt_params_per_process *pkt_params =
@@ -397,6 +404,46 @@
 			*(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);
 			success = 0;
 		}
+	} else if (iocmd == DIAG_IOCTL_DCI_REG) {
+		if (driver->dci_state == DIAG_DCI_NO_REG)
+			return DIAG_DCI_NO_REG;
+		/* use the 'list' later on to notify user space */
+		if (driver->num_dci_client >= MAX_DCI_CLIENT)
+			return DIAG_DCI_NO_REG;
+		mutex_lock(&driver->dci_mutex);
+		driver->num_dci_client++;
+		pr_debug("diag: id = %d\n", driver->dci_client_id);
+		driver->dci_client_id++;
+		mutex_unlock(&driver->dci_mutex);
+		return driver->dci_client_id;
+	} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
+		success = -1;
+		/* Delete this process from DCI table */
+		mutex_lock(&driver->dci_mutex);
+		for (i = 0; i < dci_max_reg; i++) {
+			if (driver->dci_tbl[i].pid == current->tgid) {
+				pr_debug("diag: delete %d\n", current->tgid);
+				driver->dci_tbl[i].pid = 0;
+				success = i;
+			}
+		}
+		/* if any registrations were deleted successfully OR a valid
+		   client_id was sent in DEINIT call , then its DCI client */
+		if (success >= 0 || ioarg)
+			driver->num_dci_client--;
+		driver->num_dci_client--;
+		mutex_unlock(&driver->dci_mutex);
+		for (i = 0; i < dci_max_reg; i++)
+			if (driver->dci_tbl[i].pid != 0)
+				pr_debug("diag: PID = %d, UID = %d, tag = %d\n",
+	driver->dci_tbl[i].pid, driver->dci_tbl[i].uid, driver->dci_tbl[i].tag);
+		pr_debug("diag: complete deleting registrations\n");
+		return success;
+	} else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
+		if (driver->ch_dci)
+			support_list = support_list | DIAG_CON_MPSS;
+		*(uint16_t *)ioarg = support_list;
+		return DIAG_DCI_NO_ERROR;
 	} else if (iocmd == DIAG_IOCTL_LSM_DEINIT) {
 		for (i = 0; i < driver->num_clients; i++)
 			if (driver->client_map[i].pid == current->tgid)
@@ -720,6 +767,26 @@
 		goto exit;
 	}
 
+	if (driver->data_ready[index] & DCI_DATA_TYPE) {
+		/*Copy the type of data being passed*/
+		data_type = driver->data_ready[index] & DCI_DATA_TYPE;
+		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
+		COPY_USER_SPACE_OR_EXIT(buf+4,
+			 driver->write_ptr_dci->length, 4);
+		/* check delayed vs immediate response */
+		if (*(uint8_t *)(driver->buf_in_dci+4) == DCI_CMD_CODE)
+			COPY_USER_SPACE_OR_EXIT(buf+8,
+		*(driver->buf_in_dci + 5), driver->write_ptr_dci->length);
+		else
+			COPY_USER_SPACE_OR_EXIT(buf+8,
+		*(driver->buf_in_dci + 8), driver->write_ptr_dci->length);
+		driver->in_busy_dci = 0;
+		driver->data_ready[index] ^= DCI_DATA_TYPE;
+		if (driver->ch_dci)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_dci_work));
+		goto exit;
+	}
 exit:
 	mutex_unlock(&driver->diagchar_mutex);
 	return ret;
@@ -748,6 +815,17 @@
 	/* First 4 bytes indicate the type of payload - ignore these */
 	payload_size = count - 4;
 
+	if (pkt_type == DCI_DATA_TYPE) {
+		err = copy_from_user(driver->user_space_data, buf + 4,
+							 payload_size);
+		if (err) {
+			pr_alert("diag: copy failed for DCI data\n");
+			return DIAG_DCI_SEND_DATA_FAIL;
+		}
+		err = diag_process_dci_client(driver->user_space_data,
+							payload_size);
+		return err;
+	}
 	if (pkt_type == USER_SPACE_LOG_TYPE) {
 		err = copy_from_user(driver->user_space_data, buf + 4,
 							 payload_size);
@@ -1076,6 +1154,7 @@
 		driver->used = 0;
 		timer_in_progress = 0;
 		driver->debug_flag = 1;
+		driver->dci_state = DIAG_DCI_NO_ERROR;
 		setup_timer(&drain_timer, drain_timer_func, 1234);
 		driver->itemsize = itemsize;
 		driver->poolsize = poolsize;
@@ -1100,8 +1179,11 @@
 			diag_read_smd_wcnss_work_fn);
 		INIT_WORK(&(driver->diag_read_smd_wcnss_cntl_work),
 			diag_read_smd_wcnss_cntl_work_fn);
+		INIT_WORK(&(driver->diag_read_smd_dci_work),
+						 diag_read_smd_dci_work_fn);
 		diagfwd_init();
 		diagfwd_cntl_init();
+		driver->dci_state = diag_dci_init();
 		diag_sdio_fn(INIT);
 		diag_hsic_fn(INIT);
 		pr_debug("diagchar initializing ..\n");
diff --git a/drivers/char/diag/diagchar_hdlc.c b/drivers/char/diag/diagchar_hdlc.c
index ef57d52..74dcb6b 100644
--- a/drivers/char/diag/diagchar_hdlc.c
+++ b/drivers/char/diag/diagchar_hdlc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -19,6 +19,7 @@
 #include <linux/uaccess.h>
 #include <linux/crc-ccitt.h>
 #include "diagchar_hdlc.h"
+#include "diagchar.h"
 
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/diag/diagchar_hdlc.h b/drivers/char/diag/diagchar_hdlc.h
index 2df81de..116c980 100644
--- a/drivers/char/diag/diagchar_hdlc.h
+++ b/drivers/char/diag/diagchar_hdlc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -54,7 +54,6 @@
 int diag_hdlc_decode(struct diag_hdlc_decode_type *hdlc);
 
 #define ESC_CHAR     0x7D
-#define CONTROL_CHAR 0x7E
 #define ESC_MASK     0x20
 
 #endif
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index efe0241..7066141 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -37,6 +37,8 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
 #endif
+#include "diag_dci.h"
+
 #define MODE_CMD		41
 #define RESET_ID		2
 #define ALL_EQUIP_ID		100
@@ -689,14 +691,14 @@
 	mutex_unlock(&driver->diagchar_mutex);
 }
 
-void diag_update_sleeping_process(int process_id)
+void diag_update_sleeping_process(int process_id, int data_type)
 {
 	int i;
 
 	mutex_lock(&driver->diagchar_mutex);
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == process_id) {
-			driver->data_ready[i] |= PKT_TYPE;
+			driver->data_ready[i] |= data_type;
 			break;
 		}
 	wake_up_interruptible(&driver->wait_q);
@@ -709,7 +711,7 @@
 	driver->pkt_length = len;
 	if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
 		diag_update_pkt_buffer(buf);
-		diag_update_sleeping_process(entry.process_id);
+		diag_update_sleeping_process(entry.process_id, PKT_TYPE);
 	} else {
 		if (len > 0) {
 			if (entry.client_id == MODEM_PROC && driver->ch) {
@@ -2016,6 +2018,7 @@
 	usb_diag_close(driver->legacy_ch);
 #endif
 	platform_driver_unregister(&msm_smd_ch1_driver);
+	platform_driver_unregister(&msm_diag_dci_driver);
 	platform_driver_unregister(&diag_smd_lite_driver);
 	kfree(driver->event_mask);
 	kfree(driver->log_mask);
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 5744459..0780a8e 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -32,6 +32,7 @@
 void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
 					 int ssid_last, int proc);
 void diag_send_log_mask_update(smd_channel_t *, int);
+void diag_update_sleeping_process(int process_id, int data_type);
 /* State for diag forwarding */
 #ifdef CONFIG_DIAG_OVER_USB
 int diagfwd_connect(void);
@@ -40,4 +41,5 @@
 extern int diag_debug_buf_idx;
 extern unsigned char diag_debug_buf[1024];
 extern int diag_event_num_bytes;
+extern struct platform_driver msm_diag_dci_driver;
 #endif
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cff7fec..8c29535 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -304,15 +304,22 @@
 	return result;
 }
 
-static inline unsigned int rb_offset(unsigned int index)
+static inline unsigned int rb_offset(unsigned int timestamp)
 {
-	return index*sizeof(unsigned int)*(Z180_PACKET_SIZE);
+	return (timestamp % Z180_PACKET_COUNT)
+		*sizeof(unsigned int)*(Z180_PACKET_SIZE);
 }
 
-static void addmarker(struct z180_ringbuffer *rb, unsigned int index)
+static inline unsigned int rb_gpuaddr(struct z180_device *z180_dev,
+					unsigned int timestamp)
+{
+	return z180_dev->ringbuffer.cmdbufdesc.gpuaddr + rb_offset(timestamp);
+}
+
+static void addmarker(struct z180_ringbuffer *rb, unsigned int timestamp)
 {
 	char *ptr = (char *)(rb->cmdbufdesc.hostptr);
-	unsigned int *p = (unsigned int *)(ptr + rb_offset(index));
+	unsigned int *p = (unsigned int *)(ptr + rb_offset(timestamp));
 
 	*p++ = Z180_STREAM_PACKET;
 	*p++ = (Z180_MARKER_CMD | 5);
@@ -326,11 +333,11 @@
 	*p++ = ADDR_VGV3_LAST << 24;
 }
 
-static void addcmd(struct z180_ringbuffer *rb, unsigned int index,
+static void addcmd(struct z180_ringbuffer *rb, unsigned int timestamp,
 			unsigned int cmd, unsigned int nextcnt)
 {
 	char * ptr = (char *)(rb->cmdbufdesc.hostptr);
-	unsigned int *p = (unsigned int *)(ptr + (rb_offset(index)
+	unsigned int *p = (unsigned int *)(ptr + (rb_offset(timestamp)
 			   + (Z180_MARKER_SIZE * sizeof(unsigned int))));
 
 	*p++ = Z180_STREAM_PACKET_CALL;
@@ -355,7 +362,7 @@
 	z180_cmdwindow_write(device, ADDR_VGV3_MODE, 4);
 
 	z180_cmdwindow_write(device, ADDR_VGV3_NEXTADDR,
-			z180_dev->ringbuffer.cmdbufdesc.gpuaddr);
+			     rb_gpuaddr(z180_dev, z180_dev->current_timestamp));
 
 	z180_cmdwindow_write(device, ADDR_VGV3_NEXTCMD, cmd | 5);
 
@@ -406,9 +413,7 @@
 	long result = 0;
 	unsigned int ofs        = PACKETSIZE_STATESTREAM * sizeof(unsigned int);
 	unsigned int cnt        = 5;
-	unsigned int nextaddr   = 0;
-	unsigned int index	= 0;
-	unsigned int nextindex;
+	unsigned int old_timestamp = 0;
 	unsigned int nextcnt    = Z180_STREAM_END_CMD | 5;
 	struct kgsl_mem_entry *entry = NULL;
 	unsigned int cmd;
@@ -477,26 +482,22 @@
 	}
 	result = 0;
 
-	index = z180_dev->current_timestamp % Z180_PACKET_COUNT;
+	old_timestamp = z180_dev->current_timestamp;
 	z180_dev->current_timestamp++;
-	nextindex = z180_dev->current_timestamp % Z180_PACKET_COUNT;
 	*timestamp = z180_dev->current_timestamp;
 
 	z180_dev->ringbuffer.prevctx = context->id;
 
-	addcmd(&z180_dev->ringbuffer, index, cmd + ofs, cnt);
+	addcmd(&z180_dev->ringbuffer, old_timestamp, cmd + ofs, cnt);
 	kgsl_pwrscale_busy(device);
 
 	/* Make sure the next ringbuffer entry has a marker */
-	addmarker(&z180_dev->ringbuffer, nextindex);
-
-	nextaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr
-		+ rb_offset(nextindex);
+	addmarker(&z180_dev->ringbuffer, z180_dev->current_timestamp);
 
 	/* monkey patch the IB so that it jumps back to the ringbuffer */
 	kgsl_sharedmem_writel(&entry->memdesc,
-			      ((sizedwords + 1) * sizeof(unsigned int)),
-			      nextaddr);
+		      ((sizedwords + 1) * sizeof(unsigned int)),
+		      rb_gpuaddr(z180_dev, z180_dev->current_timestamp));
 	kgsl_sharedmem_writel(&entry->memdesc,
 			      ((sizedwords + 2) * sizeof(unsigned int)),
 			      nextcnt);
diff --git a/drivers/mfd/pm8018-core.c b/drivers/mfd/pm8018-core.c
index 041815776..efe4fbf 100644
--- a/drivers/mfd/pm8018-core.c
+++ b/drivers/mfd/pm8018-core.c
@@ -529,8 +529,8 @@
 static const char * const pm8018_rev_names[] = {
 	[PM8XXX_REVISION_8018_TEST]	= "test",
 	[PM8XXX_REVISION_8018_1p0]	= "1.0",
-	[PM8XXX_REVISION_8018_1p1]	= "1.1",
 	[PM8XXX_REVISION_8018_2p0]	= "2.0",
+	[PM8XXX_REVISION_8018_2p1]	= "2.1",
 };
 
 static int __devinit pm8018_probe(struct platform_device *pdev)
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 0f41ba7..71fc3f7 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -831,6 +831,7 @@
 	[PM8XXX_REVISION_8921_1p1]	= "1.1",
 	[PM8XXX_REVISION_8921_2p0]	= "2.0",
 	[PM8XXX_REVISION_8921_3p0]	= "3.0",
+	[PM8XXX_REVISION_8921_3p1]	= "3.1",
 };
 
 static const char * const pm8922_rev_names[] = {
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index b768784..d765744 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -537,7 +537,7 @@
 void mdp4_dma_s_done_mddi(void);
 void mdp4_dma_p_done_mddi(void);
 void mdp4_dma_p_done_dsi(struct mdp_dma_data *dma);
-void mdp4_dma_p_done_dsi_video(void);
+void mdp4_dma_p_done_dsi_video(struct mdp_dma_data *dma);
 void mdp4_dma_p_done_lcdc(void);
 void mdp4_overlay1_done_dtv(void);
 void mdp4_overlay1_done_atv(void);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 0ff70f2..73aec96 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2528,10 +2528,7 @@
 #endif
 	}
 
-	if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt &&
-		(pipe->mixer_num == MDP4_MIXER0 || hdmi_prim_display)) {
-			ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
-	} else if (mfd->mdp_rev == MDP_REV_41 &&
+	if (mfd->mdp_rev >= MDP_REV_41 &&
 		mdp4_overlay_is_rgb_type(pipe->src_format) &&
 		!mfd->use_ov0_blt && (pipe->mixer_num == MDP4_MIXER0 ||
 		hdmi_prim_display)) {
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index d120071..8ab12590 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -40,6 +40,7 @@
 
 static struct mdp4_overlay_pipe *dsi_pipe;
 static struct completion dsi_video_comp;
+static int blt_cfg_changed;
 
 static cmd_fxn_t display_on;
 
@@ -550,8 +551,26 @@
  /*
  * mdp4_dma_p_done_dsi_video: called from isr
  */
-void mdp4_dma_p_done_dsi_video(void)
+void mdp4_dma_p_done_dsi_video(struct mdp_dma_data *dma)
 {
+	if (blt_cfg_changed) {
+		mdp_is_in_isr = TRUE;
+		mdp4_overlayproc_cfg(dsi_pipe);
+		mdp4_overlay_dmap_xy(dsi_pipe);
+		mdp_is_in_isr = FALSE;
+		if (dsi_pipe->blt_addr) {
+			mdp4_dsi_video_blt_ov_update(dsi_pipe);
+			dsi_pipe->ov_cnt++;
+			outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+			mdp_intr_mask |= INTR_OVERLAY0_DONE;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+			dma->busy = TRUE;
+			mdp_enable_irq(MDP_OVERLAY0_TERM);
+			/* kickoff overlay engine */
+			outpdw(MDP_BASE + 0x0004, 0);
+		}
+		blt_cfg_changed = 0;
+	}
 	complete_all(&dsi_video_comp);
 }
 
@@ -573,30 +592,6 @@
 	complete(&dma->comp);
 }
 
-static void mdp4_overlay_dsi_video_prefill(struct msm_fb_data_type *mfd)
-{
-	unsigned long flag;
-
-	if (dsi_pipe->blt_addr) {
-		mdp4_overlay_dsi_video_dma_busy_wait(mfd);
-
-		mdp4_dsi_video_blt_ov_update(dsi_pipe);
-		dsi_pipe->ov_cnt++;
-
-		spin_lock_irqsave(&mdp_spin_lock, flag);
-		outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
-		mdp_intr_mask |= INTR_OVERLAY0_DONE;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		mdp_enable_irq(MDP_OVERLAY0_TERM);
-		mfd->dma->busy = TRUE;
-		mb();	/* make sure all registers updated */
-		spin_unlock_irqrestore(&mdp_spin_lock, flag);
-		outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
-		mdp4_stat.kickoff_ov0++;
-		mb();
-	}
-}
-
 /*
  * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
  * has enough space h * w * 3 * 2
@@ -626,12 +621,18 @@
 		dsi_pipe->blt_addr = 0;
 		change++;
 	}
+
+	if (!change) {
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		return;
+	}
+
 	pr_debug("%s: enable=%d blt_addr=%x\n", __func__,
-				enable, (int)dsi_pipe->blt_addr);
+			enable, (int)dsi_pipe->blt_addr);
+	blt_cfg_changed = 1;
+
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
-	if (!change)
-		return;
 
 	/*
 	 * may need mutex here to sync with whom dsiable
@@ -641,24 +642,10 @@
 	data &= 0x01;
 	if (data) {	/* timing generator enabled */
 		mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE);
-		MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
-		msleep(20);	/* make sure last frame is finished */
-		mipi_dsi_controller_cfg(0);
+		mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC);
 	}
-	mdp4_overlayproc_cfg(dsi_pipe);
-	mdp4_overlay_dmap_xy(dsi_pipe);
 
-	if (data) {	/* timing generator enabled */
-		if (dsi_pipe->blt_addr) {
-			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
-			mdp4_overlay_dsi_video_prefill(mfd);
-			mdp4_overlay_dsi_video_prefill(mfd);
-			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
-		}
-		mipi_dsi_sw_reset();
-		mipi_dsi_controller_cfg(1);
-		MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
-	}
+
 }
 
 int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 3aa848c..9f8b5c6 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -515,7 +515,7 @@
 			mdp_intr_mask &= ~INTR_DMA_P_DONE;
 			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 			dma->waiting = FALSE;
-			mdp4_dma_p_done_dsi_video();
+			mdp4_dma_p_done_dsi_video(dma);
 			spin_unlock(&mdp_spin_lock);
 		} else if (panel & MDP4_PANEL_DSI_CMD) {
 			mdp4_dma_p_done_dsi(dma);
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 15737d6..e50a054 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -19,6 +19,7 @@
 #define PKT_TYPE			8
 #define DEINIT_TYPE			16
 #define USER_SPACE_LOG_TYPE		32
+#define DCI_DATA_TYPE			64
 #define USB_MODE			1
 #define MEMORY_DEVICE_MODE		2
 #define NO_LOGGING_MODE			3
@@ -35,6 +36,10 @@
 #define DIAG_IOCTL_SWITCH_LOGGING	7
 #define DIAG_IOCTL_GET_DELAYED_RSP_ID 	8
 #define DIAG_IOCTL_LSM_DEINIT		9
+#define DIAG_IOCTL_DCI_INIT		20
+#define DIAG_IOCTL_DCI_DEINIT		21
+#define DIAG_IOCTL_DCI_SUPPORT		22
+#define DIAG_IOCTL_DCI_REG		23
 
 /* PC Tools IDs */
 #define APQ8060_TOOLS_ID	4062
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index b907219..08e9014 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -50,6 +50,7 @@
 #define PM8XXX_REVISION_8921_1p1	2
 #define PM8XXX_REVISION_8921_2p0	3
 #define PM8XXX_REVISION_8921_3p0	4
+#define PM8XXX_REVISION_8921_3p1	5
 
 #define PM8XXX_REVISION_8821_TEST	0
 #define PM8XXX_REVISION_8821_1p0	1
@@ -58,8 +59,8 @@
 
 #define PM8XXX_REVISION_8018_TEST	0
 #define PM8XXX_REVISION_8018_1p0	1
-#define PM8XXX_REVISION_8018_1p1	2
-#define PM8XXX_REVISION_8018_2p0	3
+#define PM8XXX_REVISION_8018_2p0	2
+#define PM8XXX_REVISION_8018_2p1	3
 
 #define PM8XXX_REVISION_8922_TEST	0
 #define PM8XXX_REVISION_8922_1p0	1