Merge "ASoC: apq8064-i2s: Update machine driver for APQ8064 I2S platform"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 0eb186e..2864fd1 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -48,6 +48,12 @@
 
  - compatible : "qcom,msm-dai-fe"
 
+* msm-pcm-afe
+
+Required properties:
+
+ - compatible : "qcom,msm-pcm-afe"
+
 * msm-dai-q6
 
 [First Level Nodes]
@@ -63,6 +69,8 @@
  - compatible : "qcom,msm-dai-q6-dev"
  - qcom,msm-dai-q6-dev-id : The slimbus multi channel port ID
                             Value is from 16384 to 16393
+                            BT SCO port ID value from 12288 to 12289
+                            RT Proxy port ID values from 224 to 225 and 240 to 241
 
 * msm-auxpcm
 
@@ -166,6 +174,36 @@
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <16385>;
 		};
+
+		qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
 	};
 
         qcom,msm-auxpcm {
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 9c2ce6c..12fbfec 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -6,6 +6,8 @@
 - compatible : should be "qcom,hsusb-otg"
 - regs : offset and length of the register set in the memory map
 - interrupts: IRQ line
+- interrupt-names: OTG interrupt name(s) referenced in interrupts above
+            HSUSB OTG expects "core_irq" and optionally "async_irq".
 - qcom,hsusb-otg-phy-type: PHY type can be one of
             1 - Chipidea 45nm PHY
 	    2 - Synopsis 28nm PHY
@@ -48,6 +50,7 @@
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9690000 0x400>;
 		interrupts = <134>;
+		interrupt-names = "core_irq";
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index c3c0d56..9ed61ed 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -673,6 +673,10 @@
 		compatible = "qcom,msm-dai-fe";
 	};
 
+	qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
 	qcom,msm-dai-q6 {
 		compatible = "qcom,msm-dai-q6";
 		qcom,msm-dai-q6-sb-0-rx {
@@ -684,6 +688,36 @@
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <16385>;
 		};
+
+		qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
 	};
 
 	qcom,msm-auxpcm {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 767f385..36fad49 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -66,6 +66,26 @@
 		interrupts = <0 109 0>;
 	};
 
+	usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0 0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+		HSUSB_VDDCX-supply = <&pm8019_l12>;
+		HSUSB_1p8-supply = <&pm8019_l2>;
+		HSUSB_3p3-supply = <&pm8019_l4>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+	};
+
+	android_usb@fc42b0c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42b0c8 0xc8>;
+	};
+
 	qcom,nand@f9ac0000 {
 		compatible = "qcom,msm-nand";
 		reg = <0xf9ac0000 0x1000>,
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index d2e37e0..60eb505 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -87,6 +87,7 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 3c44a06..d00acc9 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -274,7 +274,7 @@
 obj-$(CONFIG_MACH_MSM8930_CDP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
 obj-$(CONFIG_MACH_MSM8930_MTP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
 obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
-obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
+obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
 obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
diff --git a/arch/arm/mach-msm/batterydata-lib.c b/arch/arm/mach-msm/batterydata-lib.c
new file mode 100644
index 0000000..2be591c
--- /dev/null
+++ b/arch/arm/mach-msm/batterydata-lib.c
@@ -0,0 +1,338 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
+
+int linear_interpolate(int y0, int x0, int y1, int x1, int x)
+{
+	if (y0 == y1 || x == x0)
+		return y0;
+	if (x1 == x0 || x == x1)
+		return y1;
+
+	return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
+int is_between(int left, int right, int value)
+{
+	if (left >= right && left >= value && value >= right)
+		return 1;
+	if (left <= right && left <= value && value <= right)
+		return 1;
+	return 0;
+}
+
+static int interpolate_single_lut(struct single_row_lut *lut, int x)
+{
+	int i, result;
+
+	if (x < lut->x[0]) {
+		pr_debug("x %d less than known range return y = %d lut = %pS\n",
+							x, lut->y[0], lut);
+		return lut->y[0];
+	}
+	if (x > lut->x[lut->cols - 1]) {
+		pr_debug("x %d more than known range return y = %d lut = %pS\n",
+						x, lut->y[lut->cols - 1], lut);
+		return lut->y[lut->cols - 1];
+	}
+
+	for (i = 0; i < lut->cols; i++)
+		if (x <= lut->x[i])
+			break;
+	if (x == lut->x[i]) {
+		result = lut->y[i];
+	} else {
+		result = linear_interpolate(
+			lut->y[i - 1],
+			lut->x[i - 1],
+			lut->y[i],
+			lut->x[i],
+			x);
+	}
+	return result;
+}
+
+int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp)
+{
+	/* batt_temp is in tenths of degC - convert it to degC for lookups */
+	batt_temp = batt_temp/10;
+	return interpolate_single_lut(fcc_temp_lut, batt_temp);
+}
+
+int interpolate_scalingfactor_fcc(struct single_row_lut *fcc_sf_lut,
+		int cycles)
+{
+	/*
+	 * sf table could be null when no battery aging data is available, in
+	 * that case return 100%
+	 */
+	if (fcc_sf_lut)
+		return interpolate_single_lut(fcc_sf_lut, cycles);
+	else
+		return 100;
+}
+
+int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc)
+{
+	int i, scalefactorrow1, scalefactorrow2, scalefactor, rows, cols;
+	int row1 = 0;
+	int row2 = 0;
+
+	/*
+	 * sf table could be null when no battery aging data is available, in
+	 * that case return 100%
+	 */
+	if (!sf_lut)
+		return 100;
+
+	rows = sf_lut->rows;
+	cols = sf_lut->cols;
+	if (pc > sf_lut->percent[0]) {
+		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
+		row1 = 0;
+		row2 = 0;
+	}
+	if (pc < sf_lut->percent[rows - 1]) {
+		pr_debug("pc %d less than known pc ranges for sf\n", pc);
+		row1 = rows - 1;
+		row2 = rows - 1;
+	}
+	for (i = 0; i < rows; i++) {
+		if (pc == sf_lut->percent[i]) {
+			row1 = i;
+			row2 = i;
+			break;
+		}
+		if (pc > sf_lut->percent[i]) {
+			row1 = i - 1;
+			row2 = i;
+			break;
+		}
+	}
+
+	if (row_entry < sf_lut->row_entries[0])
+		row_entry = sf_lut->row_entries[0];
+	if (row_entry > sf_lut->row_entries[cols - 1])
+		row_entry = sf_lut->row_entries[cols - 1];
+
+	for (i = 0; i < cols; i++)
+		if (row_entry <= sf_lut->row_entries[i])
+			break;
+	if (row_entry == sf_lut->row_entries[i]) {
+		scalefactor = linear_interpolate(
+				sf_lut->sf[row1][i],
+				sf_lut->percent[row1],
+				sf_lut->sf[row2][i],
+				sf_lut->percent[row2],
+				pc);
+		return scalefactor;
+	}
+
+	scalefactorrow1 = linear_interpolate(
+				sf_lut->sf[row1][i - 1],
+				sf_lut->row_entries[i - 1],
+				sf_lut->sf[row1][i],
+				sf_lut->row_entries[i],
+				row_entry);
+
+	scalefactorrow2 = linear_interpolate(
+				sf_lut->sf[row2][i - 1],
+				sf_lut->row_entries[i - 1],
+				sf_lut->sf[row2][i],
+				sf_lut->row_entries[i],
+				row_entry);
+
+	scalefactor = linear_interpolate(
+				scalefactorrow1,
+				sf_lut->percent[row1],
+				scalefactorrow2,
+				sf_lut->percent[row2],
+				pc);
+
+	return scalefactor;
+}
+
+/* get ocv given a soc  -- reverse lookup */
+int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+				int batt_temp_degc, int pc)
+{
+	int i, ocvrow1, ocvrow2, ocv, rows, cols;
+	int row1 = 0;
+	int row2 = 0;
+
+	rows = pc_temp_ocv->rows;
+	cols = pc_temp_ocv->cols;
+	if (pc > pc_temp_ocv->percent[0]) {
+		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
+		row1 = 0;
+		row2 = 0;
+	}
+	if (pc < pc_temp_ocv->percent[rows - 1]) {
+		pr_debug("pc %d less than known pc ranges for sf\n", pc);
+		row1 = rows - 1;
+		row2 = rows - 1;
+	}
+	for (i = 0; i < rows; i++) {
+		if (pc == pc_temp_ocv->percent[i]) {
+			row1 = i;
+			row2 = i;
+			break;
+		}
+		if (pc > pc_temp_ocv->percent[i]) {
+			row1 = i - 1;
+			row2 = i;
+			break;
+		}
+	}
+
+	if (batt_temp_degc < pc_temp_ocv->temp[0])
+		batt_temp_degc = pc_temp_ocv->temp[0];
+	if (batt_temp_degc > pc_temp_ocv->temp[cols - 1])
+		batt_temp_degc = pc_temp_ocv->temp[cols - 1];
+
+	for (i = 0; i < cols; i++)
+		if (batt_temp_degc <= pc_temp_ocv->temp[i])
+			break;
+	if (batt_temp_degc == pc_temp_ocv->temp[i]) {
+		ocv = linear_interpolate(
+				pc_temp_ocv->ocv[row1][i],
+				pc_temp_ocv->percent[row1],
+				pc_temp_ocv->ocv[row2][i],
+				pc_temp_ocv->percent[row2],
+				pc);
+		return ocv;
+	}
+
+	ocvrow1 = linear_interpolate(
+				pc_temp_ocv->ocv[row1][i - 1],
+				pc_temp_ocv->temp[i - 1],
+				pc_temp_ocv->ocv[row1][i],
+				pc_temp_ocv->temp[i],
+				batt_temp_degc);
+
+	ocvrow2 = linear_interpolate(
+				pc_temp_ocv->ocv[row2][i - 1],
+				pc_temp_ocv->temp[i - 1],
+				pc_temp_ocv->ocv[row2][i],
+				pc_temp_ocv->temp[i],
+				batt_temp_degc);
+
+	ocv = linear_interpolate(
+				ocvrow1,
+				pc_temp_ocv->percent[row1],
+				ocvrow2,
+				pc_temp_ocv->percent[row2],
+				pc);
+
+	return ocv;
+}
+
+int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+				int batt_temp_degc, int ocv)
+{
+	int i, j, pcj, pcj_minus_one, pc;
+	int rows = pc_temp_ocv->rows;
+	int cols = pc_temp_ocv->cols;
+
+	if (batt_temp_degc < pc_temp_ocv->temp[0]) {
+		pr_debug("batt_temp %d < known temp range\n", batt_temp_degc);
+		batt_temp_degc = pc_temp_ocv->temp[0];
+	}
+
+	if (batt_temp_degc > pc_temp_ocv->temp[cols - 1]) {
+		pr_debug("batt_temp %d > known temp range\n", batt_temp_degc);
+		batt_temp_degc = pc_temp_ocv->temp[cols - 1];
+	}
+
+	for (j = 0; j < cols; j++)
+		if (batt_temp_degc <= pc_temp_ocv->temp[j])
+			break;
+	if (batt_temp_degc == pc_temp_ocv->temp[j]) {
+		/* found an exact match for temp in the table */
+		if (ocv >= pc_temp_ocv->ocv[0][j])
+			return pc_temp_ocv->percent[0];
+		if (ocv <= pc_temp_ocv->ocv[rows - 1][j])
+			return pc_temp_ocv->percent[rows - 1];
+		for (i = 0; i < rows; i++) {
+			if (ocv >= pc_temp_ocv->ocv[i][j]) {
+				if (ocv == pc_temp_ocv->ocv[i][j])
+					return pc_temp_ocv->percent[i];
+				pc = linear_interpolate(
+					pc_temp_ocv->percent[i],
+					pc_temp_ocv->ocv[i][j],
+					pc_temp_ocv->percent[i - 1],
+					pc_temp_ocv->ocv[i - 1][j],
+					ocv);
+				return pc;
+			}
+		}
+	}
+
+	/*
+	 * batt_temp_degc is within temperature for
+	 * column j-1 and j
+	 */
+	if (ocv >= pc_temp_ocv->ocv[0][j])
+		return pc_temp_ocv->percent[0];
+	if (ocv <= pc_temp_ocv->ocv[rows - 1][j - 1])
+		return pc_temp_ocv->percent[rows - 1];
+
+	pcj_minus_one = 0;
+	pcj = 0;
+	for (i = 0; i < rows-1; i++) {
+		if (pcj == 0
+			&& is_between(pc_temp_ocv->ocv[i][j],
+				pc_temp_ocv->ocv[i+1][j], ocv)) {
+			pcj = linear_interpolate(
+				pc_temp_ocv->percent[i],
+				pc_temp_ocv->ocv[i][j],
+				pc_temp_ocv->percent[i + 1],
+				pc_temp_ocv->ocv[i+1][j],
+				ocv);
+		}
+
+		if (pcj_minus_one == 0
+			&& is_between(pc_temp_ocv->ocv[i][j-1],
+				pc_temp_ocv->ocv[i+1][j-1], ocv)) {
+			pcj_minus_one = linear_interpolate(
+				pc_temp_ocv->percent[i],
+				pc_temp_ocv->ocv[i][j-1],
+				pc_temp_ocv->percent[i + 1],
+				pc_temp_ocv->ocv[i+1][j-1],
+				ocv);
+		}
+
+		if (pcj && pcj_minus_one) {
+			pc = linear_interpolate(
+				pcj_minus_one,
+				pc_temp_ocv->temp[j-1],
+				pcj,
+				pc_temp_ocv->temp[j],
+				batt_temp_degc);
+			return pc;
+		}
+	}
+
+	if (pcj)
+		return pcj;
+
+	if (pcj_minus_one)
+		return pcj_minus_one;
+
+	pr_debug("%d ocv wasn't found for temp %d in the LUT returning 100%%\n",
+							ocv, batt_temp_degc);
+	return 100;
+}
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index f362a72..d9fa061 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
 
 static struct single_row_lut desay_5200_fcc_temp = {
 	.x		= {-20, 0, 25, 40},
@@ -76,7 +76,7 @@
 	},
 };
 
