Merge "msm_fb: display: switch mdp mode without turning off timing generator" 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 8464752..de6e0d2 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -71,6 +71,265 @@
 };
 #endif
 
+#ifdef CONFIG_MSM_VCAP
+static struct gpiomux_setting gpio_vcap_config[] = {
+	{
+		.func = GPIOMUX_FUNC_GPIO,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_1,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_2,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_3,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_4,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_5,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_6,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_7,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_8,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_9,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+	{
+		.func = GPIOMUX_FUNC_A,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+};
+
+struct msm_gpiomux_config vcap_configs[] = {
+	{
+		.gpio = 20,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[7],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[7],
+		}
+	},
+	{
+		.gpio = 25,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 24,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[1],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[1],
+		}
+	},
+	{
+		.gpio = 23,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 19,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[8],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[8],
+		}
+	},
+	{
+		.gpio = 22,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 21,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[7],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[7],
+		}
+	},
+	{
+		.gpio = 12,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[6],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[6],
+		}
+	},
+	{
+		.gpio = 18,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[9],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[9],
+		}
+	},
+	{
+		.gpio = 11,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[10],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[10],
+		}
+	},
+	{
+		.gpio = 10,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[9],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[9],
+		}
+	},
+	{
+		.gpio = 9,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 26,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[1],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[1],
+		}
+	},
+	{
+		.gpio = 8,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[3],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[3],
+		}
+	},
+	{
+		.gpio = 7,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[7],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[7],
+		}
+	},
+	{
+		.gpio = 6,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[7],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[7],
+		}
+	},
+	{
+		.gpio = 80,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 86,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[1],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[1],
+		}
+	},
+	{
+		.gpio = 85,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[4],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[4],
+		}
+	},
+	{
+		.gpio = 84,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[3],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[3],
+		}
+	},
+	{
+		.gpio = 5,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 4,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[3],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[3],
+		}
+	},
+	{
+		.gpio = 3,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[6],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[6],
+		}
+	},
+	{
+		.gpio = 2,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[5],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[5],
+		}
+	},
+	{
+		.gpio = 82,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[4],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[4],
+		}
+	},
+	{
+		.gpio = 83,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[4],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[4],
+		}
+	},
+	{
+		.gpio = 87,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[2],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[2],
+		}
+	},
+	{
+		.gpio = 13,
+		.settings = {
+			[GPIOMUX_SUSPENDED] =	&gpio_vcap_config[6],
+			[GPIOMUX_ACTIVE] =		&gpio_vcap_config[6],
+		}
+	},
+};
+#endif
+
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
@@ -658,6 +917,10 @@
 		 machine_is_mpq8064_dtv()) {
 		msm_gpiomux_install(mpq8064_gsbi5_i2c_configs,
 				ARRAY_SIZE(mpq8064_gsbi5_i2c_configs));
+#ifdef CONFIG_MSM_VCAP
+		msm_gpiomux_install(vcap_configs,
+				ARRAY_SIZE(vcap_configs));
+#endif
 	} else {
 		#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 		msm_gpiomux_install(apq8064_ethernet_configs,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5cb44b8..b4a58e8 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1068,6 +1068,7 @@
 	0,
 };
 
+#ifndef CONFIG_MSM_VCAP
 #define MXT_TS_GPIO_IRQ			6
 #define MXT_TS_PWR_EN_GPIO		PM8921_GPIO_PM_TO_SYS(23)
 #define MXT_TS_RESET_GPIO		33
@@ -1119,6 +1120,7 @@
 		.irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
 	},
 };
+#endif
 #define CYTTSP_TS_GPIO_IRQ		6
 #define CYTTSP_TS_GPIO_RESOUT		7
 #define CYTTSP_TS_GPIO_SLEEP		33
@@ -1854,9 +1856,11 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
+#ifndef CONFIG_MSM_VCAP
 	&apq8064_device_qup_i2c_gsbi1,
 	&apq8064_device_qup_i2c_gsbi3,
 	&apq8064_device_qup_i2c_gsbi4,
+#endif
 	&apq8064_device_qup_spi_gsbi5,
 	&apq8064_device_ext_5v_vreg,
 	&apq8064_device_ext_mpp8_vreg,
@@ -2054,6 +2058,9 @@
 	&mpq8064_device_ext_2p2_buck_vreg,
 	&mpq8064_device_ext_5v_buck_vreg,
 	&mpq8064_device_ext_3p3v_ldo_vreg,
+#ifdef CONFIG_MSM_VCAP
+	&msm8064_device_vcap,
+#endif
 };
 
 static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
@@ -2310,12 +2317,14 @@
 		smb349_charger_i2c_info,
 		ARRAY_SIZE(smb349_charger_i2c_info)
 	},
+#ifndef CONFIG_MSM_VCAP
 	{
 		I2C_SURF | I2C_LIQUID,
 		APQ_8064_GSBI3_QUP_I2C_BUS_ID,
 		mxt_device_info,
 		ARRAY_SIZE(mxt_device_info),
 	},
