Merge "ASoC: apq8064: Enhance the machine type check for apq8064 devices"
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 25d97af..aeb59af 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -53,6 +53,8 @@
 CONFIG_PM8XXX_RPC_VIBRATOR=y
 CONFIG_MSM_SPM_V2=y
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CPR=y
 CONFIG_MSM_VP_REGULATOR=y
 CONFIG_ARM_THUMBEE=y
@@ -379,4 +381,3 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1be6e51..70234bf 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -292,7 +292,7 @@
 obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
-obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o board-8064-bt.o
 obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
diff --git a/arch/arm/mach-msm/board-8064-bt.c b/arch/arm/mach-msm/board-8064-bt.c
new file mode 100644
index 0000000..a8ae9fa
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-bt.c
@@ -0,0 +1,547 @@
+/* Copyright (c) 2011-2012, 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
+ * 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/delay.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/marimba.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/rpc_pmapp.h>
+#include <mach/msm_xo.h>
+#include <mach/socinfo.h>
+
+#include "board-8064.h"
+
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+
+#define BAHAMA_SLAVE_ID_FM_ADDR  0x2A
+#define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
+
+struct bt_vreg_info {
+	const char *name;
+	unsigned int pmapp_id;
+	unsigned int min_level;
+	unsigned int max_level;
+	unsigned int is_pin_controlled;
+	struct regulator *reg;
+};
+
+struct bahama_config_register {
+	u8 reg;
+	u8 value;
+	u8 mask;
+};
+static struct bt_vreg_info bt_vregs[] = {
+	{"bha_vddxo",  2, 1800000, 1800000, 0, NULL},
+	{"bha_vddpx", 21, 1800000, 1800000, 0, NULL},
+	{"bha_vddpa", 21, 2900000, 3300000, 0, NULL}
+};
+
+static struct msm_xo_voter *bt_clock;
+
+static struct platform_device msm_bt_power_device = {
+	.name = "bt_power",
+	.id = -1,
+};
+
+static unsigned bt_config_pcm_on[] = {
+	/*PCM_DOUT*/
+	GPIO_CFG(43, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_DIN*/
+	GPIO_CFG(44, 1, GPIO_CFG_INPUT,  GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_SYNC*/
+	GPIO_CFG(45, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_CLK*/
+	GPIO_CFG(46, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+};
+
+static unsigned bt_config_pcm_off[] = {
+	/*PCM_DOUT*/
+	GPIO_CFG(43, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_DIN*/
+	GPIO_CFG(44, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_SYNC*/
+	GPIO_CFG(45, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_CLK*/
+	GPIO_CFG(46, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+};
+
+static int config_pcm(int mode)
+{
+	int pin, rc = 0;
+
+	if (mode == BT_PCM_ON) {
+		pr_err("%s mode =BT_PCM_ON", __func__);
+		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
+			pin++) {
+				rc = gpio_tlmm_config(bt_config_pcm_on[pin],
+					GPIO_CFG_ENABLE);
+				if (rc < 0)
+					return rc;
+		}
+	} else if (mode == BT_PCM_OFF) {
+		pr_err("%s mode =BT_PCM_OFF", __func__);
+		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
+			pin++) {
+				rc = gpio_tlmm_config(bt_config_pcm_off[pin],
+					GPIO_CFG_ENABLE);
+				if (rc < 0)
+					return rc;
+		}
+
+	}
+
+	return rc;
+}
+
+static int bahama_bt(int on)
+{
+	int rc = 0;
+	int i;
+
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+
+	struct bahama_variant_register {
+		const size_t size;
+		const struct bahama_config_register *set;
+	};
+
+	const struct bahama_config_register *p;
+
+	u8 version;
+
+	const struct bahama_config_register v10_bt_on[] = {
+		{ 0xE9, 0x00, 0xFF },
+		{ 0xF4, 0x80, 0xFF },
+		{ 0xE4, 0x00, 0xFF },
+		{ 0xE5, 0x00, 0x0F },
+#ifdef CONFIG_WLAN
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0xE9, 0x21, 0xFF },
+		{ 0x01, 0x0C, 0x1F },
+		{ 0x01, 0x08, 0x1F },
+	};
+
+	const struct bahama_config_register v20_bt_on_fm_off[] = {
+		{ 0x11, 0x0C, 0xFF },
+		{ 0x13, 0x01, 0xFF },
+		{ 0xF4, 0x80, 0xFF },
+		{ 0xF0, 0x00, 0xFF },
+		{ 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+		{ 0x81, 0x00, 0x7F },
+		{ 0x82, 0x00, 0xFF },
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0x8E, 0x15, 0xFF },
+		{ 0x8F, 0x15, 0xFF },
+		{ 0x90, 0x15, 0xFF },
+
+		{ 0xE9, 0x21, 0xFF },
+	};
+
+	const struct bahama_config_register v20_bt_on_fm_on[] = {
+		{ 0x11, 0x0C, 0xFF },
+		{ 0x13, 0x01, 0xFF },
+		{ 0xF4, 0x86, 0xFF },
+		{ 0xF0, 0x06, 0xFF },
+		{ 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+		{ 0x81, 0x00, 0x7F },
+		{ 0x82, 0x00, 0xFF },
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0xE9, 0x21, 0xFF },
+	};
+
+	const struct bahama_config_register v10_bt_off[] = {
+		{ 0xE9, 0x00, 0xFF },
+	};
+
+	const struct bahama_config_register v20_bt_off_fm_off[] = {
+		{ 0xF4, 0x84, 0xFF },
+		{ 0xF0, 0x04, 0xFF },
+		{ 0xE9, 0x00, 0xFF }
+	};
+
+	const struct bahama_config_register v20_bt_off_fm_on[] = {
+		{ 0xF4, 0x86, 0xFF },
+		{ 0xF0, 0x06, 0xFF },
+		{ 0xE9, 0x00, 0xFF }
+	};
+
+	const struct bahama_variant_register bt_bahama[2][3] = {
+	{
+		{ ARRAY_SIZE(v10_bt_off), v10_bt_off },
+		{ ARRAY_SIZE(v20_bt_off_fm_off), v20_bt_off_fm_off },
+		{ ARRAY_SIZE(v20_bt_off_fm_on), v20_bt_off_fm_on }
+	},
+	{
+		{ ARRAY_SIZE(v10_bt_on), v10_bt_on },
+		{ ARRAY_SIZE(v20_bt_on_fm_off), v20_bt_on_fm_off },
+		{ ARRAY_SIZE(v20_bt_on_fm_on), v20_bt_on_fm_on }
+	}
+	};
+
+	u8 offset = 0; /* index into bahama configs */
+	on = on ? 1 : 0;
+	version = marimba_read_bahama_ver(&config);
+	if ((int)version < 0 || version == BAHAMA_VER_UNSUPPORTED) {
+		dev_err(&msm_bt_power_device.dev,
+			"%s : Bahama version read Error, version = %d\n",
+			__func__, version);
+		return -EIO;
+	}
+	if (version == BAHAMA_VER_2_0) {
+		if (marimba_get_fm_status(&config))
+			offset = 0x01;
+	}
+
+	p = bt_bahama[on][version + offset].set;
+
+	dev_dbg(&msm_bt_power_device.dev,
+		"%s: found version %d\n", __func__, version);
+
+	for (i = 0; i < bt_bahama[on][version + offset].size; i++) {
+		u8 value = (p+i)->value;
+		rc = marimba_write_bit_mask(&config,
+			(p+i)->reg,
+			&value,
+			sizeof((p+i)->value),
+			(p+i)->mask);
+		if (rc < 0) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: reg %x write failed: %d\n",
+				__func__, (p+i)->reg, rc);
+			return rc;
+		}
+		dev_dbg(&msm_bt_power_device.dev,
+			"%s: reg 0x%02x write value 0x%02x mask 0x%02x\n",
+				__func__, (p+i)->reg,
+				value, (p+i)->mask);
+		value = 0;
+		rc = marimba_read_bit_mask(&config,
+				(p+i)->reg, &value,
+				sizeof((p+i)->value), (p+i)->mask);
+		if (rc < 0)
+			dev_err(&msm_bt_power_device.dev,
+				"%s marimba_read_bit_mask- error",
+				__func__);
+		dev_dbg(&msm_bt_power_device.dev,
+			"%s: reg 0x%02x read value 0x%02x mask 0x%02x\n",
+				__func__, (p+i)->reg,
+				value, (p+i)->mask);
+	}
+	/* Update BT Status */
+	if (on)
+		marimba_set_bt_status(&config, true);
+	else
+		marimba_set_bt_status(&config, false);
+	return rc;
+}
+
+static int bluetooth_switch_regulators(int on)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
+			bt_vregs[i].reg =
+				regulator_get(&msm_bt_power_device.dev,
+						bt_vregs[i].name);
+			if (IS_ERR(bt_vregs[i].reg)) {
+				rc = PTR_ERR(bt_vregs[i].reg);
+				dev_err(&msm_bt_power_device.dev,
+					"%s: invalid regulator handle for %s: %d\n",
+						__func__, bt_vregs[i].name, rc);
+				goto reg_disable;
+			}
+		}
+		rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+					bt_vregs[i].min_level,
+						bt_vregs[i].max_level) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not set voltage for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+
+		rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "en", bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+
+		rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
+
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "dis", bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+	}
+
+	return rc;
+reg_disable:
+	pr_err("bluetooth_switch_regulators - FAIL!!!!\n");
+	while (i) {
+		if (on) {
+			i--;
+			regulator_disable(bt_vregs[i].reg);
+			regulator_put(bt_vregs[i].reg);
+			bt_vregs[i].reg = NULL;
+		}
+	}
+	return rc;
+}
+
+static unsigned int msm_bahama_setup_power(void)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		bt_vregs[i].reg = regulator_get(&msm_bt_power_device.dev,
+						bt_vregs[i].name);
+		if (IS_ERR(bt_vregs[i].reg)) {
+			rc = PTR_ERR(bt_vregs[i].reg);
+			pr_err("%s: could not get regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+		rc = regulator_set_voltage(bt_vregs[i].reg,
+					bt_vregs[i].min_level,
+						bt_vregs[i].max_level);
+		if (rc) {
+			pr_err("%s: could not set voltage for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+		rc = regulator_enable(bt_vregs[i].reg);
+		if (rc) {
+			pr_err("%s: could not enable regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+	}
+	return rc;
+reg_fail:
+	pr_err("msm_bahama_setup_power FAILED !!!\n");
+
+	while (i) {
+		i--;
+		regulator_disable(bt_vregs[i].reg);
+		regulator_put(bt_vregs[i].reg);
+		bt_vregs[i].reg = NULL;
+	}
+	return rc;
+}
+
+static unsigned int msm_bahama_shutdown_power(int value)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		rc = regulator_disable(bt_vregs[i].reg);
+
+		if (rc < 0) {
+			pr_err("%s: could not disable regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto out;
+		}
+
+		regulator_put(bt_vregs[i].reg);
+		bt_vregs[i].reg = NULL;
+	}
+out:
+	return rc;
+}
+
+static unsigned int msm_bahama_core_config(int type)
+{
+	int rc = 0;
+
+	if (type == BAHAMA_ID) {
+		int i;
+		struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+		const struct bahama_config_register v20_init[] = {
+			/* reg, value, mask */
+			{ 0xF4, 0x84, 0xFF }, /* AREG */
+			{ 0xF0, 0x04, 0xFF } /* DREG */
+		};
+		if (marimba_read_bahama_ver(&config) == BAHAMA_VER_2_0) {
+			for (i = 0; i < ARRAY_SIZE(v20_init); i++) {
+				u8 value = v20_init[i].value;
+				rc = marimba_write_bit_mask(&config,
+					v20_init[i].reg,
+					&value,
+					sizeof(v20_init[i].value),
+					v20_init[i].mask);
+				if (rc < 0) {
+					pr_err("%s: reg %d write failed: %d\n",
+						__func__, v20_init[i].reg, rc);
+					return rc;
+				}
+				pr_debug("%s: reg 0x%02x value 0x%02x mask 0x%02x\n",
+					__func__, v20_init[i].reg,
+					v20_init[i].value, v20_init[i].mask);
+			}
+		}
+	}
+	pr_debug("core type: %d\n", type);
+	return rc;
+}
+
+static int bluetooth_power(int on)
+{
+	int rc = 0;
+	const char *id = "BTPW";
+	int cid = 0;
+
+	pr_debug("bluetooth_power entered....\n");
+	cid = adie_get_detected_connectivity_type();
+	if (cid != BAHAMA_ID) {
+		pr_err("%s: unexpected adie connectivity type: %d\n",
+					__func__, cid);
+		return -ENODEV;
+	}
+
+	if (on) {
+		rc = bluetooth_switch_regulators(on);
+		if (rc < 0) {
+			pr_err("%s: bluetooth_switch_regulators rc = %d",
+					__func__, rc);
+			goto exit;
+		}
+		/* UART GPIO configuration to be done by by UART module*/
+		/*Setup BT clocks*/
+		bt_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
+		if (IS_ERR(bt_clock)) {
+			rc = PTR_ERR(bt_clock);
+			pr_err("%s: failed to get the handle for A2(%d)\n",
+					__func__, rc);
+		}
+		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_ON);
+		if (rc < 0) {
+			pr_err("%s: Failed to vote for TCXO_A2 ON\n", __func__);
+			goto fail_xo_vote;
+		}
+		msleep(20);
+
+		/*I2C config for Bahama*/
+		rc = bahama_bt(1);
+		if (rc < 0) {
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+			goto fail_i2c;
+		}
+		msleep(20);
+
+		/*setup BT PCM lines*/
+		rc = config_pcm(BT_PCM_ON);
+		if (rc < 0) {
+			pr_err("%s: config_pcm , rc =%d\n",
+				__func__, rc);
+				goto fail_power;
+		}
+		/* TO DO - Enable PIN CTRL */
+		/*
+		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_PIN_CTRL);
+		if (rc < 0) {
+			pr_err("%s: Failed to vote for TCXO_A2 in PIN_CTRL\n",
+				__func__);
+			goto fail_xo_vote;
+		} */
+	} else {
+		rc = bahama_bt(0);
+		if (rc < 0)
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+
+		rc = config_pcm(BT_PCM_OFF);
+		if (rc < 0) {
+			pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n",
+				__func__, rc);
+		}
+fail_i2c:
+		pr_err("bluetooth_power...FAIL_I2C\n");
+
+fail_xo_vote:
+		pr_err("bluetooth_power...FAIL_XO_VOTE\n");
+		msm_xo_put(bt_clock);
+fail_power:
+		pr_err("bluetooth_power...FAIL POWER\n");
+		rc = bluetooth_switch_regulators(0);
+		if (rc < 0) {
+			pr_err("%s: switch_regulators : rc = %d",\
+				__func__, rc);
+			goto exit;
+		}
+	}
+	return rc;
+exit:
+	pr_err("%s: failed with rc = %d", __func__, rc);
+	return rc;
+}
+
+static struct marimba_platform_data marimba_pdata = {
+	.slave_id[SLAVE_ID_BAHAMA_FM]	= BAHAMA_SLAVE_ID_FM_ADDR,
+	.slave_id[SLAVE_ID_BAHAMA_QMEMBIST] = BAHAMA_SLAVE_ID_QMEMBIST_ADDR,
+	.bahama_setup			= msm_bahama_setup_power,
+	.bahama_shutdown		= msm_bahama_shutdown_power,
+	.bahama_core_config		= msm_bahama_core_config,
+	.fm			        = NULL,
+};
+
+static struct i2c_board_info bahama_devices[] = {
+{
+	I2C_BOARD_INFO("marimba", 0xc),
+	.platform_data = &marimba_pdata,
+},
+};
+
+void __init apq8064_bt_power_init(void)
+{
+	int rc = 0;
+	struct device *dev;
+
+	rc = i2c_register_board_info(APQ_8064_GSBI5_QUP_I2C_BUS_ID,
+				bahama_devices,
+				ARRAY_SIZE(bahama_devices));
+	if (rc < 0) {
+		pr_err("%s: I2C Register failed\n", __func__);
+		return;
+	}
+	rc = platform_device_register(&msm_bt_power_device);
+	if (rc < 0) {
+		pr_err("%s: device register failed\n", __func__);
+		platform_device_unregister(&msm_bt_power_device);
+		return;
+	}
+
+	dev = &msm_bt_power_device.dev;
+	dev->platform_data = &bluetooth_power;
+
+	return;
+}
+#endif
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index f4e9a8f..a08f45c 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -1477,9 +1477,9 @@
 		pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
 		return;
 	}