-struct pm8921_bms_battery_data desay_5200_data = {
+struct bms_battery_data desay_5200_data = {
 	.fcc			= 5200,
 	.fcc_temp_lut		= &desay_5200_fcc_temp,
 	.fcc_sf_lut		= &desay_5200_fcc_sf,
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 81ab121..fb4f967 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
 
 static struct single_row_lut fcc_temp = {
 	.x		= {-20, 0, 25, 40, 65},
@@ -99,7 +99,7 @@
 	}
 };
 
-struct pm8921_bms_battery_data palladium_1500_data = {
+struct bms_battery_data palladium_1500_data = {
 	.fcc			= 1500,
 	.fcc_temp_lut		= &fcc_temp,
 	.pc_temp_ocv_lut	= &pc_temp_ocv,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e9b4867..a64e6a5 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5128,7 +5128,9 @@
 	CLK_LOOKUP("core_clk", mdss_esc1_clk.c, ""),
 	CLK_LOOKUP("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi"),
 	CLK_LOOKUP("pixel_clk", mdss_pclk1_clk.c, ""),
-	CLK_LOOKUP("iface_clk", mdss_hdmi_ahb_clk.c, "fd922100.qcom,hdmi_tx"),
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd922100.qcom,hdmi_tx"),
+	CLK_LOOKUP("alt_iface_clk", mdss_hdmi_ahb_clk.c,
+		"fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, "fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("extp_clk", mdss_extpclk_clk.c, "fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c
index fbb3489..5f29406 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_smux.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c
@@ -79,6 +79,7 @@
 	unsigned long timeout_us;
 #endif
 	spinlock_t lock;
+	spinlock_t tx_queue_lock;
 	struct tasklet_struct tsklt;
 	/* IOCTL specified mode (protocol, QoS header) */
 	u32 operation_mode;
@@ -346,12 +347,15 @@
 		 ((struct net_device *)(dev))->name, p->stats.tx_packets,
 		 skb->len, skb->mark);
 	dev_kfree_skb_any(skb);
+
+	spin_lock_irqsave(&p->tx_queue_lock, flags);
 	if (netif_queue_stopped(dev) &&
 		msm_smux_is_ch_low(p->ch_id)) {
 		DBG0("%s: Low WM hit, waking queue=%p\n",
 			 __func__, skb);
 		netif_wake_queue(dev);
 	}
+	spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 }
 
 void rmnet_smux_notify(void *priv, int event_type, const void *metadata)
@@ -475,14 +479,20 @@
 
 	case SMUX_LOW_WM_HIT:
 		dev = priv;
+		p = netdev_priv(priv);
 		DBG0("[%s] Low WM hit dev:%s\n", __func__, dev->name);
+		spin_lock_irqsave(&p->tx_queue_lock, flags);
 		netif_start_queue(dev);
+		spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 		break;
 
 	case SMUX_HIGH_WM_HIT:
 		dev = priv;
-		DBG0("[%s] Low WM hit dev:%s\n", __func__, dev->name);
+		p = netdev_priv(priv);
+		DBG0("[%s] High WM hit dev:%s\n", __func__, dev->name);
+		spin_lock_irqsave(&p->tx_queue_lock, flags);
 		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 		break;
 
 	default:
@@ -573,7 +583,6 @@
 static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
-	int smux_ret;
 	struct QMI_QOS_HDR_S *qmih;
 	u32 opmode;
 	unsigned long flags;
@@ -593,21 +602,13 @@
 
 	dev->trans_start = jiffies;
 
-	/* if write() succeeds, skb access is unsafe in this process */
-	smux_ret = msm_smux_write(p->ch_id, skb, skb->data, skb->len);
-
-	if (smux_ret != 0 && smux_ret != -EAGAIN) {
-		pr_err("[%s] %s: write returned error %d",
-			   dev->name, __func__, smux_ret);
-		return -EPERM;
-	}
-
-	return smux_ret;
+	return msm_smux_write(p->ch_id, skb, skb->data, skb->len);
 }
 
 static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
 	int ret = 0;
 
 	if (netif_queue_stopped(dev) || (p->device_state == DEVICE_INACTIVE)) {
@@ -616,17 +617,10 @@
 		return 0;
 	}
 
+	spin_lock_irqsave(&p->tx_queue_lock, flags);
 	ret = _rmnet_xmit(skb, dev);
 
-	if (ret == -EPERM) {
-		/* Do not stop the queue here.
-		 * It will lead to ir-recoverable state.
-		 */
-		ret = NETDEV_TX_BUSY;
-		goto exit;
-	}
-
-	if (msm_smux_is_ch_full(p->ch_id) || (ret == -EAGAIN)) {
+	if (ret == -EAGAIN) {
 		/*
 		 * EAGAIN means we attempted to overflow the high watermark
 		 * Clearly the queue is not stopped like it should be, so
@@ -636,9 +630,9 @@
 		 */
 		netif_stop_queue(dev);
 		ret = NETDEV_TX_BUSY;
-		goto exit;
 	}
-exit:
+	spin_unlock_irqrestore(&p->tx_queue_lock, flags);
+
 	return ret;
 }
 
@@ -892,6 +886,7 @@
 		p->ch_id = n;
 		p->in_reset = 0;
 		spin_lock_init(&p->lock);
+		spin_lock_init(&p->tx_queue_lock);
 #ifdef CONFIG_MSM_RMNET_DEBUG
 		p->timeout_us = timeout_us;
 		p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index c63c99f..b107040 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,8 +10,8 @@
  * GNU General Public License for more details.
  *
  */
-#define pr_fmt(fmt)	"%s: " fmt, __func__
 
+#define pr_fmt(fmt)	"%s: " fmt, __func__
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
@@ -22,6 +22,7 @@
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
@@ -224,7 +225,6 @@
 module_param_cb(bms_end_ocv_uv, &bms_ro_param_ops, &bms_end_ocv_uv, 0644);
 module_param_cb(bms_end_cc_uah, &bms_ro_param_ops, &bms_end_cc_uah, 0644);
 
-static int interpolate_fcc(struct pm8921_bms_chip *chip, int batt_temp);
 static void readjust_fcc_table(void)
 {
 	struct single_row_lut *temp, *old;
@@ -241,7 +241,7 @@
 		return;
 	}
 
-	fcc = interpolate_fcc(the_chip, last_real_fcc_batt_temp);
+	fcc = interpolate_fcc(the_chip->fcc_temp_lut, last_real_fcc_batt_temp);
 
 	temp->cols = the_chip->fcc_temp_lut->cols;
 	for (i = 0; i < the_chip->fcc_temp_lut->cols; i++) {
@@ -583,342 +583,6 @@
 	return 0;
 }
 
-static int linear_interpolate(int y0, int x0, int y1, int x1, int x)
-{
-	if (y0 == y1 || x == x0)
-		return y0;
-	if (x1 == x0 || x == x1)
-		return y1;
-
-	return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
-}
-
-static int interpolate_single_lut(struct single_row_lut *lut, int x)
-{
-	int i, result;
-
-	if (x < lut->x[0]) {
-		pr_debug("x %d less than known range return y = %d lut = %pS\n",
-							x, lut->y[0], lut);
-		return lut->y[0];
-	}
-	if (x > lut->x[lut->cols - 1]) {
-		pr_debug("x %d more than known range return y = %d lut = %pS\n",
-						x, lut->y[lut->cols - 1], lut);
-		return lut->y[lut->cols - 1];
-	}
-
-	for (i = 0; i < lut->cols; i++)
-		if (x <= lut->x[i])
-			break;
-	if (x == lut->x[i]) {
-		result = lut->y[i];
-	} else {
-		result = linear_interpolate(
-			lut->y[i - 1],
-			lut->x[i - 1],
-			lut->y[i],
-			lut->x[i],
-			x);
-	}
-	return result;
-}
-
-static int interpolate_fcc(struct pm8921_bms_chip *chip, int batt_temp)
-{
-	/* batt_temp is in tenths of degC - convert it to degC for lookups */
-	batt_temp = batt_temp/10;
-	return interpolate_single_lut(chip->fcc_temp_lut, batt_temp);
-}
-
-static int interpolate_fcc_adjusted(struct pm8921_bms_chip *chip, int batt_temp)
-{
-	/* batt_temp is in tenths of degC - convert it to degC for lookups */
-	batt_temp = batt_temp/10;
-	return interpolate_single_lut(chip->adjusted_fcc_temp_lut, batt_temp);
-}
-
-static int interpolate_scalingfactor_fcc(struct pm8921_bms_chip *chip,
-								int cycles)
-{
-	/*
-	 * sf table could be null when no battery aging data is available, in
-	 * that case return 100%
-	 */
-	if (chip->fcc_sf_lut)
-		return interpolate_single_lut(chip->fcc_sf_lut, cycles);
-	else
-		return 100;
-}
-
-static int interpolate_scalingfactor(struct pm8921_bms_chip *chip,
-				struct sf_lut *sf_lut,
-				int row_entry, int pc)
-{
-	int i, scalefactorrow1, scalefactorrow2, scalefactor;
-	int rows, cols;
-	int row1 = 0;
-	int row2 = 0;
-
-	/*
-	 * sf table could be null when no battery aging data is available, in
-	 * that case return 100%
-	 */
-	if (!sf_lut)
-		return 100;
-
-	rows = sf_lut->rows;
-	cols = sf_lut->cols;
-	if (pc > sf_lut->percent[0]) {
-		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
-		row1 = 0;
-		row2 = 0;
-	}
-	if (pc < sf_lut->percent[rows - 1]) {
-		pr_debug("pc %d less than known pc ranges for sf", pc);
-		row1 = rows - 1;
-		row2 = rows - 1;
-	}
-	for (i = 0; i < rows; i++) {
-		if (pc == sf_lut->percent[i]) {
-			row1 = i;
-			row2 = i;
-			break;
-		}
-		if (pc > sf_lut->percent[i]) {
-			row1 = i - 1;
-			row2 = i;
-			break;
-		}
-	}
-
-	if (row_entry < sf_lut->row_entries[0])
-		row_entry = sf_lut->row_entries[0];
-	if (row_entry > sf_lut->row_entries[cols - 1])
-		row_entry = sf_lut->row_entries[cols - 1];
-
-	for (i = 0; i < cols; i++)
-		if (row_entry <= sf_lut->row_entries[i])
-			break;
-	if (row_entry == sf_lut->row_entries[i]) {
-		scalefactor = linear_interpolate(
-				sf_lut->sf[row1][i],
-				sf_lut->percent[row1],
-				sf_lut->sf[row2][i],
-				sf_lut->percent[row2],
-				pc);
-		return scalefactor;
-	}
-
-	scalefactorrow1 = linear_interpolate(
-				sf_lut->sf[row1][i - 1],
-				sf_lut->row_entries[i - 1],
-				sf_lut->sf[row1][i],
-				sf_lut->row_entries[i],
-				row_entry);
-
-	scalefactorrow2 = linear_interpolate(
-				sf_lut->sf[row2][i - 1],
-				sf_lut->row_entries[i - 1],
-				sf_lut->sf[row2][i],
-				sf_lut->row_entries[i],
-				row_entry);
-
-	scalefactor = linear_interpolate(
-				scalefactorrow1,
-				sf_lut->percent[row1],
-				scalefactorrow2,
-				sf_lut->percent[row2],
-				pc);
-
-	return scalefactor;
-}
-
-static int is_between(int left, int right, int value)
-{
-	if (left >= right && left >= value && value >= right)
-		return 1;
-	if (left <= right && left <= value && value <= right)
-		return 1;
-
-	return 0;
-}
-
-/* get ocv given a soc  -- reverse lookup */
-static int interpolate_ocv(struct pm8921_bms_chip *chip,
-				int batt_temp_degc, int pc)
-{
-	int i, ocvrow1, ocvrow2, ocv;
-	int rows, cols;
-	int row1 = 0;
-	int row2 = 0;
-
-	rows = chip->pc_temp_ocv_lut->rows;
-	cols = chip->pc_temp_ocv_lut->cols;
-	if (pc > chip->pc_temp_ocv_lut->percent[0]) {
-		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
-		row1 = 0;
-		row2 = 0;
-	}
-	if (pc < chip->pc_temp_ocv_lut->percent[rows - 1]) {
-		pr_debug("pc %d less than known pc ranges for sf\n", pc);
-		row1 = rows - 1;
-		row2 = rows - 1;
-	}
-	for (i = 0; i < rows; i++) {
-		if (pc == chip->pc_temp_ocv_lut->percent[i]) {
-			row1 = i;
-			row2 = i;
-			break;
-		}
-		if (pc > chip->pc_temp_ocv_lut->percent[i]) {
-			row1 = i - 1;
-			row2 = i;
-			break;
-		}
-	}
-
-	if (batt_temp_degc < chip->pc_temp_ocv_lut->temp[0])
-		batt_temp_degc = chip->pc_temp_ocv_lut->temp[0];
-	if (batt_temp_degc > chip->pc_temp_ocv_lut->temp[cols - 1])
-		batt_temp_degc = chip->pc_temp_ocv_lut->temp[cols - 1];
-
-	for (i = 0; i < cols; i++)
-		if (batt_temp_degc <= chip->pc_temp_ocv_lut->temp[i])
-			break;
-	if (batt_temp_degc == chip->pc_temp_ocv_lut->temp[i]) {
-		ocv = linear_interpolate(
-				chip->pc_temp_ocv_lut->ocv[row1][i],
-				chip->pc_temp_ocv_lut->percent[row1],
-				chip->pc_temp_ocv_lut->ocv[row2][i],
-				chip->pc_temp_ocv_lut->percent[row2],
-				pc);
-		return ocv;
-	}
-
-	ocvrow1 = linear_interpolate(
-				chip->pc_temp_ocv_lut->ocv[row1][i - 1],
-				chip->pc_temp_ocv_lut->temp[i - 1],
-				chip->pc_temp_ocv_lut->ocv[row1][i],
-				chip->pc_temp_ocv_lut->temp[i],
-				batt_temp_degc);
-
-	ocvrow2 = linear_interpolate(
-				chip->pc_temp_ocv_lut->ocv[row2][i - 1],
-				chip->pc_temp_ocv_lut->temp[i - 1],
-				chip->pc_temp_ocv_lut->ocv[row2][i],
-				chip->pc_temp_ocv_lut->temp[i],
-				batt_temp_degc);
-
-	ocv = linear_interpolate(
-				ocvrow1,
-				chip->pc_temp_ocv_lut->percent[row1],
-				ocvrow2,
-				chip->pc_temp_ocv_lut->percent[row2],
-				pc);
-
-	return ocv;
-}
-
-static int interpolate_pc(struct pm8921_bms_chip *chip,
-				int batt_temp_degc, int ocv)
-{
-	int i, j, pcj, pcj_minus_one, pc;
-	int rows = chip->pc_temp_ocv_lut->rows;
-	int cols = chip->pc_temp_ocv_lut->cols;
-
-
-	if (batt_temp_degc < chip->pc_temp_ocv_lut->temp[0]) {
-		pr_debug("batt_temp %d < known temp range\n", batt_temp_degc);
-		batt_temp_degc = chip->pc_temp_ocv_lut->temp[0];
-	}
-	if (batt_temp_degc > chip->pc_temp_ocv_lut->temp[cols - 1]) {
-		pr_debug("batt_temp %d > known temp range\n", batt_temp_degc);
-		batt_temp_degc = chip->pc_temp_ocv_lut->temp[cols - 1];
-	}
-
-	for (j = 0; j < cols; j++)
-		if (batt_temp_degc <= chip->pc_temp_ocv_lut->temp[j])
-			break;
-	if (batt_temp_degc == chip->pc_temp_ocv_lut->temp[j]) {
-		/* found an exact match for temp in the table */
-		if (ocv >= chip->pc_temp_ocv_lut->ocv[0][j])
-			return chip->pc_temp_ocv_lut->percent[0];
-		if (ocv <= chip->pc_temp_ocv_lut->ocv[rows - 1][j])
-			return chip->pc_temp_ocv_lut->percent[rows - 1];
-		for (i = 0; i < rows; i++) {
-			if (ocv >= chip->pc_temp_ocv_lut->ocv[i][j]) {
-				if (ocv == chip->pc_temp_ocv_lut->ocv[i][j])
-					return
-					chip->pc_temp_ocv_lut->percent[i];
-				pc = linear_interpolate(
-					chip->pc_temp_ocv_lut->percent[i],
-					chip->pc_temp_ocv_lut->ocv[i][j],
-					chip->pc_temp_ocv_lut->percent[i - 1],
-					chip->pc_temp_ocv_lut->ocv[i - 1][j],
-					ocv);
-				return pc;
-			}
-		}
-	}
-
-	/*
-	 * batt_temp_degc is within temperature for
-	 * column j-1 and j
-	 */
-	if (ocv >= chip->pc_temp_ocv_lut->ocv[0][j])
-		return chip->pc_temp_ocv_lut->percent[0];
-	if (ocv <= chip->pc_temp_ocv_lut->ocv[rows - 1][j - 1])
-		return chip->pc_temp_ocv_lut->percent[rows - 1];
-
-	pcj_minus_one = 0;
-	pcj = 0;
-	for (i = 0; i < rows-1; i++) {
-		if (pcj == 0
-			&& is_between(chip->pc_temp_ocv_lut->ocv[i][j],
-				chip->pc_temp_ocv_lut->ocv[i+1][j], ocv)) {
-			pcj = linear_interpolate(
-				chip->pc_temp_ocv_lut->percent[i],
-				chip->pc_temp_ocv_lut->ocv[i][j],
-				chip->pc_temp_ocv_lut->percent[i + 1],
-				chip->pc_temp_ocv_lut->ocv[i+1][j],
-				ocv);
-		}
-
-		if (pcj_minus_one == 0
-			&& is_between(chip->pc_temp_ocv_lut->ocv[i][j-1],
-				chip->pc_temp_ocv_lut->ocv[i+1][j-1], ocv)) {
-
-			pcj_minus_one = linear_interpolate(
-				chip->pc_temp_ocv_lut->percent[i],
-				chip->pc_temp_ocv_lut->ocv[i][j-1],
-				chip->pc_temp_ocv_lut->percent[i + 1],
-				chip->pc_temp_ocv_lut->ocv[i+1][j-1],
-				ocv);
-		}
-
-		if (pcj && pcj_minus_one) {
-			pc = linear_interpolate(
-				pcj_minus_one,
-				chip->pc_temp_ocv_lut->temp[j-1],
-				pcj,
-				chip->pc_temp_ocv_lut->temp[j],
-				batt_temp_degc);
-			return pc;
-		}
-	}
-
-	if (pcj)
-		return pcj;
-
-	if (pcj_minus_one)
-		return pcj_minus_one;
-
-	pr_debug("%d ocv wasn't found for temp %d in the LUT returning 100%%",
-							ocv, batt_temp_degc);
-	return 100;
-}
-
 #define BMS_MODE_BIT	BIT(6)
 #define EN_VBAT_BIT	BIT(5)
 #define OVERRIDE_MODE_DELAY_MS	20
@@ -1042,7 +706,7 @@
 	}
 	/* Convert the batt_temp to DegC from deciDegC */
 	batt_temp = batt_temp / 10;
-	scalefactor = interpolate_scalingfactor(chip, chip->rbatt_sf_lut,
+	scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
 							batt_temp, soc_rbatt);
 	pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
 				scalefactor, batt_temp, soc_rbatt);
@@ -1069,16 +733,18 @@
 	int initfcc, result, scalefactor = 0;
 
 	if (chip->adjusted_fcc_temp_lut == NULL) {
-		initfcc = interpolate_fcc(chip, batt_temp);
+		initfcc = interpolate_fcc(chip->fcc_temp_lut, batt_temp);
 
-		scalefactor = interpolate_scalingfactor_fcc(chip, chargecycles);
+		scalefactor = interpolate_scalingfactor_fcc(chip->fcc_sf_lut,
+				chargecycles);
 
 		/* Multiply the initial FCC value by the scale factor. */
 		result = (initfcc * scalefactor * 1000) / 100;
 		pr_debug("fcc = %d uAh\n", result);
 		return result;
 	} else {
-		return 1000 * interpolate_fcc_adjusted(chip, batt_temp);
+		return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
+				batt_temp);
 	}
 }
 
@@ -1120,17 +786,18 @@
 	return 0;
 }
 
-static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv, int batt_temp,
-							int chargecycles)
+static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv,
+					int batt_temp, int chargecycles)
 {
 	int pc, scalefactor;
 
-	pc = interpolate_pc(chip, batt_temp / 10, ocv_uv / 1000);
+	pc = interpolate_pc(chip->pc_temp_ocv_lut,
+			batt_temp / 10, ocv_uv / 1000);
 	pr_debug("pc = %u for ocv = %dmicroVolts batt_temp = %d\n",
 					pc, ocv_uv, batt_temp);
 
-	scalefactor = interpolate_scalingfactor(chip,
-					chip->pc_sf_lut, chargecycles, pc);
+	scalefactor = interpolate_scalingfactor(chip->pc_sf_lut,
+			chargecycles, pc);
 	pr_debug("scalefactor = %u batt_temp = %d\n", scalefactor, batt_temp);
 
 	/* Multiply the initial FCC value by the scale factor. */
@@ -1183,7 +850,8 @@
 	int uuc_rbatt_uv;
 
 	for (i = 0; i <= 100; i++) {
-		ocv_mv = interpolate_ocv(chip, batt_temp_degc, i);
+		ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
+				batt_temp_degc, i);
 		rbatt_mohm = get_rbatt(chip, i, batt_temp);
 		unusable_uv = (rbatt_mohm * i_ma) + (chip->v_cutoff * 1000);
 		delta_uv = ocv_mv * 1000 - unusable_uv;
@@ -1239,8 +907,8 @@
 	new_uuc = (fcc_uah * chip->prev_pc_unusable) / 100;
 
 	/* also find update the iavg_ma accordingly */
-	new_unusable_mv = interpolate_ocv(chip, batt_temp_degc,
-						chip->prev_pc_unusable);
+	new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
+			batt_temp_degc, chip->prev_pc_unusable);
 	if (new_unusable_mv < chip->v_cutoff)
 		new_unusable_mv = chip->v_cutoff;
 
@@ -1531,11 +1199,11 @@
 	pc = DIV_ROUND_CLOSEST((int)rc * 100, fcc_uah);
 	pc = clamp(pc, 0, 100);
 
-	ocv = interpolate_ocv(chip, batt_temp_degc, pc);
+	ocv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
 
 	pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
 			shutdown_soc, fcc_uah, uuc_uah, (int)rc, pc, ocv);
-	new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+	new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv);
 	pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
 
 	while (abs(new_pc - pc) > 1) {
@@ -1545,7 +1213,8 @@
 			delta_mv = -1 * delta_mv;
 
 		ocv = ocv + delta_mv;
-		new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+		new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
+				batt_temp_degc, ocv);
 		pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
 	}
 
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index e3bfbd0..817bfbb 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -80,8 +80,10 @@
 #ifdef CONFIG_TARGET_CORE
 #include "f_tcm.c"
 #endif
+#ifdef CONFIG_SND_PCM
 #include "u_uac1.c"
 #include "f_uac1.c"
+#endif
 
 MODULE_AUTHOR("Mike Lockwood");
 MODULE_DESCRIPTION("Android Composite USB Driver");
@@ -704,6 +706,7 @@
 	.init		= mbim_function_init,
 };
 
+#ifdef CONFIG_SND_PCM
 /* PERIPHERAL AUDIO */
 static int audio_function_bind_config(struct android_usb_function *f,
 					  struct usb_configuration *c)
@@ -715,6 +718,7 @@
 	.name		= "audio",
 	.bind_config	= audio_function_bind_config,
 };
+#endif
 
 
 /* DIAG */
@@ -1520,7 +1524,9 @@
 static struct android_usb_function *supported_functions[] = {
 	&mbim_function,
 	&ecm_qc_function,
+#ifdef CONFIG_SND_PCM
 	&audio_function,
+#endif
 	&rmnet_smd_function,
 	&rmnet_sdio_function,
 	&rmnet_smd_sdio_function,
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index a9f810f..8f4f4d5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -303,6 +303,7 @@
 		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
 	}
 
+	mdss_dsi_sw_reset(pdata);
 	mdss_dsi_host_init(mipi, pdata);
 
 	if (mipi->force_clk_lane_hs) {
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 3abf4d0..125644e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -813,6 +813,7 @@
 void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	u32 dsi_ctrl;
 
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
@@ -821,6 +822,16 @@
 		return;
 	}
 
+	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
+	dsi_ctrl &= ~0x01;
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
+	wmb();
+
+	/* turn esc, byte, dsi, pclk, sclk, hclk on */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x11c,
+					0x23f); /* DSI_CLK_CTRL */
+	wmb();
+
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x01);
 	wmb();
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x00);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index b247e4d..fd52e1c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -106,8 +106,6 @@
 	pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
 		 mipi->mode);
 
-	mdss_dsi_sw_reset(pdata);
-
 	if (mipi->mode == DSI_VIDEO_MODE) {
 		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
 			num_of_on_cmds);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index f720a2f..8db38d6 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -358,34 +358,25 @@
 		DEV_DBG("EDID: reading block(%d) with block-size=%d\n",
 			block, block_size);
 		for (i = 0; i < 0x80; i += block_size) {
-			/*Read EDID twice with 32bit alighnment too */
-			if (block < 2) {
-				memset(&ddc_data, 0, sizeof(ddc_data));
-				ddc_data.dev_addr = 0xA0;
-				ddc_data.offset   = block*0x80 + i;
-				ddc_data.data_buf = edid_buf+i;
-				ddc_data.data_len = block_size;
-				ddc_data.retry    = 1;
-				ddc_data.what     = "EDID";
-				ddc_data.no_align = false;
+			memset(&ddc_data, 0, sizeof(ddc_data));
+			ddc_data.dev_addr    = 0xA0;
+			ddc_data.offset      = block*0x80 + i;
+			ddc_data.data_buf    = edid_buf+i;
+			ddc_data.data_len    = block_size;
+			ddc_data.request_len = block_size;
+			ddc_data.retry       = 1;
+			ddc_data.what        = "EDID";
+			ddc_data.no_align    = false;
 
+			/*Read EDID twice with 32bit alighnment too */
+			if (block < 2)
 				status = hdmi_ddc_read(
 					edid_ctrl->init_data.ddc_ctrl,
 					&ddc_data);
-			} else {
-				memset(&ddc_data, 0, sizeof(ddc_data));
-				ddc_data.dev_addr    = 0xA0;
-				ddc_data.offset      = block*0x80 + i;
-				ddc_data.data_buf    = edid_buf+i;
-				ddc_data.data_len    = block_size;
-				ddc_data.request_len = block_size;
-				ddc_data.retry       = 1;
-				ddc_data.what        = "EDID";
-
+			else
 				status = hdmi_ddc_read_seg(
 					edid_ctrl->init_data.ddc_ctrl,
 					&ddc_data);
-			}
 			if (status)
 				break;
 		}
@@ -413,7 +404,7 @@
 	}
 
 	print_len = 0x80;
-	for (ndx = 0; ndx < print_len; ndx += 16)
+	for (ndx = 0; ndx < print_len; ndx += 4)
 		DEV_DBG("EDID[%02x-%02x] %02x %02x %02x %02x\n",
 			ndx, ndx+3,
 			b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3]);
