Merge "msm: camera: Autofocus driver support for S5K3L1 camera sensor" into msm-3.0
diff --git a/Documentation/devicetree/bindings/spi/spi_qsd.txt b/Documentation/devicetree/bindings/spi/spi_qsd.txt
index 5839f63..939f77b 100644
--- a/Documentation/devicetree/bindings/spi/spi_qsd.txt
+++ b/Documentation/devicetree/bindings/spi/spi_qsd.txt
@@ -6,11 +6,41 @@
 - interrupts : should contain the QUP core interrupt.
 - spi-max-frequency : specifies maximum SPI clock frequency, Units - Hz.
 
+Optional properties:
+- gpios : specifies the gpio pins to be used for SPI CLK, MISO, MOSI in
+  that order.
+- cs-gpios : specifies the gpio pins to be used for chipselects.
+
+SPI slave nodes must be children of the SPI master node and contain
+the following properties.
+- reg : (required) chip select address of device.
+- compatible : (required) name of SPI device following generic names
+  recommended practice
+- spi-max-frequency : (required) Maximum SPI clocking speed of device in Hz
+- interrupts : (recommended) should contain the SPI slave interrupt number
+  encoded depending on the type of the interrupt controller.
+- interrupt-parent : (recommended) the phandle for the interrupt controller
+  that services interrupts for this device.
+- spi-cpol : (optional) Empty property indicating device requires inverse
+  clock polarity (CPOL) mode
+- spi-cpha : (optional) Empty property indicating device requires shifted
+  clock phase (CPHA) mode
+- spi-cs-high : (optional) Empty property indicating device requires
+  chip select active high
+
 Example:
 	spi@f9924000 {
 		compatible = "qcom,spi-qup-v2";
 		reg = <0xf9924000 0x1000>;
-		interrupts = <96>;
+		interrupts = <0 96 0>;
 		spi-max-frequency = <24000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		device@0 {
+			compatible = "spidev";
+			reg = <0>;
+			spi-max-frequency = <5000000>;
+		};
 	};
 
diff --git a/arch/arm/boot/dts/msmcopper-rumi.dts b/arch/arm/boot/dts/msmcopper-rumi.dts
index 4e1e379..8c00535 100644
--- a/arch/arm/boot/dts/msmcopper-rumi.dts
+++ b/arch/arm/boot/dts/msmcopper-rumi.dts
@@ -46,6 +46,27 @@
 		status = "disable";
 	};
 
+	spi@f9923000 {
+		compatible = "qcom,spi-qup-v2";
+		reg = <0xf9923000 0x1000>;
+		interrupts = <0 95 0>;
+		spi-max-frequency = <24000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&msmgpio 3 0>, /* CLK  */
+			<&msmgpio 1 0>, /* MISO */
+			<&msmgpio 0 0>; /* MOSI */
+		cs-gpios = <&msmgpio 9 0>;
+
+		ethernet-switch@2 {
+			compatible = "simtec,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <90 0>;
+			spi-max-frequency = <5000000>;
+		};
+	};
+
 	slim@fe12f000 {
 		status = "disable";
 	};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 8406299..db44d13 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -30,11 +30,12 @@
 		      <0xF9002000 0x1000>;
 	};
 
-	msmgpio: gpio@fd400000 {
+	msmgpio: gpio@fd510000 {
 		compatible = "qcom,msm-gpio";
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		reg = <0xfd400000 0x4000>;
+		reg = <0xfd510000 0x4000>;
+		#gpio-cells = <2>;
 	};
 
 	timer {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7c117e8..b216027 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -231,6 +231,17 @@
 	select MSM_PM8X60 if PM
 	select CPU_HAS_L2_PMU
 	select HOLES_IN_ZONE if SPARSEMEM
+	select ENABLE_DMM
+	select MEMORY_HOTPLUG if ENABLE_DMM
+	select MEMORY_HOTREMOVE if ENABLE_DMM
+	select ARCH_ENABLE_MEMORY_HOTPLUG if ENABLE_DMM
+	select ARCH_ENABLE_MEMORY_HOTREMOVE if ENABLE_DMM
+	select MIGRATION if ENABLE_DMM
+	select ARCH_MEMORY_PROBE if ENABLE_DMM
+	select ARCH_MEMORY_REMOVE if ENABLE_DMM
+	select FIX_MOVABLE_ZONE if ENABLE_DMM
+	select CLEANCACHE
+	select QCACHE
 
 config ARCH_MSMCOPPER
 	bool "MSM Copper"
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f9b1e2e..ceae29c 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -27,6 +27,7 @@
 #include <linux/platform_data/qcom_crypto_device.h>
 #include <linux/ion.h>
 #include <linux/memory.h>
+#include <linux/memblock.h>
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/cyttsp.h>
 #include <linux/i2c/isa1200.h>
@@ -67,6 +68,7 @@
 #include <mach/msm_rtb.h>
 #include <sound/cs8427.h>
 #include <media/gpio-ir-recv.h>
+#include <linux/fmem.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
@@ -107,6 +109,11 @@
 #define MSM_ION_HEAP_NUM	1
 #endif
 
+#define APQ8064_FIXED_AREA_START 0xa0000000
+#define MAX_FIXED_AREA_SIZE	0x10000000
+#define MSM_MM_FW_SIZE		0x200000
+#define APQ8064_FW_START	(APQ8064_FIXED_AREA_START - MSM_MM_FW_SIZE)
+
 #ifdef CONFIG_KERNEL_PMEM_EBI_REGION
 static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
 static int __init pmem_kernel_ebi1_size_setup(char *p)
@@ -187,6 +194,9 @@
 #endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
 #endif /* CONFIG_ANDROID_PMEM */
 
+struct fmem_platform_data apq8064_fmem_pdata = {
+};
+
 static struct memtype_reserve apq8064_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
@@ -243,26 +253,37 @@
 	return MEMTYPE_EBI1;
 }
 
+#define FMEM_ENABLED 1
+
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
+	.reusable = FMEM_ENABLED,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_MIDDLE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
+	.reusable = 0,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_HIGH,
 };
 
 static struct ion_co_heap_pdata co_apq8064_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
+	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_apq8064_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_LOW,
 };
 #endif
 
@@ -352,15 +373,180 @@
 };
 #endif
 
+static struct platform_device apq8064_fmem_device = {
+	.name = "fmem",
+	.id = 1,
+	.dev = { .platform_data = &apq8064_fmem_pdata },
+};
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+				      unsigned long size)
+{
+	apq8064_reserve_table[mem_type].size += size;
+}
+
+static void __init apq8064_reserve_fixed_area(unsigned long fixed_area_size)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	int ret;
+
+	if (fixed_area_size > MAX_FIXED_AREA_SIZE)
+		panic("fixed area size is larger than %dM\n",
+			MAX_FIXED_AREA_SIZE >> 20);
+
+	reserve_info->fixed_area_size = fixed_area_size;
+	reserve_info->fixed_area_start = APQ8064_FW_START;
+
+	ret = memblock_remove(reserve_info->fixed_area_start,
+		reserve_info->fixed_area_size);
+	BUG_ON(ret);
+#endif
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
+ * at a higher address than FW in addition to not more than 256MB away from the
+ * base address of the firmware. This means that if MM is reusable the other
+ * two heaps must be allocated in the same region as FW. This is handled by the
+ * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * adjacent to the FW heap for content protection purposes.
+ */
 static void __init reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
-	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+	unsigned int i;
+	unsigned int reusable_count = 0;
+	unsigned int fixed_size = 0;
+	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
+	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+
+	apq8064_fmem_pdata.size = 0;
+	apq8064_fmem_pdata.reserved_size_low = 0;
+	apq8064_fmem_pdata.reserved_size_high = 0;
+	fixed_low_size = 0;
+	fixed_middle_size = 0;
+	fixed_high_size = 0;
+
+	/* We only support 1 reusable heap. Check if more than one heap
+	 * is specified as reusable and set as non-reusable if found.
+	 */
+	for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+			&(apq8064_ion_pdata.heaps[i]);
+
+		if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+			struct ion_cp_heap_pdata *data = heap->extra_data;
+
+			reusable_count += (data->reusable) ? 1 : 0;
+
+			if (data->reusable && reusable_count > 1) {
+				pr_err("%s: Too many heaps specified as "
+					"reusable. Heap %s was not configured "
+					"as reusable.\n", __func__, heap->name);
+				data->reusable = 0;
+			}
+		}
+	}
+
+	for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+			&(apq8064_ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+			int mem_is_fmem = 0;
+
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				mem_is_fmem = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				mem_is_fmem = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			if (fixed_position != NOT_FIXED)
+				fixed_size += heap->size;
+			else
+				reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+
+			if (fixed_position == FIXED_LOW)
+				fixed_low_size += heap->size;
+			else if (fixed_position == FIXED_MIDDLE)
+				fixed_middle_size += heap->size;
+			else if (fixed_position == FIXED_HIGH)
+				fixed_high_size += heap->size;
+
+			if (mem_is_fmem)
+				apq8064_fmem_pdata.size += heap->size;
+		}
+	}
+
+	if (!fixed_size)
+		return;
+
+	if (apq8064_fmem_pdata.size) {
+		apq8064_fmem_pdata.reserved_size_low = fixed_low_size;
+		apq8064_fmem_pdata.reserved_size_high = fixed_high_size;
+	}
+
+	/* Since the fixed area may be carved out of lowmem,
+	 * make sure the length is a multiple of 1M.
+	 */
+	fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
+		& SECTION_MASK;
+	apq8064_reserve_fixed_area(fixed_size);
+
+	fixed_low_start = APQ8064_FIXED_AREA_START;
+	fixed_middle_start = fixed_low_start + fixed_low_size;
+	fixed_high_start = fixed_middle_start + fixed_middle_size;
+
+	for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
+		struct ion_platform_heap *heap = &(apq8064_ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			switch (fixed_position) {
+			case FIXED_LOW:
+				heap->base = fixed_low_start;
+				break;
+			case FIXED_MIDDLE:
+				heap->base = fixed_middle_start;
+				break;
+			case FIXED_HIGH:
+				heap->base = fixed_high_start;
+				break;
+			default:
+				break;
+			}
+		}
+	}
 #endif
 }
 
@@ -381,6 +567,7 @@
 static struct reserve_info apq8064_reserve_info __initdata = {
 	.memtype_reserve_table = apq8064_reserve_table,
 	.calculate_reserve_sizes = apq8064_calculate_reserve_sizes,
+	.reserve_fixed_area = apq8064_reserve_fixed_area,
 	.paddr_to_memtype = apq8064_paddr_to_memtype,
 };
 
@@ -401,12 +588,14 @@
 
 	/* Check if 32 bit overflow occured */
 	if (high < mb->start)
-		high = ~0UL;
+		high = -PAGE_SIZE;
 
 	low &= ~(bank_size - 1);
 
 	if (high - low <= bank_size)
-		return;
+		goto no_dmm;
+
+#ifdef CONFIG_ENABLE_DMM
 	apq8064_reserve_info.low_unstable_address = mb->start -
 					MIN_MEMORY_BLOCK_SIZE + mb->size;
 	apq8064_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
@@ -416,6 +605,11 @@
 		apq8064_reserve_info.low_unstable_address,
 		apq8064_reserve_info.max_unstable_size,
 		apq8064_reserve_info.bank_size);
+	return;
+#endif
+no_dmm:
+	apq8064_reserve_info.low_unstable_address = high;
+	apq8064_reserve_info.max_unstable_size = 0;
 }
 
 static int apq8064_change_memory_power(u64 start, u64 size,
@@ -446,14 +640,29 @@
 {
 	apq8064_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
+	if (apq8064_fmem_pdata.size) {
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+		if (reserve_info->fixed_area_size) {
+			apq8064_fmem_pdata.phys =
+				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
+			pr_info("mm fw at %lx (fixed) size %x\n",
+				reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
+			pr_info("fmem start %lx (fixed) size %lx\n",
+				apq8064_fmem_pdata.phys,
+				apq8064_fmem_pdata.size);
+		}
+#endif
+	}
 }
 
 static void __init place_movable_zone(void)
 {
+#ifdef CONFIG_ENABLE_DMM
 	movable_reserved_start = apq8064_reserve_info.low_unstable_address;
 	movable_reserved_size = apq8064_reserve_info.max_unstable_size;
 	pr_info("movable zone start %lx size %lx\n",
 		movable_reserved_start, movable_reserved_size);
+#endif
 }
 
 static void __init apq8064_early_reserve(void)
@@ -1867,6 +2076,7 @@
 	&android_usb_device,
 	&msm_device_wcnss_wlan,
 	&msm_device_iris_fm,
+	&apq8064_fmem_device,
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 	&apq8064_android_pmem_device,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a3afdb0..c26b8b9 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -806,15 +806,15 @@
 	msm_reserve();
 	if (msm8960_fmem_pdata.size) {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-		msm8960_fmem_pdata.phys = reserve_info->fixed_area_start +
-			MSM_MM_FW_SIZE;
-		pr_info("mm fw at %lx (fixed) size %x\n",
-			reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
-		pr_info("fmem start %lx (fixed) size %lx\n",
-			msm8960_fmem_pdata.phys, msm8960_fmem_pdata.size);
-#else
-		msm8960_fmem_pdata.phys =
-			reserve_memory_for_fmem(msm8960_fmem_pdata.size);
+		if (reserve_info->fixed_area_size) {
+			msm8960_fmem_pdata.phys =
+				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
+			pr_info("mm fw at %lx (fixed) size %x\n",
+				reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
+			pr_info("fmem start %lx (fixed) size %lx\n",
+				msm8960_fmem_pdata.phys,
+				msm8960_fmem_pdata.size);
+		}
 #endif
 	}
 }
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 8e64a43..e330f21 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -73,9 +73,25 @@
 };
 
 #ifdef CONFIG_WEBCAM_OV7692_QRD
+static struct gpio ov7692_cam_req_gpio[] = {
+	{GPIO_SKU1_CAM_VGA_SHDN, GPIOF_DIR_OUT, "CAM_VGA_SHDN"},
+	{GPIO_SKU1_CAM_VGA_RESET_N, GPIOF_DIR_OUT, "CAM_VGA_RESET"},
+};
+
+static struct msm_gpio_set_tbl ov7692_cam_gpio_set_tbl[] = {
+	{GPIO_SKU1_CAM_VGA_SHDN, GPIOF_OUT_INIT_HIGH, 5000},
+	{GPIO_SKU1_CAM_VGA_SHDN, GPIOF_OUT_INIT_LOW, 5000},
+	{GPIO_SKU1_CAM_VGA_RESET_N, GPIOF_OUT_INIT_HIGH, 5000},
+	{GPIO_SKU1_CAM_VGA_RESET_N, GPIOF_OUT_INIT_LOW, 5000},
+	{40, GPIOF_OUT_INIT_HIGH, 5000},
+	{35, GPIOF_OUT_INIT_HIGH, 5000},
+};
+
 static struct msm_camera_gpio_conf gpio_conf_ov7692 = {
-	.camera_off_table = camera_off_gpio_table,
-	.camera_on_table = camera_on_gpio_table,
+	.cam_gpio_req_tbl = ov7692_cam_req_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(ov7692_cam_req_gpio),
+	.cam_gpio_set_tbl = ov7692_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(ov7692_cam_gpio_set_tbl),
 	.gpio_no_mux = 1,
 };
 #endif
@@ -455,38 +471,6 @@
 
 	gpio_direction_output(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 1);
 
-	rc = gpio_request(GPIO_SKU1_CAM_VGA_SHDN, "ov7692");
-	if (rc < 0)
-		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_SHDN failed!",
-			 __func__);
-
-	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_SHDN, 0,
-		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
-		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
-	if (rc < 0) {
-		pr_err("%s:unable to enable Powr Dwn gpio for frnt camera!\n",
-			 __func__);
-		gpio_free(GPIO_SKU1_CAM_VGA_SHDN);
-	}
-
-	gpio_direction_output(GPIO_SKU1_CAM_VGA_SHDN, 1);
-
-	rc = gpio_request(GPIO_SKU1_CAM_VGA_RESET_N, "ov7692");
-	if (rc < 0)
-		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_RESET_N failed!",
-			 __func__);
-
-	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_RESET_N, 0,
-		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
-		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
-
-	if (rc < 0) {
-		pr_err("%s: unable to enable reset gpio for front camera!\n",
-			 __func__);
-		gpio_free(GPIO_SKU1_CAM_VGA_RESET_N);
-	}
-	gpio_direction_output(GPIO_SKU1_CAM_VGA_RESET_N, 1);
-
 }
 
 #ifndef CONFIG_MSM_CAMERA_V4L2
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 2cf3b8d..df4ca83 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,6 +48,7 @@
 #include <mach/msm_battery.h>
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
+#include <linux/fmem.h>
 #include <linux/msm_adc.h>
 #include "devices.h"
 #include "timer.h"
