Merge changes Ifc63c2cf,I688b711e into msm-3.4

* changes:
  defconfig: msm8960: Enable HCIUART for AR3002 support
  msm: 8960: Add AR3002 Bluetooth Support
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
new file mode 100644
index 0000000..6db1150
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -0,0 +1,140 @@
+Qualcomm mdss-dsi-panel
+
+mdss-dsi-panel is a dsi panel driver which supports panels that
+are compatable with MIPI display serial interface specification.
+
+Required properties:
+- compatible:				Must be "qcom,mdss-dsi-panel"
+- status:        			A string that has to be set to "okay/ok" to enable
+					the panel driver. By default this property will be
+					set to "disable". Will be set to "ok/okay" status
+					for specific platforms.
+- qcom,mdss-pan-res:			A two dimensional array that specifies the panel
+					resolution.
+- qcom,mdss-pan-bpp:			Specifies the panel bits per pixel. Default value is 24(rgb888).
+					18 = for rgb666
+					16 = for rgb565
+- qcom,mdss-panel-on-cmds:		An array of variable length that lists the init commands
+					of the panel. Each command will have the format specified
+					as below:
+					--> data type of the command
+					--> specifies whether this command packet is last.
+					--> virtual channel
+					--> Needs acknowledge from the panel or not.
+					--> wait time after the command is transmitter.
+					--> size of payload
+					--> payload.
+- qcom,mdss-panel-off-cmds:		An array of variable length that lists the panel off
+					commands. Each command will have the format specified
+					as below:
+					--> data type of the command
+					--> specifies whether this command packet is last.
+					--> virtual channel
+					--> Needs acknowledge from the panel or not.
+					--> wait time after the command is transmitter.
+					--> size of payload
+					--> payload.
+
+Required structure:
+- A qcom,mdss-dsi-panel node must be a child of an mdss-dsi controller node that links to
+    one of the two DSI controllers.
+
+
+Optional properties:
+- label:		        	A string used as a descriptive name of the panel
+- qcom,mdss-pan-porch-values:		An array of size 6 that specifies the panel blanking values.
+- qcom,mdss-pan-underflow-clr:		Specifies the controller settings for the panel underflow clear
+					settings. Default value is 0xff.
+- qcom,mdss-pan-bl-levels:		Specifies the backlight levels supported by the panel.
+					Default range is 1 to 255.
+
+- qcom,mdss-pan-dsi-mode:		Specifies the panel operating mode.
+					0 = enable video mode(default mode).
+					1 = enable command mode.
+- qcom,mdss-pan-dsi-h-pulse-mode:	Specifies the pulse mode option for the panel.
+					0 = Don't send hsa/he following vs/ve packet(default)
+					1 = Send hsa/he following vs/ve packet
+- qcom,mdss-pan-dsi-h-power-stop:	An Array of size 3 that specifies the power mode
+					during horizontal porch and sync periods of the panel.
+					0 = high speed mode(default mode).
+					1 = Low power mode for horizontal porches and sync pulse.
+- qcom,mdss-pan-dsi-bllp-power-stop:	An Array of size 2 that specifies the power mode
+					during blanking period and after EOF(end of frame).
+					0 = high speed mode(default mode).
+					1 = Low power mode during blanking and EOF.
+- qcom,mdss-pan-dsi-traffic-mode:	Specifies the panel traffic mode.
+					0 = non burst with sync pulses (default mode).
+					1 = non burst with sync start event.
+					2 = burst mode.
+- qcom,mdss-pan-dsi-dst-format:		Specifies the destination format.
+					0 = DSI_VIDEO_DST_FORMAT_RGB565.
+					1 = DSI_VIDEO_DST_FORMAT_RGB666.
+					2 = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE.
+					3 = DSI_VIDEO_DST_FORMAT_RGB888 (Default format)
+					6 = DSI_CMD_DST_FORMAT_RGB565
+					7 = DSI_CMD_DST_FORMAT_RGB666
+					8 = DSI_CMD_DST_FORMAT_RGB888
+- qcom,mdss-pan-dsi-vc:			Specifies the virtual channel identefier.
+					0 = default value.
+- qcom,mdss-pan-dsi-rgb-swap:		Specifies the R, G and B channel ordering.
+					0 = DSI_RGB_SWAP_RGB (default value)
+					1 = DSI_RGB_SWAP_RBG
+					2 = DSI_RGB_SWAP_BGR
+					3 = DSI_RGB_SWAP_BRG
+					4 = DSI_RGB_SWAP_GRB
+					5 = DSI_RGB_SWAP_GBR
+- qcom,mdss-pan-dsi-data-lanes:		An array that specifies the data lanes enabled.
+					<1 1 0 0> = data lanes 1 and 2 are enabled.(default).
+- qcom,mdss-pan-dsi-t-clk:		An array that specifies the byte clock cycles
+					before and after each mode switch.
+- qcom,mdss-pan-dsi-stream:		Specifies the packet stream to be used.
+					0 = stream 0 (default)
+					1 = stream 1
+- qcom,mdss-pan-dsi-mdp-tr:		Specifies the trigger mechanism to be used for MDP path.
+					0 = no trigger
+					2 = Tear check signal line used for trigger
+					4 = Triggered by software (default mode)
+					6 = Software trigger and TE
+- qcom,mdss-pan-dsi-dma-tr:		Specifies the trigger mechanism to be used for DMA path.
+					0 = no trigger
+					2 = Tear check signal line used for trigger
+					4 = Triggered by software (default mode)
+					5 = Software trigger and start/end of frame trigger.
+					6 = Software trigger and TE
+- qcom,mdss-pan-dsi-frame-rate:		Specifies the frame rate for the panel.
+					60 = 60 frames per second (default)
+
+Note, if a given optional qcom,* binding is not present, then the driver will configure
+the default values specified.
+
+Example:
+	qcom,mdss_dsi@fd922800 {
+
+		qcom,mdss_dsi_sim_video {
+			compatible = "qcom,mdss-dsi-panel";
+			label = "simulator video mode dsi panel";
+			status = "disable";
+			qcom,mdss-pan-res = <640 480>;
+			qcom,mdss-pan-bpp = <24>;
+			qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
+			qcom,mdss-pan-underflow-clr = <0xff>;
+			qcom,mdss-pan-bl-levels = <1 15>;
+			qcom,mdss-pan-dsi-mode = <0>;
+			qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+			qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
+			qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+			qcom,mdss-pan-dsi-traffic-mode = <0>;
+			qcom,mdss-pan-dsi-dst-format = <3>;
+			qcom,mdss-pan-dsi-vc = <0>;
+			qcom,mdss-pan-dsi-rgb-swap = <0>;
+			qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+			qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
+			qcom,mdss-pan-dsi-stream = <0>;
+			qcom,mdss-pan-dsi-mdp-tr = <0x04>;
+			qcom,mdss-pan-dsi-dma-tr = <0x04>;
+			qcom,mdss-pan-frame-rate = <60>;
+			qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
+			qcom,panel-off-cmds = [22 01 00 00 00 00 00];
+		};
+
+	};
diff --git a/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt b/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
index 1549f10..e212aca 100644
--- a/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
+++ b/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
@@ -18,6 +18,7 @@
 		    "ocmem_irq" corresponds to OCMEM Error Interrupt.
 		    "dm_irq" corresponds to DM Interrupt.
 - qcom,ocmem-num-regions: The number of OCMEM hardware memory regions.
+- qcom,resource-type: The hardware resource type of the OCMEM core.
 
 In addition to the information on the OCMEM core, the
 device tree contains additional information describing partitions
@@ -51,6 +52,7 @@
 		interrupts = <0 76 0 0 77 0>;
 		interrupt-names = "ocmem_irq", "dm_irq";
 		qcom,ocmem-num-regions = <0x3>;
+		qcom,resource-type = <0x706d636f>
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x0 0xfec00000 0x180000>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 70c85c6..f144421 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -216,6 +216,7 @@
 		interrupts = <0 163 0 0 164 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
+		qcom,rxreg-access;
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 314f91b..00325c9 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -218,7 +218,6 @@
 # CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_DIAG_CHAR=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MSM is not set
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index aad13b8..5c5a152 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -238,7 +238,6 @@
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_DIAG_CHAR=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 5d19237..0efe658 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -282,7 +282,6 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
-CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MSM is not set
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 28d6e60..ca3e996 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -651,7 +651,8 @@
 
 	cpumask_copy(&mask, cpu_online_mask);
 	cpumask_clear_cpu(smp_processor_id(), &mask);
-	smp_cross_call(&mask, IPI_CPU_STOP);
+	if (!cpumask_empty(&mask))
+		smp_cross_call(&mask, IPI_CPU_STOP);
 
 	/* Wait up to one second for other CPUs to stop */
 	timeout = USEC_PER_SEC;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 54f3292..1665abd 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2298,6 +2298,33 @@
 	  Enable support for On-Chip Memory available on certain MSM chipsets.
 	  OCMEM is a low latency, high performance pool shared by subsystems.
 
+config MSM_OCMEM_LOCAL_POWER_CTRL
+	bool "OCMEM Local Power Control"
+	depends on MSM_OCMEM
+	help
+	  Enable direct power management of the OCMEM core by the
+	  OCMEM driver. By default power management is delegated to
+	  the RPM. Selecting this option causes the OCMEM driver to
+	  directly handle the various macro power transitions.
+
+config MSM_OCMEM_DEBUG
+	bool "OCMEM Debug Support"
+	depends on MSM_OCMEM
+	help
+	  Enable debug options for On-chip Memory (OCMEM) driver.
+	  Various debug options include memory, power and latency.
+	  Choosing one of these options allows debugging of each
+	  individual subsystem separately.
+
+config MSM_OCMEM_POWER_DEBUG
+	bool "OCMEM Power Debug Support"
+	depends on MSM_OCMEM_DEBUG
+	help
+	  Enable debug support for OCMEM power management.
+	  This adds support for verifying all power management
+	  related operations of OCMEM. Both local power management
+	  and RPM assisted power management operations are supported.
+
 config MSM_RTB
 	bool "Register tracing"
 	help
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b6ce351..b96ccec 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -336,7 +336,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
 endif
 obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
-obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o ocmem_core.o
 
 obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 639cc94..09a1be7 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -249,14 +249,16 @@
 /* 8625 PLL4 @ 1209MHz with GSM capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_1209[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
-	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 1, 61440 },
-	{ 1, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 2, 61440 },
-	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
-	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
-	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
-	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
-	{ 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 160000 },
-	{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
+	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 0, 61440 },
+	{ 0, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 1, 61440 },
+	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 1, 61440 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 2, 122880 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[2]},
 	{ 0 }
 };
 
@@ -264,13 +266,14 @@
 static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1209[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
 	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
-	{ 1, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
+	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
 	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
-	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
-	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
-	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
-	{ 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 160000 },
-	{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[2]},
 	{ 0 }
 };
 
@@ -725,7 +728,7 @@
 		if ((delta > drv_state.max_speed_delta_khz)
 				|| (strt_s->pll == ACPU_PLL_4 &&
 					tgt_s->pll == ACPU_PLL_4))
-			clk_disable_unprepare(pll_clk[backup_s->pll].clk);
+			clk_disable(pll_clk[backup_s->pll].clk);
 
 		goto done;
 	}
@@ -959,17 +962,31 @@
 		}
 	}
 
+	if (acpu_freq_tbl == NULL) {
+		pr_crit("Unknown PLL configuration!\n");
+		BUG();
+	}
+
 	/*
-	 * When PLL4 can run max @ 1401.6MHz, we have to support
-	 * dynamic reprograming of PLL4.
-	 *
+	 * Turn ON the dynamic reprogramming method
+	 * if one of the table entry has pll_rate defined.
+	 */
+	for ( ; t->tbl->a11clk_khz; t->tbl++) {
+		if (t->tbl->pll_rate) {
+			if (!dynamic_reprogram) {
+				dynamic_reprogram = 1;
+				pr_info("Dynamic reprogramming is ON\n");
+			}
+		}
+	}
+
+	/*
 	 * Also find the backup pll used during PLL4 reprogramming.
 	 * We are using PLL2@600MHz as backup PLL, since 800MHz jump
 	 * is fine.
 	 */
-	if (t->pll4_rate == 1401) {
-		dynamic_reprogram = 1;
-		for ( ; t->tbl->a11clk_khz; t->tbl++) {
+	if (dynamic_reprogram) {
+		for (t->tbl = acpu_freq_tbl; t->tbl->a11clk_khz; t->tbl++) {
 			if (t->tbl->pll == ACPU_PLL_2 &&
 					t->tbl->a11clk_src_div == 1) {
 				backup_s = t->tbl;
@@ -977,11 +994,6 @@
 			}
 		}
 	}
-
-	if (acpu_freq_tbl == NULL) {
-		pr_crit("Unknown PLL configuration!\n");
-		BUG();
-	}
 }
 
 /*
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d6217022..da849c8 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2264,7 +2264,6 @@
 	&msm_bus_8064_cpss_fpb,
 	&apq8064_msm_device_vidc,
 	&msm_pil_dsps,
-	&msm_8960_riva,
 	&msm_8960_q6_lpass,
 	&msm_pil_vidc,
 	&msm_gss,
@@ -2954,7 +2953,10 @@
 	platform_device_register(&apq8064_slim_ctrl);
 	slim_register_board_info(apq8064_slim_devices,
 		ARRAY_SIZE(apq8064_slim_devices));
-	apq8064_init_dsps();
+	if (!PLATFORM_IS_MPQ8064()) {
+		apq8064_init_dsps();
+		platform_device_register(&msm_8960_riva);
+	}
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
 	msm_spm_l2_init(msm_spm_l2_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 658b3dc..7dd3829 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4960,14 +4960,19 @@
 	CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c, ""),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c,
+						"msm-dai-q6.4106"),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
+						"msm-dai-q6.4106"),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
 	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk_src", audio_core_lpaif_pcmoe_clk_src.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pcmoe_clk.c, ""),
+	CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c,
+						"msm-dai-q6.4106"),
+	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
+						"msm-dai-q6.4106"),
 
 	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c, "pil-q6v5-mss"),
 	CLK_LOOKUP("bus_clk",       mss_bus_q6_clk.c, "pil-q6v5-mss"),
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 8a5d0e8..a6473c6 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -26,7 +26,7 @@
 #include <mach/dma.h>
 #include <mach/board.h>
 #include <asm/clkdev.h>
-
+#include <linux/ion.h>
 #include "devices.h"
 #include "footswitch.h"
 
@@ -963,8 +963,8 @@
 };
 
 struct msm_vidc_platform_data vidc_platform_data = {
-	.memtype = MEMTYPE_EBI0,
-	.enable_ion = 0,
+	.memtype = ION_CAMERA_HEAP_ID,
+	.enable_ion = 1,
 	.disable_dmx = 0,
 	.cont_mode_dpb_count = 8
 };
diff --git a/arch/arm/mach-msm/include/mach/cpuidle.h b/arch/arm/mach-msm/include/mach/cpuidle.h
index 2a5aa97..8566e7f 100644
--- a/arch/arm/mach-msm/include/mach/cpuidle.h
+++ b/arch/arm/mach-msm/include/mach/cpuidle.h
@@ -25,12 +25,16 @@
 	enum msm_pm_sleep_mode mode_nr;
 };
 
-#ifdef CONFIG_CPU_IDLE
+#ifdef CONFIG_PM
 s32 msm_cpuidle_get_deep_idle_latency(void);
+#else
+static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
+#endif
+
+#ifdef CONFIG_CPU_IDLE
 int msm_cpuidle_init(void);
 #else
 static inline int msm_cpuidle_init(void) { return -ENOSYS; }
-static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
 #endif
 
 #ifdef CONFIG_MSM_SLEEP_STATS
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index 415f8ed..904de5e 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -47,6 +47,24 @@
 	struct ocmem_chunk chunks[OCMEM_MAX_CHUNKS];
 };
 
+enum ocmem_power_state {
+	OCMEM_OFF = 0x0,
+	OCMEM_RETENTION,
+	OCMEM_ON,
+	OCMEM_MAX = OCMEM_ON,
+};
+
+struct ocmem_resource {
+	unsigned resource_id;
+	unsigned num_keys;
+	unsigned int *keys;
+};
+
+struct ocmem_vectors {
+	unsigned num_resources;
+	struct ocmem_resource *r;
+};
+
 /* List of clients that allocate/interact with OCMEM */
 /* Must be in sync with client_names */
 enum ocmem_client {
@@ -120,4 +138,14 @@
 int ocmem_evict(int client_id);
 
 int ocmem_restore(int client_id);
+
+/* Power Control APIs */
+int ocmem_set_power_state(int client_id, struct ocmem_buf *buf,
+				enum ocmem_power_state new_state);
+
+enum ocmem_power_state ocmem_get_power_state(int client_id,
+				struct ocmem_buf *buf);
+
+struct ocmem_vectors *ocmem_get_vectors(int client_id,
+						struct ocmem_buf *buf);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 70b5a45..49e283d 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -16,11 +16,11 @@
 /** All interfaces in this header should only be used by OCMEM driver
  *  Client drivers should use wrappers available in ocmem.h
  **/
-
-#include "ocmem.h"
-#include <mach/msm_iomap.h>
-#include <asm/io.h>
 #include <linux/platform_device.h>
+#include <asm/io.h>
+#include <mach/msm_iomap.h>
+#include "ocmem.h"
+
 
 #define OCMEM_PHYS_BASE 0xFEC00000
 #define OCMEM_PHYS_SIZE 0x180000
@@ -62,6 +62,13 @@
 	SCHED_DUMP,
 };
 
+/* Operational modes of each region */
+enum region_mode {
+	WIDE_MODE = 0x0,
+	THIN_MODE,
+	MODE_DEFAULT = WIDE_MODE,
+};
+
 struct ocmem_plat_data {
 	void __iomem *vbase;
 	unsigned long size;
@@ -77,6 +84,8 @@
 	int ocmem_irq;
 	int dm_irq;
 	bool interleaved;
+	bool rpm_pwr_ctrl;
+	unsigned rpm_rsc_type;
 };
 
 struct ocmem_eviction_data {
@@ -113,6 +122,8 @@
 	unsigned long req_start;
 	unsigned long req_end;
 	unsigned long req_sz;
+	/* Request Power State */
+	unsigned power_state;
 	struct ocmem_eviction_data *edata;
 };
 
@@ -154,6 +165,18 @@
 		return NULL;
 }
 
+/* Simple wrappers which will have debug features added later */
+static inline int ocmem_read(void *at)
+{
+	return readl_relaxed(at);
+}
+
+static inline int ocmem_write(unsigned long val, void *at)
+{
+	writel_relaxed(val, at);
+	return 0;
+}
+
 struct ocmem_zone *get_zone(unsigned);
 unsigned long offset_to_phys(unsigned long);
 unsigned long phys_to_offset(unsigned long);
@@ -170,6 +193,7 @@
 
 int ocmem_sched_init(void);
 int ocmem_rdm_init(struct platform_device *);
+int ocmem_core_init(struct platform_device *);
 int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
 			unsigned long, bool, bool);
 int process_free(int, struct ocmem_handle *);
@@ -180,4 +204,6 @@
 int ocmem_rdm_transfer(int, struct ocmem_map_list *,
 				unsigned long, int);
 unsigned long process_quota(int);
+int ocmem_memory_off(int, unsigned long, unsigned long);
+int ocmem_memory_on(int, unsigned long, unsigned long);
 #endif
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index e74af2e..07f3efc 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -44,7 +44,7 @@
 
 #define MDM_PBLRDY_CNT		20
 
-static int mdm_debug_on;
+static int mdm_debug_mask;
 static int power_on_count;
 static int hsic_peripheral_status;
 static DEFINE_MUTEX(hsic_status_lock);
@@ -234,7 +234,7 @@
 
 static void debug_state_changed(int value)
 {
-	mdm_debug_on = value;
+	mdm_debug_mask = value;
 }
 
 static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index d1865e4..6ca9045 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -49,10 +49,11 @@
 #define MDM_RDUMP_TIMEOUT	120000L
 #define MDM2AP_STATUS_TIMEOUT_MS 60000L
 
-static int mdm_debug_on;
+static unsigned int mdm_debug_mask;
 static struct workqueue_struct *mdm_queue;
 static struct workqueue_struct *mdm_sfr_queue;
 static unsigned int dump_timeout_ms;
+static int vddmin_gpios_sent;
 
 #define EXTERNAL_MODEM "external_modem"
 
@@ -100,6 +101,7 @@
 	if (!vddmin_res)
 		return;
 
+	pr_info("Enabling vddmin logging\n");
 	req.id = vddmin_res->rpm_id;
 	req.value = ((uint32_t)vddmin_res->ap2mdm_vddmin_gpio & 0x0000FFFF)
 							<< 16;
@@ -108,7 +110,7 @@
 
 	msm_rpm_set(MSM_RPM_CTX_SET_0, &req, 1);
 