@@ -1392,7 +1383,7 @@
 {
 	struct hdmi_edid_ctrl *edid_ctrl = NULL;
 
-	if (!init_data || !init_data->base ||
+	if (!init_data || !init_data->io ||
 		!init_data->mutex || !init_data->sysfs_kobj ||
 		!init_data->ddc_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.h b/drivers/video/msm/mdss/mdss_hdmi_edid.h
index d10ae49..5c51e7e 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.h
@@ -16,7 +16,7 @@
 #include "mdss_hdmi_util.h"
 
 struct hdmi_edid_init_data {
-	void __iomem *base;
+	struct dss_io_data *io;
 	struct mutex *mutex;
 	struct kobject *sysfs_kobj;
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 9278029..7f41221 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/bitops.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -20,7 +19,7 @@
 #include <linux/of_gpio.h>
 #include <linux/types.h>
 
-/* #define DEBUG */
+#define REG_DUMP 0
 
 #include "mdss_fb.h"
 #include "mdss_hdmi_tx.h"
@@ -91,19 +90,19 @@
 	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
 };
 
-static const char *hdmi_tx_clk_name(u32 clk)
+const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
 {
-	switch (clk) {
-	case HDMI_TX_AHB_CLK:	return "hdmi_ahb_clk";
-	case HDMI_TX_APP_CLK:	return "hdmi_app_clk";
-	case HDMI_TX_EXTP_CLK:	return "hdmi_extp_clk";
-	default:		return "???";
+	switch (module) {
+	case HDMI_TX_HPD_PM:	return "HDMI_TX_HPD_PM";
+	case HDMI_TX_CORE_PM:	return "HDMI_TX_CORE_PM";
+	case HDMI_TX_CEC_PM:	return "HDMI_TX_CEC_PM";
+	default: return "???";
 	}
-} /* hdmi_tx_clk_name */
+} /* hdmi_tx_pm_name */
 
-static const char *hdmi_tx_io_name(u32 io)
+static const char *hdmi_tx_io_name(u32 type)
 {
-	switch (io) {
+	switch (type) {
 	case HDMI_TX_CORE_IO:	return "core_physical";
 	case HDMI_TX_PHY_IO:	return "phy_physical";
 	case HDMI_TX_QFPROM_IO:	return "qfprom_physical";
@@ -190,75 +189,6 @@
 	return ret;
 } /* hdmi_tx_sysfs_rda_connected */
 
-static ssize_t hdmi_tx_sysfs_rda_fake_hpd(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	ssize_t ret;
-	struct hdmi_tx_ctrl *hdmi_ctrl =
-		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
-
-	if (!hdmi_ctrl) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&hdmi_ctrl->mutex);
-	ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->hpd_state);
-	DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_state);
-	mutex_unlock(&hdmi_ctrl->mutex);
-
-	return ret;
-} /* hdmi_tx_sysfs_rda_fake_hpd */
-
-static ssize_t hdmi_tx_sysfs_wta_fake_hpd(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	int fake_hpd, rc = 0;
-	ssize_t ret = strnlen(buf, PAGE_SIZE);
-	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
-
-	DEV_DBG("%s:\n", __func__);
-	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
-
-	if (!hdmi_ctrl) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	rc = kstrtoint(buf, 10, &fake_hpd);
-	if (rc) {
-		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
-		return rc;
-	}
-
-	mutex_lock(&hdmi_ctrl->mutex);
-	DEV_INFO("%s: fake_hpd=%d\n", __func__, fake_hpd);
-	if (fake_hpd) {
-		hdmi_ctrl->hpd_state = true;
-
-		/* todo: Remove this once HPD line is available in HW */
-		DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
-		if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_ONLINE))
-			DEV_ERR("%s: failed sending online event\n", __func__);
-		switch_set_state(&hdmi_ctrl->sdev, 1);
-		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
-			hdmi_ctrl->sdev.state);
-	} else {
-		hdmi_ctrl->hpd_state = false;
-
-		/* todo: Remove this once HPD line is available in HW */
-		DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
-		if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE))
-			DEV_ERR("%s: failed sending online event\n", __func__);
-		switch_set_state(&hdmi_ctrl->sdev, 0);
-		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
-			hdmi_ctrl->sdev.state);
-	}
-	mutex_unlock(&hdmi_ctrl->mutex);
-
-	return ret;
-} /* hdmi_tx_sysfs_wta_fake_hpd */
-
 static ssize_t hdmi_tx_sysfs_rda_hpd(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
@@ -298,16 +228,13 @@
 		return rc;
 	}
 
-	/* todo: Remove this once HPD line is available in HW */
-	if (0) {
-		if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
-			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
-		} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
-			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
-		} else {
-			rc = -EPERM;
-			ret = rc;
-		}
+	if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
+		rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+	} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
+		rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+	} else {
+		rc = -EPERM;
+		ret = rc;
 	}
 
 	if (!rc) {
@@ -325,13 +252,10 @@
 static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
 static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
 	hdmi_tx_sysfs_wta_hpd);
-static DEVICE_ATTR(fake_hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_fake_hpd,
-	hdmi_tx_sysfs_wta_fake_hpd);
 
 static struct attribute *hdmi_tx_fs_attrs[] = {
 	&dev_attr_connected.attr,
 	&dev_attr_hpd.attr,
-	&dev_attr_fake_hpd.attr,
 	NULL,
 };
 static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -385,7 +309,7 @@
 		return -EINVAL;
 	}
 
-	edid_init_data.base = hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base;
+	edid_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	edid_init_data.mutex = &hdmi_ctrl->mutex;
 	edid_init_data.sysfs_kobj = hdmi_ctrl->kobj;
 	edid_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
@@ -405,14 +329,14 @@
 
 static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
-	return HDMI_REG_R_ND(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
-		HDMI_CTRL) & BIT(0);
+	struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	return DSS_REG_R_ND(io, HDMI_CTRL) & BIT(0);
 } /* hdmi_tx_is_controller_on */
 
 static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
-	return !(HDMI_REG_R_ND(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
-		HDMI_CTRL) & BIT(1));
+	struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
 } /* hdmi_tx_is_dvi_mode */
 
 static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -473,44 +397,6 @@
 	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
 } /* hdmi_tx_setup_video_mode_lut */
 
-static inline struct clk *hdmi_tx_get_clk(struct hdmi_tx_platform_data *pdata,
-	u32 clk_idx)
-{
-	if (!pdata || clk_idx > HDMI_TX_MAX_CLK) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return NULL;
-	}
-
-	return pdata->clk[clk_idx];
-} /* hdmi_tx_get_clk */
-
-static int hdmi_tx_clk_set_rate(struct hdmi_tx_platform_data *pdata,
-	u32 clk_idx, unsigned long clk_rate)
-{
-	int rc = 0;
-	struct clk *clk = NULL;
-
-	if (!pdata) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	clk = hdmi_tx_get_clk(pdata, clk_idx);
-	if (clk) {
-		rc = clk_set_rate(clk, clk_rate);
-		if (IS_ERR_VALUE(rc))
-			DEV_ERR("%s: failed rc=%d\n", __func__, rc);
-		else
-			DEV_DBG("%s: name='%s' rate=%lu\n", __func__,
-				hdmi_tx_clk_name(clk_idx), clk_rate);
-	} else {
-		DEV_ERR("%s: FAILED: invalid clk_idx=%d\n", __func__, clk_idx);
-		rc = -EINVAL;
-	}
-
-	return rc;
-} /* hdmi_tx_clk_set_rate */
-
 static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int status;
@@ -551,9 +437,14 @@
 	}
 
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
 	DEV_DBG("%s: Got HPD interrupt\n", __func__);
 
-	hpd_state = (HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+	hpd_state = (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
 	mutex_lock(&hdmi_ctrl->mutex);
 	if ((hdmi_ctrl->hpd_prev_state != hdmi_ctrl->hpd_state) ||
 		(hdmi_ctrl->hpd_state != hpd_state)) {
@@ -605,22 +496,62 @@
 	}
 
 	/* Set IRQ for HPD */
-	HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, 4 | (hpd_state ? 0 : 2));
+	DSS_REG_W(io, HDMI_HPD_INT_CTRL, 4 | (hpd_state ? 0 : 2));
 } /* hdmi_tx_hpd_state_work */
 
-static int hdmi_tx_check_capability(void __iomem *base)
+static void hdmi_tx_hpd_int_work(struct work_struct *work)
+{
+	u32 hpd_int_status;
+	u32 hpd_int_ctrl;
+	u32 cable_detected;
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	struct dss_io_data *io = NULL;
+
+	hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_int_work);
+	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
+		DEV_DBG("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
+	/* Process HPD Interrupt */
+	hpd_int_status = DSS_REG_R(io, HDMI_HPD_INT_STATUS);
+	hpd_int_ctrl = DSS_REG_R(io, HDMI_HPD_INT_CTRL);
+
+	DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2));
+
+	cable_detected = hpd_int_status & BIT(1);
+	mutex_lock(&hdmi_ctrl->mutex);
+	hdmi_ctrl->hpd_cable_chg_detected = true;
+	hdmi_ctrl->hpd_prev_state = cable_detected ? 0 : 1;
+	hdmi_ctrl->hpd_stable = 0;
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
+
+	DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
+		hpd_int_status);
+} /* hdmi_tx_hpd_int_work */
+
+static int hdmi_tx_check_capability(struct dss_io_data *io)
 {
 	u32 hdmi_disabled, hdcp_disabled;
 
-	if (!base) {
+	if (!io) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
 
-	/* QFPROM_RAW_FEAT_CONFIG_ROW0_LSB */
-	hdcp_disabled = HDMI_REG_R_ND(base, 0x000000F8) & BIT(31);
-	/* QFPROM_RAW_FEAT_CONFIG_ROW0_MSB */
-	hdmi_disabled = HDMI_REG_R_ND(base, 0x000000FC) & BIT(0);
+	hdcp_disabled = DSS_REG_R_ND(io,
+		QFPROM_RAW_FEAT_CONFIG_ROW0_LSB) & BIT(31);
+
+	hdmi_disabled = DSS_REG_R_ND(io,
+		QFPROM_RAW_FEAT_CONFIG_ROW0_MSB) & BIT(0);
 
 	DEV_DBG("%s: Features <HDMI:%s, HDCP:%s>\n", __func__,
 		hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON");
@@ -710,25 +641,9 @@
 		goto end;
 	}
 
-	/*
-	 * extpclk is driven by hdmi phy pll. This phy pll programming requires
-	 * hdmi_ahb_clk. So enable it and then disable.
-	 */
-	rc = clk_prepare_enable(pdata->clk[HDMI_TX_AHB_CLK]);
-	if (rc) {
-		DEV_ERR("%s: failed to enable '%s' clk\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
-		goto end;
-	}
-	rc = hdmi_tx_clk_set_rate(pdata, HDMI_TX_EXTP_CLK,
-		timing->pixel_freq * 1000);
-	if (rc) {
-		DEV_ERR("%s: FAILED: '%s' clk set rate\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
-		clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
-		goto end;
-	}
-	clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
+	/* todo: find a better way */
+	hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate =
+		timing->pixel_freq * 1000;
 
 	hdmi_ctrl->video_resolution = format;
 	hdmi_edid_set_video_resolution(
@@ -772,35 +687,35 @@
 		timing->back_porch_h + timing->pulse_width_h - 1;
 	total_v = timing->active_v + timing->front_porch_v +
 		timing->back_porch_v + timing->pulse_width_v - 1;
-	HDMI_REG_W(io->base, HDMI_TOTAL,
+	DSS_REG_W(io, HDMI_TOTAL,
 		((total_v << 16) & 0x0FFF0000) |
 		((total_h << 0) & 0x00000FFF));
 
 	start_h = timing->back_porch_h + timing->pulse_width_h;
 	end_h   = (total_h + 1) - timing->front_porch_h;
-	HDMI_REG_W(io->base, HDMI_ACTIVE_H,
+	DSS_REG_W(io, HDMI_ACTIVE_H,
 		((end_h << 16) & 0x0FFF0000) |
 		((start_h << 0) & 0x00000FFF));
 
 	start_v = timing->back_porch_v + timing->pulse_width_v - 1;
 	end_v   = total_v - timing->front_porch_v;
-	HDMI_REG_W(io->base, HDMI_ACTIVE_V,
+	DSS_REG_W(io, HDMI_ACTIVE_V,
 		((end_v << 16) & 0x0FFF0000) |
 		((start_v << 0) & 0x00000FFF));
 
 	if (timing->interlaced) {
-		HDMI_REG_W(io->base, HDMI_V_TOTAL_F2,
+		DSS_REG_W(io, HDMI_V_TOTAL_F2,
 			((total_v + 1) << 0) & 0x00000FFF);
 
-		HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2,
+		DSS_REG_W(io, HDMI_ACTIVE_V_F2,
 			(((start_v + 1) << 0) & 0x00000FFF) |
 			(((end_v + 1) << 16) & 0x0FFF0000));
 	} else {
-		HDMI_REG_W(io->base, HDMI_V_TOTAL_F2, 0);
-		HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2, 0);
+		DSS_REG_W(io, HDMI_V_TOTAL_F2, 0);
+		DSS_REG_W(io, HDMI_ACTIVE_V_F2, 0);
 	}
 
-	HDMI_REG_W(io->base, HDMI_FRAME_CTRL,
+	DSS_REG_W(io, HDMI_FRAME_CTRL,
 		((timing->interlaced << 31) & 0x80000000) |
 		((timing->active_low_h << 29) & 0x20000000) |
 		((timing->active_low_v << 28) & 0x10000000));
@@ -929,28 +844,28 @@
 	regVal = regVal << 8 | avi_iframe[4];
 	regVal = regVal << 8 | avi_iframe[3];
 	regVal = regVal << 8 | checksum;
-	HDMI_REG_W(io->base, HDMI_AVI_INFO0, regVal);
+	DSS_REG_W(io, HDMI_AVI_INFO0, regVal);
 
 	regVal = avi_iframe[9];
 	regVal = regVal << 8 | avi_iframe[8];
 	regVal = regVal << 8 | avi_iframe[7];
 	regVal = regVal << 8 | avi_iframe[6];
-	HDMI_REG_W(io->base, HDMI_AVI_INFO1, regVal);
+	DSS_REG_W(io, HDMI_AVI_INFO1, regVal);
 
 	regVal = avi_iframe[13];
 	regVal = regVal << 8 | avi_iframe[12];
 	regVal = regVal << 8 | avi_iframe[11];
 	regVal = regVal << 8 | avi_iframe[10];
-	HDMI_REG_W(io->base, HDMI_AVI_INFO2, regVal);
+	DSS_REG_W(io, HDMI_AVI_INFO2, regVal);
 
 	regVal = avi_iframe[1];
 	regVal = regVal << 16 | avi_iframe[15];
 	regVal = regVal << 8 | avi_iframe[14];
-	HDMI_REG_W(io->base, HDMI_AVI_INFO3, regVal);
+	DSS_REG_W(io, HDMI_AVI_INFO3, regVal);
 
 	/* 0x3 for AVI InfFrame enable (every frame) */
-	HDMI_REG_W(io->base, HDMI_INFOFRAME_CTRL0,
-		HDMI_REG_R(io->base, HDMI_INFOFRAME_CTRL0) |
+	DSS_REG_W(io, HDMI_INFOFRAME_CTRL0,
+		DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) |
 		0x00000003L);
 } /* hdmi_tx_set_avi_infoframe */
 
@@ -986,14 +901,14 @@
 	 * 0x19 Length of Source Product Description InfoFrame
 	 */
 	packet_header  = 0x83 | (0x01 << 8) | (0x19 << 16);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_HDR, packet_header);
+	DSS_REG_W(io, HDMI_GENERIC1_HDR, packet_header);
 	check_sum += IFRAME_CHECKSUM_32(packet_header);
 
 	packet_payload = (vendor_name[3] & 0x7f)
 		| ((vendor_name[4] & 0x7f) << 8)
 		| ((vendor_name[5] & 0x7f) << 16)
 		| ((vendor_name[6] & 0x7f) << 24);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_1, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_1, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	/* Product Description (7-bit ASCII code) */
@@ -1001,28 +916,28 @@
 		| ((product_description[0] & 0x7f) << 8)
 		| ((product_description[1] & 0x7f) << 16)
 		| ((product_description[2] & 0x7f) << 24);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_2, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_2, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	packet_payload = (product_description[3] & 0x7f)
 		| ((product_description[4] & 0x7f) << 8)
 		| ((product_description[5] & 0x7f) << 16)
 		| ((product_description[6] & 0x7f) << 24);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_3, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_3, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	packet_payload = (product_description[7] & 0x7f)
 		| ((product_description[8] & 0x7f) << 8)
 		| ((product_description[9] & 0x7f) << 16)
 		| ((product_description[10] & 0x7f) << 24);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_4, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_4, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	packet_payload = (product_description[11] & 0x7f)
 		| ((product_description[12] & 0x7f) << 8)
 		| ((product_description[13] & 0x7f) << 16)
 		| ((product_description[14] & 0x7f) << 24);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_5, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_5, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	/*
@@ -1039,7 +954,7 @@
 	 * 09h PC general
 	 */
 	packet_payload = (product_description[15] & 0x7f) | 0x00 << 8;
-	HDMI_REG_W(io->base, HDMI_GENERIC1_6, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_6, packet_payload);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 
 	/* Vendor Name (7bit ASCII code) */
@@ -1048,7 +963,7 @@
 		| ((vendor_name[2] & 0x7f) << 24);
 	check_sum += IFRAME_CHECKSUM_32(packet_payload);
 	packet_payload |= ((0x100 - (0xff & check_sum)) & 0xff);
-	HDMI_REG_W(io->base, HDMI_GENERIC1_0, packet_payload);
+	DSS_REG_W(io, HDMI_GENERIC1_0, packet_payload);
 
 	/*
 	 * GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND
@@ -1056,9 +971,9 @@
 	 * Enable this packet to transmit every frame
 	 * Enable HDMI TX engine to transmit Generic packet 1
 	 */
-	packet_control = HDMI_REG_R_ND(io->base, HDMI_GEN_PKT_CTRL);
+	packet_control = DSS_REG_R_ND(io, HDMI_GEN_PKT_CTRL);
 	packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4));
-	HDMI_REG_W(io->base, HDMI_GEN_PKT_CTRL, packet_control);
+	DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
 } /* hdmi_tx_set_spd_infoframe */
 
 /* todo: revisit when new HPD debouncing logic is avialble */
@@ -1075,11 +990,17 @@
 static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
 {
 	u32 reg_val = 0;
+	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return;
 	}
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
 
 	if (power_on) {
 		/* ENABLE */
@@ -1101,77 +1022,12 @@
 		reg_val = BIT(1);
 	}
 
-	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base, HDMI_CTRL,
-		reg_val);
+	DSS_REG_W(io, HDMI_CTRL, reg_val);
 
 	DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
 		power_on ? "Enable" : "Disable", reg_val);
 } /* hdmi_tx_set_mode */
 
-static int hdmi_tx_clk_update(struct hdmi_tx_platform_data *pdata, u32 clk_idx,
-	u32 enable)
-{
-	int rc = 0;
-	struct clk *clk = hdmi_tx_get_clk(pdata, clk_idx);
-
-	if (clk) {
-		DEV_DBG("%s: clk=%d en=%d\n", __func__, clk_idx, enable);
-		if (enable) {
-			rc = clk_prepare_enable(clk);
-			if (rc)
-				DEV_ERR("%s: clk=%d enable failed\n",
-				__func__, clk_idx);
-		} else {
-			clk_disable_unprepare(clk);
-		}
-	} else {
-		DEV_ERR("%s: FAILED: invalid input for clk='%s'\n", __func__,
-			hdmi_tx_clk_name(clk_idx));
-		rc = -EINVAL;
-	}
-
-	return rc;
-} /* hdmi_tx_clk_update */
-
-/* Note: Before accessing extpclk, always make sure that hdmi_ahb_clk is on */
-static int hdmi_tx_clk_ctrl_update(struct hdmi_tx_platform_data *pdata, int on)
-{
-	int  rc = 0;
-	DEV_DBG("%s: HDMI Clk: %s\n", __func__, on ? "Enable" : "Disable");
-
-	rc = hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, on);
-	if (on && rc) {
-		DEV_ERR("%s: '%s' on failed\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_APP_CLK));
-		goto fail_hdmi_app_clk;
-	}
-	if (on) {
-		rc = hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
-		if (rc) {
-			DEV_ERR("%s: '%s' on failed\n", __func__,
-				hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
-			goto fail_hdmi_ahb_clk;
-		}
-		rc = hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
-		if (rc) {
-			DEV_ERR("%s: '%s' on failed\n", __func__,
-				hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
-			goto fail_hdmi_extp_clk;
-		}
-	} else {
-		hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
-		hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
-	}
-	return rc;
-
-fail_hdmi_extp_clk:
-	hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, 0);
-fail_hdmi_ahb_clk:
-	hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, 0);
-fail_hdmi_app_clk:
-	return rc;
-} /* hdmi_tx_clk_ctrl_update */
-
 static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl,
 	enum hdmi_tx_power_module_type module, int config)
 {
@@ -1191,17 +1047,33 @@
 		goto exit;
 	}
 