@@ -435,6 +436,9 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
+	.request_region = request_fmem_c_region,
+	.release_region = release_fmem_c_region,
+	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -756,6 +760,14 @@
 static void msm7x27a_cfg_uart2dm_serial(void) { }
 #endif
 
+struct fmem_platform_data fmem_pdata;
+
+struct platform_device fmem_device = {
+	.name = "fmem",
+	.id = 1,
+	.dev = { .platform_data = &fmem_pdata },
+};
+
 static struct platform_device *rumi_sim_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -793,6 +805,7 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
+	&fmem_device,
 	&msm_device_nand,
 	&msm_device_snd,
 	&msm_device_adspdec,
@@ -843,8 +856,19 @@
 	},
 };
 
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+		&android_pmem_adsp_pdata,
+		&android_pmem_audio_pdata,
+		&android_pmem_pdata,
+};
+#endif
+
 static void __init size_pmem_devices(void)
 {
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned int i;
+	unsigned int reusable_count = 0;
 
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
 		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -854,11 +878,30 @@
 		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
 	}
 
-#ifdef CONFIG_ANDROID_PMEM
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
+
+	fmem_pdata.size = 0;
+
+	/* Find pmem devices that should use FMEM (reusable) memory.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+		if (!reusable_count && pdata->reusable)
+			fmem_pdata.size += pdata->size;
+
+		reusable_count += (pdata->reusable) ? 1 : 0;
+
+		if (pdata->reusable && reusable_count > 1) {
+			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+				__func__, pdata->name);
+			pdata->reusable = 0;
+		}
+	}
 #endif
+
 }
 
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -869,9 +912,10 @@
 static void __init reserve_pmem_memory(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
+		reserve_memory_for(pmem_pdata_array[i]);
+
 	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
 #endif
 }
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index b52f951..32d5530 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -23,6 +23,7 @@
 #include "devices.h"
 
 #define GPIO_EXT_CAMIF_PWR_EN1 (PM8901_MPP_BASE + PM8901_MPPS + 13)
+#define GPIO_WEB_CAMIF_STANDBY1 (PM8901_MPP_BASE + PM8901_MPPS + 60)
 #ifdef CONFIG_MSM_CAMERA_FLASH
 #define VFE_CAMIF_TIMER1_GPIO 29
 #define VFE_CAMIF_TIMER2_GPIO 30
@@ -388,10 +389,10 @@
 	{47, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
 	{48, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
 	{105, GPIOF_DIR_IN, "STANDBY"},
-	{GPIO_EXT_CAMIF_PWR_EN1, GPIOF_DIR_OUT, "CAMIF_PWR_EN"},
 };
 
 static struct gpio msm8x60_back_cam_gpio[] = {
+	{GPIO_EXT_CAMIF_PWR_EN1, GPIOF_DIR_OUT, "CAMIF_PWR_EN"},
 	{106, GPIOF_DIR_OUT, "CAM_RESET"},
 };
 
@@ -468,6 +469,43 @@
 	.camera_type = BACK_CAMERA_2D,
 };
 
+static struct gpio ov7692_cam_gpio[] = {
+	{GPIO_WEB_CAMIF_STANDBY1, GPIOF_DIR_OUT, "CAM_EN"},
+};
+
+static struct msm_gpio_set_tbl ov7692_cam_gpio_set_tbl[] = {
+	{GPIO_WEB_CAMIF_STANDBY1, GPIOF_OUT_INIT_LOW, 10000},
+};
+
+static struct msm_camera_gpio_conf ov7692_cam_gpio_conf = {
+	.cam_gpio_common_tbl = msm8x60_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(msm8x60_common_cam_gpio),
+	.cam_gpio_req_tbl = ov7692_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(ov7692_cam_gpio),
+	.cam_gpio_set_tbl = ov7692_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(ov7692_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_sensor_flash_data flash_ov7692 = {
+	.flash_type	= MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov7692 = {
+	.mount_angle	= 0,
+	.cam_vreg = msm_8x60_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8x60_back_cam_vreg),
+	.gpio_conf = &ov7692_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov7692_data = {
+	.sensor_name	= "ov7692",
+	.pdata	= &msm_camera_csi_device_data[1],
+	.flash_data	= &flash_ov7692,
+	.sensor_platform_info = &sensor_board_info_ov7692,
+	.csi_if	= 1,
+	.camera_type = FRONT_CAMERA_2D,
+};
+
 static struct platform_device msm_camera_server = {
 	.name = "msm_cam_server",
 	.id = 0,
@@ -492,6 +530,10 @@
 	I2C_BOARD_INFO("mt9e013", 0x6C),
 	.platform_data = &msm_camera_sensor_mt9e013_data,
 	},
+	{
+	I2C_BOARD_INFO("ov7692", 0x78),
+	.platform_data = &msm_camera_sensor_ov7692_data,
+	},
 };
 
 struct msm_camera_board_info msm8x60_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 6b22e99..477b17d 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -3813,6 +3813,7 @@
 	REGULATOR_SUPPLY("8058_l15",		NULL),
 	REGULATOR_SUPPLY("cam_vana",		"1-001a"),
 	REGULATOR_SUPPLY("cam_vana",		"1-006c"),
+	REGULATOR_SUPPLY("cam_vana",		"1-0078"),
 };
 static struct regulator_consumer_supply vreg_consumers_PM8058_L16[] = {
 	REGULATOR_SUPPLY("8058_l16",		NULL),
@@ -3845,6 +3846,7 @@
 	REGULATOR_SUPPLY("8058_l25",		NULL),
 	REGULATOR_SUPPLY("cam_vdig",		"1-001a"),
 	REGULATOR_SUPPLY("cam_vdig",		"1-006c"),
+	REGULATOR_SUPPLY("cam_vdig",		"1-0078"),
 };
 static struct regulator_consumer_supply vreg_consumers_PM8058_S0[] = {
 	REGULATOR_SUPPLY("8058_s0",		NULL),
@@ -3865,6 +3867,7 @@
 	REGULATOR_SUPPLY("8058_lvs0",		NULL),
 	REGULATOR_SUPPLY("cam_vio",			"1-001a"),
 	REGULATOR_SUPPLY("cam_vio",			"1-006c"),
+	REGULATOR_SUPPLY("cam_vio",			"1-0078"),
 };
 static struct regulator_consumer_supply vreg_consumers_PM8058_LVS1[] = {
 	REGULATOR_SUPPLY("8058_lvs1",		NULL),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 8879576..4860d42 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5077,10 +5077,10 @@
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 
-	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
-	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
-	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.7"),
-	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.7"),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,
+			    "msm-dai-q6-mi2s"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,
+			    "msm-dai-q6-mi2s"),
 	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
 			   "msm-dai-q6.1"),
 	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
@@ -5393,10 +5393,10 @@
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
-	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
-	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.7"),
-	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.7"),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,
+			    "msm-dai-q6-mi2s"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,
+			    "msm-dai-q6-mi2s"),
 	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
 			   "msm-dai-q6.1"),
 	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index e2cfbc4..9ada0dd 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -483,14 +483,15 @@
 	},
 };
 
-struct msm_mi2s_data mpq_mi2s_tx_data = {
-	.sd_lines = MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3,
-	.capability = MSM_MI2S_CAP_TX,
+struct msm_mi2s_pdata mpq_mi2s_tx_data = {
+	.rx_sd_lines = 0,
+	.tx_sd_lines = MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 |
+		       MSM_MI2S_SD3,
 };
 
 struct platform_device mpq_cpudai_mi2s_tx = {
-	.name	= "msm-dai-q6",
-	.id	= 7, /*MI2S_TX */
+	.name	= "msm-dai-q6-mi2s",
+	.id	= -1, /*MI2S_TX */
 	.dev = {
 		.platform_data = &mpq_mi2s_tx_data,
 	},
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 0db160e..ccb18b3 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -332,29 +332,6 @@
 	}
 }
 
-unsigned long __init reserve_memory_for_fmem(unsigned long fmem_size)
-{
-	struct membank *mb;
-	int ret;
-	unsigned long fmem_phys;
-
-	if (!fmem_size)
-		return 0;
-
-	mb = &meminfo.bank[meminfo.nr_banks - 1];
-	/*
-	 * Placing fmem at the top of memory causes multimedia issues.
-	 * Instead, place it 1 page below the top of memory to prevent
-	 * the issues from occurring.
-	 */
-	fmem_phys = mb->start + (mb->size - fmem_size) - PAGE_SIZE;
-	ret = memblock_remove(fmem_phys, fmem_size);
-	BUG_ON(ret);
-
-	pr_info("fmem start %lx size %lx\n", fmem_phys, fmem_size);
-	return fmem_phys;
-}
-
 static void __init initialize_mempools(void)
 {
 	struct mem_pool *mpool;
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 7df1c3a..9a1e565 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -27,6 +27,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/subsystem_notif.h>
 #include <mach/socinfo.h>
+#include <mach/msm_smsm.h>
 
 #include "smd_private.h"
 #include "modem_notifier.h"
@@ -34,6 +35,32 @@
 
 static int crash_shutdown;
 
+#define MAX_SSR_REASON_LEN 81U
+
+static void log_modem_sfr(void)
+{
+	u32 size;
+	char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	if (!smem_reason || !size) {
+		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		return;
+	}
+	if (!smem_reason[0]) {
+		pr_err("modem subsystem failure reason: (unknown, init string found).\n");
+		return;
+	}
+
+	size = min(size, MAX_SSR_REASON_LEN-1);
+	memcpy(reason, smem_reason, size);
+	reason[size] = '\0';
+	pr_err("modem subsystem failure reason: %s.\n", reason);
+
+	smem_reason[0] = '\0';
+	wmb();
+}
+
 static void modem_sw_fatal_fn(struct work_struct *work)
 {
 	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
@@ -50,6 +77,7 @@
 		pr_err("Modem SMSM state changed to SMSM_RESET.\n"
 			"Probable err_fatal on the modem. "
 			"Calling subsystem restart...\n");
+		log_modem_sfr();
 		subsystem_restart("modem");
 
 	} else if (modem_state & reset_smsm_states) {
@@ -59,7 +87,7 @@
 			__func__);
 		kernel_restart(NULL);
 	} else {
-		/* TODO: Bus unlock code/sequence goes _here_ */
+		log_modem_sfr();
 		subsystem_restart("modem");
 	}
 }
@@ -67,6 +95,7 @@
 static void modem_fw_fatal_fn(struct work_struct *work)
 {
 	pr_err("Watchdog bite received from modem FW!\n");
+	log_modem_sfr();
 	subsystem_restart("modem");
 }
 
@@ -80,9 +109,8 @@
 		return;
 
 	if (new_state & SMSM_RESET) {
-		pr_err("Modem SMSM state changed to SMSM_RESET.\n"
-			"Probable err_fatal on the modem. "
-			"Calling subsystem restart...\n");
+		pr_err("Probable fatal error on the modem.\n");
+		log_modem_sfr();
 		subsystem_restart("modem");
 	}
 }
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 1d3a31e..60e64cd 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -750,12 +750,28 @@
 
 	collapsed = msm_pm_spm_power_collapse(cpu, from_idle, true);
 
-	if (MSM_PM_DEBUG_CLOCK & msm_pm_debug_mask)
-		pr_info("CPU%u: %s: restore clock rate to %lu\n",
-			cpu, __func__, saved_acpuclk_rate);
-	if (acpuclk_set_rate(cpu, saved_acpuclk_rate, SETRATE_PC) < 0)
-		pr_err("CPU%u: %s: failed to restore clock rate(%lu)\n",
-			cpu, __func__, saved_acpuclk_rate);
+	if (cpu_online(cpu)) {
+		if (MSM_PM_DEBUG_CLOCK & msm_pm_debug_mask)
+			pr_info("CPU%u: %s: restore clock rate to %lu\n",
+				cpu, __func__, saved_acpuclk_rate);
+		if (acpuclk_set_rate(cpu, saved_acpuclk_rate, SETRATE_PC) < 0)
+			pr_err("CPU%u: %s: failed to restore clock rate(%lu)\n",
+				cpu, __func__, saved_acpuclk_rate);
+	} else {
+		unsigned int gic_dist_enabled;
+		unsigned int gic_dist_pending;
+		gic_dist_enabled = readl_relaxed(
+				MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR);
+		gic_dist_pending = readl_relaxed(
+				MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET);
+		mb();
+		gic_dist_pending &= gic_dist_enabled;
+
+		if (gic_dist_pending)
+			pr_err("CPU %d interrupted during hotplug.Pending int 0x%x\n",
+					cpu, gic_dist_pending);
+	}
+
 
 	avs_reset_delays(avsdscr_setting);
 	msm_pm_config_hw_after_power_up();