-	/* Monitor low power gpio from mdm */
+	/* Start monitoring low power gpio from mdm */
 	irq = MSM_GPIO_TO_INT(vddmin_res->mdm2ap_vddmin_gpio);
 	if (irq < 0) {
 		pr_err("%s: could not get LPM POWER IRQ resource.\n",
@@ -478,23 +480,33 @@
 	.name = EXTERNAL_MODEM,
 };
 
-static int mdm_debug_on_set(void *data, u64 val)
+/* Once the gpios are sent to RPM and debugging
+ * starts, there is no way to stop it without
+ * rebooting the device.
+ */
+static int mdm_debug_mask_set(void *data, u64 val)
 {
-	mdm_debug_on = val;
+	if (!vddmin_gpios_sent &&
+		(val & MDM_DEBUG_MASK_VDDMIN_SETUP)) {
+		mdm_setup_vddmin_gpios();
+		vddmin_gpios_sent = 1;
+	}
+
+	mdm_debug_mask = val;
 	if (mdm_drv->ops->debug_state_changed_cb)
-		mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
+		mdm_drv->ops->debug_state_changed_cb(mdm_debug_mask);
 	return 0;
 }
 
-static int mdm_debug_on_get(void *data, u64 *val)
+static int mdm_debug_mask_get(void *data, u64 *val)
 {
-	*val = mdm_debug_on;
+	*val = mdm_debug_mask;
 	return 0;
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_on_fops,
-			mdm_debug_on_get,
-			mdm_debug_on_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_mask_fops,
+			mdm_debug_mask_get,
+			mdm_debug_mask_set, "%llu\n");
 
 static int mdm_debugfs_init(void)
 {
@@ -504,8 +516,8 @@
 	if (IS_ERR(dent))
 		return PTR_ERR(dent);
 
-	debugfs_create_file("debug_on", 0644, dent, NULL,
-			&mdm_debug_on_fops);
+	debugfs_create_file("debug_mask", 0644, dent, NULL,
+			&mdm_debug_mask_fops);
 	return 0;
 }
 
@@ -601,7 +613,7 @@
 
 	mdm_modem_initialize_data(pdev, p_mdm_cb);
 	if (mdm_drv->ops->debug_state_changed_cb)
-		mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
+		mdm_drv->ops->debug_state_changed_cb(mdm_debug_mask);
 
 	gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
 	gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
@@ -737,8 +749,6 @@
 	 */
 	if (mdm_drv->ap2mdm_pmic_pwr_en_gpio > 0)
 		gpio_direction_output(mdm_drv->ap2mdm_pmic_pwr_en_gpio, 1);
-	/* Register VDDmin gpios with RPM */
-	mdm_setup_vddmin_gpios();
 
 	/* Perform early powerup of the external modem in order to
 	 * allow tabla devices to be found.
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index 7aba83d..d1e85d3 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -13,6 +13,7 @@
 #ifndef _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
 #define _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
 
+#define MDM_DEBUG_MASK_VDDMIN_SETUP (0x00000002)
 struct mdm_modem_drv;
 
 struct mdm_ops {
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 753f6fb..a9c3f4c 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -24,14 +24,8 @@
 #include <linux/seq_file.h>
 #include <mach/ocmem_priv.h>
 
-/* This code is to temporarily work around the default state of OCMEM
-   regions in Virtio. These registers will be read from DT in a subsequent
-   patch which initializes the regions to appropriate default state.
-*/
-
 #define OCMEM_REGION_CTL_BASE 0xFDD0003C
 #define OCMEM_REGION_CTL_SIZE 0xFD0
-#define REGION_ENABLE 0x00003333
 #define GRAPHICS_REGION_CTL (0x17F000)
 
 struct ocmem_partition {
@@ -269,6 +263,30 @@
 	return i;
 }
 
+#if defined(CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL)
+static int parse_power_ctrl_config(struct ocmem_plat_data *pdata,
+					struct device_node *node)
+{
+	pdata->rpm_pwr_ctrl = false;
+	pdata->rpm_rsc_type = ~0x0;
+	return 0;
+}
+#else
+static int parse_power_ctrl_config(struct ocmem_plat_data *pdata,
+					struct device_node *node)
+{
+	unsigned rsc_type = ~0x0;
+	pdata->rpm_pwr_ctrl = false;
+	if (of_property_read_u32(node, "qcom,resource-type",
+					&rsc_type))
+		return -EINVAL;
+	pdata->rpm_pwr_ctrl = true;
+	pdata->rpm_rsc_type = rsc_type;
+	return 0;
+
+}
+#endif /* CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL */
+
 static struct ocmem_plat_data *parse_dt_config(struct platform_device *pdev)
 {
 	struct device   *dev = &pdev->dev;
@@ -393,6 +411,11 @@
 	} else
 		dev_dbg(dev, "Found %d ocmem partitions\n", nr_parts);
 
+	if (parse_power_ctrl_config(pdata, node)) {
+		dev_err(dev, "No OCMEM RPM Resource specified\n");
+		return NULL;
+	}
+
 	pdata->nr_parts = nr_parts;
 	pdata->parts = parts;
 	pdata->nr_regions = nr_regions;
@@ -516,6 +539,9 @@
 
 	platform_set_drvdata(pdev, ocmem_pdata);
 
+	if (ocmem_core_init(pdev))
+		return -EBUSY;
+
 	if (ocmem_zone_init(pdev))
 		return -EBUSY;
 
@@ -529,10 +555,7 @@
 							OCMEM_REGION_CTL_SIZE);
 	if (!ocmem_region_vbase)
 		return -EBUSY;
-	/* Enable all the 3 regions until we have support for power features */
-	writel_relaxed(REGION_ENABLE, ocmem_region_vbase);
-	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 4);
-	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 8);
+
 	/* Enable the ocmem graphics mpU as a workaround in Virtio */
 	/* This will be programmed by TZ after TZ support is integrated */
 	writel_relaxed(GRAPHICS_REGION_CTL, ocmem_region_vbase + 0xFCC);
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index bb32fca..a5aed5e 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -399,3 +399,22 @@
 	mutex_unlock(&ocmem_eviction_lock);
 	return ret;
 }
+
+/* Wrappers until power control is transitioned to clients */
+enum ocmem_power_state ocmem_get_power_state(int client_id,
+						struct ocmem_buf *buffer)
+{
+	return 0;
+}
+
+int ocmem_set_power_state(int client_id, struct ocmem_buf *buffer,
+					enum ocmem_power_state new_state)
+{
+	return 0;
+}
+
+struct ocmem_vectors *ocmem_get_vectors(int client_id,
+				struct ocmem_buf *buffer)
+{
+	return NULL;
+}
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
new file mode 100644
index 0000000..019f59f
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -0,0 +1,708 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/ocmem_priv.h>
+#include <mach/rpm-smd.h>
+
+static unsigned num_regions;
+static unsigned num_macros;
+static unsigned num_ports;
+static unsigned num_banks;
+
+static unsigned long macro_size;
+static unsigned long region_size;
+
+static bool rpm_power_control;
+
+struct ocmem_hw_macro {
+	atomic_t m_on[OCMEM_CLIENT_MAX];
+	atomic_t m_retain[OCMEM_CLIENT_MAX];
+	unsigned m_state;
+};
+
+struct ocmem_hw_region {
+	unsigned psgsc_ctrl;
+	bool interleaved;
+	unsigned int mode;
+	unsigned int num_macros;
+	struct ocmem_hw_macro *macro;
+	struct msm_rpm_request *rpm_req;
+	unsigned r_state;
+};
+
+static struct ocmem_hw_region *region_ctrl;
+static struct mutex region_ctrl_lock;
+static void *ocmem_base;
+
+#define OCMEM_V1_REGIONS 3
+#define OCMEM_V1_MACROS 8
+
+#define OC_HW_VERS (0x0)
+#define OC_HW_PROFILE (0x4)
+#define OC_GEN_STATUS (0xC)
+#define OC_PSGSC_STATUS (0x38)
+#define OC_PSGSC_CTL (0x3C)
+#define OC_REGION_CTL (0x1000)
+
+#define NUM_PORTS_MASK (0xF << 0)
+#define NUM_PORTS_SHIFT (0)
+
+#define NUM_MACROS_MASK (0xF << 8)
+#define NUM_MACROS_SHIFT (8)
+
+#define INTERLEAVING_MASK (0x1 << 17)
+#define INTERLEAVING_SHIFT (17)
+
+/* Power states of each memory macro */
+#define PASSTHROUGH (0x0)
+#define CORE_ON (0x2)
+#define PERI_ON (0x1)
+#define CLK_OFF (0x4)
+#define MACRO_ON (CORE_ON|PERI_ON)
+#define MACRO_SLEEP_RETENTION (CLK_OFF|CORE_ON)
+#define MACRO_SLEEP_RETENTION_PERI_ON (CLK_OFF|MACRO_ON)
+#define MACRO_OFF (CLK_OFF)
+
+#define M_PSCGC_CTL_n(x) (0x7 << (x * 4))
+
+#define PSCGC_CTL_IDX(x) ((x) * 0x4)
+#define PSCGC_CTL_n(x) (OC_PSGSC_CTL + (PSCGC_CTL_IDX(x)))
+
+/* Power states of each ocmem region */
+#define REGION_NORMAL_PASSTHROUGH 0x00000000
+#define REGION_FORCE_PERI_ON 0x00001111
+#define REGION_FORCE_CORE_ON 0x00002222
+#define REGION_FORCE_ALL_ON 0x00003333
+#define REGION_SLEEP_NO_RETENTION 0x00004444
+#define REGION_SLEEP_PERI_OFF 0x00006666
+#define REGION_SLEEP_PERI_ON 0x00007777
+
+#define REGION_DEFAULT_OFF REGION_SLEEP_NO_RETENTION
+#define REGION_DEFAULT_ON REGION_FORCE_ALL_ON
+#define REGION_DEFAULT_RETENTION REGION_SLEEP_PERI_OFF
+
+enum rpm_macro_state {
+	rpm_macro_off = 0x0,
+	rpm_macro_retain,
+	rpm_macro_on,
+};
+
+static int rpm_write(unsigned long val, unsigned id);
+
+static inline unsigned hw_macro_state(unsigned region_state)
+{
+	unsigned macro_state;
+
+	switch (region_state) {
+	case REGION_DEFAULT_ON:
+		macro_state = MACRO_ON;
+		break;
+	case REGION_DEFAULT_OFF:
+		macro_state = MACRO_OFF;
+		break;
+	case REGION_DEFAULT_RETENTION:
+		macro_state = MACRO_SLEEP_RETENTION;
+		break;
+	default:
+		macro_state = MACRO_OFF;
+		break;
+	}
+	return macro_state;
+}
+
+static inline unsigned rpm_macro_state(unsigned hw_macro_state)
+{
+	unsigned macro_state;
+
+	switch (hw_macro_state) {
+	case MACRO_ON:
+		macro_state = rpm_macro_on;
+		break;
+	case MACRO_OFF:
+		macro_state = rpm_macro_off;
+		break;
+	case MACRO_SLEEP_RETENTION:
+		macro_state = rpm_macro_retain;
+		break;
+	default:
+		macro_state = rpm_macro_off;
+		break;
+	}
+	return macro_state;
+}
+
+/* Generic wrapper that sets the region state either
+   by a direct write or through appropriate RPM call
+*/
+/* Must be called with region mutex held */
+static int commit_region_state(unsigned region_num)
+{
+	int rc = -1;
+	unsigned new_state;
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	new_state = region_ctrl[region_num].r_state;
+	pr_debug("ocmem: commit region (%d) new state %x\n", region_num,
+								new_state);
+	if (rpm_power_control)
+		rc = rpm_write(new_state, region_num);
+	else
+		rc = ocmem_write(new_state,
+					ocmem_base + PSCGC_CTL_n(region_num));
+	return 0;
+}
+
+/* Returns the current state of a OCMEM region */
+/* Must be called with region mutex held */
+static int read_region_state(unsigned region_num)
+{
+	int state;
+
+	pr_debug("rpm_get_region_state: #: %d\n", region_num);
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	if (rpm_power_control)
+		state = region_ctrl[region_num].r_state;
+	else
+		state = ocmem_read(ocmem_base + PSCGC_CTL_n(region_num));
+
+	pr_debug("ocmem: region (%d) state %x\n", region_num, state);
+
+	return state;
+}
+
+/* Returns the current state of a OCMEM macro that belongs to a region */
+static int read_macro_state(unsigned region_num, unsigned macro_num)
+{
+	int state;
+
+	if (macro_num >= num_banks)
+		return -EINVAL;
+
+	state = read_region_state(region_num);
+
+	if (state < 0)
+		return -EINVAL;
+
+	state &= M_PSCGC_CTL_n(macro_num);
+	state = state >> (macro_num * 4);
+
+	pr_debug("rpm_get_macro_state: macro (%d) region (%d) state %x\n",
+			macro_num, region_num, state);
+
+	return state;
+}
+
+static int apply_macro_vote(int id, unsigned region_num,
+				unsigned macro_num, int new_state)
+{
+	struct ocmem_hw_macro *m = NULL;
+	struct ocmem_hw_region *region = NULL;
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	if (macro_num >= num_banks)
+		return -EINVAL;
+
+	region = &region_ctrl[region_num];
+
+	m = &region->macro[macro_num];
+
+	pr_debug("m (%d): curr state %x votes (on: %d retain %d) new state %x\n",
+			macro_num, m->m_state,
+			atomic_read(&m->m_on[id]),
+			atomic_read(&m->m_retain[id]),
+			new_state);
+
+	switch (m->m_state) {
+	case MACRO_OFF:
+		if (new_state == MACRO_ON)
+			atomic_inc(&m->m_on[id]);
+		break;
+	case MACRO_ON:
+		if (new_state == MACRO_OFF) {
+			atomic_dec(&m->m_on[id]);
+		} else if (new_state == MACRO_SLEEP_RETENTION) {
+			atomic_inc(&m->m_retain[id]);
+			atomic_dec(&m->m_on[id]);
+		}
+		break;
+	case MACRO_SLEEP_RETENTION:
+		if (new_state == MACRO_OFF) {
+			atomic_dec(&m->m_retain[id]);
+		} else if (new_state == MACRO_ON) {
+			atomic_inc(&m->m_on[id]);
+			atomic_dec(&m->m_retain[id]);
+		}
+		break;
+	}
+
+	pr_debug("macro (%d) region (%d) votes for %d (on: %d retain %d)\n",
+				region_num, macro_num, id,
+				atomic_read(&m->m_on[id]),
+				atomic_read(&m->m_retain[id]));
+	return 0;
+}
+
+static int aggregate_macro_state(unsigned region_num, unsigned macro_num)
+{
+	struct ocmem_hw_macro *m = NULL;
+	struct ocmem_hw_region *region = NULL;
+	int i = 0;
+	/* The default is for the macro to be OFF */
+	unsigned m_state = MACRO_OFF;
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	if (macro_num >= num_banks)
+		return -EINVAL;
+
+	region = &region_ctrl[region_num];
+	m = &region->macro[macro_num];
+
+	for (i = 0; i < OCMEM_CLIENT_MAX; i++) {
+		if (atomic_read(&m->m_on[i]) > 0) {
+			/* atleast one client voted for ON state */
+			m_state = MACRO_ON;
+			goto done_aggregation;
+		} else if (atomic_read(&m->m_retain[i]) > 0) {
+			m_state = MACRO_SLEEP_RETENTION;
+			/* continue and examine votes of other clients */
+		}
+	}
+done_aggregation:
+	m->m_state = m_state;
+	pr_debug("macro (%d) region (%d) aggregated state %x", macro_num,
+						region_num, m->m_state);
+	return 0;
+}
+
+static int aggregate_region_state(unsigned region_num)
+{
+	struct ocmem_hw_region *region = NULL;
+	unsigned r_state;
+	unsigned i = 0;
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	region = &region_ctrl[region_num];
+	r_state = REGION_DEFAULT_OFF;
+
+	/* In wide mode all macros must have the same state */
+	if (region->mode == WIDE_MODE) {
+		for (i = 0; i < region->num_macros; i++) {
+			if (region->macro[i].m_state == MACRO_ON) {
+				r_state = REGION_DEFAULT_ON;
+				break;
+			} else if (region->macro[i].m_state ==
+						MACRO_SLEEP_RETENTION) {
+				r_state = REGION_DEFAULT_RETENTION;
+			}
+		}
+	} else {
+	/* In narrow mode each macro is allowed to be in a different state */
+	/* The region mode is simply the collection of all macro states */
+		for (i = 0; i < region->num_macros; i++) {
+			r_state &= ~M_PSCGC_CTL_n(i);
+			r_state |= region->macro[i].m_state << (i * 4);
+		}
+	}
+
+	pr_debug("region (%d) curr state (%x) aggregated state (%x)\n",
+			region_num, region->r_state, r_state);
+	region->r_state = r_state;
+	return 0;
+}
+
+static int rpm_write(unsigned long val, unsigned id)
+{
+	int i = 0;
+	int ret = 0;
+	struct ocmem_hw_region *region;
+
+	region = &region_ctrl[id];
+
+	for (i = 0; i < region->num_macros; i++) {
+		unsigned macro_state;
+		unsigned rpm_state;
+
+		macro_state = read_macro_state(id, i);
+		rpm_state = rpm_macro_state(macro_state);
+
+		if (val == REGION_DEFAULT_ON) {
+			pr_debug("macro (%d) region (%d) -> active\n",
+				i, id);
+			rpm_state = rpm_macro_on;
+		}
+
+		if (val == REGION_DEFAULT_OFF) {
+			pr_debug("macro (%d) region (%d) -> off\n",
+				i, id);
+			rpm_state = rpm_macro_off;
+		}
+
+		ret = msm_rpm_add_kvp_data(region->rpm_req, i,
+						(u8 *) &rpm_state, 4);
+
+		if (ret < 0) {
+			pr_err("ocmem: Error adding key %d val %d on rsc %d\n",
+					i, rpm_state, id);
+			return -EINVAL;
+		}
+	}
+
+	ret = msm_rpm_send_request(region->rpm_req);
+
+	if (ret < 0) {
+		pr_err("ocmem: Error sending RPM request\n");
+		return -EINVAL;
+	}
+
+	pr_debug("Transmit request to rpm for region %d\n", id);
+	return 0;
+}
+
+
+#if defined(CONFIG_MSM_OCMEM_POWER_DEBUG)
+
+static int read_hw_region_state(unsigned region_num)
+{
+	int state;
+
+	pr_debug("rpm_get_region_state: #: %d\n", region_num);
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	state = ocmem_read(ocmem_base + PSCGC_CTL_n(region_num));
+
+	pr_debug("ocmem: region (%d) state %x\n", region_num, state);
+
+	return state;
+}
+
+int ocmem_region_toggle(unsigned int r_num)
+{
+	unsigned reboot_state = ~0x0;
+	unsigned m_num = 0;
+
+	mutex_lock(&region_ctrl_lock);
+	/* Turn on each macro at boot for quick hw sanity check */
+	reboot_state = read_hw_region_state(r_num);
+
+	if (reboot_state != REGION_DEFAULT_OFF) {
+		pr_err("Region %d not in power off state (%x)\n",
+				r_num, reboot_state);
+		goto toggle_fail;
+	}
+
+	for (m_num = 0; m_num < num_banks; m_num++) {
+		apply_macro_vote(0, r_num, m_num, MACRO_ON);
+		aggregate_macro_state(r_num, m_num);
+	}
+
+	aggregate_region_state(r_num);
+	commit_region_state(r_num);
+
+	reboot_state = read_hw_region_state(r_num);
+
+	if (reboot_state != REGION_DEFAULT_ON) {
+		pr_err("Failed to power on Region %d(state:%x)\n",
+				r_num, reboot_state);
+		goto toggle_fail;
+	}
+
+	/* Turn off all memory macros again */
+
+	for (m_num = 0; m_num < num_banks; m_num++) {
+		apply_macro_vote(0, r_num, m_num, MACRO_OFF);
+		aggregate_macro_state(r_num, m_num);
+	}
+
+	aggregate_region_state(r_num);
+	commit_region_state(r_num);
+
+	reboot_state = read_hw_region_state(r_num);
+
+	if (reboot_state != REGION_DEFAULT_OFF) {
+		pr_err("Failed to power off Region %d(state:%x)\n",
+				r_num, reboot_state);
+		goto toggle_fail;
+	}
+	mutex_unlock(&region_ctrl_lock);
+	return 0;
+
+toggle_fail:
+	mutex_unlock(&region_ctrl_lock);
+	return -EINVAL;
+}
+
+int memory_is_off(unsigned int num)
+{
+	if (read_hw_region_state(num) == REGION_DEFAULT_OFF)
+		return 1;
+	else
+		return 0;
+}
+
+#else
+int ocmem_region_toggle(unsigned int region_num)
+{
+	return 0;
+}
+
+int memory_is_off(unsigned int num)
+{
+	return 0;
+}
+#endif /* CONFIG_MSM_OCMEM_POWER_DEBUG */
+
+/* Memory Macro Power Transition Sequences
+ * Normal to Sleep With Retention:
+	REGION_DEFAULT_ON -> REGION_DEFAULT_RETENTION
+ * Sleep With Retention to Normal:
+	REGION_DEFAULT_RETENTION -> REGION_FORCE_CORE_ON -> REGION_DEFAULT_ON
+ * Normal to OFF:
+	REGION_DEFAULT_ON -> REGION_DEFAULT_OFF
+ * OFF to Normal:
+	REGION_DEFAULT_OFF -> REGION_DEFAULT_ON
+**/
+
+static int switch_power_state(int id, unsigned long offset, unsigned long len,
+			unsigned new_state)
+{
+	unsigned region_start = num_regions;
+	unsigned region_end = num_regions;
+	unsigned curr_state = 0x0;
+	int i = 0;
+	int j = 0;
+	unsigned start_m = num_banks;
+	unsigned end_m = num_banks;
+	unsigned long region_offset = 0;
+
+	if (offset < 0)
+		return -EINVAL;
+
+	if (len < macro_size)
+		return -EINVAL;
+
+
+	pr_debug("ocmem: power_transition to %x for client %d\n", new_state,
+							id);
+
+	region_start = offset / region_size;
+	region_end = (offset + len - 1) / region_size;
+
+	pr_debug("ocmem: region start %u end %u\n", region_start, region_end);
+
+	if (region_start >= num_regions ||
+		(region_end >= num_regions))
+			return -EINVAL;
+
+	mutex_lock(&region_ctrl_lock);
+
+	for (i = region_start; i <= region_end; i++) {
+
+		curr_state = read_region_state(i);
+
+		switch (curr_state) {
+		case REGION_DEFAULT_OFF:
+			if (new_state != REGION_DEFAULT_ON)
+				goto invalid_transition;
+			break;
+		case REGION_DEFAULT_RETENTION:
+			if (new_state != REGION_DEFAULT_ON)
+				goto invalid_transition;
+			break;
+		default:
+			break;
+		}
+
+		if (len >= region_size) {
+			pr_debug("switch: entire region (%d)\n", i);
+			start_m = 0;
+			end_m = num_banks;
+		} else {
+			region_offset = offset - (i * region_size);
+			start_m = region_offset / macro_size;
+			end_m = (region_offset + len - 1) / macro_size;
+			pr_debug("switch: macro (%u to %u)\n", start_m, end_m);
+		}
+
+		for (j = start_m; j <= end_m; j++) {
+			pr_debug("vote: macro (%d) region (%d)\n", j, i);
+			apply_macro_vote(id, i, j,
+				hw_macro_state(new_state));
+			aggregate_macro_state(i, j);
+		}
+		aggregate_region_state(i);
+		commit_region_state(i);
+		len -= region_size;
+
+		/* If we voted ON/retain the banks must never be OFF */
+		if (new_state != REGION_DEFAULT_OFF) {
+			if (memory_is_off(i)) {
+				pr_err("ocmem: Accessing memory during sleep\n");
+				WARN_ON(1);
+			}
+		}
+
+	}
+	mutex_unlock(&region_ctrl_lock);
+	return 0;
+invalid_transition:
+	mutex_unlock(&region_ctrl_lock);
+	pr_err("ocmem_core: Invalid state transition detected for %d\n", id);
+	pr_err("ocmem_core: Offset %lx Len %lx curr_state %x new_state %x\n",
+			offset, len, curr_state, new_state);
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+/* Interfaces invoked from the scheduler */
+int ocmem_memory_off(int id, unsigned long offset, unsigned long len)
+{
+	return switch_power_state(id, offset, len, REGION_DEFAULT_OFF);
+}
+
+int ocmem_memory_on(int id, unsigned long offset, unsigned long len)
+{
+	return switch_power_state(id, offset, len, REGION_DEFAULT_ON);
+}
+
+int ocmem_memory_retain(int id, unsigned long offset, unsigned long len)
+{
+	return switch_power_state(id, offset, len, REGION_DEFAULT_RETENTION);
+}
+
+int ocmem_core_init(struct platform_device *pdev)
+{
+	struct device   *dev = &pdev->dev;
+	struct ocmem_plat_data *pdata = NULL;
+	unsigned hw_ver;
+	bool interleaved;
+	unsigned i, j, k;
+	unsigned rsc_type = 0;
+
+	pdata = platform_get_drvdata(pdev);
+	ocmem_base = pdata->reg_base;
+
+	hw_ver = ocmem_read(ocmem_base + OC_HW_PROFILE);
+
+	if (pdata->nr_regions != OCMEM_V1_REGIONS) {
+		pr_err("Invalid number of regions (%d)\n", pdata->nr_regions);
+		goto hw_not_supported;
+	}
+
+	num_macros = (hw_ver & NUM_MACROS_MASK) >> NUM_MACROS_SHIFT;
+	num_ports = (hw_ver & NUM_PORTS_MASK) >> NUM_PORTS_SHIFT;
+
+	if (num_macros != OCMEM_V1_MACROS) {
+		pr_err("Invalid number of macros (%d)\n", pdata->nr_macros);
+		goto hw_not_supported;
+	}
+
+	interleaved = (hw_ver & INTERLEAVING_MASK) >> INTERLEAVING_SHIFT;
+
+	if (interleaved == false) {
+		pr_err("Interleaving is disabled\n");
+		goto hw_not_supported;
+	}
+
+	num_regions = pdata->nr_regions;
+
+	pdata->interleaved = true;
+	pdata->nr_macros = num_macros;
+	pdata->nr_ports = num_ports;
+	macro_size = SZ_64K;
+	region_size = macro_size * num_ports;
+	num_banks = num_ports / 2;
+	rsc_type = pdata->rpm_rsc_type;
+
+	pr_debug("ocmem_core: ports %d regions %d macros %d interleaved %d\n",
+				num_ports, num_regions, num_macros,
+				interleaved);
+
+	region_ctrl = devm_kzalloc(dev, sizeof(struct ocmem_hw_region)
+					 * num_regions, GFP_KERNEL);
+
+	if (!region_ctrl) {
+		pr_err("ocmem: Unable to allocate memory\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&region_ctrl_lock);
+
+	for (i = 0 ; i < num_regions; i++) {
+		struct ocmem_hw_region *region = &region_ctrl[i];
+		struct msm_rpm_request *req = NULL;
+		region->interleaved = interleaved;
+		region->mode = MODE_DEFAULT;
+		region->r_state = REGION_DEFAULT_OFF;
+		region->num_macros = num_banks;
+
+		region->macro = devm_kzalloc(dev,
+					sizeof(struct ocmem_hw_macro) *
+						num_banks, GFP_KERNEL);
+		if (!region->macro) {
+			pr_err("ocmem: Unable to allocate memory\n");
+			return -EINVAL;
+		}
+
+		for (j = 0; j < num_banks; j++) {
+			struct ocmem_hw_macro *m = &region->macro[j];
+			m->m_state = MACRO_OFF;
+			for (k = 0; k < OCMEM_CLIENT_MAX; k++) {
+				atomic_set(&m->m_on[k], 0);
+				atomic_set(&m->m_retain[k], 0);
+			}
+		}
+
+		if (pdata->rpm_pwr_ctrl) {
+			rpm_power_control = true;
+			req = msm_rpm_create_request(MSM_RPM_CTX_ACTIVE_SET,
+					rsc_type, i, num_banks);
+
+			if (!req) {
+				pr_err("Unable to create RPM request\n");
+				return -EINVAL;
+			}
+
+			pr_debug("rpm request type %x (rsc: %d) with %d elements\n",
+						rsc_type, i, num_banks);
+
+			region->rpm_req = req;
+		}
+
+		if (ocmem_region_toggle(i)) {
+			pr_err("Failed to verify region %d\n", i);
+			goto hw_not_supported;
+		}
+
+	}
+	return 0;
+hw_not_supported:
+	pr_err("Unsupported OCMEM h/w configuration %x\n", hw_ver);
+	return -EINVAL;
+}
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
index 6b93d04..5649021 100644
--- a/arch/arm/mach-msm/ocmem_rdm.c
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -109,19 +109,6 @@
 	unsigned int ctrl;
 } dm_table[RDM_MAX_ENTRIES];
 
-/* Wrapper that will shadow these values later */
-static int ocmem_read(void *at)
-{
-	return readl_relaxed(at);
-}
-
-/* Wrapper that will shadow these values later */
-static int ocmem_write(unsigned long val, void *at)
-{
-	writel_relaxed(val, at);
-	return 0;
-}
-
 static inline int client_ctrl_id(int id)
 {
 	return (id == OCMEM_SENSORS) ? 1 : 0;
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index f6d066d..70e6860 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1083,6 +1083,7 @@
 static int process_grow(struct ocmem_req *req)
 {
 	int rc = 0;
+	unsigned long offset = 0;
 
 	/* Attempt to grow the region */
 	rc = do_grow(req);
@@ -1097,6 +1098,15 @@
 			return -EINVAL;
 	}
 
+	offset = phys_to_offset(req->req_start);
+
+	rc = ocmem_memory_on(req->owner, offset, req->req_sz);
+
+	if (rc < 0) {
+		pr_err("Failed to switch ON memory macros\n");
+		goto power_ctl_error;
+	}
+
 	/* Notify the client about the buffer growth */
 	rc = dispatch_notification(req->owner, OCMEM_ALLOC_GROW, req->buffer);
 	if (rc < 0) {
@@ -1105,6 +1115,8 @@
 		BUG();
 	}
 	return 0;
+power_ctl_error:
+	return -EINVAL;
 }
 
 static int do_shrink(struct ocmem_req *req, unsigned long shrink_size)
@@ -1187,6 +1199,7 @@
 {
 	struct ocmem_req *req = NULL;
 	struct ocmem_buf *buffer = NULL;
+	unsigned long offset = 0;
 	int rc = 0;
 
 	if (is_blocked(id)) {
@@ -1211,6 +1224,20 @@
 			return -EINVAL;
 	}
 
+
+	if (req->req_sz != 0) {
+
+		offset = phys_to_offset(req->req_start);
+
+		rc = ocmem_memory_off(req->owner, offset, req->req_sz);
+
+		if (rc < 0) {
+			pr_err("Failed to switch OFF memory macros\n");
+			return -EINVAL;
+		}
+
+	}
+
 	rc = do_free(req);
 
 	if (rc < 0)
@@ -1244,7 +1271,6 @@
 		event = (rc == 0) ? OCMEM_MAP_DONE : OCMEM_MAP_FAIL;
 	else
 		event = (rc == 0) ? OCMEM_UNMAP_DONE : OCMEM_UNMAP_FAIL;
-
 	up_write(&req->rw_sem);
 	kfree(work_data);
 	dispatch_notification(id, event, buffer);
@@ -1300,6 +1326,7 @@
 		goto transfer_out_error;
 	}
 
+
 	return 0;
 
 transfer_out_error:
@@ -1538,6 +1565,7 @@
 	struct ocmem_req *req = NULL;
 	struct ocmem_buf *buffer = NULL;
 	int rc = 0;
+	unsigned long offset = 0;
 
 	/* sanity checks */
 	if (is_blocked(id)) {
@@ -1579,8 +1607,21 @@
 			goto map_error;
 	}
 
+	if (req->req_sz != 0) {
+
+		offset = phys_to_offset(req->req_start);
+
+		rc = ocmem_memory_on(req->owner, offset, req->req_sz);
+
+		if (rc < 0) {
+			pr_err("Failed to switch ON memory macros\n");
+			goto power_ctl_error;
+		}
+	}
+
 	return 0;
 
+power_ctl_error:
 map_error:
 	handle->req = NULL;
 	do_free(req);
@@ -1595,6 +1636,7 @@
 	struct ocmem_handle *handle = NULL;
 	int rc = 0;
 	int id = req->owner;
+	unsigned long offset = 0;
 
 	handle = req_to_handle(req);
 	BUG_ON(handle == NULL);
@@ -1611,6 +1653,18 @@
 			goto map_error;
 	}
 
+	if (req->req_sz != 0) {
+
+		offset = phys_to_offset(req->req_start);
+
+		rc = ocmem_memory_on(req->owner, offset, req->req_sz);
+
+		if (rc < 0) {
+			pr_err("Failed to switch ON memory macros\n");
+			goto power_ctl_error;
+		}
+	}
+
 	/* Notify the client about the buffer growth */
 	rc = dispatch_notification(id, OCMEM_ALLOC_GROW, req->buffer);
 	if (rc < 0) {
@@ -1620,6 +1674,7 @@
 	}
 	return 0;
 
+power_ctl_error:
 map_error:
 	handle->req = NULL;
 	do_free(req);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 86fe3f5..5ba3778 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1822,7 +1822,8 @@
 	if (state) {
 		adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
 		adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
-		adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
+		adreno_regwrite(device, MH_INTERRUPT_MASK,
+			kgsl_mmu_get_int_mask());
 	} else {
 		adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
 		adreno_regwrite(device, REG_CP_INT_CNTL, 0);
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index bc6ec8e..5293d66 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -299,4 +299,14 @@
 		(gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
 }
 
+static inline unsigned int kgsl_mmu_get_int_mask(void)
+{
+	/* Dont enable gpummu interrupts, if iommu is enabled */
+	if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype())
+		return KGSL_MMU_INT_MASK;
+	else
+		return (MH_INTERRUPT_MASK__AXI_READ_ERROR |
+			MH_INTERRUPT_MASK__AXI_WRITE_ERROR);
+}
+
 #endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6efba45..3504dfc 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -892,7 +892,8 @@
 
 	if (state) {
 		z180_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 3);
-		z180_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
+		z180_regwrite(device, MH_INTERRUPT_MASK,
+			kgsl_mmu_get_int_mask());
 	} else {
 		z180_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 0);
 		z180_regwrite(device, MH_INTERRUPT_MASK, 0);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index e87b4bd..352e60e 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -76,12 +76,29 @@
 	if (psy->set_property)
 		return psy->set_property(psy, POWER_SUPPLY_PROP_SCOPE,
 								&ret);