-	if (config)
+	if (config) {
 		rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
 			power_data->vreg_config, power_data->num_vreg, 1);
-	else
+		if (rc) {
+			DEV_ERR("%s: Failed to config %s vreg. Err=%d\n",
+				__func__, hdmi_tx_pm_name(module), rc);
+			goto exit;
+		}
+
+		rc = msm_dss_get_clk(&hdmi_ctrl->pdev->dev,
+			power_data->clk_config, power_data->num_clk);
+		if (rc) {
+			DEV_ERR("%s: Failed to get %s clk. Err=%d\n",
+				__func__, hdmi_tx_pm_name(module), rc);
+
+			msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+			power_data->vreg_config, power_data->num_vreg, 0);
+		}
+	} else {
+		msm_dss_put_clk(power_data->clk_config, power_data->num_clk);
+
 		rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
 			power_data->vreg_config, power_data->num_vreg, 0);
-
-	if (rc)
-		DEV_ERR("%s: Failed to %s %s vreg. Error=%d\n",
-			__func__, config ? "config" : "deconfig",
-			hdmi_pm_name(module), rc);
+		if (rc)
+			DEV_ERR("%s: Fail to deconfig %s vreg. Err=%d\n",
+				__func__, hdmi_tx_pm_name(module), rc);
+	}
 
 exit:
 	return rc;
@@ -1231,18 +1103,36 @@
 			power_data->num_vreg, 1);
 		if (rc) {
 			DEV_ERR("%s: Failed to enable %s vreg. Error=%d\n",
-				__func__, hdmi_pm_name(module), rc);
+				__func__, hdmi_tx_pm_name(module), rc);
 			goto error;
 		}
 
 		rc = msm_dss_enable_gpio(power_data->gpio_config,
-			power_data->num_gpio, enable);
+			power_data->num_gpio, 1);
 		if (rc) {
 			DEV_ERR("%s: Failed to enable %s gpio. Error=%d\n",
-				__func__, hdmi_pm_name(module), rc);
+				__func__, hdmi_tx_pm_name(module), rc);
 			goto disable_vreg;
 		}
+
+		rc = msm_dss_clk_set_rate(power_data->clk_config,
+			power_data->num_clk);
+		if (rc) {
+			DEV_ERR("%s: failed to set clks rate for %s. err=%d\n",
+				__func__, hdmi_tx_pm_name(module), rc);
+			goto disable_gpio;
+		}
+
+		rc = msm_dss_enable_clk(power_data->clk_config,
+			power_data->num_clk, 1);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable clks for %s. Error=%d\n",
+				__func__, hdmi_tx_pm_name(module), rc);
+			goto disable_gpio;
+		}
 	} else {
+		msm_dss_enable_clk(power_data->clk_config,
+			power_data->num_clk, 0);
 		msm_dss_enable_gpio(power_data->gpio_config,
 			power_data->num_gpio, 0);
 		msm_dss_enable_vreg(power_data->vreg_config,
@@ -1251,6 +1141,8 @@
 
 	return rc;
 
+disable_gpio:
+	msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0);
 disable_vreg:
 	msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0);
 error:
@@ -1281,7 +1173,7 @@
 	if (rc) {
 		DEV_ERR("%s: core hdmi_msm_enable_power failed rc = %d\n",
 			__func__, rc);
-		goto error;
+		goto disable_hpd_power;
 	}
 	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CEC_PM, 1);
 	if (rc) {
@@ -1293,7 +1185,8 @@
 	return rc;
 disable_core_power:
 	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 0);
-error:
+disable_hpd_power:
+	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
 	return rc;
 } /* hdmi_tx_core_on */
 
@@ -1311,36 +1204,34 @@
 
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
-		DEV_ERR("%s: io not inititalized\n", __func__);
+		DEV_ERR("%s: core io not inititalized\n", __func__);
 		return;
 	}
 
-	val = HDMI_REG_R_ND(io->base, HDMI_PHY_CTRL);
+	val = DSS_REG_R_ND(io, HDMI_PHY_CTRL);
 
 	phy_reset_polarity = val >> 3 & 0x1;
 	pll_reset_polarity = val >> 1 & 0x1;
 
 	if (phy_reset_polarity == 0)
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET);
 	else
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET));
 
 	if (pll_reset_polarity == 0)
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL);
 	else
-		HDMI_REG_W_ND(io->base,
-			HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
 
 	if (phy_reset_polarity == 0)
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET));
 	else
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET);
 
 	if (pll_reset_polarity == 0)
-		HDMI_REG_W_ND(io->base,
-			HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
 	else
-		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+		DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL);
 } /* hdmi_tx_phy_reset */
 
 static void hdmi_tx_init_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -1354,55 +1245,58 @@
 
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO];
 	if (!io->base) {
-		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		DEV_ERR("%s: phy io is not initialized\n", __func__);
 		return;
 	}
 
-	HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG0, 0x1B);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG1, 0xF2);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_CFG0, 0x0);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN0, 0x0);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN1, 0x0);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN2, 0x0);
-	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN3, 0x0);
+	DSS_REG_W_ND(io, HDMI_PHY_ANA_CFG0, 0x1B);
+	DSS_REG_W_ND(io, HDMI_PHY_ANA_CFG1, 0xF2);
+	DSS_REG_W_ND(io, HDMI_PHY_BIST_CFG0, 0x0);
+	DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN0, 0x0);
+	DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN1, 0x0);
+	DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN2, 0x0);
+	DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN3, 0x0);
 
-	HDMI_REG_W_ND(io->base, HDMI_PHY_PD_CTRL1, 0x20);
+	DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL1, 0x20);
 } /* hdmi_tx_init_phy */
 
 static void hdmi_tx_powerdown_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
+	struct dss_io_data *io = NULL;
+
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return;
 	}
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO];
+	if (!io->base) {
+		DEV_ERR("%s: phy io is not initialized\n", __func__);
+		return;
+	}
 
-	HDMI_REG_W_ND(hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO].base,
-		HDMI_PHY_PD_CTRL0, 0x7F);
+	DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
 } /* hdmi_tx_powerdown_phy */
 
 static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
+	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io is not initialized\n", __func__);
+		return -EINVAL;
+	}
+
 	/* todo: Audio */
 
 	hdmi_tx_set_mode(hdmi_ctrl, false);
-	mutex_lock(&hdmi_ctrl->mutex);
-	rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 1);
-	if (rc) {
-		DEV_ERR("%s: hdmi_tx_clk_enable failed.\n", __func__);
-		mutex_unlock(&hdmi_ctrl->mutex);
-		return rc;
-	}
-	mutex_unlock(&hdmi_ctrl->mutex);
-
 	hdmi_tx_init_phy(hdmi_ctrl);
-	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
-		HDMI_USEC_REFTIMER, 0x0001001B);
+	DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
 
 	hdmi_tx_set_mode(hdmi_ctrl, true);
 
@@ -1413,8 +1307,7 @@
 	hdmi_tx_set_spd_infoframe(hdmi_ctrl);
 
 	/* Set IRQ for HPD */
-	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
-		HDMI_HPD_INT_CTRL, 4 | (hdmi_ctrl->hpd_state ? 0 : 2));
+	DSS_REG_W(io, HDMI_HPD_INT_CTRL, 4 | (hdmi_ctrl->hpd_state ? 0 : 2));
 
 	/* todo: HDCP/CEC */
 
@@ -1437,12 +1330,6 @@
 	/* todo: Audio */
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
 	hdmi_ctrl->panel_power_on = false;
-
-	mutex_lock(&hdmi_ctrl->mutex);
-	if (hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0))
-		DEV_ERR("%s: hdmi_tx_clk_disable failed.\n", __func__);
-	mutex_unlock(&hdmi_ctrl->mutex);
-
 	hdmi_tx_core_off(hdmi_ctrl);
 
 	return 0;
@@ -1451,6 +1338,7 @@
 static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
 {
 	int rc = 0;
+	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl =
 		hdmi_tx_get_drvdata_from_panel_data(panel_data);
 
@@ -1458,11 +1346,10 @@
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
-
-	rc = hdmi_tx_core_on(hdmi_ctrl);
-	if (rc) {
-		DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
-		return rc;
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io is not initialized\n", __func__);
+		return -EINVAL;
 	}
 
 	DEV_INFO("power: ON (%dx%d %ld)\n", hdmi_ctrl->xres, hdmi_ctrl->yres,
@@ -1471,7 +1358,12 @@
 	rc = hdmi_tx_set_video_fmt(hdmi_ctrl);
 	if (rc) {
 		DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
-		hdmi_tx_core_off(hdmi_ctrl);
+		return rc;
+	}
+
+	rc = hdmi_tx_core_on(hdmi_ctrl);
+	if (rc) {
+		DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
 		return rc;
 	}
 
@@ -1494,8 +1386,7 @@
 		mutex_unlock(&hdmi_ctrl->mutex);
 	}
 
-	hdmi_reg_dump(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
-		hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].len, "HDMI-ON: ");
+	dss_reg_dump(io->base, io->len, "HDMI-ON: ", REG_DUMP);
 
 	DEV_INFO("%s: HDMI=%s DVI= %s\n", __func__,
 		hdmi_tx_is_controller_on(hdmi_ctrl) ? "ON" : "OFF" ,
@@ -1524,13 +1415,6 @@
 
 	hdmi_tx_set_mode(hdmi_ctrl, false);
 
-	mutex_lock(&hdmi_ctrl->mutex);
-	rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0);
-	if (rc)
-		DEV_INFO("%s: Failed to disable clock. Error=%d\n",
-			__func__, rc);
-	mutex_unlock(&hdmi_ctrl->mutex);
-
 	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
 	if (rc)
 		DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
@@ -1552,7 +1436,7 @@
 
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
-		DEV_ERR("%s: io not inititalized\n", __func__);
+		DEV_ERR("%s: core io not inititalized\n", __func__);
 		return -EINVAL;
 	}
 
@@ -1566,31 +1450,21 @@
 			return rc;
 		}
 
-		mutex_lock(&hdmi_ctrl->mutex);
-		rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, true);
-		if (rc) {
-			DEV_ERR("%s: Failed to enable clocks. rc=%d\n",
-				__func__, rc);
-			mutex_unlock(&hdmi_ctrl->mutex);
-			goto disable_hpd_power;
-		}
-		mutex_unlock(&hdmi_ctrl->mutex);
-
-		hdmi_reg_dump(io->base, io->len, "HDMI-INIT: ");
+		dss_reg_dump(io->base, io->len, "HDMI-INIT: ", REG_DUMP);
 
 		hdmi_tx_set_mode(hdmi_ctrl, false);
 		hdmi_tx_phy_reset(hdmi_ctrl);
 		hdmi_tx_set_mode(hdmi_ctrl, true);
 
-		HDMI_REG_W(io->base, HDMI_USEC_REFTIMER, 0x0001001B);
+		DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
 
 		/* set timeout to 4.1ms (max) for hardware debounce */
-		reg_val = HDMI_REG_R(io->base, HDMI_HPD_CTRL) | 0x1FFF;
+		reg_val = DSS_REG_R(io, HDMI_HPD_CTRL) | 0x1FFF;
 
 		/* Toggle HPD circuit to trigger HPD sense */
-		HDMI_REG_W(io->base, HDMI_HPD_CTRL,
+		DSS_REG_W(io, HDMI_HPD_CTRL,
 			~(1 << 28) & reg_val);
-		HDMI_REG_W(io->base, HDMI_HPD_CTRL, (1 << 28) | reg_val);
+		DSS_REG_W(io, HDMI_HPD_CTRL, (1 << 28) | reg_val);
 
 		hdmi_ctrl->hpd_initialized = true;
 
@@ -1607,11 +1481,6 @@
 	mutex_unlock(&hdmi_ctrl->mutex);
 	mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
 
-	return 0;
-
-disable_hpd_power:
-	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, false);
-
 	return rc;
 } /* hdmi_tx_hpd_on */
 
@@ -1629,7 +1498,6 @@
 		rc = hdmi_tx_hpd_on(hdmi_ctrl);
 	} else {
 		hdmi_tx_hpd_off(hdmi_ctrl);
-		/* Set HDMI switch node to 0 on HPD feature disable */
 		switch_set_state(&hdmi_ctrl->sdev, 0);
 		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
 			hdmi_ctrl->sdev.state);
@@ -1640,8 +1508,6 @@
 
 static irqreturn_t hdmi_tx_isr(int irq, void *data)
 {
-	u32 hpd_int_status;
-	u32 hpd_int_ctrl;
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
 
@@ -1652,108 +1518,26 @@
 
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
-		DEV_WARN("%s: io not initialized, ISR ignored\n", __func__);
+		DEV_WARN("%s: core io not initialized, ISR ignored\n",
+			__func__);
 		return IRQ_HANDLED;
 	}
 
-	/* Process HPD Interrupt */
-	hpd_int_status = HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS);
-	hpd_int_ctrl = HDMI_REG_R(io->base, HDMI_HPD_INT_CTRL);
-	if ((hpd_int_ctrl & BIT(2)) && (hpd_int_status & BIT(0))) {
-		u32 cable_detected = hpd_int_status & BIT(1);
-
+	if (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(0)) {
 		/*
-		 * Clear all interrupts, timer will turn IRQ back on
-		 * Leaving the bit[2] on, else core goes off
-		 * on getting HPD during power off.
+		 * Turn off HPD irq and clear all interrupts,
+		 * worker will turn IRQ back on
 		 */
-		HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, BIT(2) | BIT(0));
-
-		DEV_DBG("%s: HPD IRQ, Ctrl=%04x, State=%04x\n", __func__,
-			hpd_int_ctrl, hpd_int_status);
-
-		mutex_lock(&hdmi_ctrl->mutex);
-		hdmi_ctrl->hpd_cable_chg_detected = true;
-		hdmi_ctrl->hpd_prev_state = cable_detected ? 0 : 1;
-		hdmi_ctrl->hpd_stable = 0;
-		mutex_unlock(&hdmi_ctrl->mutex);
-
-		mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
-
-		return IRQ_HANDLED;
+		DSS_REG_W(io, HDMI_HPD_INT_CTRL, ~BIT(2) | BIT(0));
+		queue_work(hdmi_ctrl->workq, &hdmi_ctrl->hpd_int_work);
 	}
 
-	if (!hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl))
-		return IRQ_HANDLED;
-
-	DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
-		hpd_int_status);
+	if (hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl) < 0)
+		DEV_ERR("%s: hdmi_ddc_isr failed\n", __func__);
 
 	return IRQ_HANDLED;
 } /* hdmi_tx_isr */
 
-static void hdmi_tx_clk_deinit(struct hdmi_tx_platform_data *pdata)
-{
-	int i;
-	if (!pdata) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return;
-	}
-
-	for (i = HDMI_TX_MAX_CLK - 1; i >= 0; i--) {
-		if (pdata->clk[i])
-			clk_put(pdata->clk[i]);
-		pdata->clk[i] = NULL;
-	}
-} /* hdmi_tx_clk_deinit */
-
-static int hdmi_tx_clk_init(struct platform_device *pdev,
-	struct hdmi_tx_platform_data *pdata)
-{
-	int rc = 0;
-	struct device *dev = NULL;
-	struct clk *clk = NULL;
-
-	if (!pdev || !pdata) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-	dev = &pdev->dev;
-
-	clk = clk_get(dev, "iface_clk");
-	rc = IS_ERR(clk);
-	if (rc) {
-		DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
-		goto error;
-	}
-	pdata->clk[HDMI_TX_AHB_CLK] = clk;
-
-	clk = clk_get(dev, "core_clk");
-	rc = IS_ERR(clk);
-	if (rc) {
-		DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_APP_CLK));
-		goto error;
-	}
-	pdata->clk[HDMI_TX_APP_CLK] = clk;
-
-	clk = clk_get(dev, "extp_clk");
-	rc = IS_ERR(clk);
-	if (rc) {
-		DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
-		goto error;
-	}
-	pdata->clk[HDMI_TX_EXTP_CLK] = clk;
-
-	return rc;
-
-error:
-	hdmi_tx_clk_deinit(pdata);
-	return rc;
-} /* hdmi_tx_clk_init */
-
 static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	if (!hdmi_ctrl) {
@@ -1785,7 +1569,7 @@
 
 	pdata = &hdmi_ctrl->pdata;
 
-	rc = hdmi_tx_check_capability(pdata->io[HDMI_TX_QFPROM_IO].base);
+	rc = hdmi_tx_check_capability(&pdata->io[HDMI_TX_QFPROM_IO]);
 	if (rc) {
 		DEV_ERR("%s: no HDMI device\n", __func__);
 		goto fail_no_hdmi;
@@ -1802,11 +1586,11 @@
 		goto fail_create_workq;
 	}
 
-	/* todo: May be move this ? */
-	hdmi_ctrl->ddc_ctrl.base = pdata->io[HDMI_TX_CORE_IO].base;
+	hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO];
 	init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
 
 	INIT_WORK(&hdmi_ctrl->hpd_state_work, hdmi_tx_hpd_state_work);
+	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
 	init_timer(&hdmi_ctrl->hpd_state_timer);
 	hdmi_ctrl->hpd_state_timer.function = hdmi_tx_hpd_state_timer;
 	hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
@@ -1868,23 +1652,16 @@
 		return;
 	}
 
-	/* CLK */
-	hdmi_tx_clk_deinit(&hdmi_ctrl->pdata);
-
-	/* VREG */
+	/* VREG & CLK */
 	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--) {
 		if (hdmi_tx_config_power(hdmi_ctrl, i, 0))
 			DEV_ERR("%s: '%s' power deconfig fail\n",
-				__func__, hdmi_pm_name(i));
+				__func__, hdmi_tx_pm_name(i));
 	}
 
 	/* IO */
-	for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
-		if (hdmi_ctrl->pdata.io[i].base)
-			iounmap(hdmi_ctrl->pdata.io[i].base);
-		hdmi_ctrl->pdata.io[i].base = NULL;
-		hdmi_ctrl->pdata.io[i].len = 0;
-	}
+	for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--)
+		msm_dss_iounmap(&hdmi_ctrl->pdata.io[i]);
 } /* hdmi_tx_deinit_resource */
 
 static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -1913,23 +1690,16 @@
 			pdata->io[i].len);
 	}
 
-	/* VREG */
+	/* VREG & CLK */
 	for (i = 0; i < HDMI_TX_MAX_PM; i++) {
 		rc = hdmi_tx_config_power(hdmi_ctrl, i, 1);
 		if (rc) {
 			DEV_ERR("%s: '%s' power config failed.rc=%d\n",
-				__func__, hdmi_pm_name(i), rc);
+				__func__, hdmi_tx_pm_name(i), rc);
 			goto error;
 		}
 	}
 
-	/* CLK */
-	rc = hdmi_tx_clk_init(hdmi_ctrl->pdev, pdata);
-	if (rc) {
-		DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
-		goto error;
-	}
-
 	return rc;
 
 error:
@@ -1937,6 +1707,98 @@
 	return rc;
 } /* hdmi_tx_init_resource */
 
+static void hdmi_tx_put_dt_clk_data(struct device *dev,
+	struct dss_module_power *module_power)
+{
+	if (!module_power) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (module_power->clk_config) {
+		devm_kfree(dev, module_power->clk_config);
+		module_power->clk_config = NULL;
+	}
+	module_power->num_clk = 0;
+} /* hdmi_tx_put_dt_clk_data */
+
+/* todo: once clk are moved to device tree then change this implementation */
+static int hdmi_tx_get_dt_clk_data(struct device *dev,
+	struct dss_module_power *mp, u32 module_type)
+{
+	int rc = 0;
+
+	if (!dev || !mp) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
+
+	switch (module_type) {
+	case HDMI_TX_HPD_PM:
+		mp->num_clk = 2;
+		mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
+			mp->num_clk, GFP_KERNEL);
+		if (!mp->clk_config) {
+			DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__,
+				hdmi_tx_pm_name(module_type));
+			goto error;
+		}
+
+		snprintf(mp->clk_config[0].clk_name, 32, "%s", "iface_clk");
+		mp->clk_config[0].type = DSS_CLK_AHB;
+		mp->clk_config[0].rate = 0;
+
+		snprintf(mp->clk_config[1].clk_name, 32, "%s", "core_clk");
+		mp->clk_config[1].type = DSS_CLK_OTHER;
+		mp->clk_config[1].rate = 19200000;
+		break;
+
+	case HDMI_TX_CORE_PM:
+		mp->num_clk = 2;
+		mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
+			mp->num_clk, GFP_KERNEL);
+		if (!mp->clk_config) {
+			DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__,
+				hdmi_tx_pm_name(module_type));
+			goto error;
+		}
+
+		snprintf(mp->clk_config[0].clk_name, 32, "%s", "extp_clk");
+		mp->clk_config[0].type = DSS_CLK_PCLK;
+		/* This rate will be overwritten when core is powered on */
+		mp->clk_config[0].rate = 148500000;
+
+		snprintf(mp->clk_config[1].clk_name, 32, "%s", "alt_iface_clk");
+		mp->clk_config[1].type = DSS_CLK_AHB;
+		mp->clk_config[1].rate = 0;
+		break;
+
+	case HDMI_TX_CEC_PM:
+		mp->num_clk = 0;
+		DEV_DBG("%s: no clk\n", __func__);
+		break;
+
+	default:
+		DEV_ERR("%s: invalid module type=%d\n", __func__,
+			module_type);
+		return -EINVAL;
+	}
+
+	return rc;
+
+error:
+	if (mp->clk_config) {
+		devm_kfree(dev, mp->clk_config);
+		mp->clk_config = NULL;
+	}
+	mp->num_clk = 0;
+
+	return rc;
+} /* hdmi_tx_get_dt_clk_data */
+
 static void hdmi_tx_put_dt_vreg_data(struct device *dev,
 	struct dss_module_power *module_power)
 {
@@ -1985,7 +1847,7 @@
 		return -EINVAL;
 	}
 