-
-	msm_gpiomux_install(wcnss_5wire_interface,
-			ARRAY_SIZE(wcnss_5wire_interface));
+	if (!(machine_is_mpq8064_hrd()))
+		msm_gpiomux_install(wcnss_5wire_interface,
+				ARRAY_SIZE(wcnss_5wire_interface));
 
 	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 		 machine_is_mpq8064_dtv()) {
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index c1798bf..bbb9a81 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -47,6 +47,7 @@
 	REGULATOR_SUPPLY("8921_l4",		NULL),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_otg"),
 	REGULATOR_SUPPLY("iris_vddxo",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddxo",		"bt_power"),
 };
 VREG_CONSUMERS(L5) = {
 	REGULATOR_SUPPLY("8921_l5",		NULL),
@@ -75,6 +76,7 @@
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8921_l10",		NULL),
 	REGULATOR_SUPPLY("iris_vddpa",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddpa",		"bt_power"),
 };
 VREG_CONSUMERS(L11) = {
 	REGULATOR_SUPPLY("8921_l11",		NULL),
@@ -182,6 +184,7 @@
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"0-000d"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"0-000d"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddpx",		"bt_power"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
 	REGULATOR_SUPPLY("vddp",		"0-0048"),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ec52d1a..8755f08 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -3443,6 +3443,11 @@
 #endif
 	}
 
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+	if (machine_is_mpq8064_hrd())
+		apq8064_bt_power_init();
+#endif
+
 	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
 		platform_device_register(&cdp_kp_pdev);
 
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 740fa39..5d6f988 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -110,6 +110,10 @@
 void apq8064_pm8xxx_gpio_mpp_init(void);
 void __init configure_apq8064_pm8917_power_grid(void);
 
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+void __init apq8064_bt_power_init(void);
+#endif
+
 #define PLATFORM_IS_MPQ8064() \
 	(machine_is_mpq8064_hrd() || \
 	 machine_is_mpq8064_dtv() || \
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..ba0e242 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -21,6 +21,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 
+#include <asm/mach-types.h>
 #include <mach/msm_iomap.h>
 
 #include "peripheral-loader.h"
@@ -358,12 +359,18 @@
 
 static int __init pil_riva_init(void)
 {
+	if (machine_is_mpq8064_hrd()) {
+		pr_err("pil_riva not supported on this target\n");
+		return 0;
+	}
 	return platform_driver_register(&pil_riva_driver);
 }
 module_init(pil_riva_init);
 
 static void __exit pil_riva_exit(void)
 {
+	if (machine_is_mpq8064_hrd())
+		return;
 	platform_driver_unregister(&pil_riva_driver);
 }
 module_exit(pil_riva_exit);
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 318523b..f014df9 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/wcnss_wlan.h>
 #include <linux/err.h>
+#include <asm/mach-types.h>
 #include <mach/irqs.h>
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
@@ -221,6 +222,11 @@
 {
 	int ret;
 
+	if (machine_is_mpq8064_hrd()) {
+		pr_err("Riva not supported on this target\n");
+		return 0;
+	}
+
 	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
 					smsm_state_cb_hdlr, 0);
 	if (ret < 0) {
@@ -259,6 +265,8 @@
 
 static void __exit riva_ssr_module_exit(void)
 {
+	if (machine_is_mpq8064_hrd())
+		return;
 	subsys_unregister(riva_8960_dev);
 	free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
 }
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7e827b9..59139dc 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -93,6 +93,9 @@
 	ret += length;						\
 } while (0)
 
+/* Identifier for data from MDM */
+#define MDM_TOKEN	-1
+
 static void drain_timer_func(unsigned long data)
 {
 	queue_work(driver->diag_wq , &(driver->diag_drain_work));
@@ -650,6 +653,10 @@
 {
 	int index = -1, i = 0, ret = 0;
 	int num_data = 0, data_type;
+#if defined(CONFIG_DIAG_SDIO_PIPE) || defined(CONFIG_DIAG_BRIDGE_CODE)
+	int mdm_token = MDM_TOKEN;
+#endif
+
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == current->tgid)
 			index = i;
@@ -789,6 +796,8 @@
 		/* copy 9K data over SDIO */
 		if (driver->in_busy_sdio == 1) {
 			num_data++;
+			/*Copy the negative  token of data being passed*/
+			COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_token, 4);
 			/*Copy the length of data being passed*/
 			COPY_USER_SPACE_OR_EXIT(buf+ret,
 				 (driver->write_ptr_mdm->length), 4);
@@ -818,6 +827,14 @@
 					 i, (unsigned int)hsic_buf_tbl[i].buf,
 					hsic_buf_tbl[i].length);
 				num_data++;
+
+				/* Copy the negative token */
+				if (copy_to_user(buf+ret, &mdm_token, 4)) {
+					num_data--;
+					goto drop_hsic;
+				}
+				ret += 4;
+
 				/* Copy the length of data being passed */
 				if (copy_to_user(buf+ret,
 					(void *)&(hsic_buf_tbl[i].length),
@@ -846,6 +863,21 @@
 				diagfwd_write_complete_hsic(NULL);
 			}
 		}
+		if (driver->in_busy_smux == 1) {
+			num_data++;
+
+			/* Copy the negative  token of data being passed */
+			COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_token, 4);
+			/* Copy the length of data being passed */
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+					(driver->write_ptr_mdm->length), 4);
+			/* Copy the actual data being passed */
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+					*(driver->buf_in_smux),
+					driver->write_ptr_mdm->length);
+			pr_debug("diag: SMUX  data copied\n");
+			driver->in_busy_smux = 0;
+		}
 #endif
 		/* copy number of data fields */
 		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