diff --git a/arch/arm/mach-msm/qdss-etb.c b/arch/arm/mach-msm/qdss-etb.c
index 9b23766..7837af0 100644
--- a/arch/arm/mach-msm/qdss-etb.c
+++ b/arch/arm/mach-msm/qdss-etb.c
@@ -299,7 +299,7 @@
 }
 ETB_ATTR(trigger_cntr);
 
-static int __init etb_sysfs_init(void)
+static int __devinit etb_sysfs_init(void)
 {
 	int ret;
 
@@ -324,7 +324,7 @@
 	return ret;
 }
 
-static void __exit etb_sysfs_exit(void)
+static void __devexit etb_sysfs_exit(void)
 {
 	sysfs_remove_file(etb.kobj, &trigger_cntr_attr.attr);
 	kobject_put(etb.kobj);
diff --git a/arch/arm/mach-msm/qdss-etm.c b/arch/arm/mach-msm/qdss-etm.c
index 251db45..61f1c1b 100644
--- a/arch/arm/mach-msm/qdss-etm.c
+++ b/arch/arm/mach-msm/qdss-etm.c
@@ -1120,7 +1120,7 @@
 	.attrs = etm_attrs,
 };
 
-static int __init etm_sysfs_init(void)
+static int __devinit etm_sysfs_init(void)
 {
 	int ret;
 
@@ -1148,14 +1148,14 @@
 	return ret;
 }
 
-static void __exit etm_sysfs_exit(void)
+static void __devexit etm_sysfs_exit(void)
 {
 	sysfs_remove_group(etm.kobj, &etm_attr_grp);
 	sysfs_remove_file(etm.kobj, &enabled_attr.attr);
 	kobject_put(etm.kobj);
 }
 