-
 	return -ENXIO;
 }
 EXPORT_SYMBOL_GPL(power_supply_set_scope);
 
 /**
+ * power_supply_set_supply_type - set type of the power supply
+ * @psy:	the power supply to control
+ * @supply_type:	sets type property of power supply
+ */
+int power_supply_set_supply_type(struct power_supply *psy,
+				enum power_supply_type supply_type)
+{
+	const union power_supply_propval ret = {supply_type,};
+
+	if (psy->set_property)
+		return psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,
+								&ret);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_supply_type);
+
+/**
  * power_supply_set_charge_type - set charge type of the power supply
  * @psy:	the power supply to control
  * @enable:	sets charge type property of power supply
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index ac88636..49d7c0f 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -99,7 +99,7 @@
 	char *dev_name;
 	struct device_attribute **attributes;
 
-	/* for android_dev.enabled_functions */
+	/* for android_conf.enabled_functions */
 	struct list_head enabled_list;
 
 	struct android_dev *android_dev;
@@ -127,8 +127,8 @@
 };
 
 struct android_dev {
+	const char *name;
 	struct android_usb_function **functions;
-	struct list_head enabled_functions;
 	struct usb_composite_dev *cdev;
 	struct device *dev;
 
@@ -143,9 +143,23 @@
 	struct pm_qos_request pm_qos_req_dma;
 	struct work_struct work;
 
+	/* A list of struct android_configuration */
+	struct list_head configs;
+	int configs_num;
+
+	/* A list node inside the android_dev_list */
 	struct list_head list_item;
 
-	struct usb_configuration config;
+};
+
+struct android_configuration {
+	struct usb_configuration usb_config;
+
+	/* A list of the functions supported by this config */
+	struct list_head enabled_functions;
+
+	/* A list node inside the struct android_dev.configs list */
+	struct list_head list_item;
 };
 
 static struct class *android_class;
@@ -154,6 +168,10 @@
 static int android_bind_config(struct usb_configuration *c);
 static void android_unbind_config(struct usb_configuration *c);
 static struct android_dev *cdev_to_android_dev(struct usb_composite_dev *cdev);
+static struct android_configuration *alloc_android_config
+						(struct android_dev *dev);
+static void free_android_config(struct android_dev *dev,
+				struct android_configuration *conf);
 
 /* string IDs are assigned dynamically */
 #define STRING_MANUFACTURER_IDX		0
@@ -296,13 +314,17 @@
 static void android_enable(struct android_dev *dev)
 {
 	struct usb_composite_dev *cdev = dev->cdev;
+	struct android_configuration *conf;
 
 	if (WARN_ON(!dev->disable_depth))
 		return;
 
 	if (--dev->disable_depth == 0) {
-		usb_add_config(cdev, &dev->config,
-					android_bind_config);
+
+		list_for_each_entry(conf, &dev->configs, list_item)
+			usb_add_config(cdev, &conf->usb_config,
+						android_bind_config);
+
 		usb_gadget_connect(cdev->gadget);
 	}
 }
@@ -310,12 +332,15 @@
 static void android_disable(struct android_dev *dev)
 {
 	struct usb_composite_dev *cdev = dev->cdev;
+	struct android_configuration *conf;
 
 	if (dev->disable_depth++ == 0) {
 		usb_gadget_disconnect(cdev->gadget);
 		/* Cancel pending control requests */
 		usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
-		usb_remove_config(cdev, &dev->config);
+
+		list_for_each_entry(conf, &dev->configs, list_item)
+			usb_remove_config(cdev, &conf->usb_config);
 	}
 }
 