@@ -950,6 +982,7 @@
 			      size_t count, loff_t *ppos)
 {
 	int err, ret = 0, pkt_type;
+	bool mdm_mask = false;
 #ifdef DIAG_DEBUG
 	int length = 0, i;
 #endif
@@ -985,6 +1018,12 @@
 							 payload_size);
 		/* Check masks for On-Device logging */
 		if (driver->mask_check) {
+			/* Check if mask is for MDM or MSM */
+			if (*(int *)driver->user_space_data == MDM_TOKEN) {
+				mdm_mask = true;
+				driver->user_space_data += 4;
+				buf += 4;
+			}
 			if (!mask_request_validate(driver->user_space_data)) {
 				pr_alert("diag: mask request Invalid\n");
 				return -EFAULT;
@@ -998,7 +1037,7 @@
 #endif
 #ifdef CONFIG_DIAG_SDIO_PIPE
 		/* send masks to 9k too */
-		if (driver->sdio_ch) {
+		if (driver->sdio_ch && mdm_mask) {
 			wait_event_interruptible(driver->wait_q,
 				 (sdio_write_avail(driver->sdio_ch) >=
 					 payload_size));
@@ -1010,7 +1049,7 @@
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
 		/* send masks to 9k too */
-		if (driver->hsic_ch && (payload_size > 0)) {
+		if (driver->hsic_ch && (payload_size > 0) && mdm_mask) {
 			/* wait sending mask updates if HSIC ch not ready */
 			if (driver->in_busy_hsic_write)
 				wait_event_interruptible(driver->wait_q,
@@ -1032,9 +1071,22 @@
 					driver->in_busy_hsic_write = 0;
 			}
 		}
+		if (driver->diag_smux_enabled && mdm_mask && driver->lcid) {
+			if (payload_size > 0) {
+				err = msm_smux_write(driver->lcid, NULL,
+						driver->user_space_data,
+						payload_size);
+				if (err) {
+					pr_err("diag:send mask to MDM err %d",
+							err);
+					return err;
+				}
+			}
+		}
 #endif
 		/* send masks to 8k now */
-		diag_process_hdlc((void *)(driver->user_space_data),
+		if (!mdm_mask)
+			diag_process_hdlc((void *)(driver->user_space_data),
 							 payload_size);
 		return 0;
 	}
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 0119ebe..996456f 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -435,6 +435,14 @@
 		return -EINVAL;
 	}
 
+	/* mark the interrupts wakeable if they support linux-key */
+	if (cfg->key_code) {
+		enable_irq_wake(cfg->state_irq);
+		/* special handling for RESIN due to a hardware bug */
+		if (cfg->pon_type == PON_RESIN && cfg->support_reset)
+			enable_irq_wake(cfg->bark_irq);
+	}
+
 	return rc;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 6faaf78..b0b9468 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -67,6 +67,7 @@
 	struct work_struct	suspend_w;
 	struct msm_hsic_peripheral_platform_data *pdata;
 	enum usb_vdd_type	vdd_type;
+	bool connected;
 };
 
 static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
@@ -381,7 +382,7 @@
 	 */
 	mb();
 
-	if (!mhsic->pdata->core_clk_always_on_workaround) {
+	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
 		clk_disable(mhsic->iface_clk);
 		clk_disable(mhsic->core_clk);
 	}
@@ -438,7 +439,7 @@
 		dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
 				__func__, ret);
 
-	if (!mhsic->pdata->core_clk_always_on_workaround) {
+	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
 		clk_enable(mhsic->iface_clk);
 		clk_enable(mhsic->core_clk);
 	}
@@ -598,22 +599,38 @@
 
 	switch (event) {
 	case CI13XXX_CONTROLLER_RESET_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
 		writel_relaxed(0, USB_AHBBURST);
 		writel_relaxed(0x08, USB_AHBMODE);
 		break;
 	case CI13XXX_CONTROLLER_CONNECT_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
-		msm_hsic_start();
+		dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
+		msm_hsic_wakeup();
+		the_mhsic->connected = true;
 		break;
 	case CI13XXX_CONTROLLER_SUSPEND_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
 		queue_work(mhsic->wq, &mhsic->suspend_w);
 		break;
 	case CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
 		msm_hsic_wakeup();
 		break;
+	case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
+		dev_info(dev, "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
+		/*
+		 * UDC started, suspend the hsic device until it will be
+		 * connected by a pullup (CI13XXX_CONTROLLER_CONNECT_EVENT)
+		 * Before suspend, finish required configurations.
+		 */
+		hw_device_state(_udc->ep0out.qh.dma);
+		msm_hsic_start();
+		usleep(10000);
+
+		mhsic->connected = false;
+		pm_runtime_put_noidle(the_mhsic->dev);
+		pm_runtime_suspend(the_mhsic->dev);
+		break;
 	default:
 		dev_dbg(dev, "unknown ci13xxx_udc event\n");
 		break;
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 831e970..5b39336 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3205,6 +3205,11 @@
 	spin_unlock_irqrestore(udc->lock, flags);
 	if (retval || put)
 		pm_runtime_put_sync(&udc->gadget.dev);
+
+	if (udc->udc_driver->notify_event)
+			udc->udc_driver->notify_event(udc,
+				CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
+
 	return retval;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 6527b76..3162e15 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -126,6 +126,8 @@
 #define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT	3
 #define CI13XXX_CONTROLLER_RESUME_EVENT	        4
 #define CI13XXX_CONTROLLER_DISCONNECT_EVENT	    5
+#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT	    6
+
 	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
 };
 
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index a9e5d91..45dfb87 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -640,26 +640,6 @@
 	clear_bit(BAM_CH_OPENED, &d->flags);
 }
 
-static void gbam2bam_disconnect_work(struct work_struct *w)
-{
-	struct gbam_port *port =
-			container_of(w, struct gbam_port, disconnect_w);
-	unsigned long		flags;
-
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	spin_lock(&port->port_lock_dl);
-	port->port_usb = 0;
-	spin_unlock(&port->port_lock_dl);
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-
-	/* disable endpoints */
-	usb_ep_disable(port->gr->out);
-	usb_ep_disable(port->gr->in);
-
-	port->gr->in->driver_data = NULL;
-	port->gr->out->driver_data = NULL;
-}
-
 static void gbam_connect_work(struct work_struct *w)
 {
 	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
@@ -699,29 +679,6 @@
 	struct bam_ch_info *d = &port->data_ch;
 	u32 sps_params;
 	int ret;
-	unsigned long flags;
-
-	ret = usb_ep_enable(port->gr->in);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
-				__func__, port->gr->in);
-		return;
-	}
-	port->gr->in->driver_data = port;
-
-	ret = usb_ep_enable(port->gr->out);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
-				__func__, port->gr->out);
-		port->gr->in->driver_data = 0;
-		return;
-	}
-	port->gr->out->driver_data = port;
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	spin_lock(&port->port_lock_dl);
-	port->port_usb = port->gr;
-	spin_unlock(&port->port_lock_dl);
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 
 	ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
 						  &d->dst_pipe_idx);