-	DEV_DBG("%s: module: '%s'\n", __func__, hdmi_pm_name(module_type));
+	DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
 
 	of_node = dev->of_node;
 
@@ -2025,7 +1887,7 @@
 			mod_vreg_total, GFP_KERNEL);
 		if (!mp->vreg_config) {
 			DEV_ERR("%s: can't alloc '%s' vreg mem\n", __func__,
-				hdmi_pm_name(module_type));
+				hdmi_tx_pm_name(module_type));
 			goto error;
 		}
 	} else {
@@ -2070,7 +1932,7 @@
 			prop_name, val_array, dt_vreg_total);
 		if (rc) {
 			DEV_ERR("%s: error read '%s' vreg type. rc=%d\n",
-				__func__, hdmi_pm_name(module_type), rc);
+				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
 		mp->vreg_config[j].type = val_array[i];
@@ -2085,7 +1947,7 @@
 			dt_vreg_total);
 		if (rc) {
 			DEV_ERR("%s: error read '%s' min volt. rc=%d\n",
-				__func__, hdmi_pm_name(module_type), rc);
+				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
 		mp->vreg_config[j].min_voltage = val_array[i];
@@ -2100,7 +1962,7 @@
 			dt_vreg_total);
 		if (rc) {
 			DEV_ERR("%s: error read '%s' max volt. rc=%d\n",
-				__func__, hdmi_pm_name(module_type), rc);
+				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
 		mp->vreg_config[j].max_voltage = val_array[i];
@@ -2115,7 +1977,7 @@
 			dt_vreg_total);
 		if (rc) {
 			DEV_ERR("%s: error read '%s' min volt. rc=%d\n",
-				__func__, hdmi_pm_name(module_type), rc);
+				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
 		mp->vreg_config[j].optimum_voltage = val_array[i];
@@ -2136,8 +1998,12 @@
 	return rc;
 
 error:
-	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
-		hdmi_tx_put_dt_vreg_data(dev, mp);
+	if (mp->vreg_config) {
+		devm_kfree(dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+	mp->num_vreg = 0;
+
 	if (val_array)
 		devm_kfree(dev, val_array);
 	return rc;
@@ -2191,7 +2057,7 @@
 		return -EINVAL;
 	}
 
-	DEV_DBG("%s: module: '%s'\n", __func__, hdmi_pm_name(module_type));
+	DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
 
 	of_node = dev->of_node;
 
@@ -2227,7 +2093,7 @@
 			mod_gpio_total, GFP_KERNEL);
 		if (!mp->gpio_config) {
 			DEV_ERR("%s: can't alloc '%s' gpio mem\n", __func__,
-				hdmi_pm_name(module_type));
+				hdmi_tx_pm_name(module_type));
 			goto error;
 		}
 	} else {
@@ -2268,8 +2134,11 @@
 	return rc;
 
 error:
-	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
-		hdmi_tx_put_dt_gpio_data(dev, mp);
+	if (mp->gpio_config) {
+		devm_kfree(dev, mp->gpio_config);
+		mp->gpio_config = NULL;
+	}
+	mp->num_gpio = 0;
 
 	return rc;
 } /* hdmi_tx_get_dt_gpio_data */
@@ -2284,6 +2153,9 @@
 	}
 
 	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
+		hdmi_tx_put_dt_clk_data(dev, &pdata->power_data[i]);
+
+	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
 		hdmi_tx_put_dt_vreg_data(dev, &pdata->power_data[i]);
 
 	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
@@ -2317,7 +2189,7 @@
 			&pdata->power_data[i], i);
 		if (rc) {
 			DEV_ERR("%s: '%s' get_dt_gpio_data failed.rc=%d\n",
-				__func__, hdmi_pm_name(i), rc);
+				__func__, hdmi_tx_pm_name(i), rc);
 			goto error;
 		}
 	}
@@ -2328,7 +2200,18 @@
 			&pdata->power_data[i], i);
 		if (rc) {
 			DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n",
-				__func__, hdmi_pm_name(i), rc);
+				__func__, hdmi_tx_pm_name(i), rc);
+			goto error;
+		}
+	}
+
+	/* CLK */
+	for (i = 0; i < HDMI_TX_MAX_PM; i++) {
+		rc = hdmi_tx_get_dt_clk_data(&pdev->dev,
+			&pdata->power_data[i], i);
+		if (rc) {
+			DEV_ERR("%s: '%s' get_dt_clk_data failed.rc=%d\n",
+				__func__, hdmi_tx_pm_name(i), rc);
 			goto error;
 		}
 	}
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 7e37d28..94e0fda 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -15,14 +15,6 @@
 
 #include <linux/switch.h>
 #include "mdss_hdmi_util.h"
-#include "mdss_io_util.h"
-
-enum hdmi_tx_clk_type {
-	HDMI_TX_AHB_CLK,
-	HDMI_TX_APP_CLK,
-	HDMI_TX_EXTP_CLK,
-	HDMI_TX_MAX_CLK
-};
 
 enum hdmi_tx_io_type {
 	HDMI_TX_CORE_IO,
@@ -42,9 +34,6 @@
 	/* Data filled from device tree nodes */
 	struct dss_io_data io[HDMI_TX_MAX_IO];
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
-
-	/* clk and regulator handles */
-	struct clk *clk[HDMI_TX_MAX_CLK];
 };
 
 struct hdmi_tx_ctrl {
@@ -67,6 +56,7 @@
 	u32 hpd_state;
 	u32 hpd_feature_on;
 	struct work_struct hpd_state_work;
+	struct work_struct hpd_int_work;
 	struct timer_list hpd_state_timer;
 
 	unsigned long pixel_clk;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 3ba9f89..e7ea8c9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -15,226 +15,6 @@
 #include <mach/board.h>
 #include "mdss_hdmi_util.h"
 
-const char *hdmi_reg_name(u32 offset)
-{
-	switch (offset) {
-	case 0x00000000: return "HDMI_CTRL";
-	case 0x00000010: return "HDMI_TEST_PATTERN";
-	case 0x00000014: return "HDMI_RANDOM_PATTERN";
-	case 0x00000018: return "HDMI_PKT_BLK_CTRL";
-	case 0x0000001C: return "HDMI_STATUS";
-	case 0x00000020: return "HDMI_AUDIO_PKT_CTRL";
-	case 0x00000024: return "HDMI_ACR_PKT_CTRL";
-	case 0x00000028: return "HDMI_VBI_PKT_CTRL";
-	case 0x0000002C: return "HDMI_INFOFRAME_CTRL0";
-	case 0x00000030: return "HDMI_INFOFRAME_CTRL1";
-	case 0x00000034: return "HDMI_GEN_PKT_CTRL";
-	case 0x0000003C: return "HDMI_ACP";
-	case 0x00000040: return "HDMI_GC";
-	case 0x00000044: return "HDMI_AUDIO_PKT_CTRL2";
-	case 0x00000048: return "HDMI_ISRC1_0";
-	case 0x0000004C: return "HDMI_ISRC1_1";
-	case 0x00000050: return "HDMI_ISRC1_2";
-	case 0x00000054: return "HDMI_ISRC1_3";
-	case 0x00000058: return "HDMI_ISRC1_4";
-	case 0x0000005C: return "HDMI_ISRC2_0";
-	case 0x00000060: return "HDMI_ISRC2_1";
-	case 0x00000064: return "HDMI_ISRC2_2";
-	case 0x00000068: return "HDMI_ISRC2_3";
-	case 0x0000006C: return "HDMI_AVI_INFO0";
-	case 0x00000070: return "HDMI_AVI_INFO1";
-	case 0x00000074: return "HDMI_AVI_INFO2";
-	case 0x00000078: return "HDMI_AVI_INFO3";
-	case 0x0000007C: return "HDMI_MPEG_INFO0";
-	case 0x00000080: return "HDMI_MPEG_INFO1";
-	case 0x00000084: return "HDMI_GENERIC0_HDR";
-	case 0x00000088: return "HDMI_GENERIC0_0";
-	case 0x0000008C: return "HDMI_GENERIC0_1";
-	case 0x00000090: return "HDMI_GENERIC0_2";
-	case 0x00000094: return "HDMI_GENERIC0_3";
-	case 0x00000098: return "HDMI_GENERIC0_4";
-	case 0x0000009C: return "HDMI_GENERIC0_5";
-	case 0x000000A0: return "HDMI_GENERIC0_6";
-	case 0x000000A4: return "HDMI_GENERIC1_HDR";
-	case 0x000000A8: return "HDMI_GENERIC1_0";
-	case 0x000000AC: return "HDMI_GENERIC1_1";
-	case 0x000000B0: return "HDMI_GENERIC1_2";
-	case 0x000000B4: return "HDMI_GENERIC1_3";
-	case 0x000000B8: return "HDMI_GENERIC1_4";
-	case 0x000000BC: return "HDMI_GENERIC1_5";
-	case 0x000000C0: return "HDMI_GENERIC1_6";
-	case 0x000000C4: return "HDMI_ACR_32_0";
-	case 0x000000C8: return "HDMI_ACR_32_1";
-	case 0x000000CC: return "HDMI_ACR_44_0";
-	case 0x000000D0: return "HDMI_ACR_44_1";
-	case 0x000000D4: return "HDMI_ACR_48_0";
-	case 0x000000D8: return "HDMI_ACR_48_1";
-	case 0x000000DC: return "HDMI_ACR_STATUS_0";
-	case 0x000000E0: return "HDMI_ACR_STATUS_1";
-	case 0x000000E4: return "HDMI_AUDIO_INFO0";
-	case 0x000000E8: return "HDMI_AUDIO_INFO1";
-	case 0x000000EC: return "HDMI_CS_60958_0";
-	case 0x000000F0: return "HDMI_CS_60958_1";
-	case 0x000000F8: return "HDMI_RAMP_CTRL0";
-	case 0x000000FC: return "HDMI_RAMP_CTRL1";
-	case 0x00000100: return "HDMI_RAMP_CTRL2";
-	case 0x00000104: return "HDMI_RAMP_CTRL3";
-	case 0x00000108: return "HDMI_CS_60958_2";
-	case 0x00000110: return "HDMI_HDCP_CTRL";
-	case 0x00000114: return "HDMI_HDCP_DEBUG_CTRL";
-	case 0x00000118: return "HDMI_HDCP_INT_CTRL";
-	case 0x0000011C: return "HDMI_HDCP_LINK0_STATUS";
-	case 0x00000120: return "HDMI_HDCP_DDC_CTRL_0";
-	case 0x00000124: return "HDMI_HDCP_DDC_CTRL_1";
-	case 0x00000128: return "HDMI_HDCP_DDC_STATUS";
-	case 0x0000012C: return "HDMI_HDCP_ENTROPY_CTRL0";
-	case 0x00000130: return "HDMI_HDCP_RESET";
-	case 0x00000134: return "HDMI_HDCP_RCVPORT_DATA0";
-	case 0x00000138: return "HDMI_HDCP_RCVPORT_DATA1";
-	case 0x0000013C: return "HDMI_HDCP_RCVPORT_DATA2_0";
-	case 0x00000140: return "HDMI_HDCP_RCVPORT_DATA2_1";
-	case 0x00000144: return "HDMI_HDCP_RCVPORT_DATA3";
-	case 0x00000148: return "HDMI_HDCP_RCVPORT_DATA4";
-	case 0x0000014C: return "HDMI_HDCP_RCVPORT_DATA5";
-	case 0x00000150: return "HDMI_HDCP_RCVPORT_DATA6";
-	case 0x00000154: return "HDMI_HDCP_RCVPORT_DATA7";
-	case 0x00000158: return "HDMI_HDCP_RCVPORT_DATA8";
-	case 0x0000015C: return "HDMI_HDCP_RCVPORT_DATA9";
-	case 0x00000160: return "HDMI_HDCP_RCVPORT_DATA10";
-	case 0x00000164: return "HDMI_HDCP_RCVPORT_DATA11";
-	case 0x00000168: return "HDMI_HDCP_RCVPORT_DATA12";
-	case 0x0000016C: return "HDMI_VENSPEC_INFO0";
-	case 0x00000170: return "HDMI_VENSPEC_INFO1";
-	case 0x00000174: return "HDMI_VENSPEC_INFO2";
-	case 0x00000178: return "HDMI_VENSPEC_INFO3";
-	case 0x0000017C: return "HDMI_VENSPEC_INFO4";
-	case 0x00000180: return "HDMI_VENSPEC_INFO5";
-	case 0x00000184: return "HDMI_VENSPEC_INFO6";
-	case 0x00000194: return "HDMI_HDCP_DEBUG";
-	case 0x0000019C: return "HDMI_TMDS_CTRL_CHAR";
-	case 0x000001A4: return "HDMI_TMDS_CTRL_SEL";
-	case 0x000001A8: return "HDMI_TMDS_SYNCCHAR01";
-	case 0x000001AC: return "HDMI_TMDS_SYNCCHAR23";
-	case 0x000001B4: return "HDMI_TMDS_DEBUG";
-	case 0x000001B8: return "HDMI_TMDS_CTL_BITS";
-	case 0x000001BC: return "HDMI_TMDS_DCBAL_CTRL";
-	case 0x000001C0: return "HDMI_TMDS_DCBAL_CHAR";
-	case 0x000001C8: return "HDMI_TMDS_CTL01_GEN";
-	case 0x000001CC: return "HDMI_TMDS_CTL23_GEN";
-	case 0x000001D0: return "HDMI_AUDIO_CFG";
-	case 0x00000204: return "HDMI_DEBUG";
-	case 0x00000208: return "HDMI_USEC_REFTIMER";
-	case 0x0000020C: return "HDMI_DDC_CTRL";
-	case 0x00000210: return "HDMI_DDC_ARBITRATION";
-	case 0x00000214: return "HDMI_DDC_INT_CTRL";
-	case 0x00000218: return "HDMI_DDC_SW_STATUS";
-	case 0x0000021C: return "HDMI_DDC_HW_STATUS";
-	case 0x00000220: return "HDMI_DDC_SPEED";
-	case 0x00000224: return "HDMI_DDC_SETUP";
-	case 0x00000228: return "HDMI_DDC_TRANS0";
-	case 0x0000022C: return "HDMI_DDC_TRANS1";
-	case 0x00000230: return "HDMI_DDC_TRANS2";
-	case 0x00000234: return "HDMI_DDC_TRANS3";
-	case 0x00000238: return "HDMI_DDC_DATA";
-	case 0x0000023C: return "HDMI_HDCP_SHA_CTRL";
-	case 0x00000240: return "HDMI_HDCP_SHA_STATUS";
-	case 0x00000244: return "HDMI_HDCP_SHA_DATA";
-	case 0x00000248: return "HDMI_HDCP_SHA_DBG_M0_0";
-	case 0x0000024C: return "HDMI_HDCP_SHA_DBG_M0_1";
-	case 0x00000250: return "HDMI_HPD_INT_STATUS";
-	case 0x00000254: return "HDMI_HPD_INT_CTRL";
-	case 0x00000258: return "HDMI_HPD_CTRL";
-	case 0x0000025C: return "HDMI_HDCP_ENTROPY_CTRL1";
-	case 0x00000260: return "HDMI_HDCP_SW_UPPER_AN";
-	case 0x00000264: return "HDMI_HDCP_SW_LOWER_AN";
-	case 0x00000268: return "HDMI_CRC_CTRL";
-	case 0x0000026C: return "HDMI_VID_CRC";
-	case 0x00000270: return "HDMI_AUD_CRC";
-	case 0x00000274: return "HDMI_VBI_CRC";
-	case 0x0000027C: return "HDMI_DDC_REF";
-	case 0x00000284: return "HDMI_HDCP_SW_UPPER_AKSV";
-	case 0x00000288: return "HDMI_HDCP_SW_LOWER_AKSV";
-	case 0x0000028C: return "HDMI_CEC_CTRL";
-	case 0x00000290: return "HDMI_CEC_WR_DATA";
-	case 0x00000294: return "HDMI_CEC_RETRANSMIT";
-	case 0x00000298: return "HDMI_CEC_STATUS";
-	case 0x0000029C: return "HDMI_CEC_INT";
-	case 0x000002A0: return "HDMI_CEC_ADDR";
-	case 0x000002A4: return "HDMI_CEC_TIME";
-	case 0x000002A8: return "HDMI_CEC_REFTIMER";
-	case 0x000002AC: return "HDMI_CEC_RD_DATA";
-	case 0x000002B0: return "HDMI_CEC_RD_FILTER";
-	case 0x000002B4: return "HDMI_ACTIVE_H";
-	case 0x000002B8: return "HDMI_ACTIVE_V";
-	case 0x000002BC: return "HDMI_ACTIVE_V_F2";
-	case 0x000002C0: return "HDMI_TOTAL";
-	case 0x000002C4: return "HDMI_V_TOTAL_F2";
-	case 0x000002C8: return "HDMI_FRAME_CTRL";
-	case 0x000002CC: return "HDMI_AUD_INT";
-	case 0x000002D0: return "HDMI_DEBUG_BUS_CTRL";
-	case 0x000002D4: return "HDMI_PHY_CTRL";
-	case 0x000002DC: return "HDMI_CEC_WR_RANGE";
-	case 0x000002E0: return "HDMI_CEC_RD_RANGE";
-	case 0x000002E4: return "HDMI_VERSION";
-	case 0x000002F4: return "HDMI_BIST_ENABLE";
-	case 0x000002F8: return "HDMI_TIMING_ENGINE_EN";
-	case 0x000002FC: return "HDMI_INTF_CONFIG";
-	case 0x00000300: return "HDMI_HSYNC_CTL";
-	case 0x00000304: return "HDMI_VSYNC_PERIOD_F0";
-	case 0x00000308: return "HDMI_VSYNC_PERIOD_F1";
-	case 0x0000030C: return "HDMI_VSYNC_PULSE_WIDTH_F0";
-	case 0x00000310: return "HDMI_VSYNC_PULSE_WIDTH_F1";
-	case 0x00000314: return "HDMI_DISPLAY_V_START_F0";
-	case 0x00000318: return "HDMI_DISPLAY_V_START_F1";
-	case 0x0000031C: return "HDMI_DISPLAY_V_END_F0";
-	case 0x00000320: return "HDMI_DISPLAY_V_END_F1";
-	case 0x00000324: return "HDMI_ACTIVE_V_START_F0";
-	case 0x00000328: return "HDMI_ACTIVE_V_START_F1";
-	case 0x0000032C: return "HDMI_ACTIVE_V_END_F0";
-	case 0x00000330: return "HDMI_ACTIVE_V_END_F1";
-	case 0x00000334: return "HDMI_DISPLAY_HCTL";
-	case 0x00000338: return "HDMI_ACTIVE_HCTL";
-	case 0x0000033C: return "HDMI_HSYNC_SKEW";
-	case 0x00000340: return "HDMI_POLARITY_CTL";
-	case 0x00000344: return "HDMI_TPG_MAIN_CONTROL";
-	case 0x00000348: return "HDMI_TPG_VIDEO_CONFIG";
-	case 0x0000034C: return "HDMI_TPG_COMPONENT_LIMITS";
-	case 0x00000350: return "HDMI_TPG_RECTANGLE";
-	case 0x00000354: return "HDMI_TPG_INITIAL_VALUE";
-	case 0x00000358: return "HDMI_TPG_BLK_WHT_PATTERN_FRAMES";
-	case 0x0000035C: return "HDMI_TPG_RGB_MAPPING";
-	default: return "???";
-	}
-} /* hdmi_reg_name */
-
-void hdmi_reg_w(void __iomem *addr, u32 offset, u32 value, u32 debug)
-{
-	u32 in_val;
-
-	writel_relaxed(value, addr+offset);
-	if (debug && PORT_DEBUG) {
-		in_val = readl_relaxed(addr+offset);
-		DEV_DBG("HDMI[%04x] => %08x [%08x] %s\n", offset, value,
-			in_val, hdmi_reg_name(offset));
-	}
-} /* hdmi_reg_w */
-
-u32 hdmi_reg_r(void __iomem *addr, u32 offset, u32 debug)
-{
-	u32 value = readl_relaxed(addr+offset);
-	if (debug && PORT_DEBUG)
-		DEV_DBG("HDMI[%04x] <= %08x %s\n", offset, value,
-			hdmi_reg_name(offset));
-	return value;
-} /* hdmi_reg_r */
-
-void hdmi_reg_dump(void __iomem *base, u32 length, const char *prefix)
-{
-	if (REG_DUMP)
-		print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
-			(void *)base, length, false);
-} /* hdmi_reg_dump */
-
 static struct hdmi_disp_mode_timing_type
 	hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX] = {
 	HDMI_SETTINGS_640x480p60_4_3,
@@ -505,7 +285,7 @@
 {
 	u32 reg_val, time_out_count;
 
-	if (!ddc_ctrl || !ddc_ctrl->base) {
+	if (!ddc_ctrl || !ddc_ctrl->io) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
@@ -515,9 +295,9 @@
 	do {
 		--time_out_count;
 		/* Clear and Enable DDC interrupt */
-		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
 			BIT(2) | BIT(1));
-		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+		reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
 	} while ((reg_val & BIT(0)) && time_out_count);
 
 	if (!time_out_count) {
@@ -535,7 +315,7 @@
 	int status = 0;
 	int log_retry_fail;
 
-	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+	if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
@@ -565,7 +345,7 @@
 	 *    INDEX = 0x0 (initial offset into buffer)
 	 *    INDEX_WRITE = 0x1 (setting initial offset)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		BIT(31) | (ddc_data->dev_addr << 8));
 
 	/*
@@ -576,7 +356,7 @@
 	 *    INDEX = 0x0
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
 
 	/*
 	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -586,7 +366,7 @@
 	 *    INDEX = 0x0
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		(ddc_data->dev_addr | BIT(0)) << 8);
 
 	/* Data setup is complete, now setup the transaction characteristics */
@@ -599,7 +379,7 @@
 	 *    STOP0 = 0x0 (do NOT insert STOP bit)
 	 *    CNT0 = 0x1 (single byte transaction excluding address)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
 
 	/*
 	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -609,7 +389,7 @@
 	 *    STOP1 = 0x1 (insert STOP bit)
 	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1,
 		BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
 
 	/* Trigger the I2C transfer */
@@ -624,11 +404,11 @@
 	 *    GO = 0x1 (kicks off hardware)
 	 */
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
 	time_out_count = wait_for_completion_interruptible_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, BIT(1));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
 	if (!time_out_count) {
 		if (ddc_data->retry-- > 0) {
 			DEV_INFO("%s: failed timout, retry=%d\n", __func__,
@@ -637,26 +417,26 @@
 		}
 		status = -ETIMEDOUT;
 		DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
 		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
 			__func__,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
 		goto error;
 	}
 
 	/* Read DDC status */
-	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
 	reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
 
 	/* Check if any NACK occurred */
 	if (reg_val) {
 		/* SW_STATUS_RESET */
-		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
 
 		if (ddc_data->retry == 1)
 			/* SOFT_RESET */
-			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+			DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
 
 		if (ddc_data->retry-- > 0) {
 			DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
@@ -687,13 +467,13 @@
 	 *    INDEX_WRITE = 0x1 (explicitly define offset)
 	 */
 	/* Write this data to DDC buffer */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		BIT(0) | (3 << 16) | BIT(31));
 
 	/* Discard first byte */
-	HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+	DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
 	for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
-		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+		reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
 		ddc_data->data_buf[ndx] = (u8)((reg_val & 0x0000FF00) >> 8);
 	}
 
@@ -705,46 +485,44 @@
 
 void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
 {
-	if (!ddc_ctrl || !ddc_ctrl->base) {
+	if (!ddc_ctrl || !ddc_ctrl->io) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return;
 	}
 
 	/* Configure Pre-Scale multiplier & Threshold */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SPEED, (10 << 16) | (2 << 0));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_SPEED, (10 << 16) | (2 << 0));
 
 	/*
 	 * Setting 31:24 bits : Time units to wait before timeout
 	 * when clock is being stalled by external sink device
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SETUP, 0xFF000000);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_SETUP, 0xFF000000);
 
 	/* Enable reference timer to 27 micro-seconds */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_REF, (1 << 16) | (27 << 0));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (27 << 0));
 } /* hdmi_ddc_config */
 
 int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
 {
-	int rc = -1;
 	u32 ddc_int_ctrl;
 
-	if (!ddc_ctrl || !ddc_ctrl->base) {
+	if (!ddc_ctrl || !ddc_ctrl->io) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
 
-	ddc_int_ctrl = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+	ddc_int_ctrl = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
 	if ((ddc_int_ctrl & BIT(2)) && (ddc_int_ctrl & BIT(0))) {
 		/* SW_DONE INT occured, clr it */
-		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
 			ddc_int_ctrl | BIT(1));
 		complete(&ddc_ctrl->ddc_sw_done);
-		return 0;
 	}
 
 	DEV_DBG("%s: ddc_int_ctrl=%04x\n", __func__, ddc_int_ctrl);
 
-	return rc;
+	return 0;
 } /* hdmi_ddc_isr */
 
 int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