@@ -1555,9 +1580,11 @@
 			       struct usb_configuration *c)
 {
 	struct android_usb_function *f;
+	struct android_configuration *conf =
+		container_of(c, struct android_configuration, usb_config);
 	int ret;
 
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+	list_for_each_entry(f, &conf->enabled_functions, enabled_list) {
 		ret = f->bind_config(f, c);
 		if (ret) {
 			pr_err("%s: %s failed", __func__, f->name);
@@ -1572,25 +1599,30 @@
 			       struct usb_configuration *c)
 {
 	struct android_usb_function *f;
+	struct android_configuration *conf =
+		container_of(c, struct android_configuration, usb_config);
 
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+	list_for_each_entry(f, &conf->enabled_functions, enabled_list) {
 		if (f->unbind_config)
 			f->unbind_config(f, c);
 	}
 }
 
-static int android_enable_function(struct android_dev *dev, char *name)
+static int android_enable_function(struct android_dev *dev,
+				   struct android_configuration *conf,
+				   char *name)
 {
 	struct android_usb_function **functions = dev->functions;
 	struct android_usb_function *f;
 	while ((f = *functions++)) {
 		if (!strcmp(name, f->name)) {
 			if (f->android_dev)
-				pr_err("%s cannot be enabled on two devices\n",
+				pr_err("%s already enabled in other " \
+					"configuration or device\n",
 					f->name);
 			else {
 				list_add_tail(&f->enabled_list,
-					      &dev->enabled_functions);
+					      &conf->enabled_functions);
 				f->android_dev = dev;
 				return 0;
 			}
@@ -1606,9 +1638,20 @@
 		struct device_attribute *attr, char *buf)
 {
 	struct android_dev *dev = dev_get_drvdata(pdev);
+	struct android_configuration *conf;
+
+	/*
+	 * Show the wakeup attribute of the first configuration,
+	 * since all configurations have the same wakeup attribute
+	 */
+	if (dev->configs_num == 0)
+		return 0;
+	conf = list_entry(dev->configs.next,
+			  struct android_configuration,
+			  list_item);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			!!(dev->config.bmAttributes &
+			!!(conf->usb_config.bmAttributes &
 				USB_CONFIG_ATT_WAKEUP));
 }
 
@@ -1616,6 +1659,7 @@
 		struct device_attribute *attr, const char *buff, size_t size)
 {
 	struct android_dev *dev = dev_get_drvdata(pdev);
+	struct android_configuration *conf;
 	int enable = 0;
 
 	sscanf(buff, "%d", &enable);
@@ -1623,10 +1667,13 @@
 	pr_debug("android_usb: %s remote wakeup\n",
 			enable ? "enabling" : "disabling");
 
-	if (enable)
-		dev->config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	else
-		dev->config.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
+	list_for_each_entry(conf, &dev->configs, list_item)
+		if (enable)
+			conf->usb_config.bmAttributes |=
+					USB_CONFIG_ATT_WAKEUP;
+		else
+			conf->usb_config.bmAttributes &=
+					~USB_CONFIG_ATT_WAKEUP;
 
 	return size;
 }
@@ -1635,13 +1682,18 @@
 functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
 {
 	struct android_dev *dev = dev_get_drvdata(pdev);
+	struct android_configuration *conf;
 	struct android_usb_function *f;
 	char *buff = buf;
 
 	mutex_lock(&dev->mutex);
 
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list)
-		buff += snprintf(buff, PAGE_SIZE, "%s,", f->name);
+	list_for_each_entry(conf, &dev->configs, list_item) {
+		if (buff != buf)
+			*(buff-1) = ':';
+		list_for_each_entry(f, &conf->enabled_functions, enabled_list)
+			buff += snprintf(buff, PAGE_SIZE, "%s,", f->name);
+	}
 
 	mutex_unlock(&dev->mutex);
 
@@ -1656,6 +1708,9 @@
 {
 	struct android_dev *dev = dev_get_drvdata(pdev);
 	struct android_usb_function *f;
+	struct list_head *curr_conf = &dev->configs;
+	struct android_configuration *conf;
+	char *conf_str;
 	char *name;
 	char buf[256], *b;
 	int err;
@@ -1668,21 +1723,45 @@
 	}
 
 	/* Clear previous enabled list */
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-		f->android_dev = NULL;
+	list_for_each_entry(conf, &dev->configs, list_item) {
+		list_for_each_entry(f, &conf->enabled_functions, enabled_list)
+			f->android_dev = NULL;
+		INIT_LIST_HEAD(&conf->enabled_functions);
 	}
-	INIT_LIST_HEAD(&dev->enabled_functions);
 
 	strlcpy(buf, buff, sizeof(buf));
 	b = strim(buf);
 
 	while (b) {
-		name = strsep(&b, ",");
-		if (name) {
-			err = android_enable_function(dev, name);
-			if (err)
-				pr_err("android_usb: Cannot enable '%s'", name);
+		conf_str = strsep(&b, ":");
+		if (conf_str) {
+			/* If the next not equal to the head, take it */
+			if (curr_conf->next != &dev->configs)
+				conf = list_entry(curr_conf->next,
+						  struct android_configuration,
+						  list_item);
+			else
+				conf = alloc_android_config(dev);
+
+			curr_conf = curr_conf->next;
 		}
+
+		while (conf_str) {
+			name = strsep(&conf_str, ",");
+			if (name) {
+				err = android_enable_function(dev, conf, name);
+				if (err)
+					pr_err("android_usb: Cannot enable %s",
+						name);
+			}
+		}
+	}
+
+	/* Free uneeded configurations if exists */
+	while (curr_conf->next != &dev->configs) {
+		conf = list_entry(curr_conf->next,
+				  struct android_configuration, list_item);
+		free_android_config(dev, conf);
 	}
 
 	mutex_unlock(&dev->mutex);
@@ -1704,6 +1783,7 @@
 	struct android_dev *dev = dev_get_drvdata(pdev);
 	struct usb_composite_dev *cdev = dev->cdev;
 	struct android_usb_function *f;
+	struct android_configuration *conf;
 	int enabled = 0;
 
 	if (!cdev)
@@ -1723,18 +1803,22 @@
 		cdev->desc.bDeviceClass = device_desc.bDeviceClass;
 		cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
 		cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
-		list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-			if (f->enable)
-				f->enable(f);
-		}
+		list_for_each_entry(conf, &dev->configs, list_item)
+			list_for_each_entry(f, &conf->enabled_functions,
+						enabled_list) {
+				if (f->enable)
+					f->enable(f);
+			}
 		android_enable(dev);
 		dev->enabled = true;
 	} else if (!enabled && dev->enabled) {
 		android_disable(dev);
-		list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-			if (f->disable)
-				f->disable(f);
-		}
+		list_for_each_entry(conf, &dev->configs, list_item)
+			list_for_each_entry(f, &conf->enabled_functions,
+						enabled_list) {
+				if (f->disable)
+					f->disable(f);
+			}
 		dev->enabled = false;
 	} else {
 		pr_err("android_usb: already %s\n",
@@ -1890,6 +1974,7 @@
 {
 	struct android_dev *dev;
 	struct usb_gadget	*gadget = cdev->gadget;
+	struct android_configuration *conf;
 	int			gcnum, id, ret;
 
 	/* Bind to the last android_dev that was probed */
@@ -1938,7 +2023,8 @@
 	device_desc.iSerialNumber = id;
 
 	if (gadget_is_otg(cdev->gadget))
-		dev->config.descriptors = otg_desc;
+		list_for_each_entry(conf, &dev->configs, list_item)
+			conf->usb_config.descriptors = otg_desc;
 
 	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
@@ -1979,6 +2065,7 @@
 	struct android_dev		*dev = cdev_to_android_dev(cdev);
 	struct usb_request		*req = cdev->req;
 	struct android_usb_function	*f;
+	struct android_configuration	*conf;
 	int value = -EOPNOTSUPP;
 	unsigned long flags;
 
@@ -1987,13 +2074,16 @@
 	req->length = 0;
 	gadget->ep0->driver_data = cdev;
 
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-		if (f->ctrlrequest) {
-			value = f->ctrlrequest(f, cdev, c);
-			if (value >= 0)
-				break;
-		}
-	}
+	list_for_each_entry(conf, &dev->configs, list_item)
+		if (&conf->usb_config == cdev->config)
+			list_for_each_entry(f,
+					    &conf->enabled_functions,
+					    enabled_list)
+				if (f->ctrlrequest) {
+					value = f->ctrlrequest(f, cdev, c);
+					if (value >= 0)
+						break;
+				}
 
 	/* Special case the accessory function.
 	 * It needs to handle control requests before it is enabled.
@@ -2084,6 +2174,38 @@
 	return dev;
 }
 
+static struct android_configuration *alloc_android_config
+						(struct android_dev *dev)
+{
+	struct android_configuration *conf;
+
+	conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+	if (!conf) {
+		pr_err("%s(): Failed to alloc memory for android conf\n",
+			__func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dev->configs_num++;
+	conf->usb_config.label = dev->name;
+	conf->usb_config.unbind = android_unbind_config;
+	conf->usb_config.bConfigurationValue = dev->configs_num;
+
+	INIT_LIST_HEAD(&conf->enabled_functions);
+
+	list_add_tail(&conf->list_item, &dev->configs);
+
+	return conf;
+}
+
+static void free_android_config(struct android_dev *dev,
+			     struct android_configuration *conf)
+{
+	list_del(&conf->list_item);
+	dev->configs_num--;
+	kfree(conf);
+}
+
 static int __devinit android_probe(struct platform_device *pdev)
 {
 	struct android_usb_platform_data *pdata = pdev->dev.platform_data;
@@ -2104,12 +2226,11 @@
 		goto err_alloc;
 	}
 
-	android_dev->config.label = pdev->name;
-	android_dev->config.unbind = android_unbind_config;
-	android_dev->config.bConfigurationValue = 1;
+	android_dev->name = pdev->name;
 	android_dev->disable_depth = 1;
 	android_dev->functions = supported_functions;
-	INIT_LIST_HEAD(&android_dev->enabled_functions);
+	android_dev->configs_num = 0;
+	INIT_LIST_HEAD(&android_dev->configs);
 	INIT_WORK(&android_dev->work, android_work);
 	mutex_init(&android_dev->mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 75d92f1..5879530 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2928,30 +2928,32 @@
 
 int mdp4_overlay_wait4vsync(struct fb_info *info, long long *vtime)
 {
-	if (info->node == 0) {
+	if (!hdmi_prim_display && info->node == 0) {
 		if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
 			mdp4_dsi_video_wait4vsync(0, vtime);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
 			mdp4_dsi_cmd_wait4vsync(0, vtime);
 		else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
 			mdp4_lcdc_wait4vsync(0, vtime);
-	} else if (info->node == 1)
+	} else if (hdmi_prim_display || info->node == 1) {
 		mdp4_dtv_wait4vsync(0, vtime);
+	}
 
 	return 0;
 }
 
 int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable)
 {
-	if (info->node == 0) {
+	if (!hdmi_prim_display && info->node == 0) {
 		if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
 			mdp4_dsi_video_vsync_ctrl(0, enable);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
 			mdp4_dsi_cmd_vsync_ctrl(0, enable);
 		else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
 			mdp4_lcdc_vsync_ctrl(0, enable);
-	} else if (info->node == 1)
+	} else if (hdmi_prim_display || info->node == 1) {
 		mdp4_dtv_vsync_ctrl(0, enable);
+	}
 
 	return 0;
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 16c5278..6445ec1 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -455,6 +455,7 @@
 
 	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
+	vctrl->fake_vsync = 1;
 
 	/* mdp clock on */
 	mdp_clk_ctrl(1);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index f857ac8..f3d9e2c 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -73,6 +73,7 @@
 	int dmae_wait_cnt;
 	int wait_vsync_cnt;
 	int blt_change;
+	int fake_vsync;
 	struct mutex update_lock;
 	struct completion dmae_comp;
 	struct completion vsync_comp;
@@ -236,6 +237,11 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 
+	if (vctrl->fake_vsync) {
+		vctrl->fake_vsync = 0;
+		schedule_work(&vctrl->vsync_work);
+	}
+
 	if (vctrl->vsync_irq_enabled == enable)
 		return;
 
@@ -521,6 +527,7 @@
 		return -EINVAL;
 
 	vctrl->dev = mfd->fbi->dev;
+	vctrl->fake_vsync = 1;
 
 	mdp_footswitch_ctrl(TRUE);
 	/* Mdp clock enable */
@@ -587,6 +594,7 @@
 
 	ret = panel_next_off(pdev);
 	mdp_footswitch_ctrl(FALSE);
+	vctrl->fake_vsync = 1;
 
 	/* Mdp clock disable */
 	mdp_clk_ctrl(0);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 2d5025b..79bb7c5 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -460,6 +460,7 @@
 
 	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
+	vctrl->fake_vsync = 1;
 
 	/* mdp clock on */
 	mdp_clk_ctrl(1);
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 492437e..b6294f4 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -7,4 +7,10 @@
 mdss-mdp-objs += mdss_mdp_wb.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
+
+mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
+mdss-dsi-objs += mdss_dsi_panel.o
+mdss-dsi-objs += msm_mdss_io_8974.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
+
 obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index a58c3e6..6145d67 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -22,6 +22,7 @@
 #define MDSS_REG_READ(addr) readl_relaxed(mdss_reg_base + addr)
 
 extern unsigned char *mdss_reg_base;
+extern spinlock_t dsi_clk_lock;
 
 enum mdss_mdp_clk_type {
 	MDSS_CLK_AHB,
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
new file mode 100644
index 0000000..d051828
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -0,0 +1,383 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_dsi.h"
+
+static struct mdss_panel_common_pdata *panel_pdata;
+
+static unsigned char *mdss_dsi_base;
+
+static int mdss_dsi_off(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	struct mdss_panel_info *pinfo;
+
+	pinfo = &pdata->panel_info;
+
+	if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
+		mdss_dsi_controller_cfg(0, pdata);
+
+	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
+
+	ret = panel_pdata->off(pdata);
+	if (ret) {
+		pr_err("%s: Panel OFF failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_bh(&dsi_clk_lock);
+	mdss_dsi_clk_disable();
+
+	/* disable dsi engine */
+	MIPI_OUTP(mdss_dsi_base + 0x0004, 0);
+
+	spin_unlock_bh(&dsi_clk_lock);
+
+	mdss_dsi_unprepare_clocks();
+
+	pr_debug("%s-:\n", __func__);
+
+	return ret;
+}
+
+static int mdss_dsi_on(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	u32 clk_rate;
+	struct mdss_panel_info *pinfo;
+	struct mipi_panel_info *mipi;
+	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+	u32 ystride, bpp, data;
+	u32 dummy_xres, dummy_yres;
+
+	pinfo = &pdata->panel_info;
+
+	cont_splash_clk_ctrl(0);
+	mdss_dsi_prepare_clocks();
+
+	spin_lock_bh(&dsi_clk_lock);
+
+	MIPI_OUTP(mdss_dsi_base + 0x118, 1);
+	MIPI_OUTP(mdss_dsi_base + 0x118, 0);
+
+	mdss_dsi_clk_enable();
+	spin_unlock_bh(&dsi_clk_lock);
+
+	clk_rate = pdata->panel_info.clk_rate;
+	clk_rate = min(clk_rate, pdata->panel_info.clk_max);
+
+	hbp = pdata->panel_info.lcdc.h_back_porch;
+	hfp = pdata->panel_info.lcdc.h_front_porch;
+	vbp = pdata->panel_info.lcdc.v_back_porch;
+	vfp = pdata->panel_info.lcdc.v_front_porch;
+	hspw = pdata->panel_info.lcdc.h_pulse_width;
+	vspw = pdata->panel_info.lcdc.v_pulse_width;
+	width = pdata->panel_info.xres;
+	height = pdata->panel_info.yres;
+
+	mipi  = &pdata->panel_info.mipi;
+	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+		dummy_xres = pdata->panel_info.lcdc.xres_pad;
+		dummy_yres = pdata->panel_info.lcdc.yres_pad;
+
+		MIPI_OUTP(mdss_dsi_base + 0x24,
+			((hspw + hbp + width + dummy_xres) << 16 |
+			(hspw + hbp)));
+		MIPI_OUTP(mdss_dsi_base + 0x28,
+			((vspw + vbp + height + dummy_yres) << 16 |
+			(vspw + vbp)));
+		MIPI_OUTP(mdss_dsi_base + 0x2C,
+			(vspw + vbp + height + dummy_yres +
+				vfp - 1) << 16 | (hspw + hbp +
+				width + dummy_xres + hfp - 1));
+
+		MIPI_OUTP(mdss_dsi_base + 0x30, (hspw << 16));
+		MIPI_OUTP(mdss_dsi_base + 0x34, 0);
+		MIPI_OUTP(mdss_dsi_base + 0x38, (vspw << 16));
+
+	} else {		/* command mode */
+		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+			bpp = 3;
+		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
+			bpp = 3;
+		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+			bpp = 2;
+		else
+			bpp = 3;	/* Default format set to RGB888 */
+
+		ystride = width * bpp + 1;
+
+		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
+		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
+		MIPI_OUTP(mdss_dsi_base + 0x60, data);
+		MIPI_OUTP(mdss_dsi_base + 0x58, data);
+
+		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
+		data = height << 16 | width;
+		MIPI_OUTP(mdss_dsi_base + 0x64, data);
+		MIPI_OUTP(mdss_dsi_base + 0x5C, data);
+	}
+
+	mdss_dsi_host_init(mipi, pdata);
+
+	if (mipi->force_clk_lane_hs) {
+		u32 tmp;
+
+		tmp = MIPI_INP(mdss_dsi_base + 0xac);
+		tmp |= (1<<28);
+		MIPI_OUTP(mdss_dsi_base + 0xac, tmp);
+		wmb();
+	}
+
+	ret = panel_pdata->on(pdata);
+	if (ret) {
+		pr_err("%s: unable to initialize the panel\n", __func__);
+		return ret;
+	}
+
+	mdss_dsi_op_mode_config(mipi->mode, pdata);
+
+	pr_debug("%s-:\n", __func__);
+	return ret;
+}
+
+unsigned char *mdss_dsi_get_base_adr(void)
+{
+	return mdss_dsi_base;
+}
+
+unsigned char *mdss_dsi_get_clk_base(void)
+{
+	return mdss_dsi_base;
+}
+
+static int mdss_dsi_resource_initialized;
+
+static int __devinit mdss_dsi_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	pr_debug("%s\n", __func__);
+
+	if (pdev->dev.of_node && !mdss_dsi_resource_initialized) {
+		struct resource *mdss_dsi_mres;
+		pdev->id = 1;
+		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!mdss_dsi_mres) {
+			pr_err("%s:%d unable to get the MDSS resources",
+				       __func__, __LINE__);
+			return -ENOMEM;
+		}
+		if (mdss_dsi_mres) {
+			mdss_dsi_base = ioremap(mdss_dsi_mres->start,
+				resource_size(mdss_dsi_mres));
+			if (!mdss_dsi_base) {
+				pr_err("%s:%d unable to remap dsi resources",
+					       __func__, __LINE__);
+				return -ENOMEM;
+			}
+		}
+
+		if (mdss_dsi_clk_init(pdev)) {
+			iounmap(mdss_dsi_base);
+			return -EPERM;
+		}
+
+		rc = of_platform_populate(pdev->dev.of_node,
+					NULL, NULL, &pdev->dev);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: failed to add child nodes, rc=%d\n",
+							__func__, rc);
+			iounmap(mdss_dsi_base);
+			return rc;
+		}
+
+		mdss_dsi_resource_initialized = 1;
+	}
+
+	if (!mdss_dsi_resource_initialized)
+		return -EPERM;
+
+	return 0;
+}
+
+static int __devexit mdss_dsi_remove(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+	iounmap(mdss_dsi_base);
+	return 0;
+}
+
+struct device dsi_dev;
+
+int dsi_panel_device_register(struct platform_device *pdev,
+			      struct mdss_panel_common_pdata *panel_data)
+{
+	struct mipi_panel_info *mipi;
+	int rc;
+	u8 lanes = 0, bpp;
+	u32 h_period, v_period, dsi_pclk_rate;
+	struct mdss_panel_data *pdata = NULL;
+
+	panel_pdata = panel_data;
+
+	h_period = ((panel_pdata->panel_info.lcdc.h_pulse_width)
+			+ (panel_pdata->panel_info.lcdc.h_back_porch)
+			+ (panel_pdata->panel_info.xres)
+			+ (panel_pdata->panel_info.lcdc.h_front_porch));
+
+	v_period = ((panel_pdata->panel_info.lcdc.v_pulse_width)
+			+ (panel_pdata->panel_info.lcdc.v_back_porch)
+			+ (panel_pdata->panel_info.yres)
+			+ (panel_pdata->panel_info.lcdc.v_front_porch));
+
+	mipi  = &panel_pdata->panel_info.mipi;
+
+	panel_pdata->panel_info.type =
+		((mipi->mode == DSI_VIDEO_MODE)
+			? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
+
+	if (mipi->data_lane3)
+		lanes += 1;
+	if (mipi->data_lane2)
+		lanes += 1;
+	if (mipi->data_lane1)
+		lanes += 1;
+	if (mipi->data_lane0)
+		lanes += 1;
+
+
+	if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+	    || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
+	    || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
+		bpp = 3;
+	else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+		 || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
+		bpp = 2;
+	else
+		bpp = 3;		/* Default format set to RGB888 */
+
+	if (panel_pdata->panel_info.type == MIPI_VIDEO_PANEL &&
+		!panel_pdata->panel_info.clk_rate) {
+		h_period += panel_pdata->panel_info.lcdc.xres_pad;
+		v_period += panel_pdata->panel_info.lcdc.yres_pad;
+
+		if (lanes > 0) {
+			panel_pdata->panel_info.clk_rate =
+			((h_period * v_period * (mipi->frame_rate) * bpp * 8)
+			   / lanes);
+		} else {
+			pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
+			panel_pdata->panel_info.clk_rate =
+				(h_period * v_period
+					 * (mipi->frame_rate) * bpp * 8);
+		}
+	}
+	pll_divider_config.clk_rate = panel_pdata->panel_info.clk_rate;
+
+	rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
+	if (rc) {
+		pr_err("%s: unable to initialize the clk dividers\n", __func__);
+		return rc;
+	}
+
+	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+		dsi_pclk_rate = 35000000;
+	mipi->dsi_pclk_rate = dsi_pclk_rate;
+
+	/*
+	 * data chain
+	 */
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->on = mdss_dsi_on;
+	pdata->off = mdss_dsi_off;
+	memcpy(&(pdata->panel_info), &(panel_pdata->panel_info),
+	       sizeof(struct mdss_panel_info));
+
+	pdata->dsi_base = mdss_dsi_base;
+
+	/*
+	 * register in mdp driver
+	 */
+	rc = mdss_register_panel(pdata);
+	if (rc) {
+		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
+		devm_kfree(&pdev->dev, pdata);
+		return rc;
+	}
+
+	pr_debug("%s: Panal data initialized\n", __func__);
+	return 0;
+}
+
+static const struct of_device_id msm_mdss_dsi_dt_match[] = {
+	{.compatible = "qcom,msm-mdss-dsi"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_mdss_dsi_dt_match);
+
+static struct platform_driver mdss_dsi_driver = {
+	.probe = mdss_dsi_probe,
+	.remove = __devexit_p(mdss_dsi_remove),
+	.shutdown = NULL,
+	.driver = {
+		.name = "mdss_dsi",
+		.of_match_table = msm_mdss_dsi_dt_match,
+	},
+};
+
+static int mdss_dsi_register_driver(void)
+{
+	return platform_driver_register(&mdss_dsi_driver);
+}
+
+static int __init mdss_dsi_driver_init(void)
+{
+	int ret;
+
+	mdss_dsi_init();
+
+	ret = mdss_dsi_register_driver();
+	if (ret) {
+		pr_err("mdss_dsi_register_driver() failed!\n");
+		return ret;
+	}
+
+	return ret;
+}
+module_init(mdss_dsi_driver_init);
+
+static void __exit mdss_dsi_driver_cleanup(void)
+{
+	iounmap(mdss_dsi_base);
+	platform_driver_unregister(&mdss_dsi_driver);
+}
+module_exit(mdss_dsi_driver_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DSI controller driver");
+MODULE_AUTHOR("Chandan Uddaraju <chandanu@codeaurora.org>");
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
new file mode 100644
index 0000000..57fce1a
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -0,0 +1,294 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDSS_DSI_H
+#define MDSS_DSI_H
+
+#include <linux/list.h>
+#include <mach/scm-io.h>
+
+#include "mdss_panel.h"
+
+#define MMSS_MDSS_CC_BASE_PHY 0xFD8C2300	/* mmss clcok control */
+#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
+
+#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
+#define MIPI_INP(addr) readl_relaxed(addr)
+
+#ifdef CONFIG_MSM_SECURE_IO
+#define MIPI_OUTP_SECURE(addr, data) secure_writel((data), (addr))
+#define MIPI_INP_SECURE(addr) secure_readl(addr)
+#else
+#define MIPI_OUTP_SECURE(addr, data) writel_relaxed((data), (addr))
+#define MIPI_INP_SECURE(addr) readl_relaxed(addr)
+#endif
+
+#define MIPI_DSI_PRIM 1
+#define MIPI_DSI_SECD 2
+
+#define MIPI_DSI_PANEL_VGA	0
+#define MIPI_DSI_PANEL_WVGA	1
+#define MIPI_DSI_PANEL_WVGA_PT	2
+#define MIPI_DSI_PANEL_FWVGA_PT	3
+#define MIPI_DSI_PANEL_WSVGA_PT	4
+#define MIPI_DSI_PANEL_QHD_PT 5
+#define MIPI_DSI_PANEL_WXGA	6
+#define MIPI_DSI_PANEL_WUXGA	7
+#define MIPI_DSI_PANEL_720P_PT	8
+#define DSI_PANEL_MAX	8
+
+enum {		/* mipi dsi panel */
+	DSI_VIDEO_MODE,
+	DSI_CMD_MODE,
+};
+
+enum {
+	ST_DSI_CLK_OFF,
+	ST_DSI_SUSPEND,
+	ST_DSI_RESUME,
+	ST_DSI_PLAYING,
+	ST_DSI_NUM
+};
+
+enum {
+	EV_DSI_UPDATE,
+	EV_DSI_DONE,
+	EV_DSI_TOUT,
+	EV_DSI_NUM
+};
+
+enum {
+	LANDSCAPE = 1,
+	PORTRAIT = 2,
+};
+
+enum dsi_trigger_type {
+	DSI_CMD_MODE_DMA,
+	DSI_CMD_MODE_MDP,
+};
+
+#define DSI_NON_BURST_SYNCH_PULSE	0
+#define DSI_NON_BURST_SYNCH_EVENT	1
+#define DSI_BURST_MODE			2
+
+#define DSI_RGB_SWAP_RGB	0
+#define DSI_RGB_SWAP_RBG	1
+#define DSI_RGB_SWAP_BGR	2
+#define DSI_RGB_SWAP_BRG	3
+#define DSI_RGB_SWAP_GRB	4
+#define DSI_RGB_SWAP_GBR	5
+
+#define DSI_VIDEO_DST_FORMAT_RGB565		0
+#define DSI_VIDEO_DST_FORMAT_RGB666		1
+#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE	2
+#define DSI_VIDEO_DST_FORMAT_RGB888		3
+
+#define DSI_CMD_DST_FORMAT_RGB111	0
+#define DSI_CMD_DST_FORMAT_RGB332	3
+#define DSI_CMD_DST_FORMAT_RGB444	4
+#define DSI_CMD_DST_FORMAT_RGB565	6
+#define DSI_CMD_DST_FORMAT_RGB666	7
+#define DSI_CMD_DST_FORMAT_RGB888	8
+
+#define DSI_INTR_ERROR_MASK		BIT(25)
+#define DSI_INTR_ERROR			BIT(24)
+#define DSI_INTR_VIDEO_DONE_MASK	BIT(17)
+#define DSI_INTR_VIDEO_DONE		BIT(16)
+#define DSI_INTR_CMD_MDP_DONE_MASK	BIT(9)
+#define DSI_INTR_CMD_MDP_DONE		BIT(8)
+#define DSI_INTR_CMD_DMA_DONE_MASK	BIT(1)
+#define DSI_INTR_CMD_DMA_DONE		BIT(0)
+
+#define DSI_CMD_TRIGGER_NONE		0x0	/* mdp trigger */
+#define DSI_CMD_TRIGGER_TE		0x02
+#define DSI_CMD_TRIGGER_SW		0x04
+#define DSI_CMD_TRIGGER_SW_SEOF		0x05	/* cmd dma only */
+#define DSI_CMD_TRIGGER_SW_TE		0x06
+
+extern struct device dsi_dev;
+extern int mdss_dsi_clk_on;
+extern u32 dsi_irq;
+
+struct dsiphy_pll_divider_config {
+	u32 clk_rate;
+	u32 fb_divider;
+	u32 ref_divider_ratio;
+	u32 bit_clk_divider;	/* oCLK1 */
+	u32 byte_clk_divider;	/* oCLK2 */
+	u32 analog_posDiv;
+	u32 digital_posDiv;
+};
+
+extern struct dsiphy_pll_divider_config pll_divider_config;
+
+struct dsi_clk_mnd_table {
+	u8 lanes;
+	u8 bpp;
+	u8 pll_digital_posDiv;
+	u8 pclk_m;
+	u8 pclk_n;
+	u8 pclk_d;
+};
+
+static const struct dsi_clk_mnd_table mnd_table[] = {
+	{ 1, 2,  8, 1, 1, 0},
+	{ 1, 3, 12, 1, 1, 0},
+	{ 2, 2,  4, 1, 1, 0},
+	{ 2, 3,  6, 1, 1, 0},
+	{ 3, 2,  1, 3, 8, 4},
+	{ 3, 3,  4, 1, 1, 0},
+	{ 4, 2,  2, 1, 1, 0},
+	{ 4, 3,  3, 1, 1, 0},
+};
+
+struct dsi_clk_desc {
+	u32 src;
+	u32 m;
+	u32 n;
+	u32 d;
+	u32 mnd_mode;
+	u32 pre_div_func;
+};
+
+#define DSI_HOST_HDR_SIZE	4
+#define DSI_HDR_LAST		BIT(31)
+#define DSI_HDR_LONG_PKT	BIT(30)
+#define DSI_HDR_BTA		BIT(29)
+#define DSI_HDR_VC(vc)		(((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype)	(((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data)	(((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data)	((data) & 0x0ff)
+#define DSI_HDR_WC(wc)		((wc) & 0x0ffff)
+
+#define DSI_BUF_SIZE	1024
+#define MDSS_DSI_MRPS	0x04  /* Maximum Return Packet Size */
+
+#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
+
+struct dsi_buf {
+	u32 *hdr;	/* dsi host header */
+	char *start;	/* buffer start addr */
+	char *end;	/* buffer end addr */
+	int size;	/* size of buffer */
+	char *data;	/* buffer */
+	int len;	/* data length */
+	dma_addr_t dmap; /* mapped dma addr */
+};
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE		0x05	/* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1	0x15	/* short write, 1 parameter */
+#define DTYPE_DCS_READ		0x06	/* read */
+#define DTYPE_DCS_LWRITE	0x39	/* long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE		0x03	/* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1	0x13	/* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2	0x23	/* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE	0x29	/* long write */
+#define DTYPE_GEN_READ		0x04	/* long read, 0 parameter */
+#define DTYPE_GEN_READ1		0x14	/* long read, 1 parameter */
+#define DTYPE_GEN_READ2		0x24	/* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON		0x35	/* set tear on */
+#define DTYPE_MAX_PKTSIZE	0x37	/* set max packet size */
+#define DTYPE_NULL_PKT		0x09	/* null packet, no data */
+#define DTYPE_BLANK_PKT		0x19	/* blankiing packet, no data */
+
+#define DTYPE_CM_ON		0x02	/* color mode off */
+#define DTYPE_CM_OFF		0x12	/* color mode on */
+#define DTYPE_PERIPHERAL_OFF	0x22
+#define DTYPE_PERIPHERAL_ON	0x32
+
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP      0x02
+#define DTYPE_EOT_RESP          0x08    /* end of tx */
+#define DTYPE_GEN_READ1_RESP    0x11    /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP    0x12    /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP    0x1a
+#define DTYPE_DCS_LREAD_RESP    0x1c
+#define DTYPE_DCS_READ1_RESP    0x21    /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP    0x22    /* 2 parameter, short */
+
+struct dsi_cmd_desc {
+	int dtype;
+	int last;
+	int vc;
+	int ack;	/* ask ACK from peripheral */
+	int wait;
+	int dlen;
+	char *payload;
+};
+
+struct dsi_kickoff_action {
+	struct list_head act_entry;
+	void (*action) (void *);
+	void *data;
+};
+
+struct mdss_panel_common_pdata {
+	struct mdss_panel_info panel_info;
+	int (*on) (struct mdss_panel_data *pdata);
+	int (*off) (struct mdss_panel_data *pdata);
+};
+
+int dsi_panel_device_register(struct platform_device *pdev,
+			      struct mdss_panel_common_pdata *panel_data);
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
+char *mdss_dsi_buf_init(struct dsi_buf *dp);
+void mdss_dsi_init(void);
+int mdss_dsi_buf_alloc(struct dsi_buf *, int size);
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
+		struct dsi_buf *dp, struct dsi_cmd_desc *cmds, int cnt);
+
+int mdss_dsi_cmd_dma_tx(struct dsi_buf *dp,
+				struct mdss_panel_data *pdata);
+int mdss_dsi_cmd_reg_tx(u32 data,
+				struct mdss_panel_data *pdata);
+int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_buf *rp,
+			struct dsi_cmd_desc *cmds, int len);
+int mdss_dsi_cmd_dma_rx(struct dsi_buf *tp, int rlen,
+				struct mdss_panel_data *pdata);
+void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
+				struct mdss_panel_data *pdata);
+void mdss_dsi_op_mode_config(int mode,
+				struct mdss_panel_data *pdata);
+void mdss_dsi_cmd_mode_ctrl(int enable);
+void mdp4_dsi_cmd_trigger(void);
+void mdss_dsi_cmd_mdp_start(void);
+void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
+void mdss_dsi_ack_err_status(unsigned char *dsi_base);
+void mdss_dsi_clk_enable(void);
+void mdss_dsi_clk_disable(void);
+void mdss_dsi_controller_cfg(int enable,
+				struct mdss_panel_data *pdata);
+void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
+
+irqreturn_t mdss_dsi_isr(int irq, void *ptr);
+
+void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
+int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
+			    u32 *expected_dsi_pclk);
+int mdss_dsi_clk_init(struct platform_device *pdev);
+void mdss_dsi_clk_deinit(struct device *dev);
+void mdss_dsi_prepare_clocks(void);
+void mdss_dsi_unprepare_clocks(void);
+void cont_splash_clk_ctrl(int enable);
+unsigned char *mdss_dsi_get_base_adr(void);
+
+#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
new file mode 100644
index 0000000..7bc0105
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -0,0 +1,1259 @@
+
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+
+#include "mdss.h"
+#include "mdss_dsi.h"
+
+static struct completion dsi_dma_comp;
+static int dsi_irq_enabled;
+static spinlock_t dsi_irq_lock;
+static spinlock_t dsi_mdp_lock;
+static int dsi_mdp_busy;
+
+spinlock_t dsi_clk_lock;
+
+struct mdss_hw mdss_dsi_hw = {
+	.hw_ndx = MDSS_HW_DSI0,
+	.irq_handler = mdss_dsi_isr,
+};
+
+void mdss_dsi_init(void)
+{
+	init_completion(&dsi_dma_comp);
+	spin_lock_init(&dsi_irq_lock);
+	spin_lock_init(&dsi_mdp_lock);
+	spin_lock_init(&dsi_clk_lock);
+}
+
+void mdss_dsi_enable_irq(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsi_irq_lock, flags);
+	if (dsi_irq_enabled) {
+		pr_debug("%s: IRQ aleady enabled\n", __func__);
+		spin_unlock_irqrestore(&dsi_irq_lock, flags);
+		return;
+	}
+	mdss_enable_irq(&mdss_dsi_hw);
+	dsi_irq_enabled = 1;
+	/* TO DO: Check whether MDSS IRQ is enabled */
+	spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+void mdss_dsi_disable_irq(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsi_irq_lock, flags);
+	if (dsi_irq_enabled == 0) {
+		pr_debug("%s: IRQ already disabled\n", __func__);
+		spin_unlock_irqrestore(&dsi_irq_lock, flags);
+		return;
+	}
+	mdss_disable_irq(&mdss_dsi_hw);
+	dsi_irq_enabled = 0;
+	/* TO DO: Check whether MDSS IRQ is Disabled */
+	spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+/*
+ * mdss_dsi_disale_irq_nosync() should be called
+ * from interrupt context
+ */
+void mdss_dsi_disable_irq_nosync(void)
+{
+	spin_lock(&dsi_irq_lock);
+	if (dsi_irq_enabled == 0) {
+		pr_debug("%s: IRQ cannot be disabled\n", __func__);
+		spin_unlock(&dsi_irq_lock);
+		return;
+	}
+
+	dsi_irq_enabled = 0;
+	spin_unlock(&dsi_irq_lock);
+}
+
+/*
+ * mipi dsi buf mechanism
+ */
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+	dp->data += len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
+{
+	dp->data -= len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
+{
+	dp->data -= len;
+	dp->len += len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+	dp->hdr = (u32 *)dp->data;
+	return mdss_dsi_buf_reserve(dp, hlen);
+}
+
+char *mdss_dsi_buf_init(struct dsi_buf *dp)
+{
+	int off;
+
+	dp->data = dp->start;
+	off = (int)dp->data;
+	/* 8 byte align */
+	off &= 0x07;
+	if (off)
+		off = 8 - off;
+	dp->data += off;
+	dp->len = 0;
+	return dp->data;
+}
+
+int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+
+	dp->start = kmalloc(size, GFP_KERNEL);
+	if (dp->start == NULL) {
+		pr_err("%s:%u\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	dp->end = dp->start + size;
+	dp->size = size;
+
+	if ((int)dp->start & 0x07)
+		pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+
+	dp->data = dp->start;
+	dp->len = 0;
+	return size;
+}
+
+/*
+ * mipi dsi generic long write
+ */
+static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	char *bp;
+	u32 *hp;
+	int i, len;
+
+	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/* fill up payload */
+	if (cm->payload) {
+		len = cm->dlen;
+		len += 3;
+		len &= ~0x03;	/* multipled by 4 */
+		for (i = 0; i < cm->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+
+	len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return dp->len;	/* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	char *bp;
+	u32 *hp;
+	int i, len;
+
+	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/*
+	 * fill up payload
+	 * dcs command byte (first byte) followed by payload
+	 */
+	if (cm->payload) {
+		len = cm->dlen;
+		len += 3;
+		len &= ~0x03;	/* multipled by 4 */
+		for (i = 0; i < cm->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	if (cm->ack)		/* ask ACK trigger msg from peripeheral */
+		*hp |= DSI_HDR_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (cm->dlen > 1) ? 1 : cm->dlen;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->dlen < 2 || cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	if (cm->ack)		/* ask ACK trigger msg from peripeheral */
+		*hp |= DSI_HDR_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs comamnd byte */
+	*hp |= DSI_HDR_DATA2(cm->payload[1]);	/* parameter */
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+
+static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_BTA;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);
+	*hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;	/* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	int len = 0;
+
+	switch (cm->dtype) {
+	case DTYPE_GEN_WRITE:
+	case DTYPE_GEN_WRITE1:
+	case DTYPE_GEN_WRITE2:
+		len = mdss_dsi_generic_swrite(dp, cm);
+		break;
+	case DTYPE_GEN_LWRITE:
+		len = mdss_dsi_generic_lwrite(dp, cm);
+		break;
+	case DTYPE_GEN_READ:
+	case DTYPE_GEN_READ1:
+	case DTYPE_GEN_READ2:
+		len = mdss_dsi_generic_read(dp, cm);
+		break;
+	case DTYPE_DCS_LWRITE:
+		len = mdss_dsi_dcs_lwrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE:
+		len = mdss_dsi_dcs_swrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE1:
+		len = mdss_dsi_dcs_swrite1(dp, cm);
+		break;
+	case DTYPE_DCS_READ:
+		len = mdss_dsi_dcs_read(dp, cm);
+		break;
+	case DTYPE_MAX_PKTSIZE:
+		len = mdss_dsi_set_max_pktsize(dp, cm);
+		break;
+	case DTYPE_NULL_PKT:
+		len = mdss_dsi_null_pkt(dp, cm);
+		break;
+	case DTYPE_BLANK_PKT:
+		len = mdss_dsi_blank_pkt(dp, cm);
+		break;
+	case DTYPE_CM_ON:
+		len = mdss_dsi_cm_on(dp, cm);
+		break;
+	case DTYPE_CM_OFF:
+		len = mdss_dsi_cm_off(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_ON:
+		len = mdss_dsi_peripheral_on(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_OFF:
+		len = mdss_dsi_peripheral_off(dp, cm);
+		break;
+	default:
+		pr_debug("%s: dtype=%x NOT supported\n",
+					__func__, cm->dtype);
+		break;
+
+	}
+
+	return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+static int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 1;
+	return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+static int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 2;
+	return rp->len;
+}
+
+static int mdss_dsi_long_read_resp(struct dsi_buf *rp)
+{
+	short len;
+
+	len = rp->data[2];
+	len <<= 8;
+	len |= rp->data[1];
+	/* strip out dcs header */
+	rp->data += 4;
+	rp->len -= 4;
+	/* strip out 2 bytes of checksum */
+	rp->len -= 2;
+	return len;
+}
+
+void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
+				struct mdss_panel_data *pdata)
+{
+	u32 dsi_ctrl, intr_ctrl;
+	u32 data;
+
+	pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+
+	if (pinfo->mode == DSI_VIDEO_MODE) {
+		data = 0;
+		if (pinfo->pulse_mode_hsa_he)
+			data |= BIT(28);
+		if (pinfo->hfp_power_stop)
+			data |= BIT(24);
+		if (pinfo->hbp_power_stop)
+			data |= BIT(20);
+		if (pinfo->hsa_power_stop)
+			data |= BIT(16);
+		if (pinfo->eof_bllp_power_stop)
+			data |= BIT(15);
+		if (pinfo->bllp_power_stop)
+			data |= BIT(12);
+		data |= ((pinfo->traffic_mode & 0x03) << 8);
+		data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
+		data |= (pinfo->vc & 0x03);
+		MIPI_OUTP((pdata->dsi_base) + 0x0010, data);
+
+		data = 0;
+		data |= ((pinfo->rgb_swap & 0x07) << 12);
+		if (pinfo->b_sel)
+			data |= BIT(8);
+		if (pinfo->g_sel)
+			data |= BIT(4);
+		if (pinfo->r_sel)
+			data |= BIT(0);
+		MIPI_OUTP((pdata->dsi_base) + 0x0020, data);
+	} else if (pinfo->mode == DSI_CMD_MODE) {
+		data = 0;
+		data |= ((pinfo->interleave_max & 0x0f) << 20);
+		data |= ((pinfo->rgb_swap & 0x07) << 16);
+		if (pinfo->b_sel)
+			data |= BIT(12);
+		if (pinfo->g_sel)
+			data |= BIT(8);
+		if (pinfo->r_sel)
+			data |= BIT(4);
+		data |= (pinfo->dst_format & 0x0f);	/* 4 bits */
+		MIPI_OUTP((pdata->dsi_base) + 0x003c, data);
+
+		/* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
+		data = pinfo->wr_mem_continue & 0x0ff;
+		data <<= 8;
+		data |= (pinfo->wr_mem_start & 0x0ff);
+		if (pinfo->insert_dcs_cmd)
+			data |= BIT(16);
+		MIPI_OUTP((pdata->dsi_base) + 0x0044, data);
+	} else
+		pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
+
+	dsi_ctrl = BIT(8) | BIT(2);	/* clock enable & cmd mode */
+	intr_ctrl = 0;
+	intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
+
+	if (pinfo->crc_check)
+		dsi_ctrl |= BIT(24);
+	if (pinfo->ecc_check)
+		dsi_ctrl |= BIT(20);
+	if (pinfo->data_lane3)
+		dsi_ctrl |= BIT(7);
+	if (pinfo->data_lane2)
+		dsi_ctrl |= BIT(6);
+	if (pinfo->data_lane1)
+		dsi_ctrl |= BIT(5);
+	if (pinfo->data_lane0)
+		dsi_ctrl |= BIT(4);
+
+	/* from frame buffer, low power mode */
+	/* DSI_COMMAND_MODE_DMA_CTRL */
+	MIPI_OUTP((pdata->dsi_base) + 0x3C, 0x14000000);
+
+	data = 0;
+	if (pinfo->te_sel)
+		data |= BIT(31);
+	data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
+	data |= pinfo->dma_trigger;	/* cmd dma trigger */
+	data |= (pinfo->stream & 0x01) << 8;
+	MIPI_OUTP((pdata->dsi_base) + 0x0084, data); /* DSI_TRIG_CTRL */
+
+	/* DSI_LAN_SWAP_CTRL */
+	MIPI_OUTP((pdata->dsi_base) + 0x00b0, pinfo->dlane_swap);
+
+	/* clock out ctrl */
+	data = pinfo->t_clk_post & 0x3f;	/* 6 bits */
+	data <<= 8;
+	data |= pinfo->t_clk_pre & 0x3f;	/*  6 bits */
+	/* DSI_CLKOUT_TIMING_CTRL */
+	MIPI_OUTP((pdata->dsi_base) + 0xc4, data);
+
+	data = 0;
+	if (pinfo->rx_eot_ignore)
+		data |= BIT(4);
+	if (pinfo->tx_eot_append)
+		data |= BIT(0);
+	MIPI_OUTP((pdata->dsi_base) + 0x00cc, data); /* DSI_EOT_PACKET_CTRL */
+
+
+	/* allow only ack-err-status  to generate interrupt */
+	/* DSI_ERR_INT_MASK0 */
+	MIPI_OUTP((pdata->dsi_base) + 0x010c, 0x13ff3fe0);
+
+	intr_ctrl |= DSI_INTR_ERROR_MASK;
+	MIPI_OUTP((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
+
+	/* turn esc, byte, dsi, pclk, sclk, hclk on */
+	MIPI_OUTP((pdata->dsi_base) + 0x11c, 0x23f); /* DSI_CLK_CTRL */
+
+	dsi_ctrl |= BIT(0);	/* enable dsi */
+	MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+
+	wmb();
+}
+
+void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
+{
+	u32 data = MIPI_INP((pdata->dsi_base) + 0x3c);
+
+	if (mode == 0)
+		data &= ~BIT(26);
+	else
+		data |= BIT(26);
+
+	MIPI_OUTP((pdata->dsi_base) + 0x3c, data);
+}
+
+void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
+{
+	MIPI_OUTP((pdata->dsi_base) + 0x118, 0x01);
+	wmb();
+	MIPI_OUTP((pdata->dsi_base) + 0x118, 0x00);
+	wmb();
+}
+
+void mdss_dsi_controller_cfg(int enable,
+			     struct mdss_panel_data *pdata)
+{
+
+	u32 dsi_ctrl;
+	u32 status;
+	u32 sleep_us = 1000;
+	u32 timeout_us = 16000;
+
+	/* Check for CMD_MODE_DMA_BUSY */
+	if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+			   status,
+			   ((status & 0x02) == 0),
+			       sleep_us, timeout_us))
+		pr_info("%s: DSI status=%x failed\n", __func__, status);
+
+	/* Check for x_HS_FIFO_EMPTY */
+	if (readl_poll_timeout(((pdata->dsi_base) + 0x000c),
+			   status,
+			   ((status & 0x11111000) == 0x11111000),
+			       sleep_us, timeout_us))
+		pr_info("%s: FIFO status=%x failed\n", __func__, status);
+
+	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	if (enable)
+		dsi_ctrl |= 0x01;
+	else
+		dsi_ctrl &= ~0x01;
+
+	MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+	wmb();
+}
+
+void mdss_dsi_op_mode_config(int mode,
+			     struct mdss_panel_data *pdata)
+{
+
+	u32 dsi_ctrl, intr_ctrl;
+
+	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	dsi_ctrl &= ~0x07;
+	if (mode == DSI_VIDEO_MODE) {
+		dsi_ctrl |= 0x03;
+		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+	} else {		/* command mode */
+		dsi_ctrl |= 0x05;
+		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
+				DSI_INTR_CMD_MDP_DONE_MASK;
+	}
+
+	pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
+
+	MIPI_OUTP((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
+	MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+	wmb();
+}
+
+void mdss_dsi_cmd_mdp_start(void)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&dsi_mdp_lock, flag);
+	mdss_dsi_enable_irq();
+	dsi_mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+}
+
+
+void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata)
+{
+	u32 status;
+	int timeout_us = 10000;
+
+	MIPI_OUTP((pdata->dsi_base) + 0x098, 0x01);	/* trigger */
+	wmb();
+
+	/* Check for CMD_MODE_DMA_BUSY */
+	if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+				status, ((status & 0x0010) == 0),
+				0, timeout_us))
+		pr_info("%s: DSI status=%x failed\n", __func__, status);
+
+	mdss_dsi_ack_err_status((pdata->dsi_base));
+
+	pr_debug("%s: BTA done, status = %d\n", __func__, status);
+}
+
+int mdss_dsi_cmd_reg_tx(u32 data,
+			struct mdss_panel_data *pdata)
+{
+	int i;
+	char *bp;
+
+	bp = (char *)&data;
+	pr_debug("%s: ", __func__);
+	for (i = 0; i < 4; i++)
+		pr_debug("%x ", *bp++);
+
+	pr_debug("\n");
+
+	MIPI_OUTP((pdata->dsi_base) + 0x0084, 0x04);/* sw trigger */
+	MIPI_OUTP((pdata->dsi_base) + 0x0004, 0x135);
+
+	wmb();
+
+	MIPI_OUTP((pdata->dsi_base) + 0x03c, data);
+	wmb();
+	MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01);	/* trigger */
+	wmb();
+
+	udelay(300);
+
+	return 4;
+}
+
+/*
+ * mdss_dsi_cmds_tx:
+ * ov_mutex need to be acquired before call this function.
+ */
+int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
+		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+	struct dsi_cmd_desc *cm;
+	u32 dsi_ctrl, ctrl;
+	int i, video_mode;
+	unsigned long flag;
+
+	/* turn on cmd mode
+	* for video mode, do not send cmds more than
+	* one pixel line, since it only transmit it
+	* during BLLP.
+	*/
+	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+	if (video_mode) {
+		ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+		MIPI_OUTP((pdata->dsi_base) + 0x0004, ctrl);
+	}
+
+	spin_lock_irqsave(&dsi_mdp_lock, flag);
+	mdss_dsi_enable_irq();
+	dsi_mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+	cm = cmds;
+	mdss_dsi_buf_init(tp);
+	for (i = 0; i < cnt; i++) {
+		mdss_dsi_buf_init(tp);
+		mdss_dsi_cmd_dma_add(tp, cm);
+		mdss_dsi_cmd_dma_tx(tp, pdata);
+		if (cm->wait)
+			msleep(cm->wait);
+		cm++;
+	}
+
+	spin_lock_irqsave(&dsi_mdp_lock, flag);
+	dsi_mdp_busy = false;
+	mdss_dsi_disable_irq();
+	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+	if (video_mode)
+		MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl); /* restore */
+
+	return cnt;
+}
+
+/* MDSS_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd[] = {
+	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
+		sizeof(max_pktsize), max_pktsize}
+};
+
+/*
+ * DSI panel reply with  MAX_RETURN_PACKET_SIZE bytes of data
+ * plus DCS header, ECC and CRC for DCS long read response
+ * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
+ * hold data per transaction.
+ * MDSS_DSI_LEN equal to 8
+ * len should be either 4 or 8
+ * any return data more than MDSS_DSI_LEN need to be break down
+ * to multiple transactions.
+ *
+ * ov_mutex need to be acquired before call this function.
+ */
+int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_buf *rp,
+			struct dsi_cmd_desc *cmds, int rlen)
+{
+	int cnt, len, diff, pkt_size;
+	unsigned long flag;
+	char cmd;
+
+	if (pdata->panel_info.mipi.no_max_pkt_size)
+		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
+
+	len = rlen;
+	diff = 0;
+
+	if (len <= 2)
+		cnt = 4;	/* short read */
+	else {
+		if (len > MDSS_DSI_LEN)
+			len = MDSS_DSI_LEN;	/* 8 bytes at most */
+
+		len = ALIGN(len, 4); /* len 4 bytes align */
+		diff = len - rlen;
+		/*
+		 * add extra 2 bytes to len to have overall
+		 * packet size is multipe by 4. This also make
+		 * sure 4 bytes dcs headerlocates within a
+		 * 32 bits register after shift in.
+		 * after all, len should be either 6 or 10.
+		 */
+		len += 2;
+		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
+	}
+
+	spin_lock_irqsave(&dsi_mdp_lock, flag);
+	mdss_dsi_enable_irq();
+	dsi_mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+	if (!pdata->panel_info.mipi.no_max_pkt_size) {
+		/* packet size need to be set at every read */
+		pkt_size = len;
+		max_pktsize[0] = pkt_size;
+		mdss_dsi_buf_init(tp);
+		mdss_dsi_cmd_dma_add(tp, pkt_size_cmd);
+		mdss_dsi_cmd_dma_tx(tp, pdata);
+	}
+
+	mdss_dsi_buf_init(tp);
+	mdss_dsi_cmd_dma_add(tp, cmds);
+
+	/* transmit read comamnd to client */
+	mdss_dsi_cmd_dma_tx(tp, pdata);
+	/*
+	 * once cmd_dma_done interrupt received,
+	 * return data from client is ready and stored
+	 * at RDBK_DATA register already
+	 */
+	mdss_dsi_buf_init(rp);
+	if (pdata->panel_info.mipi.no_max_pkt_size) {
+		/*
+		 * expect rlen = n * 4
+		 * short alignement for start addr
+		 */
+		rp->data += 2;
+	}
+
+	mdss_dsi_cmd_dma_rx(rp, cnt, pdata);
+
+	spin_lock_irqsave(&dsi_mdp_lock, flag);
+	dsi_mdp_busy = false;
+	mdss_dsi_disable_irq();
+	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+	if (pdata->panel_info.mipi.no_max_pkt_size) {
+		/*
+		 * remove extra 2 bytes from previous
+		 * rx transaction at shift register
+		 * which was inserted during copy
+		 * shift registers to rx buffer
+		 * rx payload start from long alignment addr
+		 */
+		rp->data += 2;
+	}
+
+	cmd = rp->data[0];
+	switch (cmd) {
+	case DTYPE_ACK_ERR_RESP:
+		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+		break;
+	case DTYPE_GEN_READ1_RESP:
+	case DTYPE_DCS_READ1_RESP:
+		mdss_dsi_short_read1_resp(rp);
+		break;
+	case DTYPE_GEN_READ2_RESP:
+	case DTYPE_DCS_READ2_RESP:
+		mdss_dsi_short_read2_resp(rp);
+		break;
+	case DTYPE_GEN_LREAD_RESP:
+	case DTYPE_DCS_LREAD_RESP:
+		mdss_dsi_long_read_resp(rp);
+		rp->len -= 2; /* extra 2 bytes added */
+		rp->len -= diff; /* align bytes */
+		break;
+	default:
+		break;
+	}
+
+	return rp->len;
+}
+
+int mdss_dsi_cmd_dma_tx(struct dsi_buf *tp,
+			struct mdss_panel_data *pdata)
+{
+	int len;
+	int i;
+	char *bp;
+
+	bp = tp->data;
+
+	pr_debug("%s: ", __func__);
+	for (i = 0; i < tp->len; i++)
+		pr_debug("%x ", *bp++);
+
+	pr_debug("\n");
+
+	len = tp->len;
+	len += 3;
+	len &= ~0x03;	/* multipled by 4 */
+
+	tp->dmap = dma_map_single(&dsi_dev, tp->data, len, DMA_TO_DEVICE);
+	if (dma_mapping_error(&dsi_dev, tp->dmap))
+		pr_err("%s: dmap mapp failed\n", __func__);
+
+	INIT_COMPLETION(dsi_dma_comp);
+
+	MIPI_OUTP((pdata->dsi_base) + 0x048, tp->dmap);
+	MIPI_OUTP((pdata->dsi_base) + 0x04c, len);
+	wmb();
+
+	MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01);	/* trigger */
+	wmb();
+
+	wait_for_completion(&dsi_dma_comp);
+
+	dma_unmap_single(&dsi_dev, tp->dmap, len, DMA_TO_DEVICE);
+	tp->dmap = 0;
+	return tp->len;
+}
+
+int mdss_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen,
+			struct mdss_panel_data *pdata)
+{
+	u32 *lp, data;
+	int i, off, cnt;
+
+	lp = (u32 *)rp->data;
+	cnt = rlen;
+	cnt += 3;
+	cnt >>= 2;
+
+	if (cnt > 4)
+		cnt = 4; /* 4 x 32 bits registers only */
+
+	off = 0x06c;	/* DSI_RDBK_DATA0 */
+	off += ((cnt - 1) * 4);
+
+
+	for (i = 0; i < cnt; i++) {
+		data = (u32)MIPI_INP((pdata->dsi_base) + off);
+		*lp++ = ntohl(data);	/* to network byte order */
+		off -= 4;
+		rp->len += sizeof(*lp);
+	}
+
+	return rlen;
+}
+
+void mdss_dsi_ack_err_status(unsigned char *dsi_base)
+{
+	u32 status;
+
+	status = MIPI_INP(dsi_base + 0x0068);/* DSI_ACK_ERR_STATUS */
+
+	if (status) {
+		MIPI_OUTP(dsi_base + 0x0068, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void mdss_dsi_timeout_status(unsigned char *dsi_base)
+{
+	u32 status;
+
+	status = MIPI_INP(dsi_base + 0x00c0);/* DSI_TIMEOUT_STATUS */
+	if (status & 0x0111) {
+		MIPI_OUTP(dsi_base + 0x00c0, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void mdss_dsi_dln0_phy_err(unsigned char *dsi_base)
+{
+	u32 status;
+
+	status = MIPI_INP(dsi_base + 0x00b4);/* DSI_DLN0_PHY_ERR */
+
+	if (status & 0x011111) {
+		MIPI_OUTP(dsi_base + 0x00b4, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void mdss_dsi_fifo_status(unsigned char *dsi_base)
+{
+	u32 status;
+
+	status = MIPI_INP(dsi_base + 0x000c);/* DSI_FIFO_STATUS */
+
+	if (status & 0x44444489) {
+		MIPI_OUTP(dsi_base + 0x000c, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void mdss_dsi_status(unsigned char *dsi_base)
+{
+	u32 status;
+
+	status = MIPI_INP(dsi_base + 0x0008);/* DSI_STATUS */
+
+	if (status & 0x80000000) {
+		MIPI_OUTP(dsi_base + 0x0008, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void mdss_dsi_error(unsigned char *dsi_base)
+{
+	/* DSI_ERR_INT_MASK0 */
+	mdss_dsi_ack_err_status(dsi_base);	/* mask0, 0x01f */
+	mdss_dsi_timeout_status(dsi_base);	/* mask0, 0x0e0 */
+	mdss_dsi_fifo_status(dsi_base);		/* mask0, 0x133d00 */
+	mdss_dsi_status(dsi_base);		/* mask0, 0xc0100 */
+	mdss_dsi_dln0_phy_err(dsi_base);	/* mask0, 0x3e00000 */
+}
+
+
+irqreturn_t mdss_dsi_isr(int irq, void *ptr)
+{
+	u32 isr;
+	unsigned char *dsi_base;
+
+	dsi_base = mdss_dsi_get_base_adr();
+	if (!dsi_base)
+		pr_err("%s:%d DSI base adr no Initialized",
+				       __func__, __LINE__);
+
+	isr = MIPI_INP(dsi_base + 0x0110);/* DSI_INTR_CTRL */
+	MIPI_OUTP(dsi_base + 0x0110, isr);
+
+	if (isr & DSI_INTR_ERROR)
+		mdss_dsi_error(dsi_base);
+
+	if (isr & DSI_INTR_VIDEO_DONE) {
+		/*
+		* do something  here
+		*/
+	}
+
+	if (isr & DSI_INTR_CMD_DMA_DONE)
+		complete(&dsi_dma_comp);
+
+	if (isr & DSI_INTR_CMD_MDP_DONE) {
+		spin_lock(&dsi_mdp_lock);
+		dsi_mdp_busy = false;
+		mdss_dsi_disable_irq_nosync();
+		spin_unlock(&dsi_mdp_lock);
+	}
+
+	return IRQ_HANDLED;
+}
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
new file mode 100644
index 0000000..bfb7fae
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -0,0 +1,358 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "mdss_dsi.h"
+
+#define DT_CMD_HDR 6
+
+static struct dsi_buf dsi_panel_tx_buf;
+static struct dsi_buf dsi_panel_rx_buf;
+
+static struct dsi_cmd_desc *dsi_panel_on_cmds;
+static struct dsi_cmd_desc *dsi_panel_off_cmds;
+static int num_of_on_cmds;
+static int num_of_off_cmds;
+static char *on_cmds, *off_cmds;
+
+static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
+{
+	struct mipi_panel_info *mipi;
+
+	mipi  = &pdata->panel_info.mipi;
+
+	pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
+		 mipi->mode);
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
+			num_of_on_cmds);
+	} else {
+		pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
+{
+	struct mipi_panel_info *mipi;
+
+	mipi  = &pdata->panel_info.mipi;
+
+	pr_debug("%s:%d, debug info\n", __func__, __LINE__);
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_off_cmds,
+			num_of_off_cmds);
+	} else {
+		pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mdss_panel_parse_dt(struct platform_device *pdev,
+			    struct mdss_panel_common_pdata *panel_data)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 res[6], tmp;
+	int rc, i, len;
+	int cmd_plen, data_offset;
+	const char *data;
+
+	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
+	if (rc) {
+		pr_err("%s:%d, panel resolution not specified\n",
+						__func__, __LINE__);
+		return -EINVAL;
+	}
+	panel_data->panel_info.xres = (!rc ? res[0] : 640);
+	panel_data->panel_info.yres = (!rc ? res[1] : 480);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
+	if (rc) {
+		pr_err("%s:%d, panel bpp not specified\n",
+						__func__, __LINE__);
+		return -EINVAL;
+	}
+	panel_data->panel_info.bpp = (!rc ? tmp : 24);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-porch-values", res, 6);
+	panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
+	panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
+	panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
+	panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
+	panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
+	panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-underflow-clr", &tmp);
+	panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-bl-levels", res, 2);
+	panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
+	panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
+	panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-h-power-stop", res, 3);
+	panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
+	panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
+	panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
+	panel_data->panel_info.mipi.bllp_power_stop =
+					(!rc ? res[0] : false);
+	panel_data->panel_info.mipi.eof_bllp_power_stop =
+					(!rc ? res[1] : false);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-traffic-mode", &tmp);
+	panel_data->panel_info.mipi.traffic_mode =
+			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-dst-format", &tmp);
+	panel_data->panel_info.mipi.dst_format =
+			(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-data-lanes", res, 4);
+	panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
+	panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
+	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
+	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
+
+	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
+	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
+	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+	panel_data->panel_info.mipi.mdp_trigger =
+			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
+	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+		pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
+						 __func__, __LINE__);
+		panel_data->panel_info.mipi.mdp_trigger =
+					DSI_CMD_TRIGGER_SW;
+	}
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+	panel_data->panel_info.mipi.dma_trigger =
+			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
+	if (panel_data->panel_info.mipi.dma_trigger > 6) {
+		pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
+						 __func__, __LINE__);
+		panel_data->panel_info.mipi.dma_trigger =
+					DSI_CMD_TRIGGER_SW;
+	}
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+
+	data = of_get_property(np, "qcom,panel-on-cmds", &len);
+	if (!data) {
+		pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
+		goto error;
+	}
+
+	on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+	if (!on_cmds)
+		return -ENOMEM;
+
+	memcpy(on_cmds, data, len);
+
+	data_offset = 0;
+	cmd_plen = 0;
+	while ((len - data_offset) >= DT_CMD_HDR) {
+		data_offset += (DT_CMD_HDR - 1);
+		cmd_plen = on_cmds[data_offset++];
+		data_offset += cmd_plen;
+		num_of_on_cmds++;
+	}
+	if (!num_of_on_cmds) {
+		pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
+		goto error;
+	}
+
+	dsi_panel_on_cmds =
+		kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
+						GFP_KERNEL);
+	if (!dsi_panel_on_cmds)
+		return -ENOMEM;
+
+	data_offset = 0;
+	for (i = 0; i < num_of_on_cmds; i++) {
+		dsi_panel_on_cmds[i].dtype = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].last = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].vc = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].ack = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].wait = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].dlen = on_cmds[data_offset++];
+		dsi_panel_on_cmds[i].payload = &on_cmds[data_offset];
+		data_offset += (dsi_panel_on_cmds[i].dlen);
+	}
+
+	if (data_offset != len) {
+		pr_err("%s:%d, Incorrect ON command entries",
+						__func__, __LINE__);
+		goto error;
+	}
+
+	data = of_get_property(np, "qcom,panel-off-cmds", &len);
+	if (!data) {
+		pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
+		goto error;
+	}
+
+	off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+	if (!off_cmds)
+		return -ENOMEM;
+
+	memcpy(off_cmds, data, len);
+
+	data_offset = 0;
+	cmd_plen = 0;
+	while ((len - data_offset) >= DT_CMD_HDR) {
+		data_offset += (DT_CMD_HDR - 1);
+		cmd_plen = off_cmds[data_offset++];
+		data_offset += cmd_plen;
+		num_of_off_cmds++;
+	}
+	if (!num_of_off_cmds) {
+		pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
+		goto error;
+	}
+
+	dsi_panel_off_cmds = kzalloc(num_of_off_cmds
+				* sizeof(struct dsi_cmd_desc),
+					GFP_KERNEL);
+	if (!dsi_panel_off_cmds)
+		return -ENOMEM;
+
+	data_offset = 0;
+	for (i = 0; i < num_of_off_cmds; i++) {
+		dsi_panel_off_cmds[i].dtype = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].last = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].vc = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].ack = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].wait = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].dlen = off_cmds[data_offset++];
+		dsi_panel_off_cmds[i].payload = &off_cmds[data_offset];
+		data_offset += (dsi_panel_off_cmds[i].dlen);
+	}
+
+	if (data_offset != len) {
+		pr_err("%s:%d, Incorrect OFF command entries",
+						__func__, __LINE__);
+		goto error;
+	}
+
+	return 0;
+error:
+	kfree(dsi_panel_on_cmds);
+	kfree(dsi_panel_off_cmds);
+	kfree(on_cmds);
+	kfree(off_cmds);
+
+	return -EINVAL;
+}
+
+static int __devinit mdss_dsi_panel_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct mdss_panel_common_pdata *vendor_pdata = NULL;
+	static const char *panel_name;
+
+	if (pdev->dev.parent == NULL) {
+		pr_err("%s: parent device missing\n", __func__);
+		return -ENODEV;
+	}
+
+	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
+	if (!panel_name)
+		pr_info("%s:%d, panel name not specified\n",
+						__func__, __LINE__);
+	else
+		pr_info("%s: Panel Name = %s\n", __func__, panel_name);
+
+	vendor_pdata = devm_kzalloc(&pdev->dev,
+			sizeof(*vendor_pdata), GFP_KERNEL);
+	if (!vendor_pdata)
+		return -ENOMEM;
+
+	rc = mdss_panel_parse_dt(pdev, vendor_pdata);
+	if (rc) {
+		devm_kfree(&pdev->dev, vendor_pdata);
+		vendor_pdata = NULL;
+		return rc;
+	}
+	vendor_pdata->on = mdss_dsi_panel_on;
+	vendor_pdata->off = mdss_dsi_panel_off;
+
+	rc = dsi_panel_device_register(pdev, vendor_pdata);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static const struct of_device_id mdss_dsi_panel_match[] = {
+	{.compatible = "qcom,mdss-dsi-panel"},
+	{}
+};
+
+static struct platform_driver this_driver = {
+	.probe  = mdss_dsi_panel_probe,
+	.driver = {
+		.name   = "dsi_panel",
+		.of_match_table = mdss_dsi_panel_match,
+	},
+};
+
+static int __init mdss_dsi_panel_init(void)
+{
+	mdss_dsi_buf_alloc(&dsi_panel_tx_buf, DSI_BUF_SIZE);
+	mdss_dsi_buf_alloc(&dsi_panel_rx_buf, DSI_BUF_SIZE);
+
+	return platform_driver_register(&this_driver);
+}
+module_init(mdss_dsi_panel_init);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 4ca1dce..8825cc6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -375,6 +375,7 @@
 #define MDSS_MDP_REG_INTF_FRAME_LINE_COUNT_EN		0x0A8
 #define MDSS_MDP_REG_INTF_FRAME_COUNT			0x0AC
 #define MDSS_MDP_REG_INTF_LINE_COUNT			0x0B0