@@ -916,7 +873,6 @@
 	spin_lock_init(&port->port_lock_dl);
 
 	INIT_WORK(&port->connect_w, gbam2bam_connect_work);
-	INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
 
 	/* data ch */
 	d = &port->data_ch;
@@ -1071,7 +1027,7 @@
 	d = &port->data_ch;
 	port->gr = gr;
 
-	if (trans == USB_GADGET_XPORT_BAM) {
+	if (trans == USB_GADGET_XPORT_BAM)
 		gbam_free_buffers(port);
 
 	spin_lock_irqsave(&port->port_lock_ul, flags);
@@ -1081,12 +1037,15 @@
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 
-		/* disable endpoints */
-		usb_ep_disable(gr->out);
-		usb_ep_disable(gr->in);
-	}
+	/* disable endpoints */
+	usb_ep_disable(gr->out);
+	usb_ep_disable(gr->in);
 
-	queue_work(gbam_wq, &port->disconnect_w);
+	gr->in->driver_data = NULL;
+	gr->out->driver_data = NULL;
+
+	if (trans == USB_GADGET_XPORT_BAM)
+		queue_work(gbam_wq, &port->disconnect_w);
 }
 
 int gbam_connect(struct grmnet *gr, u8 port_num,
@@ -1121,36 +1080,37 @@
 
 	d = &port->data_ch;
 
-	if (trans == USB_GADGET_XPORT_BAM) {
-		ret = usb_ep_enable(gr->in);
-		if (ret) {
-			pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
-					__func__, gr->in);
-			return ret;
-		}
-		gr->in->driver_data = port;
+	ret = usb_ep_enable(gr->in);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+			__func__, gr->in);
+		return ret;
+	}
+	gr->in->driver_data = port;
 