-static bool __init etm_arch_supported(uint8_t arch)
+static bool __devinit etm_arch_supported(uint8_t arch)
 {
 	switch (arch) {
 	case PFT_ARCH_V1_1:
@@ -1166,7 +1166,7 @@
 	return true;
 }
 
-static int __init etm_arch_init(void)
+static int __devinit etm_arch_init(void)
 {
 	int ret, i;
 	/* use cpu 0 for setup */
diff --git a/arch/arm/mach-msm/qdss-funnel.c b/arch/arm/mach-msm/qdss-funnel.c
index 2d80603..52eb2b6 100644
--- a/arch/arm/mach-msm/qdss-funnel.c
+++ b/arch/arm/mach-msm/qdss-funnel.c
@@ -134,7 +134,7 @@
 }
 FUNNEL_ATTR(priority);
 
-static int __init funnel_sysfs_init(void)
+static int __devinit funnel_sysfs_init(void)
 {
 	int ret;
 
@@ -159,7 +159,7 @@
 	return ret;
 }
 
-static void __exit funnel_sysfs_exit(void)
+static void __devexit funnel_sysfs_exit(void)
 {
 	sysfs_remove_file(funnel.kobj, &priority_attr.attr);
 	kobject_put(funnel.kobj);
diff --git a/arch/arm/mach-msm/qdss.c b/arch/arm/mach-msm/qdss.c
index 0cc3ca5..fd1fc2b 100644
--- a/arch/arm/mach-msm/qdss.c
+++ b/arch/arm/mach-msm/qdss.c
@@ -290,7 +290,7 @@
 }
 QDSS_ATTR(max_clk);
 
-static void __init qdss_add_sources(struct qdss_source *srcs, size_t num)
+static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
 {
 	mutex_lock(&qdss.sources_mutex);
 	while (num--) {
@@ -322,7 +322,7 @@
 	return ret;
 }
 
-static void __exit qdss_sysfs_exit(void)
+static void __devexit qdss_sysfs_exit(void)
 {
 	sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
 }
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 051d4de..b6d5324 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -418,7 +418,7 @@
 	mb();
 }
 
-int __init msm_spm_drv_init(struct msm_spm_driver_data *dev,
+int __devinit msm_spm_drv_init(struct msm_spm_driver_data *dev,
 		struct msm_spm_platform_data *data)
 {
 	int i;
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 838ec55..2980811 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -92,7 +92,7 @@
 	return ret;
 }
 
-static int __init msm_spm_dev_init(struct msm_spm_device *dev,
+static int __devinit msm_spm_dev_init(struct msm_spm_device *dev,
 		struct msm_spm_platform_data *data)
 {
 	int i, ret = -ENOMEM;
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 6823a5a..bd7729b 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -632,8 +632,6 @@
 	return data;
 
 out:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				buffer->size);
 	kfree(data);
 	return ERR_PTR(ret);
 }
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index 198298b..17aed88 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -84,6 +84,7 @@
 			rc-trekstor.o \
 			rc-tt-1500.o \
 			rc-twinhan1027.o \
+			rc-ue-rf4ce.o \
 			rc-videomate-m1f.o \
 			rc-videomate-s350.o \
 			rc-videomate-tv-pvr.o \
diff --git a/drivers/media/rc/keymaps/rc-ue-rf4ce.c b/drivers/media/rc/keymaps/rc-ue-rf4ce.c
new file mode 100644
index 0000000..af40976
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-ue-rf4ce.c
@@ -0,0 +1,82 @@
+/* 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 <media/rc-map.h>
+
+static struct rc_map_table ue_rf4ce[] = {
+	{ 0x0a, KEY_SETUP },
+	{ 0x6b, KEY_POWER },
+	{ 0x00, KEY_OK },
+	{ 0x03, KEY_LEFT },
+	{ 0x04, KEY_RIGHT },
+	{ 0x01, KEY_UP },
+	{ 0x02, KEY_DOWN },
+	{ 0x53, KEY_HOMEPAGE },
+	{ 0x0d, KEY_EXIT },
+	{ 0x72, KEY_TV },
+	{ 0x73, KEY_VIDEO },
+	{ 0x74, KEY_COMPOSE },
+	{ 0x71, KEY_AUX },
+	{ 0x45, KEY_STOP },
+	{ 0x0b, KEY_LIST },
+	{ 0x47, KEY_RECORD },
+	{ 0x48, KEY_REWIND },
+	{ 0x44, KEY_PLAY },
+	{ 0x49, KEY_FASTFORWARD },
+	{ 0x4c, KEY_BACK },
+	{ 0x46, KEY_PAUSE },
+	{ 0x4b, KEY_NEXT },
+	{ 0x41, KEY_VOLUMEUP },
+	{ 0x42, KEY_VOLUMEDOWN },
+	{ 0x32, KEY_LAST },
+	{ 0x43, KEY_MUTE },
+	{ 0x30, KEY_CHANNELUP },
+	{ 0x31, KEY_CHANNELDOWN },
+
+	{ 0x20, KEY_NUMERIC_0 },
+	{ 0x21, KEY_NUMERIC_1 },
+	{ 0x22, KEY_NUMERIC_2 },
+	{ 0x23, KEY_NUMERIC_3 },
+	{ 0x24, KEY_NUMERIC_4 },
+	{ 0x25, KEY_NUMERIC_5 },
+	{ 0x26, KEY_NUMERIC_6 },
+	{ 0x27, KEY_NUMERIC_7 },
+	{ 0x28, KEY_NUMERIC_8 },
+	{ 0x29, KEY_NUMERIC_9 },
+	{ 0x34, KEY_INSERT },
+	{ 0x2b, KEY_ENTER },
+};
+
+static struct rc_map_list ue_rf4ce_map = {
+	.map = {
+		.scan    = ue_rf4ce,
+		.size    = ARRAY_SIZE(ue_rf4ce),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_UE_RF4CE,
+	}
+};
+
+static int __init init_rc_map_ue_rf4ce(void)
+{
+	return rc_map_register(&ue_rf4ce_map);
+}
+
+static void __exit exit_rc_map_ue_rf4ce(void)
+{
+	rc_map_unregister(&ue_rf4ce_map);
+}
+
+module_init(init_rc_map_ue_rf4ce)
+module_exit(exit_rc_map_ue_rf4ce)
+
+MODULE_DESCRIPTION("UE RF4CE Remote Keymap ");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index c00f4c6..db10546 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -57,7 +57,7 @@
 	  Say Y here if this is msm7627A variant platform.
 config WEBCAM_OV7692_QRD
 	bool "Sensor OV7692 QRD(VGA YUV)"
-	depends on MSM_CAMERA && ARCH_MSM7X27A
+	depends on MSM_CAMERA && (ARCH_MSM7X27A || ARCH_MSM8X60)
 	default n
 	---help---
 	  Omni Vision VGA YUV Sensor for QRD Devices
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 604f8fd..4b2ec49 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -205,47 +205,6 @@
 	return 0;
 }
 
-int32_t msm_sensor_setting3(struct msm_sensor_ctrl_t *s_ctrl,
-			int update_type, int res)
-{
-	int32_t rc = 0;
-	static int csi_config;
-	if (update_type == MSM_SENSOR_REG_INIT) {
-		CDBG("Register INIT\n");
-		s_ctrl->curr_csi_params = NULL;
-		csi_config = 0;
-		msm_camera_i2c_write(
-			s_ctrl->sensor_i2c_client,
-			0x0e, 0x08,
-			MSM_CAMERA_I2C_BYTE_DATA);
-	} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
-		CDBG("PERIODIC : %d\n", res);
-		if (res == 0)
-			return 0;
-		if (!csi_config) {
-			msm_sensor_write_conf_array(
-				s_ctrl->sensor_i2c_client,
-				s_ctrl->msm_sensor_reg->mode_settings, res);
-			msleep(30);
-			s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
-			CDBG("CSI config in progress\n");
-			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-				NOTIFY_CSIC_CFG,
-				s_ctrl->curr_csic_params);
-			CDBG("CSI config is done\n");
-			mb();
-			msleep(30);
-			msm_camera_i2c_write(
-					s_ctrl->sensor_i2c_client,
-					0x0e, 0x00,
-					MSM_CAMERA_I2C_BYTE_DATA);
-			csi_config = 1;
-		}
-		msleep(50);
-	}
-	return rc;
-}
-
 int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res)
 {
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 0055fb8..d26a9d3 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -247,7 +247,7 @@
 
 struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
 
-#if (defined CONFIG_WEBCAM_OV7692_QRD || defined CONFIG_OV5647)
+#if defined(CONFIG_OV5647)
 	extern int lcd_camera_power_onoff(int on);
 #endif
 
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index 3b13d04..1e66843 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -261,6 +261,297 @@
 	{0x3509, 0x20},
 };
 
+static struct msm_camera_i2c_reg_conf ov2720_60fps_settings[] = {
+	{0x3718, 0x10},
+	{0x3702, 0x18},
+	{0x373a, 0x3c},
+	{0x3715, 0x01},
+	{0x3703, 0x1d},
+	{0x3705, 0x0b},
+	{0x3730, 0x1f},
+	{0x3704, 0x3f},
+	{0x3f06, 0x1d},
+	{0x371c, 0x00},
+	{0x371d, 0x83},
+	{0x371e, 0x00},
+	{0x371f, 0xb6},
+	{0x3708, 0x63},
+	{0x3709, 0x52},
+	{0x3800, 0x01},
+	{0x3801, 0x42},
+	{0x3802, 0x00},
+	{0x3803, 0x40},
+	{0x3804, 0x06},
+	{0x3805, 0x61},
+	{0x3806, 0x04},
+	{0x3807, 0x08},
+	{0x3808, 0x02},
+	{0x3809, 0x80},
+	{0x380a, 0x01},
+	{0x380b, 0xe0},
+	{0x380c, 0x03},
+	{0x380d, 0x0c},
+	{0x380e, 0x02},
+	{0x380f, 0x00},
+	{0x3810, 0x00},
+	{0x3811, 0x0f},
+	{0x3812, 0x00},
+	{0x3813, 0x02},
+	{0x3820, 0x80},
+	{0x3821, 0x06},
+	{0x3814, 0x31},
+	{0x3815, 0x31},
+	{0x3612, 0x0b},
+	{0x3618, 0x04},
+	{0x3a08, 0x02},
+	{0x3a09, 0x67},
+	{0x3a0a, 0x02},
+	{0x3a0b, 0x00},
+	{0x3a0d, 0x00},
+	{0x3a0e, 0x00},
+	{0x4520, 0x0a},
+	{0x4837, 0x29},
+	{0x3000, 0xff},
+	{0x3001, 0xff},
+	{0x3002, 0xf0},
+	{0x3600, 0x08},
+	{0x3621, 0xc0},
+	{0x3632, 0xd2},
+	{0x3633, 0x23},
+	{0x3634, 0x54},
+	{0x3f01, 0x0c},
+	{0x5001, 0xc1},
+	{0x3614, 0xf0},
+	{0x3630, 0x2d},
+	{0x370b, 0x62},
+	{0x3706, 0x61},
+	{0x4000, 0x02},
+	{0x4002, 0xc5},
+	{0x4005, 0x08},
+	{0x404f, 0x84},
+	{0x4051, 0x00},
+	{0x5000, 0xff},
+	{0x3a18, 0x00},
+	{0x3a19, 0x80},
+	{0x3503, 0x00},
+	{0x4521, 0x00},
+	{0x5183, 0xb0},
+	{0x5184, 0xb0},
+	{0x5185, 0xb0},
+	{0x370c, 0x0c},
+	{0x3035, 0x30},
+	{0x3036, 0x14},
+	{0x3037, 0x21},
+	{0x303e, 0x19},
+	{0x3038, 0x06},
+	{0x3018, 0x04},
+	{0x3000, 0x00},
+	{0x3001, 0x00},
+	{0x3002, 0x00},
+	{0x3a0f, 0x40},
+	{0x3a10, 0x38},
+	{0x3a1b, 0x48},
+	{0x3a1e, 0x30},
+	{0x3a11, 0x90},
+	{0x3a1f, 0x10},
+	{0x3011, 0x22},
+	{0x3a00, 0x58},
+};
+
+static struct msm_camera_i2c_reg_conf ov2720_90fps_settings[] = {
+	{0x3718, 0x10},
+	{0x3702, 0x18},
+	{0x373a, 0x3c},
+	{0x3715, 0x01},
+	{0x3703, 0x1d},
+	{0x3705, 0x0b},
+	{0x3730, 0x1f},
+	{0x3704, 0x3f},
+	{0x3f06, 0x1d},
+	{0x371c, 0x00},
+	{0x371d, 0x83},
+	{0x371e, 0x00},
+	{0x371f, 0xb6},
+	{0x3708, 0x63},
+	{0x3709, 0x52},
+	{0x3800, 0x01},
+	{0x3801, 0x42},
+	{0x3802, 0x00},
+	{0x3803, 0x40},
+	{0x3804, 0x06},
+	{0x3805, 0x61},
+	{0x3806, 0x04},
+	{0x3807, 0x08},
+	{0x3808, 0x02},
+	{0x3809, 0x80},
+	{0x380a, 0x01},
+	{0x380b, 0xe0},
+	{0x380c, 0x03},
+	{0x380d, 0x0c},
+	{0x380e, 0x02},
+	{0x380f, 0x00},
+	{0x3810, 0x00},
+	{0x3811, 0x0f},
+	{0x3812, 0x00},
+	{0x3813, 0x02},
+	{0x3820, 0x80},
+	{0x3821, 0x06},
+	{0x3814, 0x31},
+	{0x3815, 0x31},
+	{0x3612, 0x0b},
+	{0x3618, 0x04},
+	{0x3a08, 0x02},
+	{0x3a09, 0x67},
+	{0x3a0a, 0x02},
+	{0x3a0b, 0x00},
+	{0x3a0d, 0x00},
+	{0x3a0e, 0x00},
+	{0x4520, 0x0a},
+	{0x4837, 0x29},
+	{0x3000, 0xff},
+	{0x3001, 0xff},
+	{0x3002, 0xf0},
+	{0x3600, 0x08},
+	{0x3621, 0xc0},
+	{0x3632, 0xd2},
+	{0x3633, 0x23},
+	{0x3634, 0x54},
+	{0x3f01, 0x0c},
+	{0x5001, 0xc1},
+	{0x3614, 0xf0},
+	{0x3630, 0x2d},
+	{0x370b, 0x62},
+	{0x3706, 0x61},
+	{0x4000, 0x02},
+	{0x4002, 0xc5},
+	{0x4005, 0x08},
+	{0x404f, 0x84},
+	{0x4051, 0x00},
+	{0x5000, 0xff},
+	{0x3a18, 0x00},
+	{0x3a19, 0x80},
+	{0x3503, 0x00},
+	{0x4521, 0x00},
+	{0x5183, 0xb0},
+	{0x5184, 0xb0},
+	{0x5185, 0xb0},
+	{0x370c, 0x0c},
+	{0x3035, 0x20},
+	{0x3036, 0x14},
+	{0x3037, 0x21},
+	{0x303e, 0x19},
+	{0x3038, 0x06},
+	{0x3018, 0x04},
+	{0x3000, 0x00},
+	{0x3001, 0x00},
+	{0x3002, 0x00},
+	{0x3a0f, 0x40},
+	{0x3a10, 0x38},
+	{0x3a1b, 0x48},
+	{0x3a1e, 0x30},
+	{0x3a11, 0x90},
+	{0x3a1f, 0x10},
+	{0x3011, 0x22},
+	{0x3a00, 0x58},
+};
+
+static struct msm_camera_i2c_reg_conf ov2720_120fps_settings[] = {
+	{0x3718, 0x10},
+	{0x3702, 0x18},
+	{0x373a, 0x3c},
+	{0x3715, 0x01},
+	{0x3703, 0x1d},
+	{0x3705, 0x0b},
+	{0x3730, 0x1f},
+	{0x3704, 0x3f},
+	{0x3f06, 0x1d},
+	{0x371c, 0x00},
+	{0x371d, 0x83},
+	{0x371e, 0x00},
+	{0x371f, 0xb6},
+	{0x3708, 0x63},
+	{0x3709, 0x52},
+	{0x3800, 0x01},
+	{0x3801, 0x42},
+	{0x3802, 0x00},
+	{0x3803, 0x40},
+	{0x3804, 0x06},
+	{0x3805, 0x61},
+	{0x3806, 0x04},
+	{0x3807, 0x08},
+	{0x3808, 0x02},
+	{0x3809, 0x80},
+	{0x380a, 0x01},
+	{0x380b, 0xe0},
+	{0x380c, 0x03},
+	{0x380d, 0x0c},
+	{0x380e, 0x02},
+	{0x380f, 0x00},
+	{0x3810, 0x00},
+	{0x3811, 0x0f},
+	{0x3812, 0x00},
+	{0x3813, 0x02},
+	{0x3820, 0x80},
+	{0x3821, 0x06},
+	{0x3814, 0x31},
+	{0x3815, 0x31},
+	{0x3612, 0x0b},
+	{0x3618, 0x04},
+	{0x3a08, 0x02},
+	{0x3a09, 0x67},
+	{0x3a0a, 0x02},
+	{0x3a0b, 0x00},
+	{0x3a0d, 0x00},
+	{0x3a0e, 0x00},
+	{0x4520, 0x0a},
+	{0x4837, 0x29},
+	{0x3000, 0xff},
+	{0x3001, 0xff},
+	{0x3002, 0xf0},
+	{0x3600, 0x08},
+	{0x3621, 0xc0},
+	{0x3632, 0xd2},
+	{0x3633, 0x23},
+	{0x3634, 0x54},
+	{0x3f01, 0x0c},
+	{0x5001, 0xc1},
+	{0x3614, 0xf0},
+	{0x3630, 0x2d},
+	{0x370b, 0x62},
+	{0x3706, 0x61},
+	{0x4000, 0x02},
+	{0x4002, 0xc5},
+	{0x4005, 0x08},
+	{0x404f, 0x84},
+	{0x4051, 0x00},
+	{0x5000, 0xff},
+	{0x3a18, 0x00},
+	{0x3a19, 0x80},
+	{0x3503, 0x00},
+	{0x4521, 0x00},
+	{0x5183, 0xb0},
+	{0x5184, 0xb0},
+	{0x5185, 0xb0},
+	{0x370c, 0x0c},
+	{0x3035, 0x10},
+	{0x3036, 0x14},
+	{0x3037, 0x21},
+	{0x303e, 0x19},
+	{0x3038, 0x06},
+	{0x3018, 0x04},
+	{0x3000, 0x00},
+	{0x3001, 0x00},
+	{0x3002, 0x00},
+	{0x3a0f, 0x40},
+	{0x3a10, 0x38},
+	{0x3a1b, 0x48},
+	{0x3a1e, 0x30},
+	{0x3a11, 0x90},
+	{0x3a1f, 0x10},
+	{0x3011, 0x22},
+	{0x3a00, 0x58},
+};
+
 static struct msm_camera_i2c_reg_conf ov2720_recommend_settings[] = {
 	{0x0103, 0x01},
 	{0x3718, 0x10},
@@ -302,6 +593,12 @@
 	ARRAY_SIZE(ov2720_vga_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 	{&ov2720_720_settings[0],
 	ARRAY_SIZE(ov2720_720_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov2720_60fps_settings[0],
+	ARRAY_SIZE(ov2720_60fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov2720_90fps_settings[0],
+	ARRAY_SIZE(ov2720_90fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov2720_120fps_settings[0],
+	ARRAY_SIZE(ov2720_120fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
 static struct msm_sensor_output_info_t ov2720_dimensions[] = {
@@ -332,6 +629,33 @@
 		.op_pixel_clk = 72000000,
 		.binning_factor = 1,
 	},
+	{
+		.x_output = 0x280, /* 640 */
+		.y_output = 0x1E0, /* 480 */
+		.line_length_pclk = 0x30C, /* 780 */
+		.frame_length_lines = 0x200, /* 512 */
+		.vt_pixel_clk = 24000000,
+		.op_pixel_clk = 24000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x280, /* 640 */
+		.y_output = 0x1E0, /* 480 */
+		.line_length_pclk = 0x30C, /* 780 */
+		.frame_length_lines = 0x200, /* 512 */
+		.vt_pixel_clk = 36000000,
+		.op_pixel_clk = 36000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x280, /* 640 */
+		.y_output = 0x1E0, /* 480 */
+		.line_length_pclk = 0x30C, /* 780 */
+		.frame_length_lines = 0x200, /* 512 */
+		.vt_pixel_clk = 48000000,
+		.op_pixel_clk = 48000000,
+		.binning_factor = 1,
+	},
 };
 
 static struct msm_camera_csid_vc_cfg ov2720_cid_cfg[] = {
@@ -357,6 +681,9 @@
 	&ov2720_csi_params,
 	&ov2720_csi_params,
 	&ov2720_csi_params,
+	&ov2720_csi_params,
+	&ov2720_csi_params,
+	&ov2720_csi_params,
 };
 
 static struct msm_sensor_output_reg_addr_t ov2720_reg_addr = {
diff --git a/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
index 9fe2e8a..2324495 100644
--- a/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
@@ -13,252 +13,16 @@
 
 #include "msm_sensor.h"
 #define SENSOR_NAME "ov7692"
-#define PLATFORM_DRIVER_NAME "msm_camera_ov7692"
-#define ov7692_obj ov7692_##obj
-#define MSB                             1
-#define LSB                             0
 
 DEFINE_MUTEX(ov7692_mut);
 static struct msm_sensor_ctrl_t ov7692_s_ctrl;
 
-static struct msm_camera_i2c_reg_conf ov7692_prev_settings[] = {
-	{0x12, 0x80},
-	{0x0e, 0x08},
-	{0x69, 0x52},
-	{0x1e, 0xb3},
-	{0x48, 0x42},
-	{0xff, 0x01},
-	{0xae, 0xa0},
-	{0xa8, 0x26},
-	{0xb4, 0xc0},
-	{0xb5, 0x40},
-	{0xff, 0x00},
-	{0x0c, 0x00},
-	{0x62, 0x10},
-	{0x12, 0x00},
-	{0x17, 0x65},
-	{0x18, 0xa4},
-	{0x19, 0x0a},
-	{0x1a, 0xf6},
-	{0x3e, 0x30},
-	{0x64, 0x0a},
-	{0xff, 0x01},
-	{0xb4, 0xc0},
-	{0xff, 0x00},
-	{0x67, 0x20},
-	{0x81, 0x3f},
-	{0xcc, 0x02},
-	{0xcd, 0x80},
-	{0xce, 0x01},
-	{0xcf, 0xe0},
-	{0xc8, 0x02},
-	{0xc9, 0x80},
-	{0xca, 0x01},
-	{0xcb, 0xe0},
-	{0xd0, 0x48},
-	{0x82, 0x03},
-	{0x70, 0x00},
-	{0x71, 0x34},
-	{0x74, 0x28},
-	{0x75, 0x98},
-	{0x76, 0x00},
-	{0x77, 0x64},
-	{0x78, 0x01},
-	{0x79, 0xc2},
-	{0x7a, 0x4e},
-	{0x7b, 0x1f},
-	{0x7c, 0x00},
-	{0x11, 0x00},
-	{0x20, 0x00},
-	{0x21, 0x23},
-	{0x50, 0x9a},
-	{0x51, 0x80},
-	{0x4c, 0x7d},
-	{0x85, 0x10},
-	{0x86, 0x00},
-	{0x87, 0x00},
-	{0x88, 0x00},
-	{0x89, 0x2a},
-	{0x8a, 0x26},
-	{0x8b, 0x22},
-	{0xbb, 0x7a},
-	{0xbc, 0x69},
-	{0xbd, 0x11},
-	{0xbe, 0x13},
-	{0xbf, 0x81},
-	{0xc0, 0x96},
-	{0xc1, 0x1e},
-	{0xb7, 0x05},
-	{0xb8, 0x09},
-	{0xb9, 0x00},
-	{0xba, 0x18},
-	{0x5a, 0x1f},
-	{0x5b, 0x9f},
-	{0x5c, 0x6a},
-	{0x5d, 0x42},
-	{0x24, 0x78},
-	{0x25, 0x68},
-	{0x26, 0xb3},
-	{0xa3, 0x0b},
-	{0xa4, 0x15},
-	{0xa5, 0x2a},
-	{0xa6, 0x51},
-	{0xa7, 0x63},
-	{0xa8, 0x74},
-	{0xa9, 0x83},
-	{0xaa, 0x91},
-	{0xab, 0x9e},
-	{0xac, 0xaa},
-	{0xad, 0xbe},
-	{0xae, 0xce},
-	{0xaf, 0xe5},
-	{0xb0, 0xf3},
-	{0xb1, 0xfb},
-	{0xb2, 0x06},
-	{0x8c, 0x5c},
-	{0x8d, 0x11},
-	{0x8e, 0x12},
-	{0x8f, 0x19},
-	{0x90, 0x50},
-	{0x91, 0x20},
-	{0x92, 0x96},
-	{0x93, 0x80},
-	{0x94, 0x13},
-	{0x95, 0x1b},
-	{0x96, 0xff},
-	{0x97, 0x00},
-	{0x98, 0x3d},
-	{0x99, 0x36},
-	{0x9a, 0x51},
-	{0x9b, 0x43},
-	{0x9c, 0xf0},
-	{0x9d, 0xf0},
-	{0x9e, 0xf0},
-	{0x9f, 0xff},
-	{0xa0, 0x68},
-	{0xa1, 0x62},
-	{0xa2, 0x0e},
-
+static struct msm_camera_i2c_reg_conf ov7692_start_settings[] = {
+	{0x0e, 0x00},
 };
 
-static struct msm_camera_i2c_reg_conf ov7692_snap_settings[] = {
-	{0x12, 0x80},
+static struct msm_camera_i2c_reg_conf ov7692_stop_settings[] = {
 	{0x0e, 0x08},
-	{0x69, 0x52},
-	{0x1e, 0xb3},
-	{0x48, 0x42},
-	{0xff, 0x01},
-	{0xae, 0xa0},
-	{0xa8, 0x26},
-	{0xb4, 0xc0},
-	{0xb5, 0x40},
-	{0xff, 0x00},
-	{0x0c, 0x00},
-	{0x62, 0x10},
-	{0x12, 0x00},
-	{0x17, 0x65},
-	{0x18, 0xa4},
-	{0x19, 0x0a},
-	{0x1a, 0xf6},
-	{0x3e, 0x30},
-	{0x64, 0x0a},
-	{0xff, 0x01},
-	{0xb4, 0xc0},
-	{0xff, 0x00},
-	{0x67, 0x20},
-	{0x81, 0x3f},
-	{0xcc, 0x02},
-	{0xcd, 0x80},
-	{0xce, 0x01},
-	{0xcf, 0xe0},
-	{0xc8, 0x02},
-	{0xc9, 0x80},
-	{0xca, 0x01},
-	{0xcb, 0xe0},
-	{0xd0, 0x48},
-	{0x82, 0x03},
-	{0x70, 0x00},
-	{0x71, 0x34},
-	{0x74, 0x28},
-	{0x75, 0x98},
-	{0x76, 0x00},
-	{0x77, 0x64},
-	{0x78, 0x01},
-	{0x79, 0xc2},
-	{0x7a, 0x4e},
-	{0x7b, 0x1f},
-	{0x7c, 0x00},
-	{0x11, 0x00},
-	{0x20, 0x00},
-	{0x21, 0x23},
-	{0x50, 0x9a},
-	{0x51, 0x80},
-	{0x4c, 0x7d},
-	{0x85, 0x10},
-	{0x86, 0x00},
-	{0x87, 0x00},
-	{0x88, 0x00},
-	{0x89, 0x2a},
-	{0x8a, 0x26},
-	{0x8b, 0x22},
-	{0xbb, 0x7a},
-	{0xbc, 0x69},
-	{0xbd, 0x11},
-	{0xbe, 0x13},
-	{0xbf, 0x81},
-	{0xc0, 0x96},
-	{0xc1, 0x1e},
-	{0xb7, 0x05},
-	{0xb8, 0x09},
-	{0xb9, 0x00},
-	{0xba, 0x18},
-	{0x5a, 0x1f},
-	{0x5b, 0x9f},
-	{0x5c, 0x6a},
-	{0x5d, 0x42},
-	{0x24, 0x78},
-	{0x25, 0x68},
-	{0x26, 0xb3},
-	{0xa3, 0x0b},
-	{0xa4, 0x15},
-	{0xa5, 0x2a},
-	{0xa6, 0x51},
-	{0xa7, 0x63},
-	{0xa8, 0x74},
-	{0xa9, 0x83},
-	{0xaa, 0x91},
-	{0xab, 0x9e},
-	{0xac, 0xaa},
-	{0xad, 0xbe},
-	{0xae, 0xce},
-	{0xaf, 0xe5},
-	{0xb0, 0xf3},
-	{0xb1, 0xfb},
-	{0xb2, 0x06},
-	{0x8c, 0x5c},
-	{0x8d, 0x11},
-	{0x8e, 0x12},
-	{0x8f, 0x19},
-	{0x90, 0x50},
-	{0x91, 0x20},
-	{0x92, 0x96},
-	{0x93, 0x80},
-	{0x94, 0x13},
-	{0x95, 0x1b},
-	{0x96, 0xff},
-	{0x97, 0x00},
-	{0x98, 0x3d},
-	{0x99, 0x36},
-	{0x9a, 0x51},
-	{0x9b, 0x43},
-	{0x9c, 0xf0},
-	{0x9d, 0xf0},
-	{0x9e, 0xf0},
-	{0x9f, 0xff},
-	{0xa0, 0x68},
-	{0xa1, 0x62},
-	{0xa2, 0x0e},
-
 };
 
 static struct msm_camera_i2c_reg_conf ov7692_recommend_settings[] = {
@@ -287,14 +51,6 @@
 	{0xff, 0x00},
 	{0x67, 0x20},
 	{0x81, 0x3f},
-	{0xcc, 0x02},
-	{0xcd, 0x80},
-	{0xce, 0x01},
-	{0xcf, 0xe0},
-	{0xc8, 0x02},
-	{0xc9, 0x80},
-	{0xca, 0x01},
-	{0xcb, 0xe0},
 	{0xd0, 0x48},
 	{0x82, 0x03},
 	{0x70, 0x00},
@@ -378,7 +134,17 @@
 	{0xa0, 0x68},
 	{0xa1, 0x62},
 	{0xa2, 0x0e},
+};
 
+static struct msm_camera_i2c_reg_conf ov7692_full_settings[] = {
+	{0xcc, 0x02},
+	{0xcd, 0x80},
+	{0xce, 0x01},
+	{0xcf, 0xe0},
+	{0xc8, 0x02},
+	{0xc9, 0x80},
+	{0xca, 0x01},
+	{0xcb, 0xe0},
 };
 
 static struct v4l2_subdev_info ov7692_subdev_info[] = {
@@ -398,10 +164,8 @@
 };
 
 static struct msm_camera_i2c_conf_array ov7692_confs[] = {
-	{&ov7692_snap_settings[0],
-	ARRAY_SIZE(ov7692_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
-	{&ov7692_prev_settings[0],
-	ARRAY_SIZE(ov7692_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov7692_full_settings[0],
+	ARRAY_SIZE(ov7692_full_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
 static struct msm_sensor_output_info_t ov7692_dimensions[] = {
@@ -414,15 +178,6 @@
 		.op_pixel_clk = 9216000,
 		.binning_factor = 1,
 	},
-	{
-		.x_output = 0x280,
-		.y_output = 0x1E0,
-		.line_length_pclk = 0x290,
-		.frame_length_lines = 0x1EC,
-		.vt_pixel_clk = 9216000,
-		.op_pixel_clk = 9216000,
-		.binning_factor = 1,
-	},
 };
 
 
@@ -436,7 +191,6 @@
 
 static struct msm_camera_csi_params *ov7692_csi_params_array[] = {
 	&ov7692_csi_params,
-	&ov7692_csi_params,
 };
 
 static struct msm_sensor_output_reg_addr_t ov7692_reg_addr = {
@@ -451,77 +205,11 @@
 	.sensor_id = 0x7692,
 };
 
-static struct msm_sensor_exp_gain_info_t ov7692_exp_gain_info = {
-	.coarse_int_time_addr = 0x0202,
-	.global_gain_addr = 0x0204,
-	.vert_offset = 4,
-};
-
-static inline uint8_t ov7692_byte(uint16_t word, uint8_t offset)
-{
-	return word >> (offset * BITS_PER_BYTE);
-}
-
-
 static const struct i2c_device_id ov7692_i2c_id[] = {
 	{SENSOR_NAME, (kernel_ulong_t)&ov7692_s_ctrl},
 	{ }
 };
-static int ov7692_pwdn_gpio;
-static int ov7692_reset_gpio;
 
-static int ov7692_probe_init_gpio(const struct msm_camera_sensor_info *data)
-{
-	int rc = 0;
-	CDBG("%s: entered\n", __func__);
-
-	ov7692_pwdn_gpio = data->sensor_pwd;
-	ov7692_reset_gpio = data->sensor_reset ;
-
-	CDBG("%s: pwdn_gpio:%d, reset_gpio:%d\n", __func__,
-			ov7692_pwdn_gpio, ov7692_reset_gpio);
-
-	if (data->sensor_reset_enable)
-		gpio_direction_output(data->sensor_reset, 1);
-
-	gpio_direction_output(data->sensor_pwd, 1);
-
-	return rc;
-
-}
-static void ov7692_power_on(void)
-{
-	CDBG("%s\n", __func__);
-	gpio_set_value(ov7692_pwdn_gpio, 0);
-}
-
-static void ov7692_power_down(void)
-{
-	CDBG("%s\n", __func__);
-	gpio_set_value(ov7692_pwdn_gpio, 1);
-}
-
-int32_t ov7692_sensor_i2c_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	int32_t rc = 0;
-	struct msm_sensor_ctrl_t *s_ctrl;
-	rc = msm_sensor_i2c_probe(client, id);
-
-	ov7692_power_down();
-
-	if (client->dev.platform_data == NULL) {
-		pr_err("%s: NULL sensor data\n", __func__);
-		return -EFAULT;
-	}
-
-	s_ctrl = client->dev.platform_data;
-	if (s_ctrl->sensordata->pmic_gpio_enable)
-		lcd_camera_power_onoff(0);
-
-	return rc;
-
-}
 
 static struct i2c_driver ov7692_i2c_driver = {
 	.id_table = ov7692_i2c_id,
@@ -559,152 +247,26 @@
 	.video  = &ov7692_subdev_video_ops,
 };
 
-static int32_t ov7692_i2c_txdata(struct i2c_client *ov7692_client,
-		unsigned short saddr,
-		unsigned char *txdata, int length)
-{
-	struct i2c_msg msg[] = {
-		{
-			.addr = saddr,
-			.flags = 0,
-			.len = 2,
-			.buf = txdata,
-		},
-	};
-	if (i2c_transfer(ov7692_client->adapter, msg, 1) < 0) {
-		CDBG("ov7692_i2c_txdata faild 0x%x\n", ov7692_client->addr);
-		return -EIO;
-	}
-
-	return 0;
-}
-static int32_t ov7692_i2c_write_b_sensor(struct i2c_client *ov7692_client,
-		uint8_t waddr,
-		uint8_t bdata)
-{
-	int32_t rc = -EFAULT;
-	unsigned char buf[2];
-
-	memset(buf, 0, sizeof(buf));
-	buf[0] = waddr;
-	buf[1] = bdata;
-	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
-	rc = ov7692_i2c_txdata(ov7692_client, ov7692_client->addr >> 1, buf, 2);
-	if (rc < 0)
-		CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-		waddr, bdata);
-
-	return rc;
-}
-
-static int32_t ov7692_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
-		uint16_t gain, uint32_t line)
-{
-	CDBG("ov7692_write_exp_gain : Not supported\n");
-	return 0;
-}
-
-int32_t ov7692_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
-		struct fps_cfg *fps)
-{
-	CDBG("ov7692_sensor_set_fps: Not supported\n");
-	return 0;
-}
-
-
-
-static void ov7692_sw_reset(struct msm_sensor_ctrl_t *s_ctrl)
-{
-
-	CDBG("%s\n", __func__);
-	ov7692_i2c_write_b_sensor(s_ctrl->sensor_i2c_client->client,
-			0x12, 0x80);
-}
-
-static void ov7692_hw_reset(void)
-{
-	CDBG("--CAMERA-- %s ... (Start...)\n", __func__);
-	gpio_set_value(ov7692_reset_gpio, 1);   /*reset camera reset pin*/
-	usleep_range(5000, 5100);
-	gpio_set_value(ov7692_reset_gpio, 0);
-	usleep_range(5000, 5100);
-	gpio_set_value(ov7692_reset_gpio, 1);
-	usleep_range(1000, 1100);
-	CDBG("--CAMERA-- %s ... (End...)\n", __func__);
-}
-
-
-
-int32_t ov7692_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	int32_t rc = 0;
-	struct msm_camera_sensor_info *info = NULL;
-
-	CDBG("%s: %d\n", __func__, __LINE__);
-
-	rc = msm_sensor_power_up(s_ctrl);
-	if (rc < 0) {
-		CDBG("%s: msm_sensor_power_up failed\n", __func__);
-		return rc;
-	}
-	info = s_ctrl->sensordata;
-
-	rc = ov7692_probe_init_gpio(info);
-	if (rc < 0) {
-		CDBG("%s: gpio init failed\n", __func__);
-		goto power_up_fail;
-	}
-	/* turn on LDO for PVT */
-	if (info->pmic_gpio_enable)
-		lcd_camera_power_onoff(1);
-
-	ov7692_power_down();
-
-	usleep_range(5000, 5100);
-
-	ov7692_power_on();
-	usleep_range(5000, 5100);
-
-	if (info->sensor_reset_enable)
-		ov7692_hw_reset();
-	else
-		ov7692_sw_reset(s_ctrl);
-
-	return rc;
-
-power_up_fail:
-	CDBG("ov7692_sensor_power_up: OV7692 SENSOR POWER UP FAILS!\n");
-	if (info->pmic_gpio_enable)
-		lcd_camera_power_onoff(0);
-	return rc;
-
-
-}
 
 
 static struct msm_sensor_fn_t ov7692_func_tbl = {
 	.sensor_start_stream = msm_sensor_start_stream,
 	.sensor_stop_stream = msm_sensor_stop_stream,
-	.sensor_group_hold_on = msm_sensor_group_hold_on,
-	.sensor_group_hold_off = msm_sensor_group_hold_off,
-	.sensor_set_fps = ov7692_sensor_set_fps,
-	.sensor_csi_setting = msm_sensor_setting3,
+	.sensor_csi_setting = msm_sensor_setting1,
 	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
 	.sensor_mode_init = msm_sensor_mode_init,
 	.sensor_get_output_info = msm_sensor_get_output_info,
 	.sensor_config = msm_sensor_config,
-	.sensor_power_up = ov7692_sensor_power_up,
+	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
-	.sensor_write_exp_gain = ov7692_write_exp_gain,
-	.sensor_write_snapshot_exp_gain = ov7692_write_exp_gain,
 };
 
 static struct msm_sensor_reg_t ov7692_regs = {
 	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
-	.start_stream_conf_size = 0,
-	.stop_stream_conf_size = 0,
-	.group_hold_on_conf_size = 0,
-	.group_hold_off_conf_size = 0,
+	.start_stream_conf = ov7692_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(ov7692_start_settings),
+	.stop_stream_conf = ov7692_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(ov7692_stop_settings),
 	.init_settings = &ov7692_init_conf[0],
 	.init_size = ARRAY_SIZE(ov7692_init_conf),
 	.mode_settings = &ov7692_confs[0],
@@ -718,7 +280,6 @@
 	.sensor_i2c_addr = 0x78,
 	.sensor_output_reg_addr = &ov7692_reg_addr,
 	.sensor_id_info = &ov7692_id_info,
-	.sensor_exp_gain_info = &ov7692_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
 	.csic_params = &ov7692_csi_params_array[0],
 	.msm_sensor_mutex = &ov7692_mut,
@@ -731,5 +292,5 @@
 };
 
 module_init(msm_sensor_init_module);
-MODULE_DESCRIPTION("Omni VGA YUV sensor driver");
+MODULE_DESCRIPTION("Omnivision VGA YUV sensor driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 0a2b1c1..2242aa8 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -517,8 +517,10 @@
 			core, ioctl, MDP_DQ_BUFFER, (void *)&obuf_mdp);
 
 		if (rc) {
-			WFD_MSG_ERR("Either streamoff called or"
-						" MDP REPORTED ERROR\n");
+			if (rc != -ENOBUFS)
+				WFD_MSG_ERR("MDP reported err %d\n", rc);
+
+			WFD_MSG_ERR("Streamoff called\n");
 			break;
 		} else {
 			wfd_stats_update(&inst->stats,
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3b115ab..0d6c5f1 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1850,7 +1850,7 @@
 msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
-	unsigned long		flags;
+	unsigned long		flags, timeout;
 
 	/*
 	 * Get the SDIO AL client out of LPM.
@@ -1904,11 +1904,18 @@
 	     mrq->cmd->opcode, host->curr.mrq->cmd->opcode);
 
 	/*
-	 * Kick the software command timeout timer here.
-	 * Timer expires in 10 secs.
+	 * Set timeout value to 10 secs (or more in case of buggy cards)
+	 */
+	if ((mmc->card) && (mmc->card->quirks & MMC_QUIRK_INAND_DATA_TIMEOUT))
+		timeout = 20000;
+	else
+		timeout = MSM_MMC_REQ_TIMEOUT;
+	/*
+	 * Kick the software request timeout timer here with the timeout
+	 * value identified above
 	 */
 	mod_timer(&host->req_tout_timer,
-			(jiffies + msecs_to_jiffies(MSM_MMC_REQ_TIMEOUT)));
+			(jiffies + msecs_to_jiffies(timeout)));
 
 	host->curr.mrq = mrq;
 	if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 718ef43..e6bd16c 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -212,10 +212,7 @@
 
 #define MSM_MMC_IDLE_TIMEOUT	5000 /* msecs */
 
-/*
- * Set the request timeout to 10secs to allow
- * bad cards/controller to respond.
- */
+/* Set the request timeout to 10secs */
 #define MSM_MMC_REQ_TIMEOUT	10000 /* msecs */
 #define MSM_MMC_DISABLE_TIMEOUT        200 /* msecs */
 
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 9059603..3007662 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -21,8 +21,9 @@
 #include <linux/slab.h>
 
 /**
- * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
+ * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
  * @np:		device node to get GPIO from
+ * @propname:	property name containing gpio specifier(s)
  * @index:	index of the GPIO
  * @flags:	a flags pointer to fill in
  *
@@ -30,8 +31,8 @@
  * value on the error condition. If @flags is not NULL the function also fills
  * in flags for the GPIO.
  */
-int of_get_gpio_flags(struct device_node *np, int index,
-		      enum of_gpio_flags *flags)
+int of_get_named_gpio_flags(struct device_node *np, const char *propname,
+                           int index, enum of_gpio_flags *flags)
 {
 	int ret;
 	struct device_node *gpio_np;
@@ -40,7 +41,7 @@
 	const void *gpio_spec;
 	const __be32 *gpio_cells;
 
-	ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+	ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
 					  &gpio_np, &gpio_spec);
 	if (ret) {
 		pr_debug("%s: can't parse gpios property\n", __func__);
@@ -79,7 +80,7 @@
 	pr_debug("%s exited with status %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL(of_get_gpio_flags);
+EXPORT_SYMBOL(of_get_named_gpio_flags);
 
 /**
  * of_gpio_count - Count GPIOs for a device
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index fe728b2..ddc8589 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -166,6 +166,13 @@
 #define QPNP_BOOST_CURRENT_LIMIT_ENABLE_MASK	0x80
 #define QPNP_BOOST_CURRENT_LIMIT_MASK		0x07
 
+/*
+ * This voltage in uV is returned by get_voltage functions when there is no way
+ * to determine the current voltage level.  It is needed because the regulator
+ * framework treats a 0 uV voltage as an error.
+ */
+#define VOLTAGE_UNKNOWN 1
+
 struct qpnp_voltage_range {
 	int					min_uV;
 	int					max_uV;
@@ -243,15 +250,18 @@
  * properties to hold.
  */
 static struct qpnp_voltage_range pldo_ranges[] = {
-	VOLTAGE_RANGE(0,  375000,  375000, 1512500, 12500),
-	VOLTAGE_RANGE(2,  750000, 1525000, 1537500, 12500),
+	VOLTAGE_RANGE(2,  750000,  750000, 1537500, 12500),
 	VOLTAGE_RANGE(3, 1500000, 1550000, 3075000, 25000),
 	VOLTAGE_RANGE(4, 1750000, 3100000, 4900000, 50000),
 };
 
-static struct qpnp_voltage_range nldo_ranges[] = {
-	VOLTAGE_RANGE(0,  375000,  375000, 1512500, 12500),
-	VOLTAGE_RANGE(2,  750000, 1525000, 1537500, 12500),
+static struct qpnp_voltage_range nldo1_ranges[] = {
+	VOLTAGE_RANGE(2,  750000,  750000, 1537500, 12500),
+};
+
+static struct qpnp_voltage_range nldo2_ranges[] = {
+	VOLTAGE_RANGE(1,  375000,  375000,  768750,  6250),
+	VOLTAGE_RANGE(2,  750000,  775000, 1537500, 12500),
 };
 
 static struct qpnp_voltage_range smps_ranges[] = {
@@ -260,7 +270,7 @@
 };
 
 static struct qpnp_voltage_range ftsmps_ranges[] = {
-	VOLTAGE_RANGE(0,   80000,   80000, 1355000,  5000),
+	VOLTAGE_RANGE(0,   80000,  350000, 1355000,  5000),
 	VOLTAGE_RANGE(1,  160000, 1360000, 2710000, 10000),
 };
 
@@ -269,7 +279,10 @@
 };
 
 static struct qpnp_voltage_set_points pldo_set_points = SET_POINTS(pldo_ranges);
-static struct qpnp_voltage_set_points nldo_set_points = SET_POINTS(nldo_ranges);
+static struct qpnp_voltage_set_points nldo1_set_points
+					= SET_POINTS(nldo1_ranges);
+static struct qpnp_voltage_set_points nldo2_set_points
+					= SET_POINTS(nldo2_ranges);
 static struct qpnp_voltage_set_points smps_set_points = SET_POINTS(smps_ranges);
 static struct qpnp_voltage_set_points ftsmps_set_points
 					= SET_POINTS(ftsmps_ranges);
@@ -279,7 +292,8 @@
 
 static struct qpnp_voltage_set_points *all_set_points[] = {
 	&pldo_set_points,
-	&nldo_set_points,
+	&nldo1_set_points,
+	&nldo2_set_points,
 	&smps_set_points,
 	&ftsmps_set_points,
 	&boost_set_points,
@@ -629,7 +643,7 @@
 	if (!range) {
 		vreg_err(vreg, "voltage unknown, range %d is invalid\n",
 			range_sel);
-		return -EINVAL;
+		return VOLTAGE_UNKNOWN;
 	}
 
 	return range->step_uV * voltage_sel + range->min_uV;
@@ -949,11 +963,9 @@
 
 static const struct qpnp_regulator_mapping supported_regulators[] = {
 	QPNP_VREG_MAP(HF_BUCK,  GP_CTL,    SMPS,   smps,   smps,   100000),
-	QPNP_VREG_MAP(LDO,      N50,       LDO,    ldo,    nldo,     5000),
-	QPNP_VREG_MAP(LDO,      N150,      LDO,    ldo,    nldo,    10000),
-	QPNP_VREG_MAP(LDO,      N300,      LDO,    ldo,    nldo,    10000),
-	QPNP_VREG_MAP(LDO,      N600,      LDO,    ldo,    nldo,    10000),
-	QPNP_VREG_MAP(LDO,      N1200,     LDO,    ldo,    nldo,    10000),
+	QPNP_VREG_MAP(LDO,      N300,      LDO,    ldo,    nldo1,   10000),
+	QPNP_VREG_MAP(LDO,      N600,      LDO,    ldo,    nldo2,   10000),
+	QPNP_VREG_MAP(LDO,      N1200,     LDO,    ldo,    nldo2,   10000),
 	QPNP_VREG_MAP(LDO,      P50,       LDO,    ldo,    pldo,     5000),
 	QPNP_VREG_MAP(LDO,      P150,      LDO,    ldo,    pldo,    10000),
 	QPNP_VREG_MAP(LDO,      P300,      LDO,    ldo,    pldo,    10000),
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index cb0e936..2fc95af 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -39,6 +39,7 @@
 #include <linux/remote_spinlock.h>
 #include <linux/pm_qos_params.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include "spi_qsd.h"
 
 static inline int msm_spi_configure_gsbi(struct msm_spi *dd,
@@ -1773,6 +1774,7 @@
 	int                     clk_enabled = 0;
 	int                     pclk_enabled = 0;
 	struct msm_spi_platform_data *pdata;
+	enum of_gpio_flags flags;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct msm_spi));
 	if (!master) {
@@ -1797,9 +1799,35 @@
 			rc = -ENOMEM;
 			goto err_probe_exit;
 		}
+
+		for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
+			dd->spi_gpios[i] = of_get_gpio_flags(pdev->dev.of_node,
+								i, &flags);
+		}
+
+		for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
+			dd->cs_gpios[i].gpio_num = of_get_named_gpio_flags(
+						pdev->dev.of_node, "cs-gpios",
+						i, &flags);
+			dd->cs_gpios[i].valid = 0;
+		}
 	} else {
 		pdata = pdev->dev.platform_data;
 		dd->qup_ver = SPI_QUP_VERSION_NONE;
+
+		for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
+			resource = platform_get_resource(pdev, IORESOURCE_IO,
+							i);
+			dd->spi_gpios[i] = resource ? resource->start : -1;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
+			resource = platform_get_resource(pdev, IORESOURCE_IO,
+						i + ARRAY_SIZE(spi_rsrcs));
+			dd->cs_gpios[i].gpio_num = resource ?
+							resource->start : -1;
+			dd->cs_gpios[i].valid = 0;
+		}
 	}
 
 	dd->pdata = pdata;
@@ -1852,18 +1880,6 @@
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
-		resource = platform_get_resource(pdev, IORESOURCE_IO, i);
-		dd->spi_gpios[i] = resource ? resource->start : -1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
-		resource = platform_get_resource(pdev, IORESOURCE_IO,
-				i + ARRAY_SIZE(spi_rsrcs));
-		dd->cs_gpios[i].gpio_num = resource ? resource->start : -1;
-		dd->cs_gpios[i].valid = 0;
-	}
-
 	rc = msm_spi_request_gpios(dd);
 	if (rc)
 		goto err_probe_gpio;
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index 4250ff5..7a95880 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -60,6 +60,10 @@
 {
 	struct fmem_platform_data *pdata = pdev->dev.platform_data;
 
+	if (!pdata->phys)
+		pdata->phys = allocate_contiguous_ebi_nomap(pdata->size,
+			PAGE_SIZE);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 	fmem_section_start = pdata->phys >> PA_SECTION_SHIFT;
 	fmem_section_end = (pdata->phys - 1 + pdata->size) >> PA_SECTION_SHIFT;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index ba560b9..7f6585c 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -4136,6 +4136,8 @@
 	/* HDMI_USEC_REFTIMER[0x0208] */
 	HDMI_OUTP(0x0208, 0x0001001B);
 
+	hdmi_msm_set_mode(TRUE);
+
 	hdmi_msm_video_setup(external_common_state->video_resolution);
 	if (!hdmi_msm_is_dvi_mode())
 		hdmi_msm_audio_setup();
@@ -4152,8 +4154,6 @@
 	HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
 	HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
 
-	hdmi_msm_set_mode(TRUE);
-
 	/* Setup HPD IRQ */
 	HDMI_OUTP(0x0254, 4 | (external_common_state->hpd_state ? 0 : 2));
 
diff --git a/include/linux/mfd/pm8xxx/gpio.h b/include/linux/mfd/pm8xxx/gpio.h
index 9918620..ccd9c10 100644
--- a/include/linux/mfd/pm8xxx/gpio.h
+++ b/include/linux/mfd/pm8xxx/gpio.h
@@ -78,6 +78,16 @@
 #define PM8038_GPIO_VIN_L3		5
 #define PM8038_GPIO_VIN_L17		6
 
+/* vin_sel: Voltage Input Select on PM8018*/
+#define PM8018_GPIO_VIN_L4		0
+#define PM8018_GPIO_VIN_L14		1
+#define PM8018_GPIO_VIN_S3		2
+#define PM8018_GPIO_VIN_L6		3
+#define PM8018_GPIO_VIN_L2		4
+#define PM8018_GPIO_VIN_L5		5
+#define PM8018_GPIO_VIN_L8		6
+#define PM8018_GPIO_VIN_VPH		7
+
 /* out_strength */
 #define	PM_GPIO_STRENGTH_NO		0
 #define	PM_GPIO_STRENGTH_HIGH		1
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 6598c04..aec8025 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -46,8 +46,9 @@
 	return container_of(gc, struct of_mm_gpio_chip, gc);
 }
 
-extern int of_get_gpio_flags(struct device_node *np, int index,
-			     enum of_gpio_flags *flags);
+extern int of_get_named_gpio_flags(struct device_node *np,
+		const char *list_name, int index, enum of_gpio_flags *flags);
+
 extern unsigned int of_gpio_count(struct device_node *np);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
@@ -60,8 +61,8 @@
 #else /* CONFIG_OF_GPIO */
 
 /* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline int of_get_gpio_flags(struct device_node *np, int index,
-				    enum of_gpio_flags *flags)
+static inline int of_get_named_gpio_flags(struct device_node *np,
+		const char *list_name, int index, enum of_gpio_flags *flags)
 {
 	return -ENOSYS;
 }
@@ -77,7 +78,38 @@
 #endif /* CONFIG_OF_GPIO */
 
 /**
- * of_get_gpio - Get a GPIO number to use with GPIO API
+ * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * @np:		device node to get GPIO from
+ * @index:	index of the GPIO
+ * @flags:	a flags pointer to fill in
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition. If @flags is not NULL the function also fills
+ * in flags for the GPIO.
+ */
+static inline int of_get_gpio_flags(struct device_node *np, int index,
+		      enum of_gpio_flags *flags)
+{
+	return of_get_named_gpio_flags(np, "gpios", index, flags);
+}
+
+/**
+ * of_get_named_gpio() - Get a GPIO number to use with GPIO API
+ * @np:		device node to get GPIO from
+ * @propname:	Name of property containing gpio specifier(s)
+ * @index:	index of the GPIO
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition.
+ */
+static inline int of_get_named_gpio(struct device_node *np,
+                                   const char *propname, int index)
+{
+	return of_get_named_gpio_flags(np, propname, index, NULL);
+}
+
+/**
+ * of_get_gpio() - Get a GPIO number to use with GPIO API
  * @np:		device node to get GPIO from
  * @index:	index of the GPIO
  *
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 2114287..d906c9f 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -143,6 +143,7 @@
 #define RC_MAP_TREKSTOR                  "rc-trekstor"
 #define RC_MAP_TT_1500                   "rc-tt-1500"
 #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
+#define RC_MAP_UE_RF4CE			 "rc-ue-rf4ce"
 #define RC_MAP_VIDEOMATE_M1F             "rc-videomate-m1f"
 #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
 #define RC_MAP_VIDEOMATE_TV_PVR          "rc-videomate-tv-pvr"
diff --git a/include/sound/msm-dai-q6.h b/include/sound/msm-dai-q6.h
index 89a6a47..6328256 100644
--- a/include/sound/msm-dai-q6.h
+++ b/include/sound/msm-dai-q6.h
@@ -32,8 +32,8 @@
 	int pcm_clk_rate;
 };
 
-struct msm_mi2s_data {
-	u32 capability; /* RX or TX */
-	u16 sd_lines;
+struct msm_mi2s_pdata {
+	u16 rx_sd_lines;
+	u16 tx_sd_lines;
 };
 #endif
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 6ee8287..2d5eab2 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -66,8 +66,9 @@
 #define AIF1_CAP 2
 #define AIF2_PB 3
 #define AIF2_CAP 4
+#define AIF3_CAP 5
 
-#define NUM_CODEC_DAIS 4
+#define NUM_CODEC_DAIS 5
 #define TABLA_COMP_DIGITAL_GAIN_OFFSET 3
 
 struct tabla_codec_dai_data {
@@ -3038,12 +3039,26 @@
 
 	{"SLIM TX3", NULL, "SLIM TX3 MUX"},
 	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
 
 	{"SLIM TX4", NULL, "SLIM TX4 MUX"},
 	{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
 
 	{"SLIM TX5", NULL, "SLIM TX5 MUX"},
 	{"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
 
 	{"SLIM TX6", NULL, "SLIM TX6 MUX"},
 	{"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
@@ -3059,6 +3074,13 @@
 	{"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
 	{"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
 	{"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
+	{"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
 
 	{"SLIM TX8", NULL, "SLIM TX8 MUX"},
 	{"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
@@ -3776,7 +3798,8 @@
 			tabla->dai[dai->id - 1].ch_act = 0;
 			tabla->dai[dai->id - 1].ch_tot = rx_num;
 		}
-	} else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP) {
+	} else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP ||
+		   dai->id == AIF3_CAP) {
 		for (i = 0; i < tx_num; i++) {
 			tabla->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
 			tabla->dai[dai->id - 1].ch_act = 0;
@@ -3829,6 +3852,10 @@
 		tx_slot[0] = tx_ch[cnt];
 		tx_slot[1] = tx_ch[1 + cnt];
 		tx_slot[2] = tx_ch[5 + cnt];
+	} else if (dai->id == AIF3_CAP) {
+		*tx_num = tabla_dai[dai->id - 1].capture.channels_max;
+		tx_slot[cnt] = tx_ch[2 + cnt];
+		tx_slot[cnt + 1] = tx_ch[4 + cnt];
 	}
 
 	return 0;
@@ -3890,7 +3917,8 @@
 	 * If current dai is a tx dai, set sample rate to
 	 * all the txfe paths that are currently not active
 	 */
-	if ((dai->id == AIF1_CAP) || (dai->id == AIF2_CAP)) {
+	if ((dai->id == AIF1_CAP) || (dai->id == AIF2_CAP) ||
+	    (dai->id == AIF3_CAP)) {
 
 		tx_state = snd_soc_read(codec,
 				TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
@@ -4053,6 +4081,20 @@
 		},
 		.ops = &tabla_dai_ops,
 	},
+	{
+		.name = "tabla_tx3",
+		.id = AIF3_CAP,
+		.capture = {
+			.stream_name = "AIF3 Capture",
+			.rates = WCD9310_RATES,
+			.formats = TABLA_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tabla_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver tabla_i2s_dai[] = {
@@ -4103,7 +4145,8 @@
 	case SND_SOC_DAPM_POST_PMU:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
 			if ((tabla_dai[j].id == AIF1_CAP) ||
-			    (tabla_dai[j].id == AIF2_CAP))
+			    (tabla_dai[j].id == AIF2_CAP) ||
+			    (tabla_dai[j].id == AIF3_CAP))
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].playback.stream_name, 13)) {
@@ -4120,7 +4163,8 @@
 	case SND_SOC_DAPM_POST_PMD:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
 			if ((tabla_dai[j].id == AIF1_CAP) ||
-			    (tabla_dai[j].id == AIF2_CAP))
+			    (tabla_dai[j].id == AIF2_CAP) ||
+			    (tabla_dai[j].id == AIF3_CAP))
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].playback.stream_name, 13)) {
@@ -4520,7 +4564,7 @@
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
-	SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
 				0, tabla_codec_enable_slimtx,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
@@ -4530,7 +4574,7 @@
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
-	SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
 				0, tabla_codec_enable_slimtx,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
@@ -7405,6 +7449,9 @@
 		case AIF2_CAP:
 			ch_cnt = tabla_dai[i].capture.channels_max;
 			break;
+		case AIF3_CAP:
+			ch_cnt = tabla_dai[i].capture.channels_max;
+			break;
 		default:
 			continue;
 		}
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b3374fe..b0244af 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1554,6 +1554,7 @@
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx2",
+		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ops = &msm_be_ops,
 	},
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index c32527c..50f527f 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1331,7 +1331,7 @@
 	{
 		.name = LPASS_BE_MI2S_TX,
 		.stream_name = "MI2S Capture",
-		.cpu_dai_name = "msm-dai-q6.7",
+		.cpu_dai_name = "msm-dai-q6-mi2s",
 		.platform_name = "msm-pcm-routing",
 		.codec_name     = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 69d7185..28d192e 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -36,9 +36,17 @@
 	DECLARE_BITMAP(status_mask, STATUS_MAX);
 	u32 rate;
 	u32 channels;
+	u32 bitwidth;
 	union afe_port_config port_config;
 };
 
+struct msm_dai_q6_mi2s_dai_data {
+	struct msm_dai_q6_dai_data tx_dai;
+	struct msm_dai_q6_dai_data rx_dai;
+	struct snd_pcm_hw_constraint_list rate_constraint;
+	struct snd_pcm_hw_constraint_list bitwidth_constraint;
+};
+
 static struct clk *pcm_clk;
 static DEFINE_MUTEX(aux_pcm_mutex);
 static int aux_pcm_count;
@@ -106,6 +114,316 @@
 	return num_bits_set;
 }
 
+static int msm_dai_q6_mi2s_startup(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+
+	dev_dbg(dai->dev, "%s: cnst list %p\n", __func__,
+		mi2s_dai_data->rate_constraint.list);
+
+	if (mi2s_dai_data->rate_constraint.list) {
+		snd_pcm_hw_constraint_list(substream->runtime, 0,
+				SNDRV_PCM_HW_PARAM_RATE,
+				&mi2s_dai_data->rate_constraint);
+		snd_pcm_hw_constraint_list(substream->runtime, 0,
+				SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+				&mi2s_dai_data->bitwidth_constraint);
+	}
+
+	return 0;
+}
+
+static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+
+	dai_data->channels = params_channels(params);
+	switch (dai_data->channels) {
+	case 2:
+		dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
+		break;
+	case 1:
+		dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
+		break;
+	default:
+		pr_warn("greater than stereo has not been validated");
+		break;
+	}
+	dai_data->rate = params_rate(params);
+	dai_data->port_config.mi2s.bitwidth = 16;
+	dai_data->bitwidth = 16;
+	if (!mi2s_dai_data->rate_constraint.list) {
+		mi2s_dai_data->rate_constraint.list = &dai_data->rate;
+		mi2s_dai_data->bitwidth_constraint.list = &dai_data->bitwidth;
+	}
+	return 0;
+}
+
+static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr,
+	unsigned int *ch_cnt)
+{
+	u8 num_of_sd_lines;
+
+	num_of_sd_lines = num_of_bits_set(sd_lines);
+
+	switch (num_of_sd_lines) {
+	case 0:
+		pr_debug("%s: no line is assigned\n", __func__);
+		break;
+	case 1:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0:
+			*config_ptr = AFE_I2S_SD0;
+			break;
+		case MSM_MI2S_SD1:
+			*config_ptr = AFE_I2S_SD1;
+			break;
+		case MSM_MI2S_SD2:
+			*config_ptr = AFE_I2S_SD2;
+			break;
+		case MSM_MI2S_SD3:
+			*config_ptr = AFE_I2S_SD3;
+			break;
+		default:
+			pr_err("%s: invalid SD line\n",
+				   __func__);
+			goto error_invalid_data;
+		}
+		break;
+	case 2:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1:
+			*config_ptr = AFE_I2S_QUAD01;
+			break;
+		case MSM_MI2S_SD2 | MSM_MI2S_SD3:
+			*config_ptr = AFE_I2S_QUAD23;
+			break;
+		default:
+			pr_err("%s: invalid SD line\n",
+				   __func__);
+			goto error_invalid_data;
+		}
+		break;
+	case 3:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2:
+			*config_ptr = AFE_I2S_6CHS;
+			break;
+		default:
+			pr_err("%s: invalid SD lines\n",
+				   __func__);
+			goto error_invalid_data;
+		}
+		break;
+	case 4:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
+			*config_ptr = AFE_I2S_8CHS;
+			break;
+		default:
+			pr_err("%s: invalid SD lines\n",
+				   __func__);
+			goto error_invalid_data;
+		}
+		break;
+	default:
+		pr_err("%s: invalid SD lines\n", __func__);
+		goto error_invalid_data;
+	}
+
+	*ch_cnt = num_of_sd_lines;
+
+	return 0;
+
+error_invalid_data:
+	return -EINVAL;
+}
+
+static int msm_dai_q6_mi2s_platform_data_validation(
+	struct platform_device *pdev, struct snd_soc_dai_driver *dai_driver)
+{
+	struct msm_dai_q6_mi2s_dai_data *dai_data = dev_get_drvdata(&pdev->dev);
+	struct msm_mi2s_pdata *mi2s_pdata =
+			(struct msm_mi2s_pdata *) pdev->dev.platform_data;
+	u16 sdline_config;
+	unsigned int ch_cnt;
+	int rc = 0;
+
+	if ((mi2s_pdata->rx_sd_lines & mi2s_pdata->tx_sd_lines) ||
+	    (!mi2s_pdata->rx_sd_lines && !mi2s_pdata->tx_sd_lines)) {
+		dev_err(&pdev->dev,
+			"error sd line conflict or no line assigned\n");
+		rc = -EINVAL;
+		goto rtn;
+	}
+
+	rc = msm_dai_q6_mi2s_get_lineconfig(mi2s_pdata->rx_sd_lines,
+					    &sdline_config, &ch_cnt);
+
+	if (IS_ERR_VALUE(rc)) {
+		dev_err(&pdev->dev, "invalid MI2S RX sd line config\n");
+		goto rtn;
+	}
+
+	if (ch_cnt) {
+		dai_data->rx_dai.port_config.mi2s.line = sdline_config;
+		dai_driver->playback.channels_min = 1;
+		dai_driver->playback.channels_max = ch_cnt << 1;
+	} else {
+		dai_driver->playback.channels_min = 0;
+		dai_driver->playback.channels_max = 0;
+	}
+	rc = msm_dai_q6_mi2s_get_lineconfig(mi2s_pdata->tx_sd_lines,
+					    &sdline_config, &ch_cnt);
+
+	if (IS_ERR_VALUE(rc)) {
+		dev_err(&pdev->dev, "invalid MI2S TX sd line config\n");
+		goto rtn;
+	}
+
+	if (ch_cnt) {
+		dai_data->tx_dai.port_config.mi2s.line = sdline_config;
+		dai_driver->capture.channels_min = 1;
+		dai_driver->capture.channels_max = ch_cnt << 1;
+	} else {
+		dai_driver->capture.channels_min = 0;
+		dai_driver->capture.channels_max = 0;
+	}
+
+	dev_info(&pdev->dev, "%s: playback sdline %x capture sdline %x\n",
+		 __func__, dai_data->rx_dai.port_config.mi2s.line,
+		 dai_data->tx_dai.port_config.mi2s.line);
+	dev_info(&pdev->dev, "%s: playback ch_max %d capture ch_mx %d\n",
+		 __func__, dai_driver->playback.channels_max,
+		 dai_driver->capture.channels_max);
+rtn:
+	return rc;
+}
+
+static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+	dev_get_drvdata(dai->dev);
+
+	if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) ||
+	    test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+		dev_err(dai->dev, "%s: err chg i2s mode while dai running",
+			__func__);
+		return -EPERM;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		mi2s_dai_data->rx_dai.port_config.mi2s.ws = 1;
+		mi2s_dai_data->tx_dai.port_config.mi2s.ws = 1;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		mi2s_dai_data->rx_dai.port_config.mi2s.ws = 0;
+		mi2s_dai_data->tx_dai.port_config.mi2s.ws = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int msm_dai_q6_mi2s_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+	int rc = 0;
+
+	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+		/* PORT START should be set if prepare called in active state */
+		rc = afe_q6_interface_prepare();
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to open AFE APR\n");
+	}
+	return rc;
+}
+
+static int msm_dai_q6_mi2s_trigger(struct snd_pcm_substream *substream, int cmd,
+		struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+	u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		MI2S_RX : MI2S_TX);
+	int rc = 0;
+
+	dev_dbg(dai->dev, "%s: cmd:%d dai_data->status_mask = %ld",
+		__func__, cmd, *dai_data->status_mask);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+			afe_port_start_nowait(port_id,
+				&dai_data->port_config, dai_data->rate);
+			set_bit(STATUS_PORT_STARTED,
+				dai_data->status_mask);
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+			afe_port_stop_nowait(port_id);
+			clear_bit(STATUS_PORT_STARTED,
+				dai_data->status_mask);
+		}
+		break;
+
+	default:
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
+				     struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+	u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+		MI2S_RX : MI2S_TX);
+	int rc = 0;
+
+	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+		rc = afe_close(port_id);
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AFE port\n");
+		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+	}
+
+	if (!test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) &&
+	    !test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+		mi2s_dai_data->rate_constraint.list = NULL;
+		mi2s_dai_data->bitwidth_constraint.list = NULL;
+	}
+
+}
+
 static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai, int stream)
 {
@@ -134,121 +452,6 @@
 	return 0;
 }
 