+#define MDSS_MDP_PANEL_FORMAT_RGB888			0x213F
 
 enum mdss_mdp_pingpong_index {
 	MDSS_MDP_PINGPONG0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 21ef290..2f0a1f5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -135,6 +135,8 @@
 			   p->hsync_skew);
 	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_POLARITY_CTL,
 			   polarity_ctl);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_PANEL_FORMAT,
+			   MDSS_MDP_PANEL_FORMAT_RGB888);
 
 	return 0;
 }
@@ -297,14 +299,14 @@
 	itp.underflow_clr = pinfo->lcdc.underflow_clr;
 	itp.hsync_skew = pinfo->lcdc.hsync_skew;
 
-	itp.xres = fbi->var.xres;
-	itp.yres = fbi->var.yres;
-	itp.h_back_porch = fbi->var.left_margin;
-	itp.h_front_porch = fbi->var.right_margin;
-	itp.v_back_porch = fbi->var.upper_margin;
-	itp.v_front_porch = fbi->var.lower_margin;
-	itp.hsync_pulse_width = fbi->var.hsync_len;
-	itp.vsync_pulse_width = fbi->var.vsync_len;
+	itp.xres =  pinfo->xres;
+	itp.yres = pinfo->yres;
+	itp.h_back_porch =  pinfo->lcdc.h_back_porch;
+	itp.h_front_porch =  pinfo->lcdc.h_front_porch;
+	itp.v_back_porch =  pinfo->lcdc.v_back_porch;
+	itp.v_front_porch = pinfo->lcdc.h_front_porch;
+	itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
+	itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
 
 	if (mdss_mdp_video_timegen_setup(ctl, &itp)) {
 		pr_err("unable to get timing parameters\n");
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 0411d8e..3ec3a5d 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -167,6 +167,7 @@
 struct mdss_panel_data {
 	struct mdss_panel_info panel_info;
 	void (*set_backlight) (u32 bl_level);
+	unsigned char *dsi_base;
 
 	/* function entry chain */
 	int (*on) (struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
new file mode 100644
index 0000000..c766ec7
--- /dev/null
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+
+#include "mdss_dsi.h"
+
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+#define PWRDN_B BIT(7)
+
+static struct dsi_clk_desc dsi_pclk;
+
+static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_esc_clk;
+
+int mdss_dsi_clk_on;
+
+int mdss_dsi_clk_init(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	dsi_byte_div_clk = clk_get(dev, "byte_clk");
+	if (IS_ERR(dsi_byte_div_clk)) {
+		pr_err("can't find dsi_byte_div_clk\n");
+		dsi_byte_div_clk = NULL;
+		goto mdss_dsi_clk_err;
+	}
+
+	dsi_esc_clk = clk_get(dev, "core_clk");
+	if (IS_ERR(dsi_esc_clk)) {
+		printk(KERN_ERR "can't find dsi_esc_clk\n");
+		dsi_esc_clk = NULL;
+		goto mdss_dsi_clk_err;
+	}
+
+	return 0;
+
+mdss_dsi_clk_err:
+	mdss_dsi_clk_deinit(dev);
+	return -EPERM;
+}
+
+void mdss_dsi_clk_deinit(struct device *dev)
+{
+	if (dsi_byte_div_clk)
+		clk_put(dsi_byte_div_clk);
+	if (dsi_esc_clk)
+		clk_put(dsi_esc_clk);
+}
+
+#define PREF_DIV_RATIO 27
+struct dsiphy_pll_divider_config pll_divider_config;
+
+int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
+			    u32 *expected_dsi_pclk)
+{
+	u32 fb_divider, rate, vco;
+	u32 div_ratio = 0;
+	u32 pll_analog_posDiv = 1;
+	struct dsi_clk_mnd_table const *mnd_entry = mnd_table;
+	if (pll_divider_config.clk_rate == 0)
+		pll_divider_config.clk_rate = 454000000;
+
+	rate = (pll_divider_config.clk_rate / 2)
+			 / 1000000; /* Half Bit Clock In Mhz */
+
+	if (rate < 43) {
+		vco = rate * 16;
+		div_ratio = 16;
+		pll_analog_posDiv = 8;
+	} else if (rate < 85) {
+		vco = rate * 8;
+		div_ratio = 8;
+		pll_analog_posDiv = 4;
+	} else if (rate < 170) {
+		vco = rate * 4;
+		div_ratio = 4;
+		pll_analog_posDiv = 2;
+	} else if (rate < 340) {
+		vco = rate * 2;
+		div_ratio = 2;
+		pll_analog_posDiv = 1;
+	} else {
+		/* DSI PLL Direct path configuration */
+		vco = rate * 1;
+		div_ratio = 1;
+		pll_analog_posDiv = 1;
+	}
+
+	/* find the mnd settings from mnd_table entry */
+	for (; mnd_entry != mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
+		if (((mnd_entry->lanes) == lanes) &&
+			((mnd_entry->bpp) == bpp))
+			break;
+	}
+
+	if (mnd_entry == mnd_table + ARRAY_SIZE(mnd_table)) {
+		pr_err("%s: requested Lanes, %u & BPP, %u, not supported\n",
+			__func__, lanes, bpp);
+		return -EINVAL;
+	}
+	fb_divider = ((vco * PREF_DIV_RATIO) / 27);
+	pll_divider_config.fb_divider = fb_divider;
+	pll_divider_config.ref_divider_ratio = PREF_DIV_RATIO;
+	pll_divider_config.bit_clk_divider = div_ratio;
+	pll_divider_config.byte_clk_divider =
+			pll_divider_config.bit_clk_divider * 8;
+	pll_divider_config.analog_posDiv = pll_analog_posDiv;
+	pll_divider_config.digital_posDiv =
+			(mnd_entry->pll_digital_posDiv) * div_ratio;
+
+	if ((mnd_entry->pclk_d == 0)
+		|| (mnd_entry->pclk_m == 1)) {
+		dsi_pclk.mnd_mode = 0;
+		dsi_pclk.src = 0x3;
+		dsi_pclk.pre_div_func = (mnd_entry->pclk_n - 1);
+	} else {
+		dsi_pclk.mnd_mode = 2;
+		dsi_pclk.src = 0x3;
+		dsi_pclk.m = mnd_entry->pclk_m;
+		dsi_pclk.n = mnd_entry->pclk_n;
+		dsi_pclk.d = mnd_entry->pclk_d;
+	}
+	*expected_dsi_pclk = (((pll_divider_config.clk_rate) * lanes)
+				      / (8 * bpp));
+
+	return 0;
+}
+
+void cont_splash_clk_ctrl(int enable)
+{
+	static int cont_splash_clks_enabled;
+	if (enable && !cont_splash_clks_enabled) {
+			clk_prepare_enable(dsi_byte_div_clk);
+			clk_prepare_enable(dsi_esc_clk);
+			cont_splash_clks_enabled = 1;
+	} else if (!enable && cont_splash_clks_enabled) {
+			clk_disable_unprepare(dsi_byte_div_clk);
+			clk_disable_unprepare(dsi_esc_clk);
+			cont_splash_clks_enabled = 0;
+	}
+}
+
+void mdss_dsi_prepare_clocks(void)
+{
+	clk_prepare(dsi_byte_div_clk);
+	clk_prepare(dsi_esc_clk);
+}
+
+void mdss_dsi_unprepare_clocks(void)
+{
+	clk_unprepare(dsi_esc_clk);
+	clk_unprepare(dsi_byte_div_clk);
+}
+
+void mdss_dsi_clk_enable(void)
+{
+	if (mdss_dsi_clk_on) {
+		pr_info("%s: mdss_dsi_clks already ON\n", __func__);
+		return;
+	}
+
+	if (clk_set_rate(dsi_byte_div_clk, 1) < 0)	/* divided by 1 */
+		pr_err("%s: dsi_byte_div_clk - clk_set_rate failed\n",
+					__func__);
+	if (clk_set_rate(dsi_esc_clk, 2) < 0) /* divided by 2 */
+		pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
+					__func__);
+	clk_enable(dsi_byte_div_clk);
+	clk_enable(dsi_esc_clk);
+	mdss_dsi_clk_on = 1;
+}
+
+void mdss_dsi_clk_disable(void)
+{
+	if (mdss_dsi_clk_on == 0) {
+		pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
+		return;
+	}
+	clk_disable(dsi_esc_clk);
+	clk_disable(dsi_byte_div_clk);
+	mdss_dsi_clk_on = 0;
+}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index b6f4874..a984637 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1438,10 +1438,22 @@
 
 	/* cursor memory allocation */
 	if (mfd->cursor_update) {
+		unsigned long cursor_buf_iommu = 0;
 		mfd->cursor_buf = dma_alloc_coherent(NULL,
 					MDP_CURSOR_SIZE,
 					(dma_addr_t *) &mfd->cursor_buf_phys,
 					GFP_KERNEL);
+
+		msm_iommu_map_contig_buffer((unsigned long)mfd->cursor_buf_phys,
+					    DISPLAY_READ_DOMAIN,
+					    GEN_POOL,
+					    MDP_CURSOR_SIZE,
+					    SZ_4K,
+					    0,
+					    &cursor_buf_iommu);
+		if (cursor_buf_iommu)
+			mfd->cursor_buf_phys = (void *)cursor_buf_iommu;
+
 		if (!mfd->cursor_buf)
 			mfd->cursor_update = 0;
 	}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
index 02b2369..a144e06 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
@@ -42,8 +42,17 @@
 	}
 
 	DDL_MEMSET(ddl_context, 0, sizeof(struct ddl_context));