-		ret = usb_ep_enable(gr->out);
-		if (ret) {
-			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
-					__func__, gr->out);
-			gr->in->driver_data = 0;
-			return ret;
-		}
-		gr->out->driver_data = port;
+	ret = usb_ep_enable(gr->out);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+			__func__, gr->out);
+		gr->in->driver_data = 0;
+		return ret;
+	}
+	gr->out->driver_data = port;
 
 	spin_lock_irqsave(&port->port_lock_ul, flags);
 	spin_lock(&port->port_lock_dl);
 	port->port_usb = gr;
 
+	if (trans == USB_GADGET_XPORT_BAM) {
 		d->to_host = 0;
 		d->to_modem = 0;
 		d->pending_with_bam = 0;
 		d->tohost_drp_cnt = 0;
 		d->tomodem_drp_cnt = 0;
+	}
+
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-	}
 
 	if (trans == USB_GADGET_XPORT_BAM2BAM) {
 		port->gr = gr;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index a6d8c17..5637f19 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -67,6 +67,8 @@
 #define USB_PHY_VDD_DIG_VOL_MIN	1045000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
 
+#define USB_SUSPEND_DELAY_TIME	(500 * HZ/1000) /* 500 msec */
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -686,7 +688,8 @@
 	if (aca_enabled())
 		return 0;
 
-	if (atomic_read(&motg->in_lpm) == suspend)
+	if (atomic_read(&motg->in_lpm) == suspend &&
+		!atomic_read(&motg->suspend_work_pending))
 		return 0;
 
 	if (suspend) {
@@ -705,7 +708,9 @@
 			if (!(motg->caps & ALLOW_LPM_ON_DEV_SUSPEND))
 				break;
 			set_bit(A_BUS_SUSPEND, &motg->inputs);
-			queue_work(system_nrt_wq, &motg->sm_work);
+			atomic_set(&motg->suspend_work_pending, 1);
+			queue_delayed_work(system_nrt_wq, &motg->suspend_work,
+				USB_SUSPEND_DELAY_TIME);
 			break;
 
 		default:
@@ -2752,6 +2757,14 @@
 		queue_work(system_nrt_wq, &motg->sm_work);
 }
 
+static void msm_otg_suspend_work(struct work_struct *w)
+{
+	struct msm_otg *motg =
+		container_of(w, struct msm_otg, suspend_work.work);
+	atomic_set(&motg->suspend_work_pending, 0);
+	msm_otg_sm_work(&motg->sm_work);
+}
+
 static irqreturn_t msm_otg_irq(int irq, void *data)
 {
 	struct msm_otg *motg = data;
@@ -3629,6 +3642,7 @@
 	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
 	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
 	INIT_DELAYED_WORK(&motg->pmic_id_status_work, msm_pmic_id_status_w);
+	INIT_DELAYED_WORK(&motg->suspend_work, msm_otg_suspend_work);
 	setup_timer(&motg->id_timer, msm_otg_id_timer_func,
 				(unsigned long) motg);
 	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
@@ -3791,6 +3805,7 @@
 	msm_otg_debugfs_cleanup();
 	cancel_delayed_work_sync(&motg->chg_work);
 	cancel_delayed_work_sync(&motg->pmic_id_status_work);
+	cancel_delayed_work_sync(&motg->suspend_work);
 	cancel_work_sync(&motg->sm_work);
 
 	pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 82f9107..adcc450 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -328,10 +328,12 @@
 	bool sm_work_pending;
 	atomic_t pm_suspended;
 	atomic_t in_lpm;
+	atomic_t suspend_work_pending;
 	int async_int;
 	unsigned cur_power;
 	struct delayed_work chg_work;
 	struct delayed_work pmic_id_status_work;
+	struct delayed_work suspend_work;
 	enum usb_chg_state chg_state;
 	enum usb_chg_type chg_type;
 	u8 dcd_retries;
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 333f73e..499e4b6 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -54,7 +54,7 @@
 #define GPIO_SEC_I2S_RX_WS   48
 #define GPIO_SEC_I2S_RX_DOUT 49
 #define GPIO_SEC_I2S_RX_MCLK 50
-#define I2S_MCLK_RATE 1536000
+#define I2S_MCLK_RATE 12288000
 
 #define GPIO_MI2S_WS     27
 #define GPIO_MI2S_SCLK   28
@@ -813,14 +813,11 @@
 static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
 
 	struct snd_interval *channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 
 	pr_debug("%s()\n", __func__);
-	rate->min = rate->max = 48000;
 	channels->min =  channels->max = 2;
 
 	return 0;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index b76160e..a911d9d 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -578,7 +578,9 @@
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			if (compr->info.codec_param.codec.id ==
-					SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+					SND_AUDIOCODEC_AC3_PASS_THROUGH ||
+					compr->info.codec_param.codec.id ==
+					SND_AUDIOCODEC_DTS_PASS_THROUGH) {
 				msm_pcm_routing_reg_psthr_stream(
 					soc_prtd->dai_link->be_id,
 					prtd->session_id, substream->stream,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6456b2a..5180b10 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -271,8 +271,10 @@
 	}
 
 	mutex_lock(&routing_lock);
-
-	fe_dai_map[fedai_id][session_type] = dspst_id;
+	if (enable)
+		fe_dai_map[fedai_id][session_type] = dspst_id;
+	else
+		fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&