@@ -779,7 +557,7 @@
 	int log_retry_fail;
 	int seg_addr = 0x60, seg_num = 0x01;
 
-	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+	if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
@@ -808,7 +586,7 @@
 	 *    INDEX = 0x0 (initial offset into buffer)
 	 *    INDEX_WRITE = 0x1 (setting initial offset)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, BIT(31) | (seg_addr << 8));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, BIT(31) | (seg_addr << 8));
 
 	/*
 	 * 2. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -818,7 +596,7 @@
 	 *    INDEX = 0x0
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, seg_num << 8);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, seg_num << 8);
 
 	/*
 	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -828,9 +606,9 @@
 	 *    INDEX = 0x0
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->dev_addr << 8);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->dev_addr << 8);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		(ddc_data->dev_addr | BIT(0)) << 8);
 
 	/* Data setup is complete, now setup the transaction characteristics */
@@ -843,7 +621,7 @@
 	 *    STOP0 = 0x0 (do NOT insert STOP bit)
 	 *    CNT0 = 0x1 (single byte transaction excluding address)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
 
 	/*
 	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -853,7 +631,7 @@
 	 *    STOP1 = 0x1 (insert STOP bit)
 	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1, BIT(12) | BIT(16));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1, BIT(12) | BIT(16));
 
 	/*
 	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -863,7 +641,7 @@
 	 *    STOP1 = 0x1 (insert STOP bit)
 	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS2,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS2,
 		BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
 
 	/* Trigger the I2C transfer */
@@ -877,13 +655,13 @@
 	 *    GO = 0x1 (kicks off hardware)
 	 */
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(21));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(21));
 
 	time_out_count = wait_for_completion_interruptible_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
-	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
 	if (!time_out_count) {
 		if (ddc_data->retry-- > 0) {
 			DEV_INFO("%s: failed timout, retry=%d\n", __func__,
@@ -892,25 +670,25 @@
 		}
 		status = -ETIMEDOUT;
 		DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
 		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
 			__func__,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
 		goto error;
 	}
 
 	/* Read DDC status */
-	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
 	reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
 
 	/* Check if any NACK occurred */
 	if (reg_val) {
 		/* SW_STATUS_RESET */
-		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
 		if (ddc_data->retry == 1)
 			/* SOFT_RESET */
-			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+			DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
 		if (ddc_data->retry-- > 0) {
 			DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
 				__func__, ddc_data->what, reg_val,
@@ -940,14 +718,14 @@
 	 *    INDEX_WRITE = 0x1 (explicitly define offset)
 	 */
 	/* Write this data to DDC buffer */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		BIT(0) | (5 << 16) | BIT(31));
 
 	/* Discard first byte */
-	HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+	DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
 
 	for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
-		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+		reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
 		ddc_data->data_buf[ndx] = (u8) ((reg_val & 0x0000FF00) >> 8);
 	}
 
@@ -964,7 +742,7 @@
 	int status = 0, retry = 10;
 	u32 time_out_count;
 
-	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+	if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
@@ -991,7 +769,7 @@
 	 *    INDEX = 0x0 (initial offset into buffer)
 	 *    INDEX_WRITE = 0x1 (setting initial offset)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 		BIT(31) | (ddc_data->dev_addr << 8));
 
 	/*
@@ -1002,7 +780,7 @@
 	 *    INDEX = 0x0
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
 
 	/*
 	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -1013,7 +791,7 @@
 	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
 	 */
 	for (ndx = 0; ndx < ddc_data->data_len; ++ndx)
-		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
 			((u32)ddc_data->data_buf[ndx]) << 8);
 
 	/* Data setup is complete, now setup the transaction characteristics */
@@ -1026,7 +804,7 @@
 	 *    STOP0 = 0x0 (do NOT insert STOP bit)
 	 *    CNT0 = 0x1 (single byte transaction excluding address)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
 
 	/*
 	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -1038,7 +816,7 @@
 	 *    Byte count for second transition (excluding the first
 	 *    Byte which is usually the address)
 	 */
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1,
 		BIT(13) | ((ddc_data->data_len-1) << 16));
 
 	/* Trigger the I2C transfer */
@@ -1051,13 +829,13 @@
 	 *    GO = 0x1 (kicks off hardware)
 	 */
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
 	time_out_count = wait_for_completion_interruptible_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
-	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
-	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
+	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
 	if (!time_out_count) {
 		if (retry-- > 0) {
 			DEV_INFO("%s[%s]: failed timout, retry=%d\n", __func__,
@@ -1067,26 +845,26 @@
 		status = -ETIMEDOUT;
 		DEV_ERR("%s[%s]: timedout, Int Ctrl=%08x\n",
 			__func__, ddc_data->what,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
 		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
 			__func__,
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
-			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+			DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
 		goto error;
 	}
 
 	/* Read DDC status */
-	reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
 	reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
 
 	/* Check if any NACK occurred */
 	if (reg_val) {
 		if (retry > 1)
 			/* SW_STATUS_RESET */
-			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+			DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
 		else
 			/* SOFT_RESET */
-			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+			DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
 
 		if (retry-- > 0) {
 			DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n",
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index 47515ba..852a93c 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -12,26 +12,7 @@
 
 #ifndef __HDMI_UTIL_H__
 #define __HDMI_UTIL_H__
-
-#define DEV_INFO(fmt, args...)	pr_info(fmt, ##args)
-#define DEV_WARN(fmt, args...)	pr_warn(fmt, ##args)
-#define DEV_ERR(fmt, args...)	pr_err(fmt, ##args)
-
-#ifdef DEBUG
-#define DEV_DBG(fmt, args...)	pr_err(fmt, ##args)
-#else
-#define DEV_DBG(args...)	(void)0
-#endif
-
-#define PORT_DEBUG 0
-#define REG_DUMP 0
-void hdmi_reg_w(void __iomem *addr, u32 offset, u32 value, u32 debug);
-u32 hdmi_reg_r(void __iomem *addr, u32 offset, u32 debug);
-
-#define HDMI_REG_W_ND(addr, offset, val)  hdmi_reg_w(addr, offset, val, false)
-#define HDMI_REG_W(addr, offset, val)     hdmi_reg_w(addr, offset, val, true)
-#define HDMI_REG_R_ND(addr, offset)       hdmi_reg_r(addr, offset, false)
-#define HDMI_REG_R(addr, offset)          hdmi_reg_r(addr, offset, true)
+#include "mdss_io_util.h"
 
 /* HDMI_TX Registers */
 #define HDMI_CTRL                        (0x00000000)
@@ -220,7 +201,7 @@
 #define HDMI_TPG_BLK_WHT_PATTERN_FRAMES  (0x00000358)
 #define HDMI_TPG_RGB_MAPPING             (0x0000035C)
 
-/* HDMI PHY Registers, use them with PHY base and _ND macro */
+/* HDMI PHY Registers */
 #define HDMI_PHY_ANA_CFG0                (0x00000000)
 #define HDMI_PHY_ANA_CFG1                (0x00000004)
 #define HDMI_PHY_PD_CTRL0                (0x00000010)
@@ -231,6 +212,10 @@
 #define HDMI_PHY_BIST_PATN2              (0x00000044)
 #define HDMI_PHY_BIST_PATN3              (0x00000048)
 
+/* QFPROM Registers for HDMI/HDCP */
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB  (0x000000F8)
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB  (0x000000FC)
+
 /* all video formats defined by EIA CEA 861D */
 #define HDMI_VFRMT_640x480p60_4_3	0
 #define HDMI_VFRMT_720x480p60_4_3	1
@@ -397,7 +382,7 @@
 };
 
 struct hdmi_tx_ddc_ctrl {
-	void __iomem *base;
+	struct dss_io_data *io;
 	struct completion ddc_sw_done;
 };
 
@@ -412,9 +397,6 @@
 	int retry;
 };
 
-void hdmi_reg_dump(void __iomem *base, u32 length, const char *prefix);
-const char *hdmi_reg_name(u32 offset);
-
 const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
 void hdmi_set_supported_mode(u32 mode);
 const char *hdmi_get_video_fmt_2string(u32 format);
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 65d08d3..5778525 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -10,10 +10,65 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include "mdss_io_util.h"
 
+void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
+{
+	u32 in_val;
+
+	if (!io || !io->base) {
+		DEV_ERR("%pS->%s: invalid input\n",
+			__builtin_return_address(0), __func__);
+		return;
+	}
+
+	if (offset > io->len) {
+		DEV_ERR("%pS->%s: offset out of range\n",
+			__builtin_return_address(0), __func__);
+		return;
+	}
+
+	writel_relaxed(value, io->base + offset);
+	if (debug) {
+		in_val = readl_relaxed(io->base + offset);
+		DEV_DBG("[%08x] => %08x [%08x]\n", (u32)(io->base + offset),
+			value, in_val);
+	}
+} /* dss_reg_w */
+
+u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug)
+{
+	u32 value;
+	if (!io || !io->base) {
+		DEV_ERR("%pS->%s: invalid input\n",
+			__builtin_return_address(0), __func__);
+		return -EINVAL;
+	}
+
+	if (offset > io->len) {
+		DEV_ERR("%pS->%s: offset out of range\n",
+			__builtin_return_address(0), __func__);
+		return -EINVAL;
+	}
+
+	value = readl_relaxed(io->base + offset);
+	if (debug)
+		DEV_DBG("[%08x] <= %08x\n", (u32)(io->base + offset), value);
+
+	return value;
+} /* dss_reg_r */
+
+void dss_reg_dump(void __iomem *base, u32 length, const char *prefix,
+	u32 debug)
+{
+	if (debug)
+		print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
+			(void *)base, length, false);
+} /* dss_reg_dump */
+
 static struct resource *msm_dss_get_res_byname(struct platform_device *pdev,
 	unsigned int type, const char *name)
 {
@@ -21,11 +76,10 @@
 
 	res = platform_get_resource_byname(pdev, type, name);
 	if (!res)
-		pr_err("%s: '%s' resource not found\n", __func__, name);
+		DEV_ERR("%s: '%s' resource not found\n", __func__, name);
 
 	return res;
-}
-
+} /* msm_dss_get_res_byname */
 
 int msm_dss_ioremap_byname(struct platform_device *pdev,
 	struct dss_io_data *io_data, const char *name)
@@ -33,32 +87,49 @@
 	struct resource *res = NULL;
 
 	if (!pdev || !io_data) {
-		pr_err("%s: invalid input\n", __func__);
+		DEV_ERR("%pS->%s: invalid input\n",
+			__builtin_return_address(0), __func__);
 		return -EINVAL;
 	}
 
 	res = msm_dss_get_res_byname(pdev, IORESOURCE_MEM, name);
 	if (!res) {
-		pr_err("%s: '%s' msm_dss_get_res_byname failed\n",
-			__func__, name);
+		DEV_ERR("%pS->%s: '%s' msm_dss_get_res_byname failed\n",
+			__builtin_return_address(0), __func__, name);
 		return -ENODEV;
 	}
 
 	io_data->len = resource_size(res);
 	io_data->base = ioremap(res->start, io_data->len);
 	if (!io_data->base) {
-		pr_err("%s: '%s' ioremap failed\n", __func__, name);
+		DEV_ERR("%pS->%s: '%s' ioremap failed\n",
+			__builtin_return_address(0), __func__, name);
 		return -EIO;
 	}
 
 	return 0;
-}
+} /* msm_dss_ioremap_byname */
+
+void msm_dss_iounmap(struct dss_io_data *io_data)
+{
+	if (!io_data) {
+		DEV_ERR("%pS->%s: invalid input\n",
+			__builtin_return_address(0), __func__);
+		return;
+	}
+
+	if (io_data->base) {
+		iounmap(io_data->base);
+		io_data->base = NULL;
+	}
+	io_data->len = 0;
+} /* msm_dss_iounmap */
 
 int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
 	int num_vreg, int config)
 {
 	int i = 0, rc = 0;
-	struct dss_vreg *curr_vreg;
+	struct dss_vreg *curr_vreg = NULL;
 
 	if (config) {
 		for (i = 0; i < num_vreg; i++) {
@@ -67,8 +138,8 @@
 				curr_vreg->vreg_name);
 			rc = IS_ERR(curr_vreg->vreg);
 			if (rc) {
-				pr_err("%s: %s get failed. rc=%d\n",
-					 __func__,
+				DEV_ERR("%pS->%s: %s get failed. rc=%d\n",
+					 __builtin_return_address(0), __func__,
 					 curr_vreg->vreg_name, rc);
 				curr_vreg->vreg = NULL;
 				goto vreg_get_fail;
@@ -79,7 +150,8 @@
 					curr_vreg->min_voltage,
 					curr_vreg->max_voltage);
 				if (rc < 0) {
-					pr_err("%s: %s set voltage failed\n",
+					DEV_ERR("%pS->%s: %s set vltg fail\n",
+						__builtin_return_address(0),
 						__func__,
 						curr_vreg->vreg_name);
 					goto vreg_set_voltage_fail;
@@ -89,8 +161,9 @@
 						curr_vreg->vreg,
 						curr_vreg->optimum_voltage);
 					if (rc < 0) {
-						pr_err(
-						"%s: %s set opt mode failed\n",
+						DEV_ERR(
+						"%pS->%s: %s set opt m fail\n",
+						__builtin_return_address(0),
 						__func__,
 						curr_vreg->vreg_name);
 						goto vreg_set_opt_mode_fail;
@@ -144,14 +217,16 @@
 		for (i = 0; i < num_vreg; i++) {
 			rc = IS_ERR(in_vreg[i].vreg);
 			if (rc) {
-				pr_err("%s: %s regulator error. rc=%d\n",
-					__func__, in_vreg[i].vreg_name, rc);
+				DEV_ERR("%pS->%s: %s regulator error. rc=%d\n",
+					__builtin_return_address(0), __func__,
+					in_vreg[i].vreg_name, rc);
 				goto disable_vreg;
 			}
 			rc = regulator_enable(in_vreg[i].vreg);
 			if (rc < 0) {
-				pr_err("%s: %s enable failed\n",
-					__func__, in_vreg[i].vreg_name);
+				DEV_ERR("%pS->%s: %s enable failed\n",
+					__builtin_return_address(0), __func__,
+					in_vreg[i].vreg_name);
 				goto disable_vreg;
 			}
 		}
@@ -176,8 +251,9 @@
 			rc = gpio_request(in_gpio[i].gpio,
 				in_gpio[i].gpio_name);
 			if (rc < 0) {
-				pr_err("%s: %s enable failed\n",
-					__func__, in_gpio[i].gpio_name);
+				DEV_ERR("%pS->%s: %s enable failed\n",
+					__builtin_return_address(0), __func__,
+					in_gpio[i].gpio_name);
 				goto disable_gpio;
 			}
 		}
@@ -192,3 +268,117 @@
 		gpio_free(in_gpio[i].gpio);
 	return rc;
 } /* msm_dss_enable_gpio */
+
+void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
+{
+	int i;
+
+	for (i = num_clk - 1; i >= 0; i--) {
+		if (clk_arry[i].clk)
+			clk_put(clk_arry[i].clk);
+		clk_arry[i].clk = NULL;
+	}
+} /* msm_dss_put_clk */
+
+int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < num_clk; i++) {
+		clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
+		rc = IS_ERR(clk_arry[i].clk);
+		if (rc) {
+			DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
+				__builtin_return_address(0), __func__,
+				clk_arry[i].clk_name, rc);
+			goto error;
+		}
+	}
+
+	return rc;
+
+error:
+	msm_dss_put_clk(clk_arry, num_clk);
+
+	return rc;
+} /* msm_dss_get_clk */
+
+int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < num_clk; i++) {
+		if (clk_arry[i].clk) {
+			if (DSS_CLK_AHB != clk_arry[i].type) {
+				DEV_DBG("%pS->%s: '%s' rate %ld\n",
+					__builtin_return_address(0), __func__,
+					clk_arry[i].clk_name,
+					clk_arry[i].rate);
+				rc = clk_set_rate(clk_arry[i].clk,
+					clk_arry[i].rate);
+				if (rc) {
+					DEV_ERR("%pS->%s: %s failed. rc=%d\n",
+						__builtin_return_address(0),
+						__func__,
+						clk_arry[i].clk_name, rc);
+					break;
+				}
+			}
+		} else {
+			DEV_ERR("%pS->%s: '%s' is not available\n",
+				__builtin_return_address(0), __func__,
+				clk_arry[i].clk_name);
+			rc = -EPERM;
+			break;
+		}
+	}
+
+	return rc;
+} /* msm_dss_clk_set_rate */
+
+int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
+{
+	int i, rc = 0;
+
+	if (enable) {
+		for (i = 0; i < num_clk; i++) {
+			DEV_DBG("%pS->%s: enable '%s'\n",
+				__builtin_return_address(0), __func__,
+				clk_arry[i].clk_name);
+			if (clk_arry[i].clk) {
+				rc = clk_prepare_enable(clk_arry[i].clk);
+				if (rc)
+					DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
+						__builtin_return_address(0),
+						__func__,
+						clk_arry[i].clk_name, rc);
+			} else {
+				DEV_ERR("%pS->%s: '%s' is not available\n",
+					__builtin_return_address(0), __func__,
+					clk_arry[i].clk_name);
+				rc = -EPERM;
+			}
+
+			if (rc) {
+				msm_dss_enable_clk(&clk_arry[i],
+					i, false);
+				break;
+			}
+		}
+	} else {
+		for (i = num_clk - 1; i >= 0; i--) {
+			DEV_DBG("%pS->%s: disable '%s'\n",
+				__builtin_return_address(0), __func__,
+				clk_arry[i].clk_name);
+
+			if (clk_arry[i].clk)
+				clk_disable_unprepare(clk_arry[i].clk);
+			else
+				DEV_ERR("%pS->%s: '%s' is not available\n",
+					__builtin_return_address(0), __func__,
+					clk_arry[i].clk_name);
+		}
+	}
+
+	return rc;
+} /* msm_dss_enable_clk */
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index 9671414..51e9e54 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -17,11 +17,29 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
+#ifdef DEBUG
+#define DEV_DBG(fmt, args...)   pr_err(fmt, ##args)
+#else
+#define DEV_DBG(fmt, args...)   pr_debug(fmt, ##args)
+#endif
+#define DEV_INFO(fmt, args...)  pr_info(fmt, ##args)
+#define DEV_WARN(fmt, args...)  pr_warn(fmt, ##args)
+#define DEV_ERR(fmt, args...)   pr_err(fmt, ##args)
+
 struct dss_io_data {
 	u32 len;
 	void __iomem *base;
 };
 