-
 	DDL_BUSY(ddl_context);
+
+	if (res_trk_get_enable_ion()) {
+		VIDC_LOGERR_STRING("ddl_dev_init: ION framework enabled");
+		ddl_context->video_ion_client  =
+			res_trk_get_ion_client();
+		if (!ddl_context->video_ion_client) {
+			VIDC_LOGERR_STRING("ION client create failed");
+			return VCD_ERR_ILLEGAL_OP;
+		}
+	}
 	ddl_context->memtype = res_trk_get_mem_type();
 	if (ddl_context->memtype == -1) {
 		VIDC_LOGERR_STRING("ddl_dev_init:Invalid Memtype");
@@ -161,7 +170,7 @@
 
 	VIDC_LOG_STRING("FW_ENDDONE");
 	ddl_release_context_buffers(ddl_context);
-
+	ddl_context->video_ion_client = NULL;
 	DDL_IDLE(ddl_context);
 
 	return VCD_S_SUCCESS;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index e1407c8..e6d3527 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -77,6 +77,7 @@
 	u32 *align_physical_addr;
 	u32 *align_virtual_addr;
 	struct msm_mapped_buffer *mapped_buffer;
+	struct ion_handle *alloc_handle;
 	u32 buffer_size;
 	enum ddl_mem_area mem_type;
 };