+#endif
 	{
 		I2C_FFA,
 		APQ_8064_GSBI3_QUP_I2C_BUS_ID,
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index 83fb5fd..679c2fc 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -211,9 +211,11 @@
 	400000, 24000000, 48000000,
 };
 
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static unsigned int sdc3_sup_clk_rates[] = {
 	400000, 24000000, 48000000, 96000000, 192000000,
 };
+#endif
 
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
 static struct mmc_platform_data msm8960_sdc1_data = {
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index b03da38..22f8fb5 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -210,9 +210,11 @@
 	400000, 24000000, 48000000
 };
 
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static unsigned int sdc3_sup_clk_rates[] = {
 	400000, 24000000, 48000000, 96000000, 192000000
 };
+#endif
 
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
 static struct mmc_platform_data msm8960_sdc1_data = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 1ca25cc..f84d553 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -3036,9 +3036,6 @@
 	msm8960_init_mmc();
 	register_i2c_devices();
 
-	/* For 8960 Fusion 2.2 Primary IPC */
-	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
-		msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
 
 	msm8960_init_fb();
 	slim_register_board_info(msm_slim_devices,
@@ -3103,6 +3100,10 @@
 	else
 		platform_device_register(&msm8960_device_uart_gsbi5);
 
+	/* For 8960 Fusion 2.2 Primary IPC */
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+		msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index 0e18918..c600d53 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -105,6 +105,20 @@
 };
 #endif
 
+static struct gpiomux_setting wlan_active_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting wlan_suspend_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_IN,
+};
+
 static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
 	{
 		.gpio = 24,
@@ -306,6 +320,24 @@
 };
 #endif
 
+static struct msm_gpiomux_config msm9615_wlan_configs[] __initdata = {
+	{
+		.gpio	= 2,	/* WLAN_PM_ENABLE */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &wlan_active_config,
+			[GPIOMUX_SUSPENDED] = &wlan_suspend_config,
+		},
+	},
+	{
+		.gpio	= 21,	/* WLAN_RESET_N */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &wlan_active_config,
+			[GPIOMUX_SUSPENDED] = &wlan_suspend_config,
+		},
+	},
+};
+
+
 int __init msm9615_init_gpiomux(void)
 {
 	int rc;
@@ -332,6 +364,9 @@
 	msm_gpiomux_install(msm9615_audio_codec_configs,
 			ARRAY_SIZE(msm9615_audio_codec_configs));
 
+	msm_gpiomux_install(msm9615_wlan_configs,
+			ARRAY_SIZE(msm9615_wlan_configs));
+
 #ifdef CONFIG_FB_MSM_EBI2
 	msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
 			ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index ca5a63d..aa25103 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5038,11 +5038,14 @@
 	CLK_LOOKUP("bus_clk",
 			    gfx3d_axi_clk_8064.c, "footswitch-8x60.2"),
 	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,           ""),
+	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,           "msm_vcap.0"),
 	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,	"footswitch-8x60.10"),
 	CLK_LOOKUP("bus_clk",		vcap_axi_clk.c,	"footswitch-8x60.10"),
 	CLK_LOOKUP("core_clk",          vcap_clk.c,             ""),
+	CLK_LOOKUP("core_clk",          vcap_clk.c,             "msm_vcap.0"),
 	CLK_LOOKUP("core_clk",          vcap_clk.c,	"footswitch-8x60.10"),
 	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         ""),