-static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_hw_params *params,
-				    struct snd_soc_dai *dai, int stream)
-{
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-	struct msm_mi2s_data *mi2s_pdata =
-			(struct msm_mi2s_data *) dai->dev->platform_data;
-
-	dai_data->channels = params_channels(params);
-	if (num_of_bits_set(mi2s_pdata->sd_lines) == 1) {
-		switch (dai_data->channels) {
-		case 2:
-			dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
-			break;
-		case 1:
-			dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
-			break;
-		default:
-			pr_warn("greater than stereo has not been validated");
-			break;
-		}
-	}
-	dai_data->rate = params_rate(params);
-	/* Q6 only supports 16 as now */
-	dai_data->port_config.mi2s.bitwidth = 16;
-
-	pr_debug("%s: format = %d, channel = %d, line = %d\n",
-		   __func__, dai_data->port_config.mi2s.format,
-		   dai_data->port_config.mi2s.channel,
-		   dai_data->port_config.mi2s.line);
-	return 0;
-}
-
-static int msm_dai_q6_mi2s_platform_data_validation(
-					struct snd_soc_dai *dai)
-{
-	u8 num_of_sd_lines;
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-	struct msm_mi2s_data *mi2s_pdata =
-			(struct msm_mi2s_data *)dai->dev->platform_data;
-	struct snd_soc_dai_driver *dai_driver =
-			(struct snd_soc_dai_driver *)dai->driver;
-
-	num_of_sd_lines = num_of_bits_set(mi2s_pdata->sd_lines);
-
-	switch (num_of_sd_lines) {
-	case 1:
-		switch (mi2s_pdata->sd_lines) {
-		case MSM_MI2S_SD0:
-			dai_data->port_config.mi2s.line = AFE_I2S_SD0;
-			break;
-		case MSM_MI2S_SD1:
-			dai_data->port_config.mi2s.line = AFE_I2S_SD1;
-			break;
-		case MSM_MI2S_SD2:
-			dai_data->port_config.mi2s.line = AFE_I2S_SD2;
-			break;
-		case MSM_MI2S_SD3:
-			dai_data->port_config.mi2s.line = AFE_I2S_SD3;
-			break;
-		default:
-			pr_err("%s: invalid SD line\n",
-				   __func__);
-			goto error_invalid_data;
-		}
-		break;
-	case 2:
-		switch (mi2s_pdata->sd_lines) {
-		case MSM_MI2S_SD0 | MSM_MI2S_SD1:
-			dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
-			break;
-		case MSM_MI2S_SD2 | MSM_MI2S_SD3:
-			dai_data->port_config.mi2s.line = AFE_I2S_QUAD23;
-			break;
-		default:
-			pr_err("%s: invalid SD line\n",
-				   __func__);
-			goto error_invalid_data;
-		}
-		break;
-	case 3:
-		switch (mi2s_pdata->sd_lines) {
-		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2:
-			dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
-			break;
-		default:
-			pr_err("%s: invalid SD lines\n",
-				   __func__);
-			goto error_invalid_data;
-		}
-		break;
-	case 4:
-		switch (mi2s_pdata->sd_lines) {
-		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
-			dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
-			break;
-		default:
-			pr_err("%s: invalid SD lines\n",
-				   __func__);
-			goto error_invalid_data;
-		}
-		break;
-	default:
-		pr_err("%s: invalid SD lines\n", __func__);
-		goto error_invalid_data;
-	}
-	if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
-		dai_driver->playback.channels_max = num_of_sd_lines << 1;
-	else if (mi2s_pdata->capability == MSM_MI2S_CAP_TX)
-		dai_driver->capture.channels_max = num_of_sd_lines << 1;
-	return 0;
-
-error_invalid_data:
-	return -EINVAL;
-}
-
 static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