@@ -225,6 +226,7 @@
 	struct ddl_buf_addr dbg_core_dump;
 	u32 enable_dbg_core_dump;
 	struct ddl_client_context *ddl_clients[VCD_MAX_NO_CLIENT];
+	struct ion_client *video_ion_client;
 	u32 device_state;
 	u32 ddl_busy;
 	u32  intr_status;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index aa0d4b8..21f01d1 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -13,6 +13,7 @@
 #include <linux/memory_alloc.h>
 #include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
+#include "vcd_res_tracker_api.h"
 
 #if DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
@@ -91,103 +92,178 @@
 	u32 alloc_size, flags = 0;
 	struct ddl_context *ddl_context;
 	struct msm_mapped_buffer *mapped_buffer = NULL;
+	unsigned long *kernel_vaddr = NULL;
+	ion_phys_addr_t phyaddr = 0;
+	size_t len = 0;
+	int ret = -EINVAL;
 
 	if (!buff_addr) {
-		ERR("\n%s() Invalid Parameters", __func__);
+		ERR("\n%s() Invalid Parameters\n", __func__);
 		return;
 	}
-
-	DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
-
 	if (align == DDL_LINEAR_BUFFER_ALIGN_BYTES) {
-
 		guard_bytes = 31;
 		align_mask = 0xFFFFFFE0U;
-
 	} else {
-
 		guard_bytes = DDL_TILE_BUF_ALIGN_GUARD_BYTES;
 		align_mask = DDL_TILE_BUF_ALIGN_MASK;
 	}
 	ddl_context = ddl_get_context();
 	alloc_size = sz + guard_bytes;
+	if (res_trk_get_enable_ion()) {
+		if (!ddl_context->video_ion_client)
+			ddl_context->video_ion_client =
+				res_trk_get_ion_client();
+		if (!ddl_context->video_ion_client) {
+			ERR("\n%s(): DDL ION Client Invalid handle\n",
+				__func__);
+			goto bailout;
+		}
+		buff_addr->mem_type = res_trk_get_mem_type();
+		buff_addr->alloc_handle = ion_alloc(
+					ddl_context->video_ion_client,
+					alloc_size,
+					SZ_4K,
+					buff_addr->mem_type);
+		if (!buff_addr->alloc_handle) {
+			ERR("\n%s(): DDL ION alloc failed\n",
+					__func__);
+			goto bailout;
+		}
+		ret = ion_phys(ddl_context->video_ion_client,
+					buff_addr->alloc_handle,
+					&phyaddr,
+					&len);
+		if (ret || !phyaddr) {
+			ERR("\n%s(): DDL ION client physical failed\n",
+					__func__);
+			goto free_ion_buffer;
+		}
+		buff_addr->physical_base_addr = (u32 *)phyaddr;
+		kernel_vaddr = (unsigned long *) ion_map_kernel(
+					ddl_context->video_ion_client,
+					buff_addr->alloc_handle,
+					UNCACHED);
+		if (IS_ERR_OR_NULL(kernel_vaddr)) {
+			ERR("\n%s(): DDL ION map failed\n", __func__);
+			goto unmap_ion_buffer;
+		}
+		buff_addr->virtual_base_addr = (u32 *)kernel_vaddr;
+		DBG("ddl_ion_alloc: handle(0x%x), mem_type(0x%x), "\
+			"phys(0x%x), virt(0x%x), size(%u), align(%u), "\
+			"alloced_len(%u)", (u32)buff_addr->alloc_handle,
+			(u32)buff_addr->mem_type,
+			(u32)buff_addr->physical_base_addr,
+			(u32)buff_addr->virtual_base_addr,
+			alloc_size, align, len);
+	} else {
+		physical_addr = (u32)
+			allocate_contiguous_memory_nomap(alloc_size,
+						ddl_context->memtype, SZ_4K);
+		if (!physical_addr) {
+			ERR("\n%s(): DDL pmem allocate failed\n",
+			       __func__);
+			goto bailout;
+		}
+		buff_addr->physical_base_addr = (u32 *) physical_addr;
+		flags = MSM_SUBSYSTEM_MAP_KADDR;
+		buff_addr->mapped_buffer =
+		msm_subsystem_map_buffer((unsigned long)physical_addr,
+		alloc_size, flags, NULL, 0);
+		if (IS_ERR(buff_addr->mapped_buffer)) {
+			ERR("\n%s() buffer map failed\n", __func__);
+			goto free_pmem_buffer;
+		}
+		mapped_buffer = buff_addr->mapped_buffer;
+		if (!mapped_buffer->vaddr) {
+			ERR("\n%s() mapped virtual address is NULL\n",
+				__func__);
+			goto unmap_pmem_buffer;
+		}
+		buff_addr->virtual_base_addr = mapped_buffer->vaddr;
+		DBG("ddl_pmem_alloc: mem_type(0x%x), phys(0x%x),"\
+			" virt(0x%x), sz(%u), align(%u)",
+			(u32)buff_addr->mem_type,
+			(u32)buff_addr->physical_base_addr,
+			(u32)buff_addr->virtual_base_addr,
+			alloc_size, SZ_4K);
+	}
 
-	physical_addr = (u32)
-		allocate_contiguous_memory_nomap(alloc_size,
-					ddl_context->memtype, SZ_4K);
-
-	if (!physical_addr) {
-		pr_err("%s(): could not allocate kernel pmem buffers\n",
-		       __func__);
-		goto bailout;
-	}
-	buff_addr->physical_base_addr = (u32 *) physical_addr;
-	flags = MSM_SUBSYSTEM_MAP_KADDR;
-	buff_addr->mapped_buffer =
-	msm_subsystem_map_buffer((unsigned long)physical_addr,
-	alloc_size, flags, NULL, 0);
-	if (IS_ERR(buff_addr->mapped_buffer)) {
-		pr_err(" %s() buffer map failed", __func__);
-		goto free_acm_alloc;
-	}
-	mapped_buffer = buff_addr->mapped_buffer;
-	if (!mapped_buffer->vaddr) {
-		pr_err("%s() mapped virtual address is NULL", __func__);
-		goto free_map_buffers;
-	}
-	buff_addr->virtual_base_addr = mapped_buffer->vaddr;
 	memset(buff_addr->virtual_base_addr, 0 , sz + guard_bytes);
 	buff_addr->buffer_size = sz;
-
-	buff_addr->align_physical_addr =
-	    (u32 *) ((physical_addr + guard_bytes) & align_mask);
-
-	align_offset =
-	    (u32) (buff_addr->align_physical_addr) - physical_addr;
-
+	buff_addr->align_physical_addr = (u32 *)
+		(((u32)buff_addr->physical_base_addr + guard_bytes) &
+		align_mask);
+	align_offset = (u32) (buff_addr->align_physical_addr) -
+		(u32)buff_addr->physical_base_addr;
 	buff_addr->align_virtual_addr =
 	    (u32 *) ((u32) (buff_addr->virtual_base_addr)
 		     + align_offset);
-
-	DBG_PMEM("\n%s() OUT: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
-		buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
-		buff_addr->buffer_size);
-
+	DBG("%s(): phys(0x%x) align_phys(0x%x), virt(0x%x),"\
+		" align_virt(0x%x)", __func__,
+		(u32)buff_addr->physical_base_addr,
+		(u32)buff_addr->align_physical_addr,
+		(u32)buff_addr->virtual_base_addr,
+		(u32)buff_addr->align_virtual_addr);
 	return;
-free_map_buffers:
-	msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
-free_acm_alloc:
-	free_contiguous_memory_by_paddr(
-		(unsigned long) physical_addr);
+
+unmap_pmem_buffer:
+	if (buff_addr->mapped_buffer)
+		msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
+free_pmem_buffer:
+	if (buff_addr->physical_base_addr)
+		free_contiguous_memory_by_paddr((unsigned long)
+			buff_addr->physical_base_addr);
+	memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
+	return;
+
+unmap_ion_buffer:
+	if (ddl_context->video_ion_client) {
+		if (buff_addr->alloc_handle)
+			ion_unmap_kernel(ddl_context->video_ion_client,
+				buff_addr->alloc_handle);
+	}
+free_ion_buffer:
+	if (ddl_context->video_ion_client) {
+		if (buff_addr->alloc_handle)
+			ion_free(ddl_context->video_ion_client,
+				buff_addr->alloc_handle);
+	}
 bailout:
-	buff_addr->physical_base_addr = NULL;
-	buff_addr->virtual_base_addr = NULL;
-	buff_addr->buffer_size = 0;
-	buff_addr->mapped_buffer = NULL;
+	memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
 }
 
 void ddl_pmem_free(struct ddl_buf_addr *buff_addr)
 {
+	struct ddl_context *ddl_context;
+	ddl_context = ddl_get_context();
 	if (!buff_addr) {
 		ERR("\n %s() invalid arguments %p", __func__, buff_addr);
 		return;
 	}
-	DBG_PMEM("\n%s() IN: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
-		buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
+	DBG("ddl_pmem_free: phys(0x%x) align_phys(0x%x), "\
+		"virt(0x%x), align_virt(0x%x), size(%u)",
+		(u32)buff_addr->physical_base_addr,
+		(u32)buff_addr->align_physical_addr,
+		(u32)buff_addr->virtual_base_addr,
+		(u32)buff_addr->align_virtual_addr,
 		buff_addr->buffer_size);
-
-	if (buff_addr->mapped_buffer)
-		msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
-	if (buff_addr->physical_base_addr)
-		free_contiguous_memory_by_paddr(
-			(unsigned long) buff_addr->physical_base_addr);
-	DBG_PMEM("\n%s() OUT: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
-		buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
-		buff_addr->buffer_size);
-	buff_addr->buffer_size = 0;
-	buff_addr->physical_base_addr = NULL;
-	buff_addr->virtual_base_addr = NULL;
-	buff_addr->mapped_buffer = NULL;
+	if (ddl_context->video_ion_client) {
+		if (buff_addr->alloc_handle) {
+			ion_unmap_kernel(ddl_context->video_ion_client,
+				buff_addr->alloc_handle);
+			ion_free(ddl_context->video_ion_client,
+				buff_addr->alloc_handle);
+		}
+	} else {
+		if (buff_addr->mapped_buffer)
+			msm_subsystem_unmap_buffer(
+				buff_addr->mapped_buffer);
+		if (buff_addr->physical_base_addr)
+			free_contiguous_memory_by_paddr((unsigned long)
+				buff_addr->physical_base_addr);
+	}
+	memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
 }
 #endif
 
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index e51bf45..aee9dfe 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -677,8 +677,16 @@
 	return false;
 }
 