+	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         "msm_vcap.0"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
 	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		""),
 	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            ""),
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 09bf036..fb5b580 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -132,8 +132,11 @@
 {
 	int ret = 0;
 	struct clk *parent;
+
 	if (!clk)
 		return 0;
+	if (IS_ERR(clk))
+		return -EINVAL;
 
 	mutex_lock(&clk->prepare_lock);
 	if (clk->prepare_count == 0) {
@@ -174,6 +177,8 @@
 
 	if (!clk)
 		return 0;
+	if (IS_ERR(clk))
+		return -EINVAL;
 
 	spin_lock_irqsave(&clk->lock, flags);
 	if (WARN(!clk->warned && !clk->prepare_count,
@@ -230,7 +235,7 @@
 {
 	unsigned long flags;
 
-	if (!clk)
+	if (IS_ERR_OR_NULL(clk))
 		return;
 
 	spin_lock_irqsave(&clk->lock, flags);
@@ -259,7 +264,7 @@
 
 void clk_unprepare(struct clk *clk)
 {
-	if (!clk)
+	if (IS_ERR_OR_NULL(clk))
 		return;
 
 	mutex_lock(&clk->prepare_lock);
@@ -290,6 +295,9 @@
 
 int clk_reset(struct clk *clk, enum clk_reset_action action)
 {
+	if (IS_ERR_OR_NULL(clk))
+		return -EINVAL;
+
 	if (!clk->ops->reset)
 		return -ENOSYS;
 
@@ -299,6 +307,9 @@
 
 unsigned long clk_get_rate(struct clk *clk)
 {
+	if (IS_ERR_OR_NULL(clk))
+		return 0;
+
 	if (!clk->ops->get_rate)
 		return clk->rate;
 
@@ -311,6 +322,9 @@
 	unsigned long start_rate, flags;
 	int rc;
 
+	if (IS_ERR_OR_NULL(clk))
+		return -EINVAL;
+
 	if (!clk->ops->set_rate)
 		return -ENOSYS;
 
@@ -347,6 +361,9 @@
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	if (IS_ERR_OR_NULL(clk))
+		return -EINVAL;
+
 	if (!clk->ops->round_rate)
 		return -ENOSYS;
 
@@ -356,6 +373,9 @@
 
 int clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
+	if (IS_ERR_OR_NULL(clk))
+		return -EINVAL;
+
 	if (!clk->ops->set_max_rate)
 		return -ENOSYS;
 
@@ -374,6 +394,9 @@
 
 struct clk *clk_get_parent(struct clk *clk)
 {
+	if (IS_ERR_OR_NULL(clk))
+		return NULL;
+
 	if (!clk->ops->get_parent)
 		return NULL;
 
@@ -383,7 +406,7 @@
 
 int clk_set_flags(struct clk *clk, unsigned long flags)
 {
-	if (clk == NULL || IS_ERR(clk))
+	if (IS_ERR_OR_NULL(clk))
 		return -EINVAL;
 	if (!clk->ops->set_flags)
 		return -ENOSYS;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index b760226..e729a63 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2258,6 +2258,109 @@
 	},
 };
 
+#ifdef CONFIG_MSM_VCAP
+#define VCAP_HW_BASE         0x05900000
+
+static struct msm_bus_vectors vcap_init_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_CAP,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+
+static struct msm_bus_vectors vcap_480_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_CAP,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1280 * 720 * 3 * 60 / 16,
+		.ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+	},
+};
+
+static struct msm_bus_vectors vcap_720_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_CAP,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1280 * 720 * 3 * 60 / 16,
+		.ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+	},
+};
+
+static struct msm_bus_vectors vcap_1080_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_CAP,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1920 * 1080 * 3 * 60 / 16,
+		.ib = 1920 * 1080 * 3 * 60 / 16 * 1.5,
+	},
+};
+
+static struct msm_bus_paths vcap_bus_usecases[]  = {
+	{
+		ARRAY_SIZE(vcap_init_vectors),
+		vcap_init_vectors,
+	},
+	{
+		ARRAY_SIZE(vcap_480_vectors),
+		vcap_480_vectors,
+	},
+	{
+		ARRAY_SIZE(vcap_720_vectors),
+		vcap_720_vectors,
+	},
+	{
+		ARRAY_SIZE(vcap_1080_vectors),
+		vcap_1080_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata vcap_axi_client_pdata = {
+	vcap_bus_usecases,
+	ARRAY_SIZE(vcap_bus_usecases),
+};
+
+static struct resource msm_vcap_resources[] = {
+	{
+		.name	= "vcap",
+		.start	= VCAP_HW_BASE,
+		.end	= VCAP_HW_BASE + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "vcap",
+		.start	= VCAP_VC,
+		.end	= VCAP_VC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static unsigned vcap_gpios[] = {
+	2, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 12, 13, 18, 19, 20, 21,
+	22, 23, 24, 25, 26, 80, 82,
+	83, 84, 85, 86, 87,
+};
+
+static struct vcap_platform_data vcap_pdata = {
+	.gpios = vcap_gpios,
+	.num_gpios = ARRAY_SIZE(vcap_gpios),
+	.bus_client_pdata = &vcap_axi_client_pdata
+};
+
+struct platform_device msm8064_device_vcap = {
+	.name           = "msm_vcap",
+	.id             = 0,
+	.resource       = msm_vcap_resources,
+	.num_resources  = ARRAY_SIZE(msm_vcap_resources),
+	.dev = {
+		.platform_data = &vcap_pdata,
+	},
+};
+#endif
+
 static struct resource msm_cache_erp_resources[] = {
 	{
 		.name = "l1_irq",
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 0c25434..48a38f0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -171,6 +171,9 @@
 extern struct platform_device msm_device_tssc;
 
 extern struct platform_device msm_rotator_device;
+#ifdef CONFIG_MSM_VCAP
+extern struct platform_device msm8064_device_vcap;
+#endif
 
 #ifdef CONFIG_MSM_BUS_SCALING
 extern struct msm_bus_scale_pdata rotator_bus_scale_pdata;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 59e55de..e6a0175 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -210,6 +210,7 @@
 #endif
 
 #define CSI_EMBED_DATA 0x12
+#define CSI_RESERVED_DATA_0 0x13
 #define CSI_YUV422_8  0x1E
 #define CSI_RAW8    0x2A
 #define CSI_RAW10   0x2B
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index d896013..4934c0f 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -132,10 +132,25 @@
 	int disable_smsm_reset_handshake;
 };
 
+/*
+ * Shared Memory Regions
+ *
+ * the array of these regions is expected to be in ascending order by phys_addr
+ *
+ * @phys_addr: physical base address of the region
+ * @size: size of the region in bytes
+ */
+struct smd_smem_regions {
+	void *phys_addr;
+	unsigned size;
+};
+
 struct smd_platform {
 	uint32_t num_ss_configs;
 	struct smd_subsystem_config *smd_ss_configs;
 	struct smd_subsystem_restart_config *smd_ssr_config;
+	uint32_t num_smem_areas;
+	struct smd_smem_regions *smd_smem_areas;
 };
 
 #ifdef CONFIG_MSM_SMD
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 538dbbe..6fa435a 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -457,8 +457,12 @@
 	INIT_LIST_HEAD(&port_ptr->port_rx_q);
 	mutex_init(&port_ptr->port_rx_q_lock);
 	init_waitqueue_head(&port_ptr->port_rx_wait_q);
+	snprintf(port_ptr->rx_wakelock_name, MAX_WAKELOCK_NAME_SZ,
+		 "msm_ipc_read%08x:%08x",
+		 port_ptr->this_port.node_id,
+		 port_ptr->this_port.port_id);
 	wake_lock_init(&port_ptr->port_rx_wake_lock,
-			WAKE_LOCK_SUSPEND, "msm_ipc_read");
+			WAKE_LOCK_SUSPEND, port_ptr->rx_wakelock_name);
 
 	port_ptr->endpoint = endpoint;
 	port_ptr->notify = notify;
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index ae13e2f..a90be23 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -95,6 +95,7 @@
 /* internals */
 
 #define IPC_ROUTER_MAX_REMOTE_SERVERS		100
+#define MAX_WAKELOCK_NAME_SZ 32
 
 struct rr_packet {
 	struct list_head list;
@@ -116,6 +117,7 @@
 
 	struct list_head port_rx_q;
 	struct mutex port_rx_q_lock;
+	char rx_wakelock_name[MAX_WAKELOCK_NAME_SZ];
 	struct wake_lock port_rx_wake_lock;
 	wait_queue_head_t port_rx_wait_q;
 
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 998e606..8344496 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -251,7 +251,7 @@
 	if (!drv->base)
 		return -ENOMEM;
 
-	drv->xo = clk_get(&pdev->dev, "xo");
+	drv->xo = devm_clk_get(&pdev->dev, "xo");
 	if (IS_ERR(drv->xo))
 		return PTR_ERR(drv->xo);
 
@@ -274,7 +274,6 @@
 	}
 	drv->pil = msm_pil_register(desc);
 	if (IS_ERR(drv->pil)) {
-		clk_put(drv->xo);
 		return PTR_ERR(drv->pil);
 	}
 	return 0;
@@ -284,7 +283,6 @@
 {
 	struct modem_data *drv = platform_get_drvdata(pdev);
 	msm_pil_unregister(drv->pil);
-	clk_put(drv->xo);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 235d881..28b9dee 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -221,7 +221,7 @@
 	if (!drv)
 		return -ENOMEM;
 
-	drv->pll = clk_get(&pdev->dev, "pll4");
+	drv->pll = devm_clk_get(&pdev->dev, "pll4");
 	if (IS_ERR(drv->pll))
 		return PTR_ERR(drv->pll);
 
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index ecbbcb9..8a16b43 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -318,14 +318,14 @@
 		if (ret) {
 			dev_err(&pdev->dev,
 				"failed to set pll supply voltage\n");
-			goto err;
+			return ret;
 		}
 
 		ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
 		if (ret < 0) {
 			dev_err(&pdev->dev,
 				"failed to set pll supply optimum mode\n");
-			goto err;
+			return ret;
 		}
 	}
 
@@ -342,29 +342,20 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 
-	drv->xo = clk_get(&pdev->dev, "cxo");
-	if (IS_ERR(drv->xo)) {
-		ret = PTR_ERR(drv->xo);
-		goto err;
-	}
+	drv->xo = devm_clk_get(&pdev->dev, "cxo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
 
 	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil)) {
-		ret = PTR_ERR(drv->pil);
-		goto err_register;
-	}
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
 	return 0;
-err_register:
-	clk_put(drv->xo);
-err:
-	return ret;
 }
 
 static int __devexit pil_riva_remove(struct platform_device *pdev)
 {
 	struct riva_data *drv = platform_get_drvdata(pdev);
 	msm_pil_unregister(drv->pil);
-	clk_put(drv->xo);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 19b3ea6..c1e4118 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -34,6 +34,7 @@
 #include <linux/kfifo.h>
 #include <linux/wakelock.h>
 #include <linux/notifier.h>
+#include <linux/sort.h>
 #include <mach/msm_smd.h>
 #include <mach/msm_iomap.h>
 #include <mach/system.h>
@@ -163,6 +164,16 @@
 		.smsm.irq_handler = NULL, /* does not support smsm */
 	},
 };
+
+struct smem_area {
+	void *phys_addr;
+	unsigned size;
+	void __iomem *virt_addr;
+};
+static uint32_t num_smem_areas;
+static struct smem_area *smem_areas;
+static void *smem_range_check(void *base, unsigned offset);
+
 struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
 
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
@@ -2198,6 +2209,37 @@
 
 /* -------------------------------------------------------------------------- */
 
+/*
+ * Shared Memory Range Check
+ *
+ * Takes a physical address and an offset and checks if the resulting physical
+ * address would fit into one of the aux smem regions.  If so, returns the
+ * corresponding virtual address.  Otherwise returns NULL.  Expects the array
+ * of smem regions to be in ascending physical address order.
+ *
+ * @base: physical base address to check
+ * @offset: offset from the base to get the final address
+ */
+static void *smem_range_check(void *base, unsigned offset)
+{
+	int i;
+	void *phys_addr;
+	unsigned size;
+
+	for (i = 0; i < num_smem_areas; ++i) {
+		phys_addr = smem_areas[i].phys_addr;
+		size = smem_areas[i].size;
+		if (base < phys_addr)
+			return NULL;
+		if (base > phys_addr + size)
+			continue;
+		if (base >= phys_addr && base + offset < phys_addr + size)
+			return smem_areas[i].virt_addr + offset;
+	}
+
+	return NULL;
+}
+
 /* smem_alloc returns the pointer to smem item if it is already allocated.
  * Otherwise, it returns NULL.
  */
@@ -2273,7 +2315,12 @@
 	if (toc[id].allocated) {
 		*size = toc[id].size;
 		barrier();
-		ret = (void *) (MSM_SHARED_RAM_BASE + toc[id].offset);
+		if (!(toc[id].reserved & BASE_ADDR_MASK))
+			ret = (void *) (MSM_SHARED_RAM_BASE + toc[id].offset);
+		else
+			ret = smem_range_check(
+				(void *)(toc[id].reserved & BASE_ADDR_MASK),
+				toc[id].offset);
 	} else {
 		*size = 0;
 	}
@@ -3184,6 +3231,14 @@
 	return ret;
 }
 
+int sort_cmp_func(const void *a, const void *b)
+{
+	struct smem_area *left = (struct smem_area *)(a);
+	struct smem_area *right = (struct smem_area *)(b);
+
+	return left->phys_addr - right->phys_addr;
+}
+
 int smd_core_platform_init(struct platform_device *pdev)
 {
 	int i;
@@ -3193,6 +3248,8 @@
 	struct smd_subsystem_config *smd_ss_config_list;
 	struct smd_subsystem_config *cfg;
 	int err_ret = 0;
+	struct smd_smem_regions *smd_smem_areas;
+	int smem_idx = 0;
 
 	smd_platform_data = pdev->dev.platform_data;
 	num_ss = smd_platform_data->num_ss_configs;
@@ -3202,6 +3259,40 @@
 		disable_smsm_reset_handshake = smd_platform_data->
 			   smd_ssr_config->disable_smsm_reset_handshake;
 
+	smd_smem_areas = smd_platform_data->smd_smem_areas;
+	if (smd_smem_areas) {
+		num_smem_areas = smd_platform_data->num_smem_areas;
+		smem_areas = kmalloc(sizeof(struct smem_area) * num_smem_areas,
+						GFP_KERNEL);
+		if (!smem_areas) {
+			pr_err("%s: smem_areas kmalloc failed\n", __func__);
+			err_ret = -ENOMEM;
+			goto smem_areas_alloc_fail;
+		}
+
+		for (smem_idx = 0; smem_idx < num_smem_areas; ++smem_idx) {
+			smem_areas[smem_idx].phys_addr =
+					smd_smem_areas[smem_idx].phys_addr;
+			smem_areas[smem_idx].size =
+					smd_smem_areas[smem_idx].size;
+			smem_areas[smem_idx].virt_addr = ioremap_nocache(
+				(unsigned long)(smem_areas[smem_idx].phys_addr),
+				smem_areas[smem_idx].size);
+			if (!smem_areas[smem_idx].virt_addr) {
+				pr_err("%s: ioremap_nocache() of addr:%p"
+					" size: %x\n", __func__,
+					smem_areas[smem_idx].phys_addr,
+					smem_areas[smem_idx].size);
+				err_ret = -ENOMEM;
+				++smem_idx;
+				goto smem_failed;
+			}
+		}
+		sort(smem_areas, num_smem_areas,
+				sizeof(struct smem_area),
+				sort_cmp_func, NULL);
+	}
+
 	for (i = 0; i < num_ss; i++) {
 		cfg = &smd_ss_config_list[i];
 
@@ -3215,7 +3306,7 @@
 			err_ret = ret;
 			pr_err("smd: register irq failed on %s\n",
 				cfg->smd_int.irq_name);
-			break;
+			goto intr_failed;
 		}
 
 		/* only init smsm structs if this edge supports smsm */
@@ -3230,7 +3321,7 @@
 			err_ret = ret;
 			pr_err("smd: register irq failed on %s\n",
 				cfg->smsm_int.irq_name);
-			break;
+			goto intr_failed;
 		}
 
 		if (cfg->subsys_name)
@@ -3238,26 +3329,30 @@
 				cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
 	}
 
-	if (err_ret < 0) {
-		pr_err("smd: deregistering IRQs\n");
-		for (i = 0; i < num_ss; ++i) {
-			cfg = &smd_ss_config_list[i];
-
-			if (cfg->smd_int.irq_id >= 0)
-				free_irq(cfg->smd_int.irq_id,
-					(void *)cfg->smd_int.dev_id
-					);
-			if (cfg->smsm_int.irq_id >= 0)
-				free_irq(cfg->smsm_int.irq_id,
-					(void *)cfg->smsm_int.dev_id
-					);
-		}
-		return err_ret;
-	}
 
 	SMD_INFO("smd_core_platform_init() done\n");
 	return 0;
 
+intr_failed:
+	pr_err("smd: deregistering IRQs\n");
+	for (i = 0; i < num_ss; ++i) {
+		cfg = &smd_ss_config_list[i];
+
+		if (cfg->smd_int.irq_id >= 0)
+			free_irq(cfg->smd_int.irq_id,
+				(void *)cfg->smd_int.dev_id
+				);
+		if (cfg->smsm_int.irq_id >= 0)
+			free_irq(cfg->smsm_int.irq_id,
+				(void *)cfg->smsm_int.dev_id
+				);
+	}
+smem_failed:
+	for (smem_idx = smem_idx - 1; smem_idx >= 0; --smem_idx)
+		iounmap(smem_areas[smem_idx].virt_addr);
+	kfree(smem_areas);
+smem_areas_alloc_fail:
+	return err_ret;
 }
 
 static int __devinit msm_smd_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 3464140..6ffd5d2 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -44,8 +44,9 @@
 	unsigned allocated;
 	unsigned offset;
 	unsigned size;