@@ -384,10 +587,7 @@
 	case SECONDARY_I2S_RX:
 		rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
 		break;
-	case MI2S_RX:
-	case MI2S_TX:
-		rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
-		break;
+
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
 	case SLIMBUS_0_TX:
@@ -766,43 +966,68 @@
 
 	return 0;
 }
+
 static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
 {
-	struct msm_dai_q6_dai_data *dai_data;
-	struct msm_mi2s_data *mi2s_pdata =
-			(struct msm_mi2s_data *)dai->dev->platform_data;
-	const struct snd_kcontrol_new *kcontrol;
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct snd_kcontrol *kcontrol = NULL;
 	int rc = 0;
 
-	dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
-		GFP_KERNEL);
+	if (mi2s_dai_data->rx_dai.port_config.mi2s.line) {
+		kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
+					&mi2s_dai_data->rx_dai);
+		rc = snd_ctl_add(dai->card->snd_card, kcontrol);
 
-	if (!dai_data) {
-		dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
-		dai->id);
-		rc = -ENOMEM;
-		goto rtn;
-	} else
-		dev_set_drvdata(dai->dev, dai_data);
-
-	rc = msm_dai_q6_mi2s_platform_data_validation(dai);
-	if (rc != 0) {
-		pr_err("%s: The msm_dai_q6_mi2s_platform_data_validation failed\n",
-			    __func__);
-		kfree(dai_data);
-		goto rtn;
+		if (IS_ERR_VALUE(rc)) {
+			dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
+			goto rtn;
+		}
 	}