+void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug);
+u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug);
+void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug);
+
+#define DSS_REG_W_ND(io, offset, val)  dss_reg_w(io, offset, val, false)
+#define DSS_REG_W(io, offset, val)     dss_reg_w(io, offset, val, true)
+#define DSS_REG_R_ND(io, offset)       dss_reg_r(io, offset, false)
+#define DSS_REG_R(io, offset)          dss_reg_r(io, offset, true)
+
 enum dss_vreg_type {
 	DSS_REG_LDO,
 	DSS_REG_VS,
@@ -41,19 +59,42 @@
 	char gpio_name[32];
 };
 
+enum dss_clk_type {
+	DSS_CLK_AHB, /* no set rate. rate controlled through rpm */
+	DSS_CLK_PCLK,
+	DSS_CLK_OTHER,
+};
+
+struct dss_clk {
+	struct clk *clk; /* clk handle */
+	char clk_name[32];
+	enum dss_clk_type type;
+	unsigned long rate;
+};
+
 struct dss_module_power {
 	unsigned num_vreg;
 	struct dss_vreg *vreg_config;
 	unsigned num_gpio;
 	struct dss_gpio *gpio_config;
+	unsigned num_clk;
+	struct dss_clk *clk_config;
 };
 
 int msm_dss_ioremap_byname(struct platform_device *pdev,
 	struct dss_io_data *io_data, const char *name);
+void msm_dss_iounmap(struct dss_io_data *io_data);
+
 int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
 int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);
+
 int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
 	int num_vreg, int config);
 int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg,	int enable);
 
+int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk);
+void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
+int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
+int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
+
 #endif /* __MDSS_IO_UTIL_H__ */
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
new file mode 100644
index 0000000..c55e47e
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -0,0 +1,155 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PM8XXX_BMS_BATTERYDATA_H
+#define __PM8XXX_BMS_BATTERYDATA_H
+
+#include <linux/errno.h>
+
+#define FCC_CC_COLS		5
+#define FCC_TEMP_COLS		8
+
+#define PC_CC_ROWS             29
+#define PC_CC_COLS             13
+
+#define PC_TEMP_ROWS		29
+#define PC_TEMP_COLS		8
+
+#define MAX_SINGLE_LUT_COLS	20
+
+struct single_row_lut {
+	int x[MAX_SINGLE_LUT_COLS];
+	int y[MAX_SINGLE_LUT_COLS];
+	int cols;
+};
+
+/**
+ * struct sf_lut -
+ * @rows:	number of percent charge entries should be <= PC_CC_ROWS
+ * @cols:	number of charge cycle entries should be <= PC_CC_COLS
+ * @row_entries:	the charge cycles/temperature at which sf data
+ *			is available in the table.
+ *		The charge cycles must be in increasing order from 0 to rows.
+ * @percent:	the percent charge at which sf data is available in the table
+ *		The  percentcharge must be in decreasing order from 0 to cols.
+ * @sf:		the scaling factor data
+ */
+struct sf_lut {
+	int rows;
+	int cols;
+	int row_entries[PC_CC_COLS];
+	int percent[PC_CC_ROWS];
+	int sf[PC_CC_ROWS][PC_CC_COLS];
+};
+
+/**
+ * struct pc_temp_ocv_lut -
+ * @rows:	number of percent charge entries should be <= PC_TEMP_ROWS
+ * @cols:	number of temperature entries should be <= PC_TEMP_COLS
+ * @temp:	the temperatures at which ocv data is available in the table
+ *		The temperatures must be in increasing order from 0 to rows.
+ * @percent:	the percent charge at which ocv data is available in the table
+ *		The  percentcharge must be in decreasing order from 0 to cols.
+ * @ocv:	the open circuit voltage
+ */
+struct pc_temp_ocv_lut {
+	int rows;
+	int cols;
+	int temp[PC_TEMP_COLS];
+	int percent[PC_TEMP_ROWS];
+	int ocv[PC_TEMP_ROWS][PC_TEMP_COLS];
+};
+
+enum battery_type {
+	BATT_UNKNOWN = 0,
+	BATT_PALLADIUM,
+	BATT_DESAY,
+};
+
+/**
+ * struct bms_battery_data -
+ * @fcc:		full charge capacity (mAmpHour)
+ * @fcc_temp_lut:	table to get fcc at a given temp
+ * @pc_temp_ocv_lut:	table to get percent charge given batt temp and cycles
+ * @pc_sf_lut:		table to get percent charge scaling factor given cycles
+ *			and percent charge
+ * @rbatt_sf_lut:	table to get battery resistance scaling factor given
+ *			temperature and percent charge
+ * @default_rbatt_mohm:	the default value of battery resistance to use when
+ *			readings from bms are not available.
+ * @delta_rbatt_mohm:	the resistance to be added towards lower soc to
+ *			compensate for battery capacitance.
+ */
+
+struct bms_battery_data {
+	unsigned int		fcc;
+	struct single_row_lut	*fcc_temp_lut;
+	struct single_row_lut	*fcc_sf_lut;
+	struct pc_temp_ocv_lut	*pc_temp_ocv_lut;
+	struct sf_lut		*pc_sf_lut;
+	struct sf_lut		*rbatt_sf_lut;
+	int			default_rbatt_mohm;
+	int			delta_rbatt_mohm;
+};
+
+#if defined(CONFIG_PM8921_BMS) || \
+	defined(CONFIG_PM8921_BMS_MODULE)
+extern struct bms_battery_data  palladium_1500_data;
+extern struct bms_battery_data  desay_5200_data;
+
+int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp);
+int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc);
+int interpolate_scalingfactor_fcc(struct single_row_lut *fcc_sf_lut,
+				int cycles);
+int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+				int batt_temp_degc, int ocv);
+int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+				int batt_temp_degc, int pc);
+int linear_interpolate(int y0, int x0, int y1, int x1, int x);
+int is_between(int left, int right, int value);
+#else
+static inline int interpolate_fcc(struct single_row_lut *fcc_temp_lut,
+			int batt_temp)
+{
+	return -EINVAL;
+}
+static inline int interpolate_scalingfactor(struct sf_lut *sf_lut,
+			int row_entry, int pc)
+{
+	return -EINVAL;
+}
+static inline int interpolate_scalingfactor_fcc(
+			struct single_row_lut *fcc_sf_lut, int cycles)
+{
+	return -EINVAL;
+}
+static inline int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+			int batt_temp_degc, int ocv)
+{
+	return -EINVAL;
+}
+static inline int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+			int batt_temp_degc, int pc)
+{
+	return -EINVAL;
+}
+static inline int linear_interpolate(int y0, int x0, int y1, int x1, int x)
+{
+	return -EINVAL;
+}
+static inline int is_between(int left, int right, int value)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index a73a284..5f2fe9f 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -14,87 +14,10 @@
 #define __PM8XXX_BMS_H
 
 #include <linux/errno.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
 
 #define PM8921_BMS_DEV_NAME	"pm8921-bms"
 
-#define FCC_CC_COLS		5
-#define FCC_TEMP_COLS		8
-
-#define PC_CC_ROWS             29
-#define PC_CC_COLS             13
-
-#define PC_TEMP_ROWS		29
-#define PC_TEMP_COLS		8
-
-#define MAX_SINGLE_LUT_COLS	20
-
-struct single_row_lut {
-	int x[MAX_SINGLE_LUT_COLS];
-	int y[MAX_SINGLE_LUT_COLS];
-	int cols;
-};
-
-/**
- * struct sf_lut -
- * @rows:	number of percent charge entries should be <= PC_CC_ROWS
- * @cols:	number of charge cycle entries should be <= PC_CC_COLS
- * @row_entries:	the charge cycles/temperature at which sf data
- *			is available in the table.
- *		The charge cycles must be in increasing order from 0 to rows.
- * @percent:	the percent charge at which sf data is available in the table
- *		The  percentcharge must be in decreasing order from 0 to cols.
- * @sf:		the scaling factor data
- */
-struct sf_lut {
-	int rows;
-	int cols;
-	int row_entries[PC_CC_COLS];
-	int percent[PC_CC_ROWS];
-	int sf[PC_CC_ROWS][PC_CC_COLS];
-};
-
-/**
- * struct pc_temp_ocv_lut -
- * @rows:	number of percent charge entries should be <= PC_TEMP_ROWS
- * @cols:	number of temperature entries should be <= PC_TEMP_COLS
- * @temp:	the temperatures at which ocv data is available in the table
- *		The temperatures must be in increasing order from 0 to rows.
- * @percent:	the percent charge at which ocv data is available in the table
- *		The  percentcharge must be in decreasing order from 0 to cols.
- * @ocv:	the open circuit voltage
- */
-struct pc_temp_ocv_lut {
-	int rows;
-	int cols;
-	int temp[PC_TEMP_COLS];
-	int percent[PC_TEMP_ROWS];
-	int ocv[PC_TEMP_ROWS][PC_TEMP_COLS];
-};
-
-/**
- * struct pm8921_bms_battery_data -
- * @fcc:		full charge capacity (mAmpHour)
- * @fcc_temp_lut:	table to get fcc at a given temp
- * @pc_temp_ocv_lut:	table to get percent charge given batt temp and cycles
- * @pc_sf_lut:		table to get percent charge scaling factor given cycles
- *			and percent charge
- * @rbatt_sf_lut:	table to get battery resistance scaling factor given
- *			temperature and percent charge
- * @default_rbatt_mohm:	the default value of battery resistance to use when
- *			readings from bms are not available.
- * @delta_rbatt_mohm:	the resistance to be added towards lower soc to
- *			compensate for battery capacitance.
- */
-struct pm8921_bms_battery_data {
-	unsigned int		fcc;
-	struct single_row_lut	*fcc_temp_lut;
-	struct single_row_lut	*fcc_sf_lut;
-	struct pc_temp_ocv_lut	*pc_temp_ocv_lut;
-	struct sf_lut		*pc_sf_lut;
-	struct sf_lut		*rbatt_sf_lut;
-	int			default_rbatt_mohm;
-	int			delta_rbatt_mohm;
-};
 
 struct pm8xxx_bms_core_data {
 	unsigned int	batt_temp_channel;
@@ -104,12 +27,6 @@
 	unsigned int	batt_id_channel;
 };
 
-enum battery_type {
-	BATT_UNKNOWN = 0,
-	BATT_PALLADIUM,
-	BATT_DESAY,
-};
-
 /**
  * struct pm8921_bms_platform_data -
  * @batt_type:		allows to force chose battery calibration data
@@ -137,8 +54,6 @@
 };
 
 #if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
-extern struct pm8921_bms_battery_data  palladium_1500_data;
-extern struct pm8921_bms_battery_data  desay_5200_data;
 /**
  * pm8921_bms_get_vsense_avg - return the voltage across the sense
  *				resitor in microvolts
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 647a7ef..03390b1 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -223,9 +223,14 @@
 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);
+extern int power_supply_register(struct device *parent,
+				 struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+extern int power_supply_powers(struct power_supply *psy, struct device *dev);
 #else
 static inline struct power_supply *power_supply_get_by_name(char *name)
-							{ return -ENOSYS; }
+							{ return NULL; }
+static inline void power_supply_changed(struct power_supply *psy) { }
 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)
@@ -243,16 +248,18 @@
 							int type)
 							{ return -ENOSYS; }
 static inline int power_supply_set_supply_type(struct power_supply *psy,
-					enum power_supply_type supply_type);
+					enum power_supply_type supply_type)
 							{ return -ENOSYS; }
 static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
+static inline int power_supply_register(struct device *parent,
+					struct power_supply *psy)
+							{ return -ENOSYS; }
+static inline void power_supply_unregister(struct power_supply *psy) { }
+static inline int power_supply_powers(struct power_supply *psy,
+				      struct device *dev)
+							{ return -ENOSYS; }
 #endif
 
-extern int power_supply_register(struct device *parent,
-				 struct power_supply *psy);
-extern void power_supply_unregister(struct power_supply *psy);
-extern int power_supply_powers(struct power_supply *psy, struct device *dev);
-
 /* For APM emulation, think legacy userspace. */
 extern struct class *power_supply_class;
 
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 1da6aa2..d902881 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1890,6 +1890,7 @@
 	struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch;
 	struct afe_param_id_slimbus_cfg           slim_sch;
 	struct afe_param_id_rt_proxy_port_cfg     rtproxy;
+	struct afe_param_id_internal_bt_fm_cfg    int_bt_fm;
 } __packed;
 
 struct afe_audioif_config_command {
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 8ccc9f4..e107130 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -13,6 +13,8 @@
 #define __Q6AFE_V2_H__
 #include <sound/apr_audio-v2.h>
 
+#define IN			0x000
+#define OUT			0x001
 #define MSM_AFE_MONO        0
 #define MSM_AFE_MONO_RIGHT  1
 #define MSM_AFE_MONO_LEFT   2
@@ -71,6 +73,40 @@
 	AFE_MAX_PORTS
 };
 
+struct afe_audio_buffer {
+	dma_addr_t phys;
+	void       *data;
+	uint32_t   used;
+	uint32_t   size;/* size of buffer */
+	uint32_t   actual_size; /* actual number of bytes read by DSP */
+	struct      ion_handle *handle;
+	struct      ion_client *client;
+};
+
+struct afe_audio_port_data {
+	struct afe_audio_buffer *buf;
+	uint32_t	    max_buf_cnt;
+	uint32_t	    dsp_buf;
+	uint32_t	    cpu_buf;
+	struct list_head    mem_map_handle;
+	uint32_t	    tmp_hdl;
+	/* read or write locks */
+	struct mutex	    lock;
+	spinlock_t	    dsp_lock;
+};
+
+struct afe_audio_client {
+	atomic_t	       cmd_state;
+	/* Relative or absolute TS */
+	uint32_t	       time_flag;
+	void		       *priv;
+	uint64_t	       time_stamp;
+	struct mutex	       cmd_lock;
+	/* idx:1 out port, 0: in port*/
+	struct afe_audio_port_data port[2];
+	wait_queue_head_t      cmd_wait;
+};
+
 int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
 int afe_close(int port_id);
 int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
@@ -80,6 +116,7 @@
 int afe_get_port_index(u16 port_id);
 int afe_start_pseudo_port(u16 port_id);
 int afe_stop_pseudo_port(u16 port_id);
+uint32_t afe_req_mmap_handle(void);
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_unmap(u32 dma_addr_p);
@@ -98,6 +135,14 @@
 int afe_apply_gain(u16 port_id, u16 gain);
 int afe_q6_interface_prepare(void);
 int afe_get_port_type(u16 port_id);
+int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
+			struct afe_audio_client *ac,
+			unsigned int bufsz,
+			unsigned int bufcnt);
+struct afe_audio_client *q6afe_audio_client_alloc(void *priv);
+int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
+			struct afe_audio_client *ac);
+void q6afe_audio_client_free(struct afe_audio_client *ac);
 /* if port_id is virtual, convert to physical..
  * if port_id is already physical, return physical
  */
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 92b7324..f462299 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -81,6 +81,7 @@
 static int msm_slim_0_tx_ch = 1;
 
 static int msm_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm_btsco_ch = 1;
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
@@ -480,6 +481,21 @@
 		     msm_btsco_rate_get, msm_btsco_rate_put),
 };
 
+static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	rate->min = rate->max = msm_btsco_rate;
+	channels->min = channels->max = msm_btsco_ch;
+
+	return 0;
+}
+
 static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -495,6 +511,19 @@
 
 	return 0;
 }
+
+static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm_aux_pcm_get_gpios(void)
 {
 	int ret = 0;
@@ -780,19 +809,19 @@
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
 	},
 	{
-		.name = "MSM VoIP",
-		.stream_name = "VoIP",
-		.cpu_dai_name	= "VoIP",
-		.platform_name  = "msm-voip-dsp",
+		.name = "MSM8974 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name   = "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
 		.ignore_suspend = 1,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
-		.be_id = MSM_FRONTEND_DAI_VOIP,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
 	},
 	{
 		.name = "Circuit-Switch Voice",
@@ -811,6 +840,21 @@
 		.be_id = MSM_FRONTEND_DAI_CS_VOICE,
 	},
 	{
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name	= "VoIP",
+		.platform_name  = "msm-voip-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{
 		.name = "MSM8974 LPA",
 		.stream_name = "LPA",
 		.cpu_dai_name	= "MultiMedia3",
@@ -841,6 +885,41 @@
 		.codec_name = "snd-soc-dummy",
 	},
 	{
+		.name = "INT_FM Hostless",
+		.stream_name = "INT_FM Hostless",
+		.cpu_dai_name	= "INT_FM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6-dev.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6-dev.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
 		.name = "MSM8974 Compr",
 		.stream_name = "COMPR",
 		.cpu_dai_name	= "MultiMedia4",
@@ -870,19 +949,55 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
+	/* Backend BT/FM DAI Links */
 	{
-		.name = "MSM8974 Media2",
-		.stream_name = "MultiMedia2",
-		.cpu_dai_name	= "MultiMedia2",
-		.platform_name = "msm-pcm-dsp",
-		.dynamic = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.ignore_suspend = 1,
+		.name = LPASS_BE_INT_BT_SCO_RX,
+		.stream_name = "Internal BT-SCO Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.12288",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
-		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{
+		.name = LPASS_BE_INT_BT_SCO_TX,
+		.stream_name = "Internal BT-SCO Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.12289",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+	},
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.224",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.225",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
 	},
 	/* AUX PCM Backend DAI Links */
 	{
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 3eab972..a6cdad2 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -540,6 +540,14 @@
 
 	memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
 
+	pr_debug("%s: setting bt_fm parameters\n", __func__);
+
+	dai_data->port_config.int_bt_fm.bt_fm_cfg_minor_version =
+					AFE_API_VERSION_INTERNAL_BT_FM_CONFIG;
+	dai_data->port_config.int_bt_fm.num_channels = dai_data->channels;
+	dai_data->port_config.int_bt_fm.sample_rate = dai_data->rate;
+	dai_data->port_config.int_bt_fm.bit_width = 16;
+
 	return 0;
 }
 
@@ -805,6 +813,36 @@
 	return 0;
 }
 