-	unsigned reserved;
+	unsigned reserved; /* bits 1:0 reserved, bits 31:2 aux smem base addr */
 };
+#define BASE_ADDR_MASK 0xfffffffc
 
 struct smem_proc_comm {
 	unsigned command;
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/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 21bcac0..1ecbfca 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -54,6 +54,8 @@
 #define CSID_RST_DONE_IRQ_BITSHIFT                  11
 #define CSID_RST_STB_ALL                            0x7FFF
 
+#define DBG_CSID 0
+
 static int msm_csid_cid_lut(
 	struct msm_camera_csid_lut_params *csid_lut_params,
 	void __iomem *csidbase)
@@ -82,6 +84,20 @@
 	return rc;
 }
 
+#if DBG_CSID
+static void msm_csid_set_debug_reg(void __iomem *csidbase,
+	struct msm_camera_csid_params *csid_params)
+{
+	uint32_t val = 0;
+	val = ((1 << csid_params->lane_cnt) - 1) << 20;
+	msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_MASK_ADDR);
+	msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+}
+#else
+static void msm_csid_set_debug_reg(void __iomem *csidbase,
+	struct msm_camera_csid_params *csid_params) {}
+#endif
+
 static int msm_csid_config(struct csid_cfg_params *cfg_params)
 {
 	int rc = 0;
@@ -106,11 +122,8 @@
 	if (rc < 0)
 		return rc;
 
-	val = ((1 << csid_params->lane_cnt) - 1) << 20;
-	msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_MASK_ADDR);
-	msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+	msm_csid_set_debug_reg(csidbase, csid_params);
 