-	if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
-		kcontrol = &mi2s_config_controls[0];
-	else
-		kcontrol = &mi2s_config_controls[2];
 
-	rc = snd_ctl_add(dai->card->snd_card,
-					 snd_ctl_new1(kcontrol, dai_data));
+	if (mi2s_dai_data->tx_dai.port_config.mi2s.line) {
+		rc = snd_ctl_add(dai->card->snd_card,
+				 snd_ctl_new1(&mi2s_config_controls[2],
+					      &mi2s_dai_data->tx_dai));
+
+		if (IS_ERR_VALUE(rc)) {
+			if (kcontrol)
+				snd_ctl_remove(dai->card->snd_card, kcontrol);
+			dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
+		}
+	}
+
 rtn:
 	return rc;
 }
 
+static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
+		dev_get_drvdata(dai->dev);
+	int rc;
+
+	/* If AFE port is still up, close it */
+	if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+		rc = afe_close(MI2S_RX); /* can block */
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close MI2S_RX port\n");
+		clear_bit(STATUS_PORT_STARTED,
+			  mi2s_dai_data->rx_dai.status_mask);
+	}
+	if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->tx_dai.status_mask)) {
+		rc = afe_close(MI2S_TX); /* can block */
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close MI2S_TX port\n");
+		clear_bit(STATUS_PORT_STARTED,
+			  mi2s_dai_data->tx_dai.status_mask);
+	}
+	kfree(mi2s_dai_data);
+	snd_soc_unregister_dai(dai->dev);
+
+	return 0;
+}
+
 static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
 {
 	struct msm_dai_q6_dai_data *dai_data;
@@ -866,8 +1091,6 @@
 	switch (dai->id) {
 	case PRIMARY_I2S_TX:
 	case PRIMARY_I2S_RX:
-	case MI2S_RX:
-	case MI2S_TX:
 	case SECONDARY_I2S_RX:
 		rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
 		break;
@@ -947,6 +1170,15 @@
 	return rc;
 }
 
+static struct snd_soc_dai_ops msm_dai_q6_mi2s_ops = {
+	.startup	= msm_dai_q6_mi2s_startup,
+	.prepare	= msm_dai_q6_mi2s_prepare,
+	.trigger	= msm_dai_q6_mi2s_trigger,
+	.hw_params	= msm_dai_q6_mi2s_hw_params,
+	.shutdown	= msm_dai_q6_mi2s_shutdown,
+	.set_fmt	= msm_dai_q6_mi2s_set_fmt,
+};
+
 static struct snd_soc_dai_ops msm_dai_q6_ops = {
 	.prepare	= msm_dai_q6_prepare,
 	.trigger	= msm_dai_q6_trigger,
@@ -1169,32 +1401,25 @@
 	.remove = msm_dai_q6_dai_auxpcm_remove,
 };
 
-static struct snd_soc_dai_driver msm_dai_q6_mi2s_rx_dai = {
+/* Channel min and max are initialized base on platform data */
+static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
 		SNDRV_PCM_RATE_16000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		.channels_min = 1,
 		.rate_min =     8000,
 		.rate_max =	48000,
 	},
-	.ops = &msm_dai_q6_ops,
-	.probe = msm_dai_q6_dai_mi2s_probe,
-	.remove = msm_dai_q6_dai_probe,
-};
-
-static struct snd_soc_dai_driver msm_dai_q6_mi2s_tx_dai = {
 	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
 		SNDRV_PCM_RATE_16000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		.channels_min = 1,
-		.rate_min = 8000,
-		.rate_max = 48000,
+		.rate_min =     8000,
+		.rate_max =     48000,
 	},