+static struct ion_client *res_trk_create_ion_client(void){
+	struct ion_client *video_client;
+	VCDRES_MSG_LOW("%s", __func__);
+	video_client = msm_ion_client_create(-1, "video_client");
+	return video_client;
+}
+
 void res_trk_init(struct device *device, u32 irq)
 {
+	VCDRES_MSG_LOW("%s", __func__);
 	if (resource_context.device || resource_context.irq_num ||
 		!device) {
 		VCDRES_MSG_ERROR("%s() Resource Tracker Init error\n",
@@ -695,9 +703,27 @@
 		(struct msm_vidc_platform_data *) device->platform_data;
 	if (resource_context.vidc_platform_data) {
 		resource_context.memtype =
-		resource_context.vidc_platform_data->memtype;
+			resource_context.vidc_platform_data->memtype;
+		VCDRES_MSG_LOW("%s(): resource_context.memtype = 0x%x",
+			__func__, (u32)resource_context.memtype);
+		if (resource_context.vidc_platform_data->enable_ion) {
+			resource_context.res_ion_client =
+				res_trk_create_ion_client();
+			if (!(resource_context.res_ion_client)) {
+				VCDRES_MSG_ERROR("%s()ION createfail\n",
+						__func__);
+				return;
+			}
+			VCDRES_MSG_LOW("%s(): ion_client = 0x%x", __func__,
+				(u32)resource_context.res_ion_client);
+		} else {
+			VCDRES_MSG_ERROR("%s(): ION not disabled\n",
+					__func__);
+		}
 	} else {
 		resource_context.memtype = -1;
+		VCDRES_MSG_ERROR("%s(): vidc_platform_data is NULL",
+			__func__);
 	}
 }
 
@@ -705,18 +731,23 @@
 	return resource_context.core_type;
 }
 
-u32 res_trk_get_mem_type(void){
-	return resource_context.memtype;
-}
-
 u32 res_trk_get_enable_ion(void)
 {
-	return 0;
+	if (resource_context.vidc_platform_data->enable_ion)
+		return 1;
+	else
+		return 0;
 }
 
 struct ion_client *res_trk_get_ion_client(void)
 {
-	return NULL;
+	return resource_context.res_ion_client;
+}
+
+u32 res_trk_get_mem_type(void)
+{
+	u32 mem_type = ION_HEAP(resource_context.memtype);
+	return mem_type;
 }
 
 void res_trk_set_mem_type(enum ddl_mem_area mem_type)
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
index 2b92a42..f8d9053 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
@@ -13,6 +13,7 @@
 #ifndef _VIDEO_720P_RESOURCE_TRACKER_H_
 #define _VIDEO_720P_RESOURCE_TRACKER_H_
 #include <mach/board.h>
+#include <linux/ion.h>
 #include "vcd_res_tracker_api.h"
 
 #define VCD_RESTRK_MIN_PERF_LEVEL 37900
@@ -36,6 +37,8 @@
 	u32 core_type;
 	int memtype;
 	u32 secure_session;
+	struct ion_client *res_ion_client;
+	enum ddl_mem_area res_mem_type;
 };
 
 #if DEBUG
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index c3803b1..927f19b 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -915,7 +915,8 @@
 				 __func__);
 			goto import_ion_error;
 		}
-		if (res_trk_check_for_sec_session()) {
+		if (res_trk_check_for_sec_session() ||
+		   (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
 			rc = ion_phys(client_ctx->user_ion_client,
 				client_ctx->h264_mv_ion_handle,
 				(unsigned long *) (&(vcd_h264_mv_buffer->
@@ -1038,7 +1039,8 @@
 	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
-		if (!res_trk_check_for_sec_session()) {
+		if (!res_trk_check_for_sec_session() &&
+		   (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
 			ion_unmap_iommu(client_ctx->user_ion_client,
 				client_ctx->h264_mv_ion_handle,
 				VIDEO_DOMAIN,
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 9450ee7..50cccbb 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1844,7 +1844,8 @@
 				 __func__);
 			goto import_ion_error;
 		}
-		if (res_trk_check_for_sec_session()) {
+		if (res_trk_check_for_sec_session() ||
+		   (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
 			rc = ion_phys(client_ctx->user_ion_client,
 				client_ctx->recon_buffer_ion_handle[i],
 				&phy_addr, &ion_len);
@@ -1945,7 +1946,8 @@
 		if (client_ctx->recon_buffer_ion_handle[i]) {
 			ion_unmap_kernel(client_ctx->user_ion_client,
 				client_ctx->recon_buffer_ion_handle[i]);
-			if (!res_trk_check_for_sec_session()) {
+			if (!res_trk_check_for_sec_session() &&
+			   (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
 				ion_unmap_iommu(client_ctx->user_ion_client,
 				client_ctx->recon_buffer_ion_handle[i],
 				VIDEO_DOMAIN,
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index dcacb3c..c884cf5 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -432,7 +432,9 @@
 				ion_unmap_kernel(client_ctx->user_ion_client,
 						buf_addr_table[i].
 						buff_ion_handle);
-				if (!res_trk_check_for_sec_session()) {
+				if (!res_trk_check_for_sec_session() &&
+				   (res_trk_get_core_type() !=
+				   (u32)VCD_CORE_720P)) {
 					ion_unmap_iommu(
 						client_ctx->user_ion_client,
 						buf_addr_table[i].
@@ -456,7 +458,8 @@
 		if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
 			ion_unmap_kernel(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
-			if (!res_trk_check_for_sec_session()) {
+			if (!res_trk_check_for_sec_session() &&
+			    (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
 				ion_unmap_iommu(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle,
 					VIDEO_DOMAIN,
@@ -652,7 +655,8 @@
 				*kernel_vaddr = (unsigned long)NULL;
 				goto ion_free_error;
 			}
-			if (res_trk_check_for_sec_session()) {
+			if (res_trk_check_for_sec_session() ||
+			   (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
 				if (ion_phys(client_ctx->user_ion_client,
 					buff_ion_handle,
 					&phys_addr, &ion_len)) {
@@ -780,7 +784,7 @@
 		*num_of_buffers = *num_of_buffers + 1;
 		DBG("%s() : client_ctx = %p, user_virt_addr = 0x%08lx, "
 			"kernel_vaddr = 0x%08lx inserted!", __func__,
-			client_ctx, user_vaddr, *kernel_vaddr);
+			client_ctx, user_vaddr, kernel_vaddr);
 	}
 	mutex_unlock(&client_ctx->enrty_queue_lock);
 	return true;
@@ -833,7 +837,8 @@
 	if (buf_addr_table[i].buff_ion_handle) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 				buf_addr_table[i].buff_ion_handle);
-		if (!res_trk_check_for_sec_session()) {
+		if (!res_trk_check_for_sec_session() &&
+		   (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
 			ion_unmap_iommu(client_ctx->user_ion_client,
 				buf_addr_table[i].buff_ion_handle,
 				VIDEO_DOMAIN,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index c11ac30..28ea453 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -41,6 +41,8 @@
 	unsigned long buffer_size = 0;
 	int ret = 0;
 	unsigned long ionflag = 0;
+	ion_phys_addr_t phyaddr = 0;
+	size_t len = 0;
 
 	if (!kernel_vaddr || !phy_addr || !cctxt) {
 		pr_err("\n%s: Invalid parameters", __func__);
@@ -84,6 +86,9 @@
 		}
 		*phy_addr = (u8 *) mapped_buffer->iova[0];
 		*kernel_vaddr = (u8 *) mapped_buffer->vaddr;
+		VCD_MSG_LOW("vcd_pmem_alloc: phys(0x%x), virt(0x%x), "\
+			"sz(%u), flags(0x%x)", (u32)*phy_addr,
+			(u32)*kernel_vaddr, sz, (u32)flags);
 	} else {
 		map_buffer->alloc_handle = ion_alloc(
 			    cctxt->vcd_ion_client, sz, SZ_4K,
@@ -106,7 +111,8 @@
 			pr_err("%s() ION map failed", __func__);
 			goto ion_free_bailout;
 		}
-		ret = ion_map_iommu(cctxt->vcd_ion_client,
+		if (res_trk_get_core_type() != (u32)VCD_CORE_720P) {
+			ret = ion_map_iommu(cctxt->vcd_ion_client,
 				map_buffer->alloc_handle,
 				VIDEO_DOMAIN,
 				VIDEO_MAIN_POOL,
@@ -115,18 +121,32 @@
 				(unsigned long *)&iova,
 				(unsigned long *)&buffer_size,
 				UNCACHED, 0);
-		if (ret) {
-			pr_err("%s() ION iommu map failed", __func__);
-			goto ion_map_bailout;
+			if (ret) {
+				pr_err("%s() ION iommu map failed", __func__);
+				goto ion_map_bailout;
+			}
+			map_buffer->phy_addr = iova;
+		} else {
+			ret = ion_phys(cctxt->vcd_ion_client,
+				map_buffer->alloc_handle,
+				&phyaddr,
+				&len);
+			if (ret) {
+				pr_err("%s() ion_phys failed", __func__);
+				goto ion_map_bailout;
+			}
+			map_buffer->phy_addr = phyaddr;
 		}
-		map_buffer->phy_addr = iova;
 		if (!map_buffer->phy_addr) {
 			pr_err("%s() acm alloc failed", __func__);
 			goto free_map_table;
 		}
-		*phy_addr = (u8 *)iova;
+		*phy_addr = (u8 *)map_buffer->phy_addr;
 		mapped_buffer = NULL;
 		map_buffer->mapped_buffer = NULL;
+		VCD_MSG_LOW("vcd_ion_alloc: phys(0x%x), virt(0x%x), "\
+			"sz(%u), ionflags(0x%x)", (u32)*phy_addr,
+			(u32)*kernel_vaddr, sz, (u32)ionflag);
 	}
 
 	return 0;
@@ -176,10 +196,13 @@
 	if (map_buffer->mapped_buffer)
 		msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
 	if (cctxt->vcd_enable_ion) {
+		VCD_MSG_LOW("vcd_ion_free: phys(0x%x), virt(0x%x)",
+			(u32)phy_addr, (u32)kernel_vaddr);
 		if (map_buffer->alloc_handle) {
 			ion_unmap_kernel(cctxt->vcd_ion_client,
 					map_buffer->alloc_handle);
-			ion_unmap_iommu(cctxt->vcd_ion_client,
+			if (res_trk_get_core_type() != (u32)VCD_CORE_720P)
+				ion_unmap_iommu(cctxt->vcd_ion_client,
 					map_buffer->alloc_handle,
 					VIDEO_DOMAIN,
 					VIDEO_MAIN_POOL);
@@ -187,6 +210,8 @@
 			map_buffer->alloc_handle);
 		}
 	} else {
+		VCD_MSG_LOW("vcd_pmem_free: phys(0x%x), virt(0x%x)",
+			(u32)phy_addr, (u32)kernel_vaddr);
 		free_contiguous_memory_by_paddr(
 			(unsigned long)map_buffer->phy_addr);
 	}
diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
index 8e8c55b..4dd618f 100644
--- a/fs/yaffs2/yaffs_vfs.c
+++ b/fs/yaffs2/yaffs_vfs.c
@@ -497,8 +497,16 @@
 
 	if (ret_val == YAFFS_OK) {
 		if (target) {
-			drop_nlink(new_dentry->d_inode);
-			mark_inode_dirty(new_dentry->d_inode);
+			/*
+			 * We have identified target to be a
+			 * valid directory earlier. If it is
+			 * not the case throw a warning.
+			 */
+			WARN_ON(!new_dentry->d_inode);
+			if (new_dentry->d_inode) {
+				drop_nlink(new_dentry->d_inode);
+				mark_inode_dirty(new_dentry->d_inode);
+			}
 		}
 
 		update_dir_time(old_dir);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 32d8ec2..cb56293 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -210,6 +210,7 @@
 	int use_for_apm;
 };
 
+#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
 extern struct power_supply *power_supply_get_by_name(char *name);
 extern void power_supply_changed(struct power_supply *psy);
 extern int power_supply_am_i_supplied(struct power_supply *psy);
@@ -218,10 +219,31 @@
 extern int power_supply_set_online(struct power_supply *psy, bool enable);
 extern int power_supply_set_scope(struct power_supply *psy, int scope);
 extern int power_supply_set_charge_type(struct power_supply *psy, int type);
-
-#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
+extern int power_supply_set_supply_type(struct power_supply *psy,
+					enum power_supply_type supply_type);
 extern int power_supply_is_system_supplied(void);
 #else
+static inline struct power_supply *power_supply_get_by_name(char *name)
+							{ return -ENOSYS; }
+static inline int power_supply_am_i_supplied(struct power_supply *psy)
+							{ return -ENOSYS; }
+static inline int power_supply_set_battery_charged(struct power_supply *psy)
+							{ return -ENOSYS; }
+static inline int power_supply_set_current_limit(struct power_supply *psy,
+							int limit)
+							{ return -ENOSYS; }
+static inline int power_supply_set_online(struct power_supply *psy,
+							bool enable)
+							{ return -ENOSYS; }
+static inline int power_supply_set_scope(struct power_supply *psy,
+							int scope)
+							{ return -ENOSYS; }
+static inline int power_supply_set_charge_type(struct power_supply *psy,
+							int type)
+							{ return -ENOSYS; }
+static inline int power_supply_set_supply_type(struct power_supply *psy,
+					enum power_supply_type supply_type);
+							{ return -ENOSYS; }
 static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
 #endif
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 99fd1d3..485569b 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -40,7 +40,11 @@
 	union afe_port_config port_config;
 };
 
-static struct clk *pcm_clk;
+static struct clk *pcm_src_clk;
+static struct clk *pcm_branch_clk;
+static struct clk *pcm_oe_src_clk;
+static struct clk *pcm_oe_branch_clk;
+
 static DEFINE_MUTEX(aux_pcm_mutex);
 static int aux_pcm_count;
 
@@ -120,6 +124,9 @@
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close AUX PCM TX port\n");
 
+	clk_disable_unprepare(pcm_branch_clk);
+	clk_disable_unprepare(pcm_oe_branch_clk);
+
 	mutex_unlock(&aux_pcm_mutex);
 }
 
@@ -127,8 +134,11 @@
 		struct snd_soc_dai *dai)
 {
 	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
 	int rc = 0;
 
+	auxpcm_pdata = dai->dev->platform_data;
+
 	mutex_lock(&aux_pcm_mutex);
 
 	if (aux_pcm_count == 2) {
@@ -170,12 +180,37 @@
 	 * assert/deasset and afe_open sequence is not followed.
 	 */
 
+	rc = clk_set_rate(pcm_src_clk, auxpcm_pdata->pcm_clk_rate);
+	if (rc < 0) {
+		pr_err("%s: clk_set_rate failed\n", __func__);
+		goto fail;
+	}
+
+	rc = clk_prepare_enable(pcm_branch_clk);
+	if (rc) {
+		pr_err("%s: clk enable failed\n", __func__);
+		goto fail;
+	}
+
+	rc = clk_set_rate(pcm_oe_src_clk, 24576000>>1);
+	if (rc < 0) {
+		pr_err("%s: clk_set_rate on pcm oe failed\n", __func__);
+		goto fail;
+	}
+
+	rc = clk_prepare_enable(pcm_oe_branch_clk);
+	if (rc) {
+		pr_err("%s: clk enable pcm_oe_branch_clk failed\n", __func__);
+		goto fail;
+	}
+
 	afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
 
 	afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
 
 	mutex_unlock(&aux_pcm_mutex);
 
+fail:
 	return rc;
 }
 
@@ -217,6 +252,7 @@
 	auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)
 					dev_get_drvdata(dai->dev);
 	dai->dev->platform_data = auxpcm_pdata;
+	dai->id = dai->dev->id;
 
 	mutex_lock(&aux_pcm_mutex);
 
@@ -225,9 +261,41 @@
 	 * data to the cpu driver, since cpu drive is unaware of any
 	 * boarc specific configuration.
 	 */
-	if (!pcm_clk)
-		pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
+	if ((!pcm_src_clk) || (!pcm_branch_clk)) {
+		pcm_src_clk = clk_get(dai->dev, auxpcm_pdata->clk);
 
+		if (IS_ERR(pcm_src_clk)) {
+			pr_err("%s: could not get pcm_src_clk\n", __func__);
+			pcm_src_clk = NULL;
+			return -ENODEV;
+		}
+
+		pcm_branch_clk = clk_get(dai->dev, "ibit_clk");
+
+		if (IS_ERR(pcm_branch_clk)) {
+			pr_err("%s: could not get pcm_branch_clk\n", __func__);
+			pcm_branch_clk = NULL;
+			return -ENODEV;
+		}
+	}
+
+	if ((!pcm_oe_src_clk) || (!pcm_oe_branch_clk)) {
+
+		pcm_oe_src_clk = clk_get(dai->dev, "core_oe_src_clk");
+
+		if (IS_ERR(pcm_oe_src_clk)) {
+			pr_err("%s: could not get pcm_oe_src_clk\n", __func__);
+			pcm_oe_src_clk = NULL;
+			return -ENODEV;
+		}
+
+		pcm_oe_branch_clk = clk_get(dai->dev, "core_oe_clk");
+		if (IS_ERR(pcm_oe_branch_clk)) {
+			pr_err("%s: could not get pcm_oe_clk\n", __func__);
+			pcm_oe_branch_clk = NULL;
+			return -ENODEV;
+		}
+	}
 	mutex_unlock(&aux_pcm_mutex);
 
 	dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
@@ -813,7 +881,7 @@
 	.remove = msm_dai_q6_dai_remove,
 };
 
-static int msm_auxpcm_dev_probe(struct platform_device *pdev)
+static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
 {
 	int id;
 	void *plat_data;
@@ -837,6 +905,7 @@
 	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
 
 	dev_set_drvdata(&pdev->dev, plat_data);
+	pdev->dev.id = id;
 
 	switch (id) {
 	case AFE_PORT_ID_PRIMARY_PCM_RX:
@@ -855,7 +924,7 @@
 	return rc;
 }
 
-static int msm_auxpcm_resource_probe(
+static int __devinit msm_auxpcm_resource_probe(
 			struct platform_device *pdev)
 {
 	int rc = 0;
@@ -950,13 +1019,13 @@
 	return rc;
 }
 
-static int msm_auxpcm_dev_remove(struct platform_device *pdev)
+static int __devexit msm_auxpcm_dev_remove(struct platform_device *pdev)
 {
 	snd_soc_unregister_dai(&pdev->dev);
 	return 0;
 }
 
-static int msm_auxpcm_resource_remove(
+static int __devexit msm_auxpcm_resource_remove(
 				struct platform_device *pdev)
 {
 	void *auxpcm_pdata;
@@ -967,22 +1036,20 @@
 	return 0;
 }
 
-static const struct of_device_id msm_auxpcm_resource_dt_match[] = {
+static struct of_device_id msm_auxpcm_resource_dt_match[] = {
 	{ .compatible = "qcom,msm-auxpcm-resource", },
 	{}
 };
-MODULE_DEVICE_TABLE(of, msm_auxpcm_resource_dt_match);
 
-static const struct of_device_id msm_auxpcm_dev_dt_match[] = {
+static struct of_device_id msm_auxpcm_dev_dt_match[] = {
 	{ .compatible = "qcom,msm-auxpcm-dev", },
 	{}
 };
-MODULE_DEVICE_TABLE(of, msm_auxpcm_dev_dt_match);
 
 
-static struct platform_driver msm_auxpcm_dev = {
+static struct platform_driver msm_auxpcm_dev_driver = {
 	.probe  = msm_auxpcm_dev_probe,
-	.remove = msm_auxpcm_dev_remove,
+	.remove = __devexit_p(msm_auxpcm_dev_remove),
 	.driver = {
 		.name = "msm-auxpcm-dev",
 		.owner = THIS_MODULE,
@@ -990,9 +1057,9 @@
 	},
 };
 
-static struct platform_driver msm_auxpcm_resource = {
+static struct platform_driver msm_auxpcm_resource_driver = {
 	.probe  = msm_auxpcm_resource_probe,
-	.remove  = msm_auxpcm_resource_remove,
+	.remove  = __devexit_p(msm_auxpcm_resource_remove),
 	.driver = {
 		.name = "msm-auxpcm-resource",
 		.owner = THIS_MODULE,
@@ -1134,22 +1201,23 @@
 {
 	int rc;
 
-	rc = platform_driver_register(&msm_auxpcm_dev);
+	rc = platform_driver_register(&msm_auxpcm_dev_driver);
 	if (rc)
 		goto fail;
 
-	rc = platform_driver_register(&msm_auxpcm_resource);
+	rc = platform_driver_register(&msm_auxpcm_resource_driver);
+
 	if (rc) {
 		pr_err("%s: fail to register cpu dai driver\n", __func__);
-		platform_driver_unregister(&msm_auxpcm_dev);
+		platform_driver_unregister(&msm_auxpcm_dev_driver);
 		goto fail;
 	}
 
 	rc = platform_driver_register(&msm_dai_q6);
 	if (rc) {
 		pr_err("%s: fail to register dai q6 driver", __func__);
-		platform_driver_unregister(&msm_auxpcm_dev);
-		platform_driver_unregister(&msm_auxpcm_resource);
+		platform_driver_unregister(&msm_auxpcm_dev_driver);
+		platform_driver_unregister(&msm_auxpcm_resource_driver);
 		goto fail;
 	}
 
@@ -1157,8 +1225,8 @@
 	if (rc) {
 		pr_err("%s: fail to register dai q6 dev driver", __func__);
 		platform_driver_unregister(&msm_dai_q6);
-		platform_driver_unregister(&msm_auxpcm_dev);
-		platform_driver_unregister(&msm_auxpcm_resource);
+		platform_driver_unregister(&msm_auxpcm_dev_driver);
+		platform_driver_unregister(&msm_auxpcm_resource_driver);
 		goto fail;
 	}
 fail:
@@ -1170,8 +1238,8 @@
 {
 	platform_driver_unregister(&msm_dai_q6_dev);
 	platform_driver_unregister(&msm_dai_q6);
-	platform_driver_unregister(&msm_auxpcm_dev);
-	platform_driver_unregister(&msm_auxpcm_resource);
+	platform_driver_unregister(&msm_auxpcm_dev_driver);
+	platform_driver_unregister(&msm_auxpcm_resource_driver);
 }
 module_exit(msm_dai_q6_exit);