-	msleep(20);
 	return rc;
 }
 
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 5330d7b..67b7140 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -184,13 +184,14 @@
 static struct msm_camera_csid_vc_cfg imx074_cid_cfg[] = {
 	{0, CSI_RAW10, CSI_DECODE_10BIT},
 	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
+	{2, CSI_RESERVED_DATA_0, CSI_DECODE_8BIT},
 };
 
 static struct msm_camera_csi2_params imx074_csi_params = {
 	.csid_params = {
 		.lane_cnt = 4,
 		.lut_params = {
-			.num_cid = 2,
+			.num_cid = ARRAY_SIZE(imx074_cid_cfg),
 			.vc_cfg = imx074_cid_cfg,
 		},
 	},
diff --git a/drivers/media/video/msm/sensors/imx091.c b/drivers/media/video/msm/sensors/imx091.c
index 34f0820..62e97ac 100644
--- a/drivers/media/video/msm/sensors/imx091.c
+++ b/drivers/media/video/msm/sensors/imx091.c
@@ -211,13 +211,14 @@
 static struct msm_camera_csid_vc_cfg imx091_cid_cfg[] = {
 	{0, CSI_RAW10, CSI_DECODE_10BIT},
 	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
+	{2, CSI_RESERVED_DATA_0, CSI_DECODE_8BIT},
 };
 
 static struct msm_camera_csi2_params imx091_csi_params = {
 	.csid_params = {
 		.lane_cnt = 4,
 		.lut_params = {
-			.num_cid = 2,
+			.num_cid = ARRAY_SIZE(imx091_cid_cfg),
 			.vc_cfg = imx091_cid_cfg,
 		},
 	},
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 4a790f8..8d022b6 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -538,6 +538,7 @@
 
 static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
 	{0, CSI_RAW10, CSI_DECODE_10BIT},
+	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
 };
 
 static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
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/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6b3400d..b428bd2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1993,10 +1993,13 @@
 				clear_bit(B_SESS_VLD, &motg->inputs);
 		} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
 			if (pdata->pmic_id_irq) {
+				unsigned long flags;
+				local_irq_save(flags);
 				if (irq_read_line(pdata->pmic_id_irq))
 					set_bit(ID, &motg->inputs);
 				else
 					clear_bit(ID, &motg->inputs);
+				local_irq_restore(flags);
 			}
 			/*
 			 * VBUS initial state is reported after PMIC
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
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index a2b8797..d2f58a5 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -5427,8 +5427,9 @@
 	return true;
 }
 
+/* called under codec_resource_lock acquisition */
 static int tabla_determine_button(const struct tabla_priv *priv,
-				  const s32 bias_mv)
+				  const s32 micmv)
 {
 	s16 *v_btn_low, *v_btn_high;
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
@@ -5438,8 +5439,9 @@
 	v_btn_low = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_LOW);
 	v_btn_high = tabla_mbhc_cal_btn_det_mp(btn_det,
 				TABLA_BTN_DET_V_BTN_HIGH);