-	.ops = &msm_dai_q6_ops,
+	.ops = &msm_dai_q6_mi2s_ops,
 	.probe = msm_dai_q6_dai_mi2s_probe,
-	.remove = msm_dai_q6_dai_remove,
+	.remove = msm_dai_q6_dai_mi2s_remove,
 };
 
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
@@ -1264,14 +1489,7 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_aux_pcm_tx_dai);
 		break;
-	case MI2S_RX:
-		rc = snd_soc_register_dai(&pdev->dev,
-					&msm_dai_q6_mi2s_rx_dai);
-		break;
-	case MI2S_TX:
-		rc = snd_soc_register_dai(&pdev->dev,
-					&msm_dai_q6_mi2s_tx_dai);
-		break;
+
 	case SLIMBUS_0_RX:
 	case SLIMBUS_4_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
@@ -1338,6 +1556,49 @@
 	return 0;
 }
 
+static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
+{
+	struct msm_dai_q6_mi2s_dai_data *dai_data;
+	int rc = 0;
+
+	dev_dbg(&pdev->dev, "%s: pdev %p dev %p\n", __func__, pdev, &pdev->dev);
+
+	dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
+		GFP_KERNEL);
+
+	if (!dai_data) {
+		dev_err(&pdev->dev, "fail to allocate dai data\n");
+		rc = -ENOMEM;
+		goto rtn;
+	} else
+		dev_set_drvdata(&pdev->dev, dai_data);
+
+	rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
+						      &msm_dai_q6_mi2s_dai);
+	if (IS_ERR_VALUE(rc))
+		goto err_pdata;
+
+	dai_data->rate_constraint.count = 1;
+	dai_data->bitwidth_constraint.count = 1;
+	rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
+
+	if (IS_ERR_VALUE(rc))
+		goto err_pdata;
+
+	return 0;
+
+err_pdata:
+	kfree(dai_data);
+rtn:
+	return rc;
+}
+
+static __devexit int msm_dai_q6_mi2s_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&pdev->dev);
+	return 0;
+}
+
 static struct platform_driver msm_dai_q6_driver = {
 	.probe  = msm_dai_q6_dev_probe,
 	.remove = msm_dai_q6_dev_remove,
@@ -1347,9 +1608,30 @@
 	},
 };
 
+static struct platform_driver msm_dai_q6_mi2s_driver = {
+	.probe  = msm_dai_q6_mi2s_dev_probe,
+	.remove = msm_dai_q6_mi2s_dev_remove,
+	.driver = {
+		.name = "msm-dai-q6-mi2s",
+		.owner = THIS_MODULE,
+	},
+};
+
 static int __init msm_dai_q6_init(void)
 {
-	return platform_driver_register(&msm_dai_q6_driver);
+	int rc1, rc2;
+
+	rc1 = platform_driver_register(&msm_dai_q6_mi2s_driver);
+
+	if (IS_ERR_VALUE(rc1))
+		pr_err("%s: fail to register mi2s dai driver\n", __func__);
+
+	rc2 = platform_driver_register(&msm_dai_q6_driver);
+
+	if (IS_ERR_VALUE(rc2))
+		pr_err("%s: fail to register mi2s dai driver\n", __func__);
+
+	return (IS_ERR_VALUE(rc1) && IS_ERR_VALUE(rc2)) ? -1 : 0;
 }
 module_init(msm_dai_q6_init);
 
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index a6a3266..2a73fd6 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -48,6 +48,7 @@
 	unsigned long   vers;
 	unsigned long   vers2;
 	unsigned long   rpc_set_snd_device;
+	unsigned long	rpc_set_device_vol;
 	int device;
 };
 
@@ -125,6 +126,7 @@
 	 * index for snd_set_device
 	 */
 	snd_rpc_ids.rpc_set_snd_device = 2;
+	snd_rpc_ids.rpc_set_device_vol = 3;
 	return 0;
 }
 
@@ -235,6 +237,67 @@
 	return rc;
 }
 
+static int snd_msm_device_vol_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2; /* Device/Volume */
+
+	/*
+	 * The number of devices supported is 37 (0 to 36)
+	 */
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 36;
+	return 0;
+}
+
+static int snd_msm_device_vol_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	struct snd_vol_req {
+		struct rpc_request_hdr hdr;
+		uint32_t device;
+		uint32_t method;
+		uint32_t volume;
+		uint32_t cb_func;
+		uint32_t client_data;
+	} req;
+
+	snd_rpc_ids.device = (int)ucontrol->value.integer.value[0];
+
+	if ((ucontrol->value.integer.value[1] < 0) ||
+		(ucontrol->value.integer.value[1] > 6)) {
+		pr_err("Device volume should be in range of 1 to 6\n");
+		return -EINVAL;
+	}
+	if ((ucontrol->value.integer.value[0] > 36) ||
+		(ucontrol->value.integer.value[0] < 0)) {
+		pr_err("Device range supported is 0 to 36\n");
+		return -EINVAL;
+	}
+
+	req.device = cpu_to_be32((int)ucontrol->value.integer.value[0]);
+	req.method = cpu_to_be32(0);
+	req.volume = cpu_to_be32((int)ucontrol->value.integer.value[1]);
+	req.cb_func = -1;
+	req.client_data = cpu_to_be32(0);
+
+	rc = msm_rpc_call(snd_ep, snd_rpc_ids.rpc_set_device_vol ,
+			&req, sizeof(req), 5 * HZ);
+
+	if (rc < 0) {
+		printk(KERN_ERR "%s: snd rpc call failed! rc = %d\n",
+			__func__, rc);
+	} else {
+		printk(KERN_ERR "%s: device [%d] volume set to [%d]\n",
+				__func__, (int)ucontrol->value.integer.value[0],
+				(int)ucontrol->value.integer.value[1]);
+	}
+
+	return rc;
+}
+
 /* Supported range -50dB to 18dB */
 static const DECLARE_TLV_DB_LINEAR(db_scale_linear, -5000, 1800);
 
@@ -262,6 +325,8 @@
 	snd_msm_volume_get, snd_msm_volume_put, 0, db_scale_linear),
 	MSM_EXT("device", 0, snd_msm_device_info, snd_msm_device_get, \
 						 snd_msm_device_put, 0),
+	MSM_EXT("Device Volume", 0, snd_msm_device_vol_info, NULL, \
+						 snd_msm_device_vol_put, 0),
 };
 
 static int msm_new_mixer(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 40f81e8..f78f58d 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1370,6 +1370,7 @@
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla1x_codec",
 		.codec_dai_name = "tabla_tx2",
+		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ops = &msm8960_be_ops,
 	},
@@ -1410,6 +1411,7 @@
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx2",
+		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ops = &msm8960_be_ops,
 	},