+static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+		SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min =     8000,
+		.rate_max =	48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
+	.capture = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+		SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 4,
+		.rate_min =     8000,
+		.rate_max =	48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
@@ -833,6 +871,34 @@
 	.remove = msm_dai_q6_dai_remove,
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 1,
+		.rate_max = 16000,
+		.rate_min = 8000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 1,
+		.rate_max = 16000,
+		.rate_min = 8000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
 {
 	int id;
@@ -1084,6 +1150,22 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 					  &msm_dai_q6_slimbus_1_tx_dai);
 		break;
+	case INT_BT_SCO_RX:
+		rc = snd_soc_register_dai(&pdev->dev,
+					&msm_dai_q6_bt_sco_rx_dai);
+		break;
+	case INT_BT_SCO_TX:
+		rc = snd_soc_register_dai(&pdev->dev,
+					&msm_dai_q6_bt_sco_tx_dai);
+		break;
+	case RT_PROXY_DAI_001_RX:
+	case RT_PROXY_DAI_002_RX:
+		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
+		break;
+	case RT_PROXY_DAI_001_TX:
+	case RT_PROXY_DAI_002_TX:
+		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
+		break;
 	default:
 		rc = -ENODEV;
 		break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 4593784..73a04c2 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -29,6 +29,8 @@
 #include <sound/control.h>
 #include <sound/q6adm-v2.h>
 #include <asm/dma.h>
+#include <linux/memory_alloc.h>
+#include <mach/msm_subsystem_map.h>
 #include "msm-pcm-afe-v2.h"
 
 #define MIN_PERIOD_SIZE (128 * 2)
@@ -63,6 +65,11 @@
 	struct snd_pcm_substream *substream = prtd->substream;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	u32 mem_map_handle = 0;
+
+	mem_map_handle = afe_req_mmap_handle();
+	if (!mem_map_handle)
+		pr_err("%s: mem_map_handle is NULL\n", __func__);
+
 	if (prtd->start) {
 		pr_debug("sending frame to DSP: poll_time: %d\n",
 				prtd->poll_time);
@@ -89,10 +96,15 @@
 	struct snd_pcm_substream *substream = prtd->substream;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	u32 mem_map_handle = 0;
+
+	mem_map_handle = afe_req_mmap_handle();
+	if (!mem_map_handle)
+		pr_err("%s: mem_map_handle is NULL\n", __func__);
+
 	if (prtd->start) {
 		if (prtd->dsp_cnt == runtime->periods)
 			prtd->dsp_cnt = 0;
-		pr_err("%s: mem_map_handle 0x%x\n", __func__, mem_map_handle);
+		pr_debug("%s: mem_map_handle 0x%x\n", __func__, mem_map_handle);
 		afe_rt_proxy_port_read(
 		(prtd->dma_addr + (prtd->dsp_cnt
 		* snd_pcm_lib_period_bytes(prtd->substream))), mem_map_handle,
@@ -137,9 +149,6 @@
 						runtime->channels * 2)));
 				pr_debug("prtd->poll_time: %d",
 						prtd->poll_time);
-				hrtimer_start(&prtd->hrt,
-					ns_to_ktime(0),
-					HRTIMER_MODE_REL);
 				break;
 			}
 			case AFE_EVENT_RTPORT_STOP:
@@ -203,9 +212,6 @@
 				snd_pcm_lib_period_bytes(prtd->substream)
 					* 1000 * 1000)/(runtime->rate
 					* runtime->channels * 2)));
-			hrtimer_start(&prtd->hrt,
-				ns_to_ktime(0),
-				HRTIMER_MODE_REL);
 			pr_debug("prtd->poll_time : %d", prtd->poll_time);
 			break;
 		}
@@ -321,13 +327,21 @@
 	runtime->hw = msm_afe_hardware;
 	prtd->substream = substream;
 	runtime->private_data = prtd;
-	mutex_unlock(&prtd->lock);
+	prtd->audio_client = q6afe_audio_client_alloc(prtd);
+	if (!prtd->audio_client) {
+		pr_debug("%s: Could not allocate memory\n", __func__);
+		kfree(prtd);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+
 	hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		prtd->hrt.function = afe_hrtimer_callback;
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		prtd->hrt.function = afe_hrtimer_rec_callback;
 
+	mutex_unlock(&prtd->lock);
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -350,6 +364,7 @@
 	struct pcm_afe_info *prtd;
 	struct snd_soc_pcm_runtime *rtd = NULL;
 	struct snd_soc_dai *dai = NULL;
+	int dir = IN;
 	int ret = 0;
 
 	pr_debug("%s\n", __func__);
@@ -365,17 +380,19 @@
 	mutex_lock(&prtd->lock);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dir = IN;
 		ret =  afe_unregister_get_events(dai->id);
 		if (ret < 0)
 			pr_err("AFE unregister for events failed\n");
 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		dir = OUT;
 		ret =  afe_unregister_get_events(dai->id);
 		if (ret < 0)
 			pr_err("AFE unregister for events failed\n");
 	}
 	hrtimer_cancel(&prtd->hrt);
 
-	rc = afe_cmd_memory_unmap(runtime->dma_addr);
+	rc = afe_cmd_memory_unmap(afe_req_mmap_handle());
 	if (rc < 0)
 		pr_err("AFE memory unmap failed\n");
 
@@ -384,15 +401,14 @@
 	if (dma_buf == NULL) {
 		pr_debug("dma_buf is NULL\n");
 			goto done;
-		}
-	if (dma_buf->area != NULL) {
-		dma_free_coherent(substream->pcm->card->dev,
-			runtime->hw.buffer_bytes_max, dma_buf->area,
-			dma_buf->addr);
-		dma_buf->area = NULL;
 	}
+
+	if (dma_buf->area)
+		dma_buf->area = NULL;
+	q6afe_audio_client_buf_free_contiguous(dir, prtd->audio_client);
 done:
 	pr_debug("%s: dai->id =%x\n", __func__, dai->id);
+	q6afe_audio_client_free(prtd->audio_client);
 	mutex_unlock(&prtd->lock);
 	prtd->prepared--;
 	kfree(prtd);
@@ -420,14 +436,21 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pcm_afe_info *prtd = runtime->private_data;
+	int result = 0;
 
 	pr_debug("%s\n", __func__);
 	prtd->mmap_flag = 1;
-	dma_mmap_coherent(substream->pcm->card->dev, vma,
-				runtime->dma_area,
-				runtime->dma_addr,
-				runtime->dma_bytes);
-	return 0;
+	if (runtime->dma_addr && runtime->dma_bytes) {
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		result = remap_pfn_range(vma, vma->vm_start,
+				runtime->dma_addr >> PAGE_SHIFT,
+				runtime->dma_bytes,
+				vma->vm_page_prot);
+	} else {
+		pr_err("Physical address or size of buf is NULL");
+		return -EINVAL;
+	}
+	return result;
 }
 static int msm_afe_trigger(struct snd_pcm_substream *substream, int cmd)
 {
@@ -441,6 +464,8 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
 		prtd->start = 1;
+		hrtimer_start(&prtd->hrt, ns_to_ktime(0),
+					HRTIMER_MODE_REL);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -460,27 +485,45 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
 	struct pcm_afe_info *prtd = runtime->private_data;
-	int rc;
+	struct afe_audio_buffer *buf;
+	int dir, rc;
 
 	pr_debug("%s:\n", __func__);
 
 	mutex_lock(&prtd->lock);
-
-	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	dma_buf->dev.dev = substream->pcm->card->dev;
-	dma_buf->private_data = NULL;
-	dma_buf->area = dma_alloc_coherent(dma_buf->dev.dev,
-				runtime->hw.buffer_bytes_max,
-				&dma_buf->addr, GFP_KERNEL);
-
-	pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__,
-			(unsigned int *) dma_buf->area, dma_buf->addr);
-	if (!dma_buf->area) {
-		pr_err("%s:MSM AFE memory allocation failed\n", __func__);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	rc = q6afe_audio_client_buf_alloc_contiguous(dir,
+			prtd->audio_client,
+			runtime->hw.period_bytes_min,
+			runtime->hw.periods_max);
+	if (rc < 0) {
+		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", rc);
 		mutex_unlock(&prtd->lock);
 		return -ENOMEM;
 	}
+	buf = prtd->audio_client->port[dir].buf;
+
+	if (buf == NULL || buf[0].data == NULL) {
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+
+	pr_debug("%s:buf = %p\n", __func__, buf);
+	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	dma_buf->dev.dev = substream->pcm->card->dev;
+	dma_buf->private_data = NULL;
+	dma_buf->area = buf[0].data;
+	dma_buf->addr = buf[0].phys;
 	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	if (!dma_buf->area) {
+		pr_err("%s:MSM AFE physical memory allocation failed\n",
+							__func__);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
 	memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
 	prtd->dma_addr = (u32) dma_buf->addr;
 
@@ -542,6 +585,9 @@
 
 static __devinit int msm_afe_probe(struct platform_device *pdev)
 {
+	if (pdev->dev.of_node)
+		dev_set_name(&pdev->dev, "%s", "msm-pcm-afe");
+
 	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
 	return snd_soc_register_platform(&pdev->dev,
 				   &msm_soc_platform);
@@ -553,11 +599,17 @@
 	snd_soc_unregister_platform(&pdev->dev);
 	return 0;
 }
+static const struct of_device_id msm_pcm_afe_dt_match[] = {
+	{.compatible = "qcom,msm-pcm-afe"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_pcm_afe_dt_match);
 
 static struct platform_driver msm_afe_driver = {
 	.driver = {
 		.name = "msm-pcm-afe",
 		.owner = THIS_MODULE,
+		.of_match_table = msm_pcm_afe_dt_match,
 	},
 	.probe = msm_afe_probe,
 	.remove = __devexit_p(msm_afe_remove),
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
index 20d6377..446409f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
@@ -30,6 +30,7 @@
 	int prepared;
 	struct hrtimer hrt;
 	int poll_time;
+	struct afe_audio_client *audio_client;
 };
 
 
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 0b25545..f0465a5 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -18,6 +18,7 @@
 #include <linux/wait.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
+#include <linux/msm_ion.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 #include <sound/apr_audio-v2.h>
 #include <sound/q6afe-v2.h>
@@ -37,6 +38,7 @@
 		uint32_t token, uint32_t *payload, void *priv);
 	void *tx_private_data;
 	void *rx_private_data;
+	uint32_t mmap_handle;
 };
 
 static struct afe_ctl this_afe;
@@ -107,6 +109,13 @@
 						payload[0]);
 				break;
 			}
+		} else if (data->opcode ==
+				AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
+			pr_debug("%s: mmap_handle: 0x%x\n",
+						__func__, payload[0]);
+			this_afe.mmap_handle = (uint32_t)payload[0];
+			atomic_set(&this_afe.state, 0);
+			wake_up(&this_afe.wait[data->token]);
 		} else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
 			port_id = (uint16_t)(0x0000FFFF & payload[0]);
 		}
@@ -266,17 +275,21 @@
 		ret = -EINVAL;
 		return ret;
 	}
-	index = q6audio_get_port_index(port_id);
-	if (q6audio_validate_port(port_id) < 0)
-		return -EINVAL;
 
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
 		(port_id == RT_PROXY_DAI_002_TX))
-		return -EINVAL;
+		return 0;
 	if ((port_id == RT_PROXY_DAI_002_RX) ||
 		(port_id == RT_PROXY_DAI_001_TX))
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 
+	pr_debug("%s: port id: %d\n", __func__, port_id);
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_validate_port(port_id) < 0) {
+		pr_err("%s: port id: %d\n", __func__, port_id);
+		return -EINVAL;
+	}
+
 	ret = afe_q6_interface_prepare();
 	if (IS_ERR_VALUE(ret))
 		return ret;
@@ -325,6 +338,14 @@
 	case SLIMBUS_4_TX:
 		cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
 		break;
+	case RT_PROXY_PORT_001_RX:
+	case RT_PROXY_PORT_001_TX:
+		cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
+		break;
+	case INT_BT_SCO_RX:
+	case INT_BT_SCO_TX:
+		cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
+		break;
 	default:
 		pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
 		ret = -EINVAL;
@@ -904,7 +925,133 @@
 	return 0;
 }
 
-/*bharath, memory map handle needs to be stored by AFE client */
+uint32_t afe_req_mmap_handle(void)
+{
+	return this_afe.mmap_handle;
+}
+
+struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
+{
+	struct afe_audio_client *ac;
+	int lcnt = 0;
+
+	ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
+	if (!ac) {
+		pr_err("%s: cannot allocate audio client for afe\n", __func__);
+		return NULL;
+	}
+	ac->priv = priv;
+
+	init_waitqueue_head(&ac->cmd_wait);
+	INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
+	INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
+	pr_debug("%s: mem_map_handle list init'ed\n", __func__);
+	mutex_init(&ac->cmd_lock);
+	for (lcnt = 0; lcnt <= OUT; lcnt++) {
+		mutex_init(&ac->port[lcnt].lock);
+		spin_lock_init(&ac->port[lcnt].dsp_lock);
+	}
+	atomic_set(&ac->cmd_state, 0);
+
+	return ac;
+}
+
+int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
+			struct afe_audio_client *ac,
+			unsigned int bufsz,
+			unsigned int bufcnt)
+{
+	int cnt = 0;
+	int rc = 0;
+	struct afe_audio_buffer *buf;
+	int len;
+
+	if (!(ac) || ((dir != IN) && (dir != OUT)))
+		return -EINVAL;
+
+	pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
+			__func__,
+			bufsz, bufcnt);
+
+	if (ac->port[dir].buf) {
+		pr_debug("%s: buffer already allocated\n", __func__);
+		return 0;
+	}
+	mutex_lock(&ac->cmd_lock);
+	buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
+			GFP_KERNEL);
+
+	if (!buf) {
+		mutex_unlock(&ac->cmd_lock);
+		goto fail;
+	}
+
+	ac->port[dir].buf = buf;
+
+	buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
+	if (IS_ERR_OR_NULL((void *)buf[0].client)) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		goto fail;
+	}
+	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
+				  (0x1 << ION_AUDIO_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
+		pr_err("%s: ION memory allocation for AUDIO failed\n",
+			__func__);
+		goto fail;
+	}
+
+	rc = ion_phys(buf[0].client, buf[0].handle,
+		  (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
+	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto fail;
+	}
+	memset((void *)buf[0].data, 0, (bufsz * bufcnt));
+	if (!buf[0].data) {
+		pr_err("%s:invalid vaddr, iomap failed\n", __func__);
+		mutex_unlock(&ac->cmd_lock);
+		goto fail;
+	}
+
+	buf[0].used = dir ^ 1;
+	buf[0].size = bufsz;
+	buf[0].actual_size = bufsz;
+	cnt = 1;
+	while (cnt < bufcnt) {
+		if (bufsz > 0) {
+			buf[cnt].data =  buf[0].data + (cnt * bufsz);
+			buf[cnt].phys =  buf[0].phys + (cnt * bufsz);
+			if (!buf[cnt].data) {
+				pr_err("%s Buf alloc failed\n",
+							__func__);
+				mutex_unlock(&ac->cmd_lock);
+				goto fail;
+			}
+			buf[cnt].used = dir ^ 1;
+			buf[cnt].size = bufsz;
+			buf[cnt].actual_size = bufsz;
+			pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
+				   (void *)buf[cnt].data,
+				   (void *)buf[cnt].phys,
+				   (void *)&buf[cnt].phys);
+		}
+		cnt++;
+	}
+	ac->port[dir].max_buf_cnt = cnt;
+	mutex_unlock(&ac->cmd_lock);
+	return 0;
+fail:
+	q6afe_audio_client_buf_free_contiguous(dir, ac);
+	return -EINVAL;
+}
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
 {
 	int ret = 0;
@@ -941,7 +1088,7 @@
 							mmap_region_cmd;
 	mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
-	mregion->hdr.pkt_size = sizeof(mregion);
+	mregion->hdr.pkt_size = cmd_size;
 	mregion->hdr.src_port = 0;
 	mregion->hdr.dest_port = 0;
 	mregion->hdr.token = 0;
@@ -961,13 +1108,15 @@
 	mregion_pl->shm_addr_msw = 0x00;
 	mregion_pl->mem_size_bytes = dma_buf_sz;
 
+	pr_debug("%s: dma_addr_p 0x%x , size %d\n", __func__,
+					dma_addr_p, dma_buf_sz);
 	atomic_set(&this_afe.state, 1);
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
 	if (ret < 0) {
 		pr_err("%s: AFE memory map cmd failed %d\n",
 		       __func__, ret);
 		ret = -EINVAL;
-		return ret;
+		goto fail_cmd;
 	}
 
 	ret = wait_event_timeout(this_afe.wait[index],
@@ -976,10 +1125,13 @@
 	if (!ret) {
 		pr_err("%s: wait_event timeout\n", __func__);
 		ret = -EINVAL;
-		return ret;
+		goto fail_cmd;
 	}
-
+	pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
 	return 0;
+fail_cmd:
+	kfree(mmap_region_cmd);
+	return ret;
 }
 
 int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz)
@@ -1047,6 +1199,60 @@
 	}
 	return 0;
 }
+int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
+			struct afe_audio_client *ac)
+{
+	struct afe_audio_port_data *port;
+	int cnt = 0;
+	mutex_lock(&ac->cmd_lock);
+	port = &ac->port[dir];
+	if (!port->buf) {
+		mutex_unlock(&ac->cmd_lock);
+		return 0;
+	}
+	cnt = port->max_buf_cnt - 1;
+
+	if (port->buf[0].data) {
+		ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
+		ion_free(port->buf[0].client, port->buf[0].handle);
+		ion_client_destroy(port->buf[0].client);
+		pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
+			__func__,
+			(void *)port->buf[0].data,
+			(void *)port->buf[0].phys,
+			(void *)&port->buf[0].phys,
+			(void *)port->buf[0].client,
+			(void *)port->buf[0].handle);
+	}
+
+	while (cnt >= 0) {
+		port->buf[cnt].data = NULL;
+		port->buf[cnt].phys = 0;
+		cnt--;
+	}
+	port->max_buf_cnt = 0;
+	kfree(port->buf);
+	port->buf = NULL;
+	mutex_unlock(&ac->cmd_lock);
+	return 0;
+}
+
+void q6afe_audio_client_free(struct afe_audio_client *ac)
+{
+	int loopcnt;
+	struct afe_audio_port_data *port;
+	if (!ac)
+		return;
+	for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
+		port = &ac->port[loopcnt];
+		if (!port->buf)
+			continue;
+		pr_debug("%s:loopcnt = %d\n", __func__, loopcnt);
+		q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
+	}
+	kfree(ac);
+	return;
+}
 
 int afe_cmd_memory_unmap(u32 mem_map_handle)
 {
@@ -1143,7 +1349,7 @@
 	int ret = 0;
 	struct afe_service_cmd_register_rt_port_driver rtproxy;
 
-	pr_debug("%s:\n", __func__);
+	pr_debug("%s: port_id: %d\n", __func__, port_id);
 
 	if (this_afe.apr == NULL) {
 		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
@@ -1206,9 +1412,6 @@
 			return ret;
 		}
 	}
-	index = q6audio_get_port_index(port_id);
-	if (q6audio_validate_port(port_id) < 0)
-		return -EINVAL;
 
 	if ((port_id == RT_PROXY_DAI_002_RX) ||
 		(port_id == RT_PROXY_DAI_001_TX))
@@ -1216,6 +1419,10 @@
 	else
 		return -EINVAL;
 
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_validate_port(port_id) < 0)
+		return -EINVAL;
+
 	rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	rtproxy.hdr.pkt_size = sizeof(rtproxy);
@@ -1318,6 +1525,7 @@
 	afecmd_rd.buffer_address_lsw = (uint32_t)buf_addr_p;
 	afecmd_rd.buffer_address_msw = 0x00;
 	afecmd_rd.available_bytes = bytes;
+	afecmd_rd.mem_map_handle = mem_map_handle;
 
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
 	if (ret < 0) {
@@ -1665,11 +1873,11 @@
 	}
 	pr_debug("%s: port_id=%d\n", __func__, port_id);
 
+	port_id = q6audio_convert_virtual_to_portid(port_id);
 	index = q6audio_get_port_index(port_id);
 	if (q6audio_validate_port(port_id) < 0)
 		return -EINVAL;
 
-	port_id = q6audio_convert_virtual_to_portid(port_id);
 
 	stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -1708,6 +1916,7 @@
 	atomic_set(&this_afe.state, 0);
 	atomic_set(&this_afe.status, 0);
 	this_afe.apr = NULL;
+	this_afe.mmap_handle = 0;
 	for (i = 0; i < AFE_MAX_PORTS; i++)
 		init_waitqueue_head(&this_afe.wait[i]);