+
 	for (i = 0; i < btn_det->num_btn; i++) {
-		if ((v_btn_low[i] <= bias_mv) && (v_btn_high[i] >= bias_mv)) {
+		if ((v_btn_low[i] <= micmv) && (v_btn_high[i] >= micmv)) {
 			btn = i;
 			break;
 		}
@@ -5447,7 +5449,7 @@
 
 	if (btn == -1)
 		pr_debug("%s: couldn't find button number for mic mv %d\n",
-			 __func__, bias_mv);
+			 __func__, micmv);
 
 	return btn;
 }
@@ -5487,8 +5489,9 @@
 static irqreturn_t tabla_dce_handler(int irq, void *data)
 {
 	int i, mask;
-	short dce, sta, bias_value_dce;
-	s32 mv, stamv, bias_mv_dce;
+	short dce, sta;
+	s32 mv, mv_s, stamv_s;
+	bool vddio;
 	int btn = -1, meas = 0;
 	struct tabla_priv *priv = data;
 	const struct tabla_mbhc_btn_detect_cfg *d =
@@ -5527,6 +5530,10 @@
 		goto done;
 	}
 
+	vddio = (priv->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+		 priv->mbhc_micbias_switched);
+	mv_s = vddio ? tabla_scale_v_micb_vddio(priv, mv, false) : mv;
+
 	if (mbhc_status != TABLA_MBHC_STATUS_REL_DETECTION) {
 		if (priv->mbhc_last_resume &&
 		    !time_after(jiffies, priv->mbhc_last_resume + HZ)) {
@@ -5537,27 +5544,32 @@
 			pr_debug("%s: Button is already released without "
 				 "resume", __func__);
 			sta = tabla_codec_read_sta_result(codec);
-			stamv = tabla_codec_sta_dce_v(codec, 0, sta);
-			btn = tabla_determine_button(priv, mv);
-			if (btn != tabla_determine_button(priv, stamv))
+			stamv_s = tabla_codec_sta_dce_v(codec, 0, sta);
+			if (vddio)
+				stamv_s = tabla_scale_v_micb_vddio(priv,
+								   stamv_s,
+								   false);
+			btn = tabla_determine_button(priv, mv_s);
+			if (btn != tabla_determine_button(priv, stamv_s))
 				btn = -1;
 			goto done;
 		}
 	}
 
 	/* determine pressed button */
-	btnmeas[meas++] = tabla_determine_button(priv, mv);
-	pr_debug("%s: meas %d - DCE %d,%d, button %d\n", __func__,
-		 meas - 1, dce, mv, btnmeas[meas - 1]);
+	btnmeas[meas++] = tabla_determine_button(priv, mv_s);
+	pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n", __func__,
+		 meas - 1, dce, mv, mv_s, btnmeas[meas - 1]);
 	if (n_btn_meas == 0)
 		btn = btnmeas[0];
 	for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
-		bias_value_dce = tabla_codec_sta_dce(codec, 1, false);
-		bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
-		btnmeas[meas] = tabla_determine_button(priv, bias_mv_dce);
-		pr_debug("%s: meas %d - DCE %d,%d, button %d\n",
-			 __func__, meas, bias_value_dce, bias_mv_dce,
-			 btnmeas[meas]);
+		dce = tabla_codec_sta_dce(codec, 1, false);
+		mv = tabla_codec_sta_dce_v(codec, 1, dce);
+		mv_s = vddio ? tabla_scale_v_micb_vddio(priv, mv, false) : mv;
+
+		btnmeas[meas] = tabla_determine_button(priv, mv_s);
+		pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n",
+			 __func__, meas, dce, mv, mv_s, btnmeas[meas]);
 		/* if large enough measurements are collected,
 		 * start to check if last all n_btn_con measurements were
 		 * in same button low/high range */
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 4bb9282..6bac324 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -47,6 +47,7 @@
 static struct mutex routing_lock;
 
 static int fm_switch_enable;
+static int fm_pcmrx_switch_enable;
 
 #define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
@@ -594,6 +595,31 @@
 	return 1;
 }
 
+static int msm_routing_get_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = fm_pcmrx_switch_enable;
+	pr_debug("%s: FM Switch enable %ld\n", __func__,
+		ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int msm_routing_put_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+
+	pr_debug("%s: FM Switch enable %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+	if (ucontrol->value.integer.value[0])
+		snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
+	else
+		snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
+	fm_pcmrx_switch_enable = ucontrol->value.integer.value[0];
+	return 1;
+}
+
 static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1178,11 +1204,22 @@
 	msm_routing_put_port_mixer),
 };
 
+static const struct snd_kcontrol_new afe_pcm_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new fm_switch_mixer_controls =
 	SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
 	0, 1, 0, msm_routing_get_switch_mixer,
 	msm_routing_put_switch_mixer);
 
+static const struct snd_kcontrol_new pcm_rx_switch_mixer_controls =
+	SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
+	0, 1, 0, msm_routing_get_fm_pcmrx_switch_mixer,
+	msm_routing_put_fm_pcmrx_switch_mixer);
+
 static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
@@ -1452,6 +1489,8 @@
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
 				&fm_switch_mixer_controls),
+	SND_SOC_DAPM_SWITCH("PCM_RX_DL_HL", SND_SOC_NOPM, 0, 0,
+				&pcm_rx_switch_mixer_controls),
 	/* Mixer definitions */
 	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
@@ -1531,6 +1570,9 @@
 	SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Port Mixer", SND_SOC_NOPM, 0, 0,
 	bt_sco_rx_port_mixer_controls,
 	ARRAY_SIZE(bt_sco_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("AFE_PCM_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, afe_pcm_rx_port_mixer_controls,
+	ARRAY_SIZE(afe_pcm_rx_port_mixer_controls)),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -1656,11 +1698,16 @@
 	{"INTFM_UL_HL", NULL, "INT_FM_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
 	{"AUXPCM_UL_HL", NULL, "AUX_PCM_TX"},
+	{"PCM_RX_DL_HL", "Switch", "SLIM0_DL_HL"},
+	{"PCM_RX", NULL, "PCM_RX_DL_HL"},
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
 
+	{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+	{"PCM_RX", NULL, "AFE_PCM_RX Port Mixer"},
+
 	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index d2f259c..de98aa3 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -649,21 +649,21 @@
 	btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
 	btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
 	btn_low[0] = -50;
-	btn_high[0] = 10;
-	btn_low[1] = 11;
-	btn_high[1] = 38;
-	btn_low[2] = 39;
-	btn_high[2] = 64;
-	btn_low[3] = 65;
-	btn_high[3] = 91;
-	btn_low[4] = 92;
-	btn_high[4] = 115;
-	btn_low[5] = 116;
-	btn_high[5] = 141;
-	btn_low[6] = 142;
-	btn_high[6] = 163;
-	btn_low[7] = 164;
-	btn_high[7] = 250;
+	btn_high[0] = 20;
+	btn_low[1] = 21;
+	btn_high[1] = 62;
+	btn_low[2] = 63;
+	btn_high[2] = 104;
+	btn_low[3] = 105;
+	btn_high[3] = 143;
+	btn_low[4] = 144;
+	btn_high[4] = 181;
+	btn_low[5] = 182;
+	btn_high[5] = 218;
+	btn_low[6] = 219;
+	btn_high[6] = 254;
+	btn_low[7] = 255;
+	btn_high[7] = 330;
 	n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
 	n_ready[0] = 80;
 	n_ready[1] = 68;