Merge "Merge android-4.9.217(d2adeff) into msm-4.9"
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 240bc5b..41c98e3 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -521,6 +521,7 @@
 					in floating state(not LP00 or LP11) to turn on this property. Software
 					turns off PHY pmic power supply, phy ldo and DSI Lane ldo during
 					idle screen (footswitch control off) when this property is enabled.
+- qcom,skip-panel-reset:		Boolean. when set, will skip panel reset during panel ON/OFF.
 [[Optional config sub-nodes]]		These subnodes provide different configurations for a given same panel.
 					Default configuration can be chosen by specifying phandle of the
 					selected subnode in the qcom,config-select.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt
new file mode 100644
index 0000000..4e640e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt
@@ -0,0 +1,52 @@
+Raydium WT030 touch controller
+
+Please add this description here: The Raydium Touch controller is connected to the
+host processor via I2C. The controller generates interrupts when the user touches
+the panel. The host controller is expected to read the touch coordinates over I2C and
+pass the coordinates to the rest of the system.
+
+Required properties:
+
+ - compatible                     : should be "raydium,raydium-ts".
+ - reg                                : i2c slave address of the device.
+ - interrupt-parent               : parent of interrupt.
+ - raydium,irq-gpio               : irq gpio.
+ - raydium,reset-gpio         : reset gpio.
+ - vdd_ana-supply                         : analog voltage power supply needed to power device.
+ - vcc_i2c-supply                         : i2c voltage power supply needed to power device.
+
+Optional property:
+ - raydium,max-num-touches   : addr of ub-i2c.
+ - raydium,display-coords    : array of display coordinates.
+ - raydium,x_max                    : maximal x value of the panel.
+ - raydium,y_max                    : maximal y value of the panel.
+ - raydium,fw_id             : firmare id.
+ - raydium,soft-reset-delay-ms    : reset delay for controller (ms), default 100.
+ - raydium,hard-reset-delay-ms    : reset delay for controller (ms), default 100.
+
+Example:
+       i2c@78b7000 {
+               status = "ok";
+               raydium_ts@39 {
+                       compatible = "raydium,raydium-ts";
+                       reg = <0x39>;
+                       interrupt-parent = <&msm_gpio>;
+                       interrupts = <13 0x2008>;
+                       vdd_ana-supply = <&pm8916_l17>;
+                       vcc_i2c-supply = <&pm8916_l6>;
+                       pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release";
+                       pinctrl-0 = <&ts_int_active &ts_reset_active>;
+                       pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+                       pinctrl-2 = <&ts_release>;
+                       raydium,reset-gpio = <&msm_gpio 12 0x00>;
+                       raydium,irq-gpio = <&msm_gpio 13 0x00>;
+                       raydium,num-max-touches = <2>;
+                       raydium,soft-reset-delay-ms = <50>;
+                       raydium,hard-reset-delay-ms = <100>;
+                       raydium,x_max = <390>;
+                       raydium,y_max = <390>;
+                       raydium,display-coords= <0  0 390 390>;
+                       raydium,fw_id = <0x2202>
+               };
+       };
+
diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts
index 2eaca02..a14ad6f 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts
+++ b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, 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
@@ -58,3 +58,7 @@
 &mhi_net_device {
 	status = "okay";
 };
+
+&sdx_ext_ipc {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi b/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi
index 91ebc96..a1649bb 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi
+++ b/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi
@@ -146,6 +146,15 @@
 		gpio = <&tlmm 23 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	sdx_ext_ipc: qcom,sdx_ext_ipc {
+		compatible = "qcom,sdx-ext-ipc";
+		qcom,ap2mdm-status-gpio = <&tlmm 95 0x00>;
+		qcom,mdm2ap-status-gpio = <&tlmm 36 0x00>;
+		qcom,mdm2ap-status2-gpio = <&tlmm 88 0x00>;
+		status = "disabled";
+	};
+
 };
 
 &emac_hw {
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
index 1e4c7231..7d91330 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
@@ -20,6 +20,26 @@
 	compatible = "qcom,sa415m-ttp",
 		"qcom,sdxpoorwills", "qcom,ttp";
 	qcom,board-id = <30 0x102>;
+
+	qcom_gadget {
+		compatible = "qcom,usb-gadget";
+		qcom,vid = <0x05c6>;
+
+		composition1 {
+			qcom,pid = <0x9103>;
+			qcom,composition = "diag.diag,ipc.ipc,gsi.rmnet,gsi.rmnet.v2x,ecm.ecm,gsi.dpl";
+		};
+
+		composition2 {
+			qcom,pid = <0x9105>;
+			qcom,composition = "diag.diag,gsi.dpl";
+		};
+
+		composition3 {
+			qcom,pid = <0x9107>;
+			qcom,composition = "diag.diag,ipc.ipc,gsi.rmnet.v2x,gsi.ecm,gsi.dpl";
+		};
+	};
 };
 
 &blsp1_uart2b_hs {
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
index 289c539c..e0b4b6f 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
@@ -147,6 +147,7 @@
 	       interrupt-parent = <&tlmm>;
 	       interrupts = <78 IRQ_TYPE_EDGE_RISING>;
 	       st,drdy-int-pin= <2>;
+	       qcom,asm330_hrtimer;
 	};
 };
 
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index 23149f0..96e2d66 100755
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -226,11 +226,15 @@
 CONFIG_CHR_DEV_SCH=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
 CONFIG_DM_UEVENT=y
 CONFIG_DM_VERITY=y
 CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_ANDROID_VERITY=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
@@ -255,6 +259,10 @@
 CONFIG_KEYBOARD_MATRIX=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_STMVL53L0X=y
@@ -492,9 +500,11 @@
 CONFIG_CRYPTO_ANSI_CPRNG=y
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
 CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
 CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem"
 CONFIG_ARM_CRYPTO=y
 CONFIG_CRYPTO_SHA1_ARM_NEON=y
 CONFIG_CRYPTO_SHA2_ARM_CE=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 9ce2354..f8f04b9 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -239,12 +239,16 @@
 CONFIG_SCSI_UFS_QCOM_ICE=y
 CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
 CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_DEBUG=y
 CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
 CONFIG_DM_UEVENT=y
 CONFIG_DM_VERITY=y
 CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_ANDROID_VERITY=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
@@ -272,6 +276,10 @@
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_JOYSTICK_XPAD=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_STMVL53L0X=y
@@ -500,6 +508,7 @@
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_ANDROID_BINDER_IPC_32BIT=y
+CONFIG_STM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT2_FS=y
@@ -573,19 +582,6 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
-CONFIG_CORESIGHT_SINK_TPIU=y
-CONFIG_CORESIGHT_SOURCE_ETM3X=y
-CONFIG_CORESIGHT_REMOTE_ETM=y
-CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
-CONFIG_CORESIGHT_QCOM_REPLICATOR=y
-CONFIG_CORESIGHT_DBGUI=y
-CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_TPDA=y
-CONFIG_CORESIGHT_TPDM=y
-CONFIG_CORESIGHT_CTI=y
-CONFIG_CORESIGHT_EVENT=y
-CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_LSM_MMAP_MIN_ADDR=4096
@@ -604,6 +600,7 @@
 CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
 CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem"
 CONFIG_ARM_CRYPTO=y
 CONFIG_CRYPTO_SHA1_ARM_NEON=y
 CONFIG_CRYPTO_SHA2_ARM_CE=y
diff --git a/arch/arm/configs/sa415m-perf_defconfig b/arch/arm/configs/sa415m-perf_defconfig
index ab40fe1..192094e 100644
--- a/arch/arm/configs/sa415m-perf_defconfig
+++ b/arch/arm/configs/sa415m-perf_defconfig
@@ -224,11 +224,12 @@
 CONFIG_PPPOL2TP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
-CONFIG_CNSS2=y
+CONFIG_CNSS2=m
 CONFIG_CNSS2_DEBUG=y
 CONFIG_CNSS2_QMI=y
 CONFIG_CLD_HL_SDIO_CORE=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_UTILS=y
 CONFIG_CNSS_GENL=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
@@ -374,6 +375,7 @@
 CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_BOOT_TIME_MARKER=y
+CONFIG_SDX_EXT_IPC=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
diff --git a/arch/arm/configs/sa415m_defconfig b/arch/arm/configs/sa415m_defconfig
index f6be866..96e21cc 100644
--- a/arch/arm/configs/sa415m_defconfig
+++ b/arch/arm/configs/sa415m_defconfig
@@ -225,11 +225,12 @@
 CONFIG_PPPOL2TP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
-CONFIG_CNSS2=y
+CONFIG_CNSS2=m
 CONFIG_CNSS2_DEBUG=y
 CONFIG_CNSS2_QMI=y
 CONFIG_CLD_HL_SDIO_CORE=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_UTILS=y
 CONFIG_CNSS_GENL=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
@@ -391,6 +392,7 @@
 CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_BOOT_TIME_MARKER=y
+CONFIG_SDX_EXT_IPC=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
diff --git a/arch/arm/configs/sdm429-bg-perf_defconfig b/arch/arm/configs/sdm429-bg-perf_defconfig
index 3b6ff05..bbb4c4e 100644
--- a/arch/arm/configs/sdm429-bg-perf_defconfig
+++ b/arch/arm/configs/sdm429-bg-perf_defconfig
@@ -284,6 +284,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
 CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_QTI_HAPTICS=y
diff --git a/arch/arm/configs/sdm429-bg_defconfig b/arch/arm/configs/sdm429-bg_defconfig
index c76c09b..6c345f7 100644
--- a/arch/arm/configs/sdm429-bg_defconfig
+++ b/arch/arm/configs/sdm429-bg_defconfig
@@ -289,6 +289,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
 CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_QTI_HAPTICS=y
@@ -574,6 +575,7 @@
 CONFIG_DEBUG_OBJECTS_WORK=y
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
 CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index a9df306..f6df01c 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -607,7 +607,9 @@
 	sdw3100-msm8909w-1gb-wtp.dtb \
 	sdw2500-apq8009w-wtp.dtb \
 	sdw2500-msm8909w-wtp.dtb \
-	msm8905-qrd-skub_qseev4.dtb
+	msm8905-qrd-skub_qseev4.dtb \
+	msm8909-mtp.dtb \
+	msm8909-1gb-mtp.dtb
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index d654bf8..763aa9b 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -19,7 +19,6 @@
 #include "apq8009-audio-external_codec.dtsi"
 #include "msm8909-pm8916-camera.dtsi"
 #include "msm8909-pm8916-camera-sensor-robot-som.dtsi"
-#include "dsi-panel-osd-disp-fwvga-video.dtsi"
 #include "dsi-panel-ili9806e-fwvga-video.dtsi"
 
 / {
@@ -397,10 +396,6 @@
 	status = "okay";
 };
 
-&dsi_osd_disp_fwvga_video {
-	qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;
-};
-
 &dsi_ili9806e_fwvga_video {
 	qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
@@ -427,15 +422,17 @@
 };
 
 &mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_osd_disp_fwvga_video>;
+	qcom,dsi-pref-prim-pan = <&dsi_ili9806e_fwvga_video>;
 
 	pinctrl-names = "mdss_default", "mdss_sleep";
 	pinctrl-0 = <&mdss_dsi_active &mdss_dsi_select_gpio>;
 	pinctrl-1 = <&mdss_dsi_suspend &mdss_dsi_select_gpio>;
 
+	qcom,platform-te-gpio = <&msm_gpio 24 0>;
 	qcom,platform-reset-gpio = <&msm_gpio 28 0>;
 	qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
 
+	/delete-property/ qcom,platform-enable-gpio;
 	vdd-supply = <&pm8916_l17>;
 	vddio-supply = <&pm8916_l6>;
 	status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi
new file mode 100644
index 0000000..ca83d82
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi
@@ -0,0 +1,78 @@
+/* Copyright (c) 2014-2015, 2020, 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.
+ */
+
+&mdss_mdp {
+	dsi_hx8394d_720_vid: qcom,mdss_dsi_hx8394d_720p_video {
+		qcom,mdss-dsi-panel-name = "hx8394d 720p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <52>;
+		qcom,mdss-dsi-h-back-porch = <100>;
+		qcom,mdss-dsi-h-pulse-width = <24>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <20>;
+		qcom,mdss-dsi-v-front-porch = <8>;
+		qcom,mdss-dsi-v-pulse-width = <4>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 b9 ff 83 94
+				39 01 00 00 00 00 03 ba 33 83
+				39 01 00 00 00 00 10 b1 6c 12 12 37 04 11 f1 80 ec 94 23 80 c0 d2 18
+				39 01 00 00 00 00 0c b2 00 64 0e 0d 32 23 08 08 1c 4d 00
+				39 01 00 00 00 00 0d b4 00 ff 03 50 03 50 03 50 01 6a 01 6a
+				39 01 00 00 00 00 02 bc 07
+				39 01 00 00 00 00 04 bf 41 0e 01
+				39 01 00 00 00 00 1f d3 00 07 00 00 00 10 00 32 10 05 00 00 32 10 00 00 00 32 10 00 00 00 36 03 09 09 37 00 00 37
+				39 01 00 00 00 00 2d d5 02 03 00 01 06 07 04 05 20 21 22 23 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 24 25 18 18 19 19
+				39 01 00 00 00 00 2d d6 05 04 07 06 01 00 03 02 23 22 21 20 18 18 18 18 18 18 58 58 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 25 24 19 19 18 18
+				39 01 00 00 00 00 02 cc 09
+				39 01 00 00 00 00 03 c0 30 14
+				39 01 00 00 00 00 05 c7 00 c0 40 c0
+				39 01 00 00 00 00 03 b6 43 43
+				05 01 00 00 c8 00 02 11 00
+				05 01 00 00 0a 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 00 00 02 28 00
+				05 01 00 00 00 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [79 1a 12 00 3e 42 16 1e 15 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
+		qcom,mdss-pan-physical-width-dimension = <59>;
+		qcom,mdss-pan-physical-height-dimension = <104>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi b/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi
index c13c031..51b7d78 100644
--- a/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi
@@ -17,8 +17,17 @@
 		qcom,pin-func = <2>;
 		label = "SY7807_pins";
 		SY7807_default: en_default {
-		drive-strength = <2>;
-		bias-pull-down;
+			mux {
+				pins = "gpio32";
+				function = "gpio";
+			};
+
+			configs {
+				pins = "gpio32";
+				drive-strength = <0x2>;
+				bias-pull-down;
+			};
+
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi b/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi
index a94f887..0e2d39f 100644
--- a/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi
@@ -231,9 +231,30 @@
 };
 
 &soc {
+	qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+		msm_audio_apr_dummy {
+			compatible = "qcom,msm-audio-apr-dummy";
+		};
+	};
+
+	qcom,avtimer@c0a300c {
+		compatible = "qcom,avtimer";
+		reg = <0x0c0a300c 0x4>,
+			<0x0c0a3010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <27>;
+	};
+
 	sound {
-		compatible = "qcom,msm8x16-audio-codec";
+		compatible = "qcom,msm8952-audio-codec";
 		qcom,model = "msm8909-skub-snd-card";
+		reg = <0x7702000 0x4>,
+		      <0x7702004 0x4>,
+		      <0x7702008 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel";
 		qcom,msm-snd-card-id = <0>;
 		qcom,msm-codec-type = "internal";
 		qcom,msm-ext-pa = "primary";
@@ -251,23 +272,24 @@
 			"MIC BIAS Internal2", "Headset Mic",
 			"AMIC1", "MIC BIAS Internal1",
 			"AMIC2", "MIC BIAS Internal2";
-		pinctrl-names = "cdc_lines_act",
-				"cdc_lines_sus";
-		pinctrl-0 = <&cdc_pdm_lines_act>;
-		pinctrl-1 = <&cdc_pdm_lines_sus>;
-		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>,
+				<&voip>, <&voice>,
 				<&loopback>, <&compress>, <&hostless>,
-				<&afe>, <&lsm>, <&routing>, <&lpa>,
-				<&voice_svc>;
+				<&afe>, <&lsm>, <&routing>, <&pcm_noirq>;
 		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2",
 				"msm-voip-dsp", "msm-pcm-voice",
 				"msm-pcm-loopback", "msm-compress-dsp",
 				"msm-pcm-hostless", "msm-pcm-afe",
 				"msm-lsm-client", "msm-pcm-routing",
-				"msm-pcm-lpa", "msm-voice-svc";
+				"msm-pcm-dsp-noirq";
 		asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>,
 				<&dai_mi2s0>, <&dai_mi2s1>,
 				<&dai_mi2s2>, <&dai_mi2s3>,
+				<&dai_mi2s4>, <&dai_mi2s5>,
 				<&sb_0_rx>, <&sb_0_tx>,
 				<&sb_1_rx>, <&sb_1_tx>,
 				<&sb_3_rx>, <&sb_3_tx>,
@@ -281,6 +303,7 @@
 		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
 				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
 				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
 				"msm-dai-q6-dev.16384",	"msm-dai-q6-dev.16385",
 				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
 				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
@@ -292,8 +315,17 @@
 				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
 				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
 				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
-		asoc-codec = <&stub_codec>, <&pm8909_conga_dig>;
-		asoc-codec-names = "msm-stub-codec.1", "tombak_codec";
+		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+				<&pmic_analog_codec>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+				"analog-codec";
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_lines_act>;
+		pinctrl-1 = <&cdc_pdm_lines_sus>;
 	};
 
 	spi@78b9000 { /* BLSP1 QUP5 */
@@ -344,6 +376,82 @@
 	};
 };
 
+&pm8909_1 {
+	pmic_analog_codec: analog-codec@f100 {
+		status = "okay";
+		compatible = "qcom,pmic-analog-codec";
+		reg = <0xf000 0x200>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts =
+			<0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+		interrupt-names =
+			"spk_cnp_int",
+			"spk_clip_int",
+			"spk_ocp_int",
+			"ins_rem_det1",
+			"but_rel_det",
+			"but_press_det",
+			"ins_rem_det",
+			"mbhc_int",
+			"ear_ocp_int",
+			"hphr_ocp_int",
+			"hphl_ocp_det",
+			"ear_cnp_int",
+			"hphr_cnp_int",
+			"hphl_cnp_int";
+
+		cdc-vdda-cp-supply = <&pm8909_s2>;
+		qcom,cdc-vdda-cp-voltage = <1800000 2200000>;
+		qcom,cdc-vdda-cp-current = <500000>;
+
+		cdc-vdda-h-supply = <&pm8909_l5>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <5000>;
+
+		cdc-vdd-px-supply = <&pm8909_l5>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <5000>;
+
+		cdc-vdd-pa-supply = <&pm8909_s2>;
+		qcom,cdc-vdd-pa-voltage = <1800000 2200000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8909_l13>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <5000>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-static-supplies =
+					"cdc-vdda-h",
+					"cdc-vdd-px",
+					"cdc-vdd-pa",
+					"cdc-vdda-cp";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+		msm_digital_codec: msm-dig-codec@f000 {
+			compatible = "qcom,msm-digital-codec";
+			reg = <0x771c000 0x100>;
+		};
+	};
+};
+
 &pm8909_mpps {
 	mpp@a100 { /* MPP 2 */
 		/* Backlight PWM */
@@ -406,12 +514,13 @@
 
 &pm8909_gpios {
 	/* GPIO 2 (NFC_CLK_REQ) */
-	gpio@c100 {
-		qcom,mode = <0>;
-		qcom,vin-sel = <1>;
-		qcom,src-sel = <0>;
-		qcom,master-en = <1>;
-		status = "okay";
+	nfc-clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio2";
+			function = "normal";
+			input-enable;
+			power-source = <1>;
+		};
 	};
 };
 
@@ -430,7 +539,8 @@
 		interrupts = <21 0>;
 		interrupt-names = "nfc_irq";
 		pinctrl-names = "nfc_active", "nfc_suspend";
-		pinctrl-0 = <&nfc_int_active &nfc_disable_active>;
+		pinctrl-0 = <&nfc_int_active &nfc_disable_active
+				&nfc_clk_default>;
 		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
 		clocks = <&clock_rpm clk_bb_clk2_pin>;
 		clock-names = "ref_clk";
@@ -456,3 +566,11 @@
 &actuator0 {
 	status = "disabled";
 };
+
+&pm8909_conga_dig {
+	status = "disabled";
+};
+
+&pm8909_conga_analog {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts b/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts
new file mode 100644
index 0000000..4d52997
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2016,2018, 2020, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909-pm8909.dtsi"
+#include "msm8909-pm8909-mtp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB MTP";
+	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
+	qcom,board-id= <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi
index 0a657da..15f0c31 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 2020, 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
@@ -11,6 +11,7 @@
  */
 
 #include "dsi-panel-390p-auo-cmd.dtsi"
+#include "dsi-panel-hx8394d-720p-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dts b/arch/arm64/boot/dts/qcom/msm8909-mtp.dts
new file mode 100644
index 0000000..a4ca87a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2014-2015, 2020, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909-pm8909.dtsi"
+#include "msm8909-pm8909-mtp.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8909-PM8909 MTP";
+	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
+	qcom,board-id= <8 0x100>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
index 48448862..5b4fd6d 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 2020, 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
@@ -71,7 +71,7 @@
 
 	i2c@78b9000 { /* BLSP1 QUP5 */
 		synaptics@20 {
-			compatible = "synaptics,dsx";
+			compatible = "synaptics,dsx-i2c";
 			reg = <0x20>;
 			interrupt-parent = <&msm_gpio>;
 			interrupts = <13 0x2008>;
@@ -84,10 +84,16 @@
 			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
 			pinctrl-2 = <&ts_release>;
 			synaptics,irq-gpio = <&msm_gpio 13 0x2008>;
+			synaptics,irq-on-state = <0>;
+			synaptics,irq-flags = <0x2008>;
+
 			synaptics,reset-gpio = <&msm_gpio 12 0x0>;
-			synaptics,disable-gpios;
-			synaptics,display-coords = <0 0 719 1279>;
-			synaptics,panel-coords = <0 0 719 1405>;
+			synaptics,reset-on-state = <0>;
+			synaptics,reset-active-ms = <20>;
+			synaptics,cap-button-codes = <139 158 172>;
+			/delete-property/ synaptics,disable-gpios;
+			/delete-property/ synaptics,display-coords;
+			/delete-property/ synaptics,panel-coords;
 		};
 	};
 
@@ -110,6 +116,16 @@
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "synaptics_dsx_i2c";
+		qcom,disp-maxx = <719>;
+		qcom,disp-maxy = <1279>;
+		qcom,panel-maxx = <719>;
+		qcom,panel-maxy = <1405>;
+		qcom,key-codes = <158 139 172 217>;
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
@@ -326,6 +342,13 @@
 	qcom,mdss-pref-prim-intf = "dsi";
 };
 
+&dsi_hx8394d_720_vid {
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
 &msm_gpio {
 	pmx_mdss {
 		mdss_dsi_active: mdss_dsi_active {
@@ -412,3 +435,13 @@
 		};
 	};
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8394d_720_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-reset-gpio = <&msm_gpio 25 0>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi
new file mode 100644
index 0000000..b67b712
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014-2015, 2017, 2020, 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.
+ */
+
+&pm8909_chg {
+	status = "ok";
+	qcom,charging-disabled;
+};
+
+&pm8909_bms {
+	status = "ok";
+	qcom,battery-data = <&mtp_batterydata>;
+	qcom,batt-aging-comp;
+};
+
+&usb_otg {
+	extcon = <&pm8909_chg>;
+};
+
+&dsi_hx8394d_720_vid {
+	qcom,cont-splash-enabled;
+	qcom,mdss-dsi-pwm-gpio = <&pm8909_mpps 4 0>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&spmi_bus {
+	qcom,pm8909@0 {
+		qcom,leds@a300 {
+			status = "okay";
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "manual";
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
+	qcom,pm8909@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
+};
+
+&pm8909_mpps {
+	mpp@a000 { /* MPP 1 */
+		/* VDD_PX */
+		status = "disabled";
+	};
+
+	mpp@a100 { /* MPP 2 */
+		/* Backlight PWM */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,invert = <0>;		/* Disable invert */
+		qcom,src-sel = <4>;		/* DTEST1 */
+		qcom,vin-sel = <0>;		/* VPH_PWR */
+		qcom,master-en = <1>;		/* Enable MPP */
+	};
+
+	mpp@a200 { /* MPP 3 */
+		/* VREF DAC */
+		status = "disabled";
+	};
+
+	mpp@a300 { /* MPP 4 */
+		/* HR LED */
+		status = "disabled";
+	};
+};
+
+&pm8909_gpios {
+	gpio@c000 { /* GPIO 1 */
+		/* Battery UICC Alarm */
+		status = "disabled";
+	};
+
+	gpio@c100 { /* GPIO 2 */
+		/* NFC_CLK_REQ */
+		qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+		qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+		qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		/* External regulator control for WTR */
+		status = "disabled";
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		/* External regulator control for APC */
+		status = "disabled";
+	};
+};
+
+&audio_codec_mtp {
+	qcom,msm-micbias2-ext-cap;
+};
+
+&spk_vreg {
+	status = "okay";
+};
+
+&pm8909_conga_dig {
+	cdc-vdd-spkdrv-supply = <&spk_vreg>;
+	qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+	qcom,cdc-vdd-spkdrv-current = <20000>;
+	qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias",
+				      "cdc-vdd-spkdrv";
+	qcom,subsys-name = "modem";
+};
+
+&wcnss {
+	qcom,wcnss-vadc = <&pm8909_vadc>;
+};
+
+&soc {
+	i2c@78b6000 {
+		nq@28 {
+			qcom,nq-clkreq = <&pm8909_gpios 2 0>;
+		};
+	};
+};
+
+&mdss_dsi {
+	vdda-supply = <&pm8909_l2>;
+	vddio-supply = <&pm8909_l6>;
+	qcom,mdss_dsi_ctrl0@1ac8000 {
+		vdd-supply = <&pm8909_l17>;
+		vddio-supply = <&pm8909_l6>;
+	};
+};
+
+&vendor_fstab {
+	status = "disabled";
+};
+
+&system_fstab {
+	status = "disabled";
+};
+
+&dsi_hx8394d_720_vid {
+	qcom,cont-splash-enabled;
+	qcom,mdss-dsi-pwm-gpio = <&pm8909_mpps 4 0>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi
index 86bee6e..626172e 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 2020, 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
@@ -78,6 +78,12 @@
 	};
 };
 
+&dsi_hx8394d_720_vid {
+	qcom,cont-splash-enabled;
+	qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
 &spmi_bus {
 	pm8916@0 {
 		qcom,leds@a300 {
@@ -185,3 +191,11 @@
 		};
 	};
 };
+
+&vendor_fstab {
+	status = "disabled";
+};
+
+&system_fstab {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 3f3c8da..d21f39e 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, 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
@@ -51,7 +51,7 @@
 };
 
 &pil_gpu_mem {
-	reg = <0 0x90f15000 0 0x2000>;
+	reg = <0 0x90f15000 0 0x4000>;
 };
 
 &adsp_mem {
diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
index d179b7b..39c1847 100644
--- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
@@ -148,6 +148,9 @@
 &mdss_dsi0 {
 	qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>;
 	/delete-property/ vdd-supply;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_te_active>;
+	pinctrl-1 = <&mdss_te_suspend>;
 	vddio-supply = <&L11A>;
 	qcom,platform-enable-gpio = <&pm660_gpios 12 0>;
 };
@@ -156,6 +159,36 @@
 	/delete-node/ qcom,panel-supply-entry@0;
 };
 
+&i2c_4 {
+	status = "ok";
+	tsc@24 {
+		status = "disabled";
+	};
+
+	raydium_ts@39 {
+		compatible = "raydium,raydium-ts";
+		reg = <0x39>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <13 0x2008>;
+		vdd_ana-supply = <&pm660_l11>;
+		vcc_i2c-supply = <&pm660_l13>;
+		pinctrl-names = "pmx_ts_active","pmx_ts_suspend",
+					"pmx_ts_release";
+		pinctrl-0 = <&ts_int_active &ts_reset_active>;
+		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+		pinctrl-2 = <&ts_release>;
+		raydium,reset-gpio = <&tlmm 64 0x00>;
+		raydium,irq-gpio = <&tlmm 65 0x00>;
+		raydium,num-max-touches = <2>;
+		raydium,soft-reset-delay-ms = <50>;
+		raydium,hard-reset-delay-ms = <100>;
+		raydium,x_max = <416>;
+		raydium,y_max = <416>;
+		raydium,display-coords= <0  0 416 416>;
+		raydium,fw_id = <0x2202>;
+	};
+};
+
 &usb_otg {
 	HSUSB_3p3-supply = <&L16A>;
 };
@@ -177,3 +210,39 @@
 		};
 	};
 };
+
+&msm_gpu {
+	qcom,initial-pwrlevel = <0>;
+	qcom,gpu-pwrlevels {
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <2>;
+			qcom,bus-min = <2>;
+			qcom,bus-max = <2>;
+		};
+		qcom,gpu-pwrlevel@1{
+			reg = <1>;
+			qcom,gpu-freq = <19200000>;
+			qcom,bus-freq = <0>;
+			qcom,bus-min = <0>;
+			qcom,bus-max = <0>;
+		};
+	};
+};
+
+&msm_cpufreq {
+	qcom,cpufreq-table =
+		<  960000 >,
+		< 1305600 >,
+		< 1497600 >,
+		< 1708800 >;
+};
+
+&cpubw {
+	qcom,bw-tbl =
+		<  1611 /*  211.2 MHz */ >,     /*Low SVS*/
+		<  2929 /*  384   MHz */ >,     /* SVS */
+		<  5053 /*  662.4 MHz */ >,     /* SVS+  */
+		<  5712 /*  748.8 MHz */ >;     /* NOM   */
+};
diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts
index d755b0f..98b8c12 100644
--- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts
+++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts
@@ -24,3 +24,16 @@
 	qcom,board-id = <0x00010b 8>;
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
+
+&msm_gpu {
+	/delete-property/qcom,enable-ca-jump;
+	/delete-property/qcom,ca-busy-penalty;
+	/delete-property/qcom,ca-target-pwrlevel;
+
+	qcom,gpu-pwrlevels {
+		/delete-node/qcom,gpu-pwrlevel@2;
+		/delete-node/qcom,gpu-pwrlevel@3;
+		/delete-node/qcom,gpu-pwrlevel@4;
+		/delete-node/qcom,gpu-pwrlevel@5;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
index 37ff160..2a4a02d2 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
@@ -20,7 +20,7 @@
 	model = "Qualcomm Technologies, Inc. SDM429 QRD BG WDP Overlay";
 	compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd";
 	qcom,msm-id = <416 0x0>;
-	qcom,board-id = <0x01000b 9>;
+	qcom,board-id = <0x00010b 9>;
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts
index d945659..af981b4 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts
@@ -21,6 +21,6 @@
 	model = "Qualcomm Technologies, Inc. SDM429 BG WDP";
 	compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd";
 	qcom,msm-id = <416 0x0>;
-	qcom,board-id = <0x01000b 9>;
+	qcom,board-id = <0x00010b 9>;
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
index 32ae531..a0ea543 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
@@ -149,6 +149,9 @@
 	qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>;
 	/delete-property/ vdd-supply;
 	vddio-supply = <&L11A>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_te_active>;
+	pinctrl-1 = <&mdss_te_suspend>;
 	qcom,platform-enable-gpio = <&pm660_gpios 12 0>;
 };
 
@@ -156,6 +159,36 @@
 	/delete-node/ qcom,panel-supply-entry@0;
 };
 
+&i2c_4 {
+	status = "ok";
+	tsc@24 {
+		status = "disabled";
+	};
+
+	raydium_ts@39 {
+		compatible = "raydium,raydium-ts";
+		reg = <0x39>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <13 0x2008>;
+		vdd_ana-supply = <&pm660_l11>;
+		vcc_i2c-supply = <&pm660_l13>;
+		pinctrl-names = "pmx_ts_active","pmx_ts_suspend",
+					"pmx_ts_release";
+		pinctrl-0 = <&ts_int_active &ts_reset_active>;
+		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+		pinctrl-2 = <&ts_release>;
+		raydium,reset-gpio = <&tlmm 64 0x00>;
+		raydium,irq-gpio = <&tlmm 65 0x00>;
+		raydium,num-max-touches = <2>;
+		raydium,soft-reset-delay-ms = <50>;
+		raydium,hard-reset-delay-ms = <100>;
+		raydium,x_max = <416>;
+		raydium,y_max = <416>;
+		raydium,display-coords= <0  0 416 416>;
+		raydium,fw_id = <0x2202>;
+	};
+};
+
 &usb_otg {
 	HSUSB_3p3-supply = <&L16A>;
 };
@@ -177,3 +210,38 @@
 		};
 	};
 };
+
+&msm_gpu {
+	qcom,initial-pwrlevel = <0>;
+	qcom,gpu-pwrlevels {
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <2>;
+			qcom,bus-min = <2>;
+			qcom,bus-max = <2>;
+		};
+		qcom,gpu-pwrlevel@1{
+			reg = <1>;
+			qcom,gpu-freq = <19200000>;
+			qcom,bus-freq = <0>;
+			qcom,bus-min = <0>;
+			qcom,bus-max = <0>;
+		};
+	};
+};
+
+&msm_cpufreq {
+	qcom,cpufreq-table =
+		<  960000 >,
+		< 1305600 >,
+		< 1497600 >,
+		< 1708800 >;
+};
+&cpubw {
+	qcom,bw-tbl =
+		<  1611 /*  211.2 MHz */ >,     /*Low SVS*/
+		<  2929 /*  384   MHz */ >,     /* SVS */
+		<  5053 /*  662.4 MHz */ >,     /* SVS+  */
+		<  5712 /*  748.8 MHz */ >;     /* NOM   */
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts
index abbbbce..12cea26 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts
@@ -24,3 +24,16 @@
 	qcom,board-id = <0x00010b 8>;
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
+
+&msm_gpu {
+	/delete-property/qcom,enable-ca-jump;
+	/delete-property/qcom,ca-busy-penalty;
+	/delete-property/qcom,ca-target-pwrlevel;
+
+	qcom,gpu-pwrlevels {
+		/delete-node/qcom,gpu-pwrlevel@2;
+		/delete-node/qcom,gpu-pwrlevel@3;
+		/delete-node/qcom,gpu-pwrlevel@4;
+		/delete-node/qcom,gpu-pwrlevel@5;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
index cc06f8a..b3b2d2b 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
@@ -109,4 +109,5 @@
 	qcom,mdss-dsi-panel-status-check-mode = "te_signal_check";
 	qcom,mdss-dsi-power-off-disable;
 	qcom,mdss-dsi-tear-disable;
+	qcom,mdss-skip-panel-reset;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
index 15874ff..0ea1660 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 2020, 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
@@ -71,11 +71,12 @@
 			<&incall_music_2_rx>,
 			<&usb_audio_rx>, <&usb_audio_tx>,
 			<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
-			<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>,
-			<&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>,
-			<&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>,
-			<&dai_quin_tdm_rx_0>, <&dai_quin_tdm_tx_0>,
-			<&afe_loopback_tx>;
+			<&dai_pri_tdm_tx_1>, <&dai_pri_tdm_tx_2>,
+			<&dai_pri_tdm_tx_3>, <&dai_sec_tdm_rx_0>,
+			<&dai_sec_tdm_tx_0>, <&dai_tert_tdm_rx_0>,
+			<&dai_tert_tdm_tx_0>, <&dai_quat_tdm_rx_0>,
+			<&dai_quat_tdm_tx_0>, <&dai_quin_tdm_rx_0>,
+			<&dai_quin_tdm_tx_0>, <&afe_loopback_tx>;
 		asoc-cpu-names = "msm-dai-q6-dp.24608",
 			"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
 			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
@@ -98,11 +99,12 @@
 			"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
 			"msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673",
 			"msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865",
-			"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
-			"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
-			"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913",
-			"msm-dai-q6-tdm.36928", "msm-dai-q6-tdm.36929",
-			"msm-dai-q6-dev.24577";
+			"msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36869",
+			"msm-dai-q6-tdm.36871", "msm-dai-q6-tdm.36880",
+			"msm-dai-q6-tdm.36881", "msm-dai-q6-tdm.36896",
+			"msm-dai-q6-tdm.36897", "msm-dai-q6-tdm.36912",
+			"msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36928",
+			"msm-dai-q6-tdm.36929", "msm-dai-q6-dev.24577";
 	};
 
 	tasha_snd: sound-tasha {
@@ -241,6 +243,40 @@
 		compatible = "qcom,msm-cpe-lsm";
 		qcom,msm-cpe-lsm-id = <3>;
 	};
+
+	pri_tdm_tx: qcom,msm-dai-tdm-pri-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37121>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36865 36867 36869 36871>;
+		qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <1>;
+		qcom,msm-cpudai-tdm-data-delay = <1>;
+		dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36865>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36867>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_2: qcom,msm-dai-q6-tdm-pri-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36869>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_3: qcom,msm-dai-q6-tdm-pri-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36871>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
 };
 
 &slim_aud {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
index 948c51d..670dc4a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, 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
@@ -308,5 +308,84 @@
 				input-enable;
 			};
 		};
+
+		quat_mi2s_sck_active: quat_mi2s_sck_active {
+			mux {
+				pins = "gpio23";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio23";
+				drive-strength = <2>;   /* 2 mA */
+				output-low;
+			};
+		};
+
+		quat_mi2s_sck_sleep: quat_mi2s_sck_sleep {
+			mux {
+				pins = "gpio23";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio23";
+				drive-strength = <2>;   /* 2 mA */
+				pull-down;
+			};
+		};
+
+		quat_mi2s_ws_active: quat_mi2s_ws_active {
+			mux {
+				pins = "gpio24";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio24";
+				drive-strength = <2>;   /* 2 mA */
+				output-low;
+			};
+		};
+
+		quat_mi2s_ws_sleep: quat_mi2s_ws_sleep {
+			mux {
+				pins = "gpio24";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio24";
+				drive-strength = <2>;   /* 2 mA */
+				pull-down;
+			};
+		};
+
+		quat_mi2s_d0_active: quat_mi2s_d0_active {
+			mux {
+				pins = "gpio25";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio25";
+				drive-strength = <2>;   /* 2 mA */
+				bias-disable;
+				input-enable;
+			};
+		};
+
+		quat_mi2s_d0_sleep: quat_mi2s_d0_sleep {
+			mux {
+				pins = "gpio25";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio25";
+				drive-strength = <2>;   /* 2 mA */
+			};
+		};
+
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi b/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi
index bc242b0..40aceac 100644
--- a/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi
@@ -265,6 +265,19 @@
 		};
 	};
 
+	quat_mi2s_gpios: quat_mi2s_pinctrl {
+		status = "ok";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_sck_active
+				 &quat_mi2s_ws_active
+				 &quat_mi2s_d0_active>;
+		pinctrl-1 = <&quat_mi2s_sck_sleep
+				 &quat_mi2s_ws_sleep
+				 &quat_mi2s_d0_sleep>;
+		qcom,lpi-gpios;
+	};
+
 };
 
 
@@ -437,7 +450,7 @@
 };
 
 &tavil_snd {
-	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <0>, <1>;
 	qcom,audio-routing =
 		"AIF4 VI", "MCLK",
 		"RX_BIAS", "MCLK",
@@ -466,6 +479,8 @@
 		"MIC BIAS3", "Digital Mic5",
 		"SpkrLeft IN", "SPK1 OUT",
 		"SpkrRight IN", "SPK2 OUT";
+
+	qcom,quat-mi2s-gpios = <&quat_mi2s_gpios>;
 	qcom,msm-mbhc-hphl-swh = <1>;
 	qcom,msm-mbhc-gnd-swh = <1>;
 	qcom,hph-en0-gpio = <&tavil_hph_en0>;
@@ -493,3 +508,13 @@
 &pm660_charger {
 	qcom,ufp-only-mode;
 };
+
+&dai_mi2s3 {
+	qcom,msm-mi2s-rx-lines = <0>;
+	qcom,msm-mi2s-tx-lines = <1>;
+
+};
+
+&cdc_pdm_gpios {
+	status = "disabled";
+};
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 2d39856..c285875 100755
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -253,6 +253,9 @@
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QCOM_XR_SMRTVWR_MISC=y
+CONFIG_TUSB1064_XR_MISC=y
+CONFIG_VXR200_XR_MISC=y
 CONFIG_QSEECOM=y
 CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index ccfcf65..70b4d60 100755
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -262,6 +262,9 @@
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QCOM_XR_SMRTVWR_MISC=y
+CONFIG_TUSB1064_XR_MISC=y
+CONFIG_VXR200_XR_MISC=y
 CONFIG_QSEECOM=y
 CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c
index 66cb2a9..1b81eb8 100644
--- a/drivers/bus/mhi/core/mhi_main.c
+++ b/drivers/bus/mhi/core/mhi_main.c
@@ -1285,6 +1285,10 @@
 			local_rp->ptr, local_rp->dword[0], local_rp->dword[1]);
 
 		chan = MHI_TRE_GET_EV_CHID(local_rp);
+		if (chan >= mhi_cntrl->max_chan) {
+			MHI_ERR("invalid channel id %u\n", chan);
+			continue;
+		}
 		mhi_chan = &mhi_cntrl->mhi_chan[chan];
 
 		if (likely(type == MHI_PKT_TYPE_TX_EVENT)) {
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 548bd58..2a3b46b 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, 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
@@ -3133,6 +3133,7 @@
 		kfree(new_entry);
 		new_entry = NULL;
 	}
+	put_task_struct(current);
 	mutex_unlock(&driver->dci_mutex);
 	return DIAG_DCI_NO_REG;
 }
diff --git a/drivers/clk/msm/clock-gcc-8909.c b/drivers/clk/msm/clock-gcc-8909.c
index d96a398..caeb55a 100644
--- a/drivers/clk/msm/clock-gcc-8909.c
+++ b/drivers/clk/msm/clock-gcc-8909.c
@@ -817,6 +817,7 @@
 };
 
 static struct clk_freq_tbl ftbl_gcc_camss_gp0_1_clk[] = {
+	F(   150000,	xo,	1,	1,	128),
 	F( 100000000,	gpll0,	8,	0,	0),
 	F( 200000000,	gpll0,	4,	0,	0),
 	F_END
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index 6732ebe..98a1ecd 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 2020, 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
@@ -714,12 +714,24 @@
 	},
 };
 
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+	F(144000, P_BI_TCXO, 16, 3, 25),
+	F(400000, P_BI_TCXO, 12, 1, 4),
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3),
+	F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
 	.cmd_rcgr = 0xf00c,
 	.mnd_width = 8,
 	.hid_width = 5,
 	.parent_map = gcc_parent_map_0,
-	.freq_tbl = ftbl_gcc_gp1_clk_src,
+	.freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_sdcc1_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a5deca6..811316c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1169,77 +1169,77 @@
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
 		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9,},
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 94 - 3840x2160p@25Hz 16:9 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
 		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 95 - 3840x2160p@30Hz 16:9 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
 		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 96 - 3840x2160p@50Hz 16:9 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
 		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 97 - 3840x2160p@60Hz 16:9 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
 		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 98 - 4096x2160p@24Hz 256:135 */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
 		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
 	/* 99 - 4096x2160p@25Hz 256:135 */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
 		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
 	/* 100 - 4096x2160p@30Hz 256:135 */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
 		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
 	/* 101 - 4096x2160p@50Hz 256:135 */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
 		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
 	/* 102 - 4096x2160p@60Hz 256:135 */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
 		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
 	/* 103 - 3840x2160p@24Hz 64:27 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
 		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 	/* 104 - 3840x2160p@25Hz 64:27 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
 		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 	/* 105 - 3840x2160p@30Hz 64:27 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
 		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 	/* 106 - 3840x2160p@50Hz 64:27 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
 		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 	/* 107 - 3840x2160p@60Hz 64:27 */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
 		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
 		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 };
 
 /*
@@ -4313,11 +4313,11 @@
 	 * modes and forbids YCRCB422 support for all video modes per
 	 * HDMI 1.3 spec.
 	 */
-	info->color_formats = DRM_COLOR_FORMAT_RGB444;
+	info->color_formats |= DRM_COLOR_FORMAT_DC_RGB444;
 
 	/* YCRCB444 is optional according to spec. */
 	if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
-		info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
+		info->color_formats |= DRM_COLOR_FORMAT_DC_YCRCB444;
 		DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
 			  connector->name);
 	}
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 97387cf..615c85a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -997,6 +997,7 @@
 	    mode1->vsync_end == mode2->vsync_end &&
 	    mode1->vtotal == mode2->vtotal &&
 	    mode1->vscan == mode2->vscan &&
+	    mode1->picture_aspect_ratio == mode2->picture_aspect_ratio &&
 	    (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
 	     (mode2->flags & ~DRM_MODE_FLAG_3D_MASK))
 		return true;
@@ -1506,6 +1507,27 @@
 	out->vrefresh = in->vrefresh;
 	out->flags = in->flags;
 	out->type = in->type;
+	out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
+
+	switch (in->picture_aspect_ratio) {
+	case HDMI_PICTURE_ASPECT_4_3:
+		out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
+		break;
+	case HDMI_PICTURE_ASPECT_16_9:
+		out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
+		break;
+	case HDMI_PICTURE_ASPECT_64_27:
+		out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
+		break;
+	case DRM_MODE_PICTURE_ASPECT_256_135:
+		out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
+		break;
+	case HDMI_PICTURE_ASPECT_RESERVED:
+	default:
+		out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
+		break;
+	}
+
 	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
 	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
@@ -1551,6 +1573,27 @@
 	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
 	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 
+	/* Clearing picture aspect ratio bits from out flags */
+	out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
+
+	switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
+	case DRM_MODE_FLAG_PIC_AR_4_3:
+		out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3;
+		break;
+	case DRM_MODE_FLAG_PIC_AR_16_9:
+		out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9;
+		break;
+	case DRM_MODE_FLAG_PIC_AR_64_27:
+		out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27;
+		break;
+	case DRM_MODE_FLAG_PIC_AR_256_135:
+		out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135;
+		break;
+	default:
+		out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
+		break;
+	}
+
 	out->status = drm_mode_validate_basic(out);
 	if (out->status != MODE_OK)
 		goto out;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 4da21d9..6b83368 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, 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
@@ -51,4 +51,6 @@
 int dp_display_get_num_of_displays(void);
 int dp_display_get_displays(void **displays, int count);
 bool dp_connector_mode_needs_full_range(void *display);
+enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn,
+	void *data);
 #endif /* _DP_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 5b78218..fdd40a7 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, 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
@@ -26,6 +26,11 @@
 
 #define to_dp_bridge(x)     container_of((x), struct dp_bridge, base)
 
+enum dp_connector_hdr_state {
+	HDR_DISABLE,
+	HDR_ENABLE
+};
+
 static void convert_to_dp_mode(const struct drm_display_mode *drm_mode,
 			struct dp_display_mode *dp_mode, struct dp_display *dp)
 {
@@ -384,6 +389,38 @@
 	return false;
 }
 
+enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn,
+	void *data)
+{
+	struct dp_display *display = data;
+	struct sde_connector_state *c_state;
+	struct drm_msm_ext_hdr_metadata *hdr_meta;
+
+	if (!display || !conn) {
+		pr_err("invalid input\n");
+		goto error;
+	}
+
+	c_state = to_sde_connector_state(conn->state);
+
+	if (!c_state) {
+		pr_err("invalid input\n");
+		goto error;
+	}
+
+	hdr_meta = &c_state->hdr_meta;
+
+	if ((hdr_meta->hdr_state == HDR_ENABLE)
+		&& (hdr_meta->eotf != 0))
+		return SDE_CSC_RGB2YUV_2020L;
+	else if (dp_connector_mode_needs_full_range(data)
+		|| conn->yuv_qs)
+		return SDE_CSC_RGB2YUV_601FR;
+
+error:
+	return SDE_CSC_RGB2YUV_601L;
+}
+
 enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
 		bool force,
 		void *display)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index efd6a77..25523b0 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -53,12 +53,16 @@
  */
 /* Enable RGB444 30 bit deep color */
 #define MSM_MODE_FLAG_RGB444_DC_ENABLE		(1<<5)
+/* Enable YUV422 30 bit deep color */
+#define MSM_MODE_FLAG_YUV422_DC_ENABLE		(1<<6)
 /* Enable YUV420 30 bit deep color */
-#define MSM_MODE_FLAG_YUV420_DC_ENABLE		(1<<6)
+#define MSM_MODE_FLAG_YUV420_DC_ENABLE		(1<<7)
 /* Choose RGB444 format to display */
-#define MSM_MODE_FLAG_COLOR_FORMAT_RGB444	(1<<7)
+#define MSM_MODE_FLAG_COLOR_FORMAT_RGB444	(1<<8)
+/* Choose YUV422 format to display */
+#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422	(1<<9)
 /* Choose YUV420 format to display */
-#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420	(1<<8)
+#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420	(1<<10)
 
 /* As there are different display controller blocks depending on the
  * snapdragon version, the kms support is split out and the appropriate
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 9fba20f..2d2f352 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2020, 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
@@ -724,6 +724,28 @@
 	return rc;
 }
 
+enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn)
+{
+	struct sde_connector *c_conn;
+
+	if (!conn) {
+		SDE_ERROR("invalid argument\n");
+		return -EINVAL;
+	}
+
+	c_conn = to_sde_connector(conn);
+
+	if (!c_conn->display) {
+		SDE_ERROR("invalid argument\n");
+		return -EINVAL;
+	}
+
+	if (!c_conn->ops.get_csc_type)
+		return SDE_CSC_RGB2YUV_601L;
+
+	return c_conn->ops.get_csc_type(conn, c_conn->display);
+}
+
 bool sde_connector_mode_needs_full_range(struct drm_connector *connector)
 {
 	struct sde_connector *c_conn;
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 87c2ee2..2543822 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2020, 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
@@ -198,6 +198,15 @@
 	 * @enable: State of clks
 	 */
 	int (*clk_ctrl)(void *handle, u32 type, u32 state);
+	/**
+	 * get_csc_type - returns the CSC type to be used
+	 * by the CDM block based on HDR state
+	 * @connector: Pointer to drm connector structure
+	 * @display: Pointer to private display structure
+	 * Returns: type of CSC matrix to be used
+	 */
+	enum sde_csc_type (*get_csc_type)(struct drm_connector *connector,
+		void *display);
 
 	/**
 	 * set_power - update dpms setting
@@ -719,6 +728,14 @@
 bool sde_connector_mode_needs_full_range(struct drm_connector *connector);
 
 /**
+ * sde_connector_get_csc_type - query csc type
+ * to be used for the connector
+ * @connector: Pointer to drm connector object
+ * Returns: csc type based on connector HDR state
+ */
+enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn);
+
+/**
  * sde_connector_get_dither_cfg - get dither property data
  * @conn: Pointer to drm_connector struct
  * @state: Pointer to drm_connector_state struct
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 8594f54..0956c01 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -186,6 +186,54 @@
 		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
 		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
 	},
+
+	[SDE_CSC_RGB2YUV_709L] = {
+		{
+			TO_S15D16(0x005d), TO_S15D16(0x013a), TO_S15D16(0x0020),
+			TO_S15D16(0xffcc), TO_S15D16(0xff53), TO_S15D16(0x00e1),
+			TO_S15D16(0x00e1), TO_S15D16(0xff34), TO_S15D16(0xffeb),
+		},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0040, 0x0200, 0x0200,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+		{ 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
+	},
+
+	[SDE_CSC_RGB2YUV_709FR] = {
+		{
+			TO_S15D16(0x006d), TO_S15D16(0x016e), TO_S15D16(0x0025),
+			TO_S15D16(0xffc5), TO_S15D16(0xff3b), TO_S15D16(0x0100),
+			TO_S15D16(0x0100), TO_S15D16(0xff17), TO_S15D16(0xffe9),
+		},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0040, 0x0200, 0x0200,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+	},
+
+	[SDE_CSC_RGB2YUV_2020L] = {
+		{
+			TO_S15D16(0x0073), TO_S15D16(0x0129), TO_S15D16(0x001a),
+			TO_S15D16(0xffc1), TO_S15D16(0xff5e), TO_S15D16(0x00e0),
+			TO_S15D16(0x00e0), TO_S15D16(0xff32), TO_S15D16(0xffee),
+		},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0040, 0x0200, 0x0200,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+		{ 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
+	},
+
+	[SDE_CSC_RGB2YUV_2020FR] = {
+		{
+			TO_S15D16(0x0086), TO_S15D16(0x015b), TO_S15D16(0x001e),
+			TO_S15D16(0xffb9), TO_S15D16(0xff47), TO_S15D16(0x0100),
+			TO_S15D16(0x0100), TO_S15D16(0xff15), TO_S15D16(0xffeb),
+		},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0, 0x0200, 0x0200,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+	},
 };
 
 /**
@@ -4058,10 +4106,15 @@
 	struct sde_encoder_phys *phys;
 	struct sde_kms *sde_kms = NULL;
 	struct msm_drm_private *priv = NULL;
+	struct drm_connector *conn_mas = NULL;
+	struct drm_display_mode *mode;
+	struct sde_hw_cdm *hw_cdm;
+	enum sde_csc_type conn_csc;
 	bool needs_hw_reset = false;
 	uint32_t ln_cnt1, ln_cnt2;
 	unsigned int i;
 	int rc, ret = 0;
+	int mode_is_yuv = 0;
 
 	if (!drm_enc || !params || !drm_enc->dev ||
 		!drm_enc->dev->dev_private) {
@@ -4131,13 +4184,48 @@
 	_sde_encoder_update_roi(drm_enc);
 
 	if (sde_enc->cur_master && sde_enc->cur_master->connector) {
-		rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
+		conn_mas = sde_enc->cur_master->connector;
+		rc = sde_connector_pre_kickoff(conn_mas);
 		if (rc) {
-			SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
-					sde_enc->cur_master->connector->base.id,
-					rc);
+			SDE_ERROR_ENC(sde_enc,
+				"kickoff conn%d failed rc %d\n",
+				conn_mas->base.id,
+				rc);
 			ret = rc;
 		}
+
+		for (i = 0; i < sde_enc->num_phys_encs; i++) {
+			phys = sde_enc->phys_encs[i];
+			if (phys) {
+				mode = &phys->cached_mode;
+				mode_is_yuv = (mode->private_flags &
+					MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420);
+			}
+			/**
+			 * Check the CSC matrix type to which the
+			 * CDM CSC matrix should be updated to based
+			 * on the connector HDR state
+			 */
+			conn_csc = sde_connector_get_csc_type(conn_mas);
+			if (phys && mode_is_yuv) {
+				if (phys->enc_cdm_csc != conn_csc) {
+					hw_cdm = phys->hw_cdm;
+					rc = hw_cdm->ops.setup_csc_data(hw_cdm,
+					&sde_csc_10bit_convert[conn_csc]);
+
+					if (rc)
+						SDE_ERROR_ENC(sde_enc,
+							"CSC setup failed rc %d\n",
+							rc);
+					SDE_DEBUG_ENC(sde_enc,
+						"updating CSC %d to %d\n",
+						phys->enc_cdm_csc,
+						conn_csc);
+					phys->enc_cdm_csc = conn_csc;
+
+				}
+			}
+		}
 	}
 
 	if (_sde_encoder_is_dsc_enabled(drm_enc) &&
@@ -5242,12 +5330,12 @@
 
 	if (output_type == CDM_CDWN_OUTPUT_HDMI) {
 		if (connector && connector->yuv_qs)
-			csc_type = SDE_CSC_RGB2YUV_601FR;
+			csc_type = SDE_CSC_RGB2YUV_709FR;
 		else if (connector &&
 			sde_connector_mode_needs_full_range(connector))
-			csc_type = SDE_CSC_RGB2YUV_601FR;
+			csc_type = SDE_CSC_RGB2YUV_709FR;
 		else
-			csc_type = SDE_CSC_RGB2YUV_601L;
+			csc_type = SDE_CSC_RGB2YUV_709L;
 	} else if (output_type == CDM_CDWN_OUTPUT_WB) {
 		csc_type = SDE_CSC_RGB2YUV_601L;
 	}
@@ -5261,6 +5349,9 @@
 		}
 	}
 
+	/* Cache the CSC default matrix type */
+	phys_enc->enc_cdm_csc = csc_type;
+
 	if (hw_cdm && hw_cdm->ops.setup_cdwn) {
 		ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
 		if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index 685d5b2..b1547ab 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, 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
@@ -252,6 +252,7 @@
  * @intf_mode:		Interface mode
  * @intf_idx:		Interface index on sde hardware
  * @comp_type:      Type of compression supported
+ * @enc_cdm_csc:	Cached CSC type of CDM block
  * @enc_spinlock:	Virtual-Encoder-Wide Spin Lock for IRQ purposes
  * @enable_state:	Enable state tracking
  * @vblank_refcount:	Reference count of vblank request
@@ -291,6 +292,7 @@
 	enum sde_intf_mode intf_mode;
 	enum sde_intf intf_idx;
 	enum msm_display_compression_type comp_type;
+	enum sde_csc_type enc_cdm_csc;
 	spinlock_t *enc_spinlock;
 	enum sde_enc_enable_state enable_state;
 	struct mutex *vblank_ctl_lock;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 798717b..a1c3bfa 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, 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
@@ -792,6 +792,8 @@
 
 	if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)
 		fmt = sde_get_sde_format(DRM_FORMAT_YUV420);
+	else if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422)
+		fmt = sde_get_sde_format(DRM_FORMAT_NV61);
 
 	if (fmt) {
 		struct sde_rect hdmi_roi;
@@ -838,22 +840,33 @@
 		struct drm_connector_state *conn_state)
 {
 	struct sde_encoder_phys_vid *vid_enc;
+	struct sde_mdss_cfg *vid_catalog;
 
 	if (!phys_enc || !hw_res) {
 		SDE_ERROR("invalid arg(s), enc %d hw_res %d conn_state %d\n",
-				phys_enc != 0, hw_res != 0, conn_state != 0);
+			phys_enc != NULL, hw_res != NULL, conn_state != NULL);
 		return;
 	}
 
+	vid_catalog = phys_enc->sde_kms->catalog;
 	vid_enc = to_sde_encoder_phys_vid(phys_enc);
-	if (!vid_enc->hw_intf) {
-		SDE_ERROR("invalid arg(s), hw_intf\n");
+	if (!vid_enc->hw_intf || !vid_catalog) {
+		SDE_ERROR("invalid arg(s), hw_intf %d vid_catalog %d\n",
+			  vid_enc->hw_intf != NULL, vid_catalog != NULL);
 		return;
 	}
 
 	SDE_DEBUG_VIDENC(vid_enc, "\n");
+	if (vid_enc->hw_intf->idx > INTF_MAX) {
+		SDE_ERROR("invalid arg(s), idx %d\n",
+			  vid_enc->hw_intf->idx);
+		return;
+	}
 	hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO;
-	hw_res->needs_cdm = true;
+
+	if (vid_catalog->intf[vid_enc->hw_intf->idx - INTF_0].type
+			== INTF_DP)
+		hw_res->needs_cdm = true;
 	SDE_DEBUG_DRIVER("[vid] needs_cdm=%d\n", hw_res->needs_cdm);
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 84b731e..6066d6a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, 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
@@ -2348,7 +2348,7 @@
 
 		/* intf3 and wb2 for cdm block */
 		cdm->wb_connect = sde_cfg->wb_count ? BIT(WB_2) : BIT(31);
-		cdm->intf_connect = sde_cfg->intf_count ? BIT(INTF_3) : BIT(31);
+		cdm->intf_connect = sde_cfg->intf_count ? BIT(INTF_0) : BIT(31);
 	}
 
 end:
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
index 0c3a967..322613d 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, 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
@@ -396,6 +396,10 @@
 enum sde_csc_type {
 	SDE_CSC_RGB2YUV_601L,
 	SDE_CSC_RGB2YUV_601FR,
+	SDE_CSC_RGB2YUV_709L,
+	SDE_CSC_RGB2YUV_709FR,
+	SDE_CSC_RGB2YUV_2020L,
+	SDE_CSC_RGB2YUV_2020FR,
 	SDE_MAX_CSC
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index cf646bd..48fedfd 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -159,7 +159,7 @@
 	if (cfg->wb_en)
 		out_ctl |= BIT(24);
 	else if (cfg->intf_en)
-		out_ctl |= BIT(19);
+		out_ctl |= BIT(28);
 
 	SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl);
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 68c3ca0..1b59ac7 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -1319,6 +1319,7 @@
 		.cont_splash_config = NULL,
 		.get_panel_vfp = NULL,
 		.mode_needs_full_range = dp_connector_mode_needs_full_range,
+		.get_csc_type = dp_connector_get_csc_type,
 	};
 	static const struct sde_connector_ops ext_bridge_ops = {
 		.set_info_blob = dsi_conn_set_info_blob,
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c
index c2ba3b97..89b5e3e 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.c
+++ b/drivers/gpu/drm/msm/sde_edid_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -242,7 +242,7 @@
 		if ((cea_mode != 0) && (cea_mode == video_format)) {
 			SDE_EDID_DEBUG("%s found match for %d ", __func__,
 			video_format);
-			mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV;
+			mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV420;
 		}
 	}
 }
@@ -251,12 +251,13 @@
 struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl,
 const u8 *db)
 {
-	u32 offset = 0;
 	u8 cmdb_len = 0;
 	u8 svd_len = 0;
 	const u8 *svd = NULL;
-	u32 i = 0, j = 0;
+	u32 i = 0;
 	u32 video_format = 0;
+	u32 num_cmdb_svd = 0;
+	const u32 mult = 8;
 
 	if (!edid_ctrl) {
 		SDE_ERROR("%s: edid_ctrl is NULL\n", __func__);
@@ -270,8 +271,8 @@
 	SDE_EDID_DEBUG("%s +\n", __func__);
 	cmdb_len = db[0] & 0x1f;
 
-	/* Byte 3 to L+1 contain SVDs */
-	offset += 2;
+	if (cmdb_len < 1)
+		return;
 
 	svd = sde_edid_find_block(edid_ctrl->edid, VIDEO_DATA_BLOCK);
 
@@ -281,21 +282,26 @@
 		++svd;
 	}
 
-	for (i = 0; i < svd_len; i++, j++) {
-		video_format = *(svd + i) & 0x7F;
-		if (cmdb_len == 1) {
-			/* If cmdb_len is 1, it means all SVDs support YUV */
-			sde_edid_set_y420_support(connector, video_format);
-		} else if (db[offset] & (1 << j)) {
-			sde_edid_set_y420_support(connector, video_format);
+	if (cmdb_len == 1)
+		num_cmdb_svd = svd_len;
+	else {
+		num_cmdb_svd = (cmdb_len - 1) * mult;
+		if (num_cmdb_svd > svd_len)
+			num_cmdb_svd = svd_len;
+	}
 
-			if (j & 0x80) {
-				j = j/8;
-				offset++;
-				if (offset >= cmdb_len)
-					break;
-			}
-		}
+	for (i = 0; i < num_cmdb_svd; i++) {
+		video_format = *(svd + i) & 0x7F;
+		/*
+		 * If cmdb_len is 1, it means all SVDs support YUV
+		 * Else, we check each byte of the cmdb bitmap bitwise
+		 * and match those bits with the formats populated
+		 * during the parsing of the Video Data Blocks.
+		 * Refer to CTA 861-F section 7.5.11 YCBCR 4:2:0 Capability
+		 * Map Data Block for more details on this.
+		 */
+		if (cmdb_len == 1 || (db[2 + i / mult] & (1 << (i % mult))))
+			sde_edid_set_y420_support(connector, video_format);
 	}
 
 	SDE_EDID_DEBUG("%s -\n", __func__);
@@ -335,6 +341,7 @@
 {
 	const u8 *db = NULL;
 	struct drm_display_mode *mode;
+	struct drm_display_info *info = &connector->display_info;
 
 	SDE_EDID_DEBUG("%s +\n", __func__);
 	/* Set YUV mode support flags for YCbcr420VDB */
@@ -347,8 +354,11 @@
 
 	/* Set RGB supported on all modes where YUV is not set */
 	list_for_each_entry(mode, &connector->probed_modes, head) {
-		if (!(mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV))
+		if (!(mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV420)) {
 			mode->flags |= DRM_MODE_FLAG_SUPPORTS_RGB;
+			if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
+				mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV422;
+		}
 	}
 
 
@@ -359,6 +369,34 @@
 	else
 		SDE_EDID_DEBUG("YCbCr420 CMDB is not present\n");
 
+	/*
+	 * As per HDMI 2.0 spec, a sink supporting any modes
+	 * requiring more than 340Mhz clock rate should support
+	 * SCDC as well. This is required because we need the SCDC
+	 * channel to set the TMDS clock ratio. However in cases
+	 * where the TV publishes such a mode in its list of modes
+	 * but does not have SCDC support as per HDMI HFVSDB block
+	 * remove RGB mode support from the flags. Currently, in
+	 * the list of modes not having deep color support only RGB
+	 * modes shall requre a clock of 340Mhz and above such as the
+	 * 4K@60fps case. All other modes shall be YUV.
+	 * Deep color case is handled separately while choosing the
+	 * best mode in the _sde_hdmi_choose_best_format API where
+	 * we enable deep color only if it satisfies both source and
+	 * sink requirements. However, that API assumes that at least
+	 * RGB mode is supported on the mode. Hence, it would be better
+	 * to remove the format support flags while parsing the EDID
+	 * itself if it doesn't satisfy the HDMI spec requirement.
+	 */
+
+	list_for_each_entry(mode, &connector->probed_modes, head) {
+		if ((mode->clock > MIN_SCRAMBLER_REQ_RATE) &&
+			!connector->scdc_present) {
+			mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_RGB;
+			mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_YUV422;
+		}
+	}
+
 	SDE_EDID_DEBUG("%s -\n", __func__);
 }
 
@@ -378,6 +416,7 @@
 	}
 
 	disp_info = &connector->display_info;
+	disp_info->y420_bpc = 8;
 
 	edid_ext = sde_find_cea_extension(edid_ctrl->edid);
 
@@ -398,16 +437,19 @@
 				continue;
 
 			if (hdmi[7] & DRM_EDID_YCBCR420_DC_30) {
+				disp_info->y420_bpc = 10;
 				hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_30;
 				SDE_EDID_DEBUG("Y420 30-bit supported\n");
 			}
 
 			if (hdmi[7] & DRM_EDID_YCBCR420_DC_36) {
+				disp_info->y420_bpc = 12;
 				hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36;
 				SDE_EDID_DEBUG("Y420 36-bit supported\n");
 			}
 
 			if (hdmi[7] & DRM_EDID_YCBCR420_DC_48) {
+				disp_info->y420_bpc = 16;
 				hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36;
 				SDE_EDID_DEBUG("Y420 48-bit supported\n");
 			}
@@ -548,6 +590,12 @@
 {
 	int rc = 0;
 	struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input);
+	struct drm_display_info *disp_info;
+
+	disp_info = &connector->display_info;
+
+	if (disp_info)
+		disp_info->edid_hdmi_dc_modes = 0;
 
 	SDE_EDID_DEBUG("%s +", __func__);
 	if (edid_ctrl->edid) {
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.h b/drivers/gpu/drm/msm/sde_edid_parser.h
index fd56116..422ce08 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.h
+++ b/drivers/gpu/drm/msm/sde_edid_parser.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -33,7 +33,11 @@
 #define SDE_CEA_EXT    0x02
 #define SDE_EXTENDED_TAG 0x07
 
-#define SDE_DRM_MODE_FLAG_FMT_MASK (0x3 << 20)
+#define MIN_SCRAMBLER_REQ_RATE 340000
+
+#define SDE_DRM_MODE_FLAG_FMT_MASK (DRM_MODE_FLAG_SUPPORTS_RGB | \
+				DRM_MODE_FLAG_SUPPORTS_YUV422 | \
+				DRM_MODE_FLAG_SUPPORTS_YUV420)
 
 enum extended_data_block_types {
 	VIDEO_CAPABILITY_DATA_BLOCK = 0x0,
diff --git a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
index f8d13cc..30f6799 100644
--- a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
+++ b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
@@ -809,8 +809,8 @@
 {
 	int i = 0;
 
+	st->gyro_buffer_inv_samples = false;
 	if (enable_read) {
-		st->gyro_buffer_inv_samples = false;
 		for (i = 0; i < st->gyro_bufsample_cnt; i++) {
 			dev_dbg(st->dev, "gyro_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
 					i, st->inv_gyro_samplist[i]->xyz[0],
@@ -853,8 +853,8 @@
 {
 	int i = 0;
 
+	st->acc_buffer_inv_samples = false;
 	if (enable_read) {
-		st->acc_buffer_inv_samples = false;
 		for (i = 0; i < st->acc_bufsample_cnt; i++) {
 			dev_dbg(st->dev, "acc_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
 					i, st->inv_acc_samplist[i]->xyz[0],
@@ -922,7 +922,9 @@
 				"Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+	mutex_lock(&st->gyro_sensor_buff);
 	err = inv_gyro_read_bootsampl(st, enable);
+	mutex_unlock(&st->gyro_sensor_buff);
 	if (err)
 		return err;
 	st->read_gyro_boot_sample = enable;
@@ -958,7 +960,9 @@
 				"Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+	mutex_lock(&st->acc_sensor_buff);
 	err = inv_acc_read_bootsampl(st, enable);
+	mutex_unlock(&st->acc_sensor_buff);
 	if (err)
 		return err;
 	st->read_acc_boot_sample = enable;
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
index 65089f2..8b45d90 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
@@ -439,6 +439,9 @@
 	st->acc_buffer_inv_samples = true;
 	st->gyro_buffer_inv_samples = true;
 
+	mutex_init(&st->acc_sensor_buff);
+	mutex_init(&st->gyro_sensor_buff);
+
 	inv_enable_acc_gyro(st);
 
 	return 1;
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
index 1e0a176..7a687c2 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
@@ -871,6 +871,8 @@
 	struct input_dev *accbuf_dev;
 	struct input_dev *gyrobuf_dev;
 	int report_evt_cnt;
+	struct mutex acc_sensor_buff;
+	struct mutex gyro_sensor_buff;
 #endif
 
 };
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
index de64b2c..8b1c067 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
@@ -301,6 +301,7 @@
 static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
 						s16 x, s16 y, s16 z)
 {
+	mutex_lock(&st->acc_sensor_buff);
 	if (false == st->acc_buffer_inv_samples)
 		return;
 	st->timestamp.tv64 = t;
@@ -328,11 +329,13 @@
 					st->acc_bufsample_cnt);
 		st->acc_buffer_inv_samples = false;
 	}
+	mutex_unlock(&st->acc_sensor_buff);
 }
 static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t,
 						s16 x, s16 y, s16 z)
 {
 
+	mutex_lock(&st->gyro_sensor_buff);
 	if (false == st->gyro_buffer_inv_samples)
 		return;
 	st->timestamp.tv64 = t;
@@ -360,6 +363,7 @@
 					st->gyro_bufsample_cnt);
 		st->gyro_buffer_inv_samples = false;
 	}
+	mutex_unlock(&st->gyro_sensor_buff);
 }
 #else
 static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
index c582e4f..39a99a2 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
@@ -43,6 +43,9 @@
 
 #define ST_ASM330LHH_MAX_ODR			416
 
+/* Timestamp Tick 25us/LSB */
+#define ST_ASM330LHH_TS_DELTA_NS		25000ULL
+
 /* Define Custom events for FIFO flush */
 #define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1)
 #define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2)
@@ -82,8 +85,8 @@
 	.num_event_specs = 1,				\
 }
 
-#define ST_ASM330LHH_RX_MAX_LENGTH	8
-#define ST_ASM330LHH_TX_MAX_LENGTH	8
+#define ST_ASM330LHH_RX_MAX_LENGTH	64
+#define ST_ASM330LHH_TX_MAX_LENGTH	16
 
 #ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
 #define ASM_MAXSAMPLE        4000
@@ -188,6 +191,7 @@
 	int max_buffer_time;
 	struct input_dev *buf_dev;
 	int report_evt_cnt;
+	struct mutex sensor_buff;
 #endif
 };
 
@@ -197,6 +201,7 @@
  * @irq: Device interrupt line (I2C or SPI).
  * @lock: Mutex to protect read and write operations.
  * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
+ * @page_lock: Mutex to prevent concurrent memory page configuration.
  * @fifo_mode: FIFO operating mode supported by the device.
  * @state: hw operational state.
  * @enable_mask: Enabled sensor bitmask.
@@ -204,6 +209,13 @@
  * @hw_ts: Latest hw timestamp from the sensor.
  * @ts: Latest timestamp from irq handler.
  * @delta_ts: Delta time between two consecutive interrupts.
+ * @ts_delta_ns: Calibrate delta time tick.
+ * @hw_ts: Latest hw timestamp from the sensor.
+ * @val_ts_old: Hold hw timestamp for timer rollover.
+ * @hw_ts_high: Save MSB hw timestamp.
+ * @tsample: Timestamp for each sensor sample.
+ * @delta_ts: Delta time between two consecutive interrupts.
+ * @ts: Latest timestamp from irq handler.
  * @iio_devs: Pointers to acc/gyro iio_dev instances.
  * @tf: Transfer function structure used by I/O operations.
  * @tb: Transfer buffers used by SPI I/O operations.
@@ -214,34 +226,51 @@
 
 	struct mutex lock;
 	struct mutex fifo_lock;
+	struct mutex page_lock;
 
 	enum st_asm330lhh_fifo_mode fifo_mode;
 	unsigned long state;
 	u8 enable_mask;
 
 	s64 ts_offset;
-	u32 hw_val;
-	u32 hw_val_old;
+	u64 ts_delta_ns;
 	s64 hw_ts;
-	s64 hw_ts_high;
+	u32 val_ts_old;
+	u32 hw_ts_high;
+	s64 tsample;
 	s64 delta_ts;
 	s64 ts;
-	s64 tsample;
-	s64 hw_ts_old;
-	s64 delta_hw_ts;
-
-	/* Timestamp sample ODR */
-	u16 odr;
-
 	struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX];
 
 	const struct st_asm330lhh_transfer_function *tf;
 	struct st_asm330lhh_transfer_buffer tb;
 	int enable_gpio;
+	bool asm330_hrtimer;
+	struct hrtimer st_asm330lhh_hrtimer;
 };
 
 extern const struct dev_pm_ops st_asm330lhh_pm_ops;
 
+static inline int st_asm330lhh_read_atomic(struct st_asm330lhh_hw *hw, u8 addr,
+					 int len, u8 *data)
+{
+	int err;
+
+	mutex_lock(&hw->page_lock);
+	err = hw->tf->read(hw->dev, addr, len, data);
+	mutex_unlock(&hw->page_lock);
+
+	return err;
+}
+
+static inline s64 st_asm330lhh_get_time_ns(void)
+{
+	struct timespec ts;
+
+	get_monotonic_boottime(&ts);
+	return timespec_to_ns(&ts);
+}
+
 int st_asm330lhh_probe(struct device *dev, int irq,
 		       const struct st_asm330lhh_transfer_function *tf_ops);
 int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor,
@@ -268,4 +297,6 @@
 int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable);
 int asm330_check_acc_gyro_early_buff_enable_flag(
 		struct st_asm330lhh_sensor *sensor);
+void st_asm330lhh_set_cpu_idle_state(bool value);
+void st_asm330lhh_hrtimer_reset(struct st_asm330lhh_hw *hw, s64 irq_delta_ts);
 #endif /* ST_ASM330LHH_H */
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
index c224427..32937e1 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
@@ -1,7 +1,7 @@
 /*
  * STMicroelectronics st_asm330lhh FIFO buffer library driver
  *
- * Copyright 2018 STMicroelectronics Inc.
+ * Copyright 2020 STMicroelectronics Inc.
  *
  * Lorenzo Bianconi <lorenzo.bianconi@st.com>
  *
@@ -10,41 +10,41 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/iio/iio.h>
 #include <linux/iio/kfifo_buf.h>
 #include <linux/iio/events.h>
 #include <asm/unaligned.h>
+#include <linux/iio/buffer.h>
 #include <linux/of.h>
 
 #include "st_asm330lhh.h"
 
 #define ST_ASM330LHH_REG_FIFO_THL_ADDR		0x07
 #define ST_ASM330LHH_REG_FIFO_LEN_MASK		GENMASK(8, 0)
+#define ST_ASM330LHH_REG_FIFO_STATUS_DIFF	GENMASK(9, 0)
 #define ST_ASM330LHH_REG_FIFO_MODE_MASK		GENMASK(2, 0)
 #define ST_ASM330LHH_REG_DEC_TS_MASK		GENMASK(7, 6)
 #define ST_ASM330LHH_REG_HLACTIVE_ADDR		0x12
 #define ST_ASM330LHH_REG_HLACTIVE_MASK		BIT(5)
 #define ST_ASM330LHH_REG_PP_OD_ADDR		0x12
 #define ST_ASM330LHH_REG_PP_OD_MASK		BIT(4)
-#define ST_ASM330LHH_REG_FIFO_DIFFL_ADDR	0x3a
+#define ST_ASM330LHH_REG_FIFO_STATUS1_ADDR	0x3a
 #define ST_ASM330LHH_REG_TS0_ADDR		0x40
 #define ST_ASM330LHH_REG_TS2_ADDR		0x42
 #define ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR	0x78
-#define ST_ASM330LHH_GYRO_TAG			0x01
-#define ST_ASM330LHH_ACC_TAG			0x02
-#define ST_ASM330LHH_TS_TAG			0x04
 
-#define ST_ASM330LHH_TS_DELTA_NS		25000ULL /* 25us/LSB */
+#define ST_ASM330LHH_SAMPLE_DISCHARD		0x7ffd
 
-static inline s64 st_asm330lhh_get_time_ns(void)
-{
-	struct timespec ts;
-
-	get_monotonic_boottime(&ts);
-	return timespec_to_ns(&ts);
-}
-
+/* Timestamp convergence filter parameter */
 #define ST_ASM330LHH_EWMA_LEVEL			120
 #define ST_ASM330LHH_EWMA_DIV			128
+
+enum {
+	ST_ASM330LHH_GYRO_TAG = 0x01,
+	ST_ASM330LHH_ACC_TAG = 0x02,
+	ST_ASM330LHH_TS_TAG = 0x04,
+};
+
 static inline s64 st_asm330lhh_ewma(s64 old, s64 new, int weight)
 {
 	s64 diff, incr;
@@ -62,10 +62,12 @@
 
 	hw->ts = st_asm330lhh_get_time_ns();
 	hw->ts_offset = hw->ts;
-	hw->hw_ts_old = 0ull;
+	hw->val_ts_old = 0;
+	hw->hw_ts_high = 0;
 	hw->tsample = 0ull;
-	hw->hw_ts_high = 0ull;
-	hw->hw_val_old = 0ull;
+
+	if (hw->asm330_hrtimer)
+		st_asm330lhh_set_cpu_idle_state(true);
 
 	return hw->tf->write(hw->dev, ST_ASM330LHH_REG_TS2_ADDR, sizeof(data),
 			     &data);
@@ -84,6 +86,11 @@
 
 	hw->fifo_mode = fifo_mode;
 
+	if (fifo_mode == ST_ASM330LHH_FIFO_BYPASS)
+		clear_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state);
+	else
+		set_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state);
+
 	return 0;
 }
 
@@ -105,24 +112,6 @@
 					    sensor->batch_mask, data);
 }
 
-static u16 st_asm330lhh_ts_odr(struct st_asm330lhh_hw *hw)
-{
-	struct st_asm330lhh_sensor *sensor;
-	u16 odr = 0;
-	u8 i;
-
-	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
-		if (!hw->iio_devs[i])
-			continue;
-
-		sensor = iio_priv(hw->iio_devs[i]);
-		if (hw->enable_mask & BIT(sensor->id))
-			odr = max_t(u16, odr, sensor->odr);
-	}
-
-	return odr;
-}
-
 int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
 					 u16 watermark)
 {
@@ -134,6 +123,9 @@
 	u8 data;
 
 	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
 		cur_sensor = iio_priv(hw->iio_devs[i]);
 
 		if (!(hw->enable_mask & BIT(cur_sensor->id)))
@@ -146,6 +138,7 @@
 	}
 
 	fifo_watermark = max_t(u16, fifo_watermark, 2);
+
 	mutex_lock(&hw->lock);
 
 	err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR + 1,
@@ -165,14 +158,6 @@
 	return err < 0 ? err : 0;
 }
 
-static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts)
-{
-	s64 delta = ts - hw->hw_ts;
-
-	hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta,
-					  ST_ASM330LHH_EWMA_LEVEL);
-}
-
 static struct iio_dev *st_asm330lhh_get_iiodev_from_tag(struct st_asm330lhh_hw *hw,
 							u8 tag)
 {
@@ -215,6 +200,7 @@
 {
 	int x, y, z;
 
+	mutex_lock(&sensor->sensor_buff);
 	if (false == sensor->buffer_asm_samples)
 		return;
 
@@ -240,6 +226,7 @@
 				sensor->id, sensor->bufsample_cnt);
 		sensor->buffer_asm_samples = false;
 	}
+	mutex_unlock(&sensor->sensor_buff);
 }
 #else
 static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor,
@@ -248,111 +235,116 @@
 }
 #endif
 
+static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts)
+{
+	s64 delta = ts - hw->hw_ts;
+
+	hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta,
+					  ST_ASM330LHH_EWMA_LEVEL);
+}
+
 static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw)
 {
 	u8 iio_buf[ALIGN(ST_ASM330LHH_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
 	u8 buf[30 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr;
-	s64 ts_delta_hw_ts = 0, ts_irq;
-	s64 ts_delta_offs;
-	int i, err, read_len, word_len, fifo_len;
-	struct st_asm330lhh_sensor *sensor;
+	int i, err, word_len, fifo_len, read_len;
 	struct iio_dev *iio_dev;
+	struct st_asm330lhh_sensor *sensor;
+	s64 ts_irq, hw_ts_old;
 	__le16 fifo_status;
 	u16 fifo_depth;
-	int ts_processed = 0;
-	s64 hw_ts = 0ull, delta_hw_ts, cpu_timestamp;
+	s16 drdymask;
+	u32 val;
+
+	/* return if FIFO is already disabled */
+	if (!test_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state)) {
+		dev_warn(hw->dev, "%s: FIFO in bypass mode\n", __func__);
+
+		return 0;
+	}
 
 	ts_irq = hw->ts - hw->delta_ts;
 
-	do {
-		err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_DIFFL_ADDR,
-				   sizeof(fifo_status), (u8 *)&fifo_status);
+	err = st_asm330lhh_read_atomic(hw, ST_ASM330LHH_REG_FIFO_STATUS1_ADDR,
+				     sizeof(fifo_status), (u8 *)&fifo_status);
+	if (err < 0)
+		return err;
+
+	fifo_depth = le16_to_cpu(fifo_status) &
+		ST_ASM330LHH_REG_FIFO_STATUS_DIFF;
+	if (!fifo_depth)
+		return 0;
+
+	fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE;
+	read_len = 0;
+	while (read_len < fifo_len) {
+		word_len = min_t(int, fifo_len - read_len, sizeof(buf));
+		err = st_asm330lhh_read_atomic(hw,
+					     ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR,
+					     word_len, buf);
 		if (err < 0)
 			return err;
+		for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) {
+			ptr = &buf[i + ST_ASM330LHH_TAG_SIZE];
+			tag = buf[i] >> 3;
 
-		fifo_depth = le16_to_cpu(fifo_status) & ST_ASM330LHH_REG_FIFO_LEN_MASK;
-		if (!fifo_depth)
-			return 0;
+			if (tag == ST_ASM330LHH_TS_TAG) {
+				val = get_unaligned_le32(ptr);
 
-		read_len = 0;
-		fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE;
-		while (read_len < fifo_len) {
-			word_len = min_t(int, fifo_len - read_len, sizeof(buf));
-			err = hw->tf->read(hw->dev,
-					   ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR,
-					   word_len, buf);
-			if (err < 0)
-				return err;
+				if (hw->val_ts_old > val)
+					hw->hw_ts_high++;
 
-			for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) {
-				ptr = &buf[i + ST_ASM330LHH_TAG_SIZE];
-				tag = buf[i] >> 3;
+				hw_ts_old = hw->hw_ts;
 
-				if (tag == ST_ASM330LHH_TS_TAG) {
-					hw->hw_val = get_unaligned_le32(ptr);
+				/* check hw rollover */
+				hw->val_ts_old = val;
+				hw->hw_ts = (val + ((s64)hw->hw_ts_high <<
+							32)) * hw->ts_delta_ns;
+				hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset,
+						ts_irq - hw->hw_ts,
+						ST_ASM330LHH_EWMA_LEVEL);
 
-					/* check for timer rollover */
-					if (hw->hw_val < hw->hw_val_old)
-						hw->hw_ts_high++;
-					hw->hw_ts =
-					(hw->hw_val + (hw->hw_ts_high << 32))
-						* ST_ASM330LHH_TS_DELTA_NS;
-					ts_delta_hw_ts = hw->hw_ts - hw->hw_ts_old;
-					hw_ts += ts_delta_hw_ts;
-					ts_delta_offs =
-						div_s64(hw->delta_hw_ts * ST_ASM330LHH_MAX_ODR, hw->odr);
+				if (!test_bit(ST_ASM330LHH_HW_FLUSH,
+							&hw->state))
+					/* sync ap timestamp and sensor one */
+					st_asm330lhh_sync_hw_ts(hw, ts_irq);
 
-					hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, ts_irq -
-						hw->hw_ts + ts_delta_offs, ST_ASM330LHH_EWMA_LEVEL);
+				ts_irq += hw->hw_ts;
 
-					ts_irq += (hw->hw_ts + ts_delta_offs);
-					hw->hw_ts_old = hw->hw_ts;
-					hw->hw_val_old = hw->hw_val;
-					ts_processed++;
+				if (!hw->tsample)
+					hw->tsample = hw->ts_offset + hw->hw_ts;
+				else
+					hw->tsample = hw->tsample +
+						hw->hw_ts - hw_ts_old;
+			} else {
+				iio_dev = st_asm330lhh_get_iiodev_from_tag(hw,
+						tag);
+				if (!iio_dev)
+					continue;
+				sensor = iio_priv(iio_dev);
 
-					if (!hw->tsample)
-						hw->tsample =
-							hw->ts_offset + (hw->hw_ts + ts_delta_offs);
-					else
-						hw->tsample =
-							hw->tsample + (ts_delta_hw_ts + ts_delta_offs);
-				} else {
-					iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, tag);
-					if (!iio_dev)
-						continue;
-
-					sensor = iio_priv(iio_dev);
-					if (sensor->std_samples < sensor->std_level) {
-						sensor->std_samples++;
-						continue;
-					}
-
-					sensor = iio_priv(iio_dev);
-
-					/* Check if timestamp is in the future. */
-					cpu_timestamp = st_asm330lhh_get_time_ns();
-
-					/* Avoid samples in the future. */
-					if (hw->tsample > cpu_timestamp)
-						hw->tsample = cpu_timestamp;
-
-					memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE);
-					iio_push_to_buffers_with_timestamp(iio_dev,
-									   iio_buf,
-									   hw->tsample);
-					store_acc_gyro_boot_sample(sensor,
-							iio_buf, hw->tsample);
+				/* skip samples if not ready */
+				drdymask = (s16)le16_to_cpu(
+						get_unaligned_le16(ptr));
+				if (unlikely(drdymask
+					>= ST_ASM330LHH_SAMPLE_DISCHARD)) {
+					continue;
 				}
-			}
-			read_len += word_len;
-		}
+				memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE);
 
-		delta_hw_ts = div_s64(hw->delta_ts - hw_ts, ts_processed);
-		delta_hw_ts = div_s64(delta_hw_ts * hw->odr, ST_ASM330LHH_MAX_ODR);
-		hw->delta_hw_ts = st_asm330lhh_ewma(hw->delta_hw_ts,
-							delta_hw_ts,
-							ST_ASM330LHH_EWMA_LEVEL);
-	} while(read_len);
+				hw->tsample = min_t(s64,
+						    hw->ts,
+						    hw->tsample);
+
+				iio_push_to_buffers_with_timestamp(iio_dev,
+								   iio_buf,
+								   hw->tsample);
+				store_acc_gyro_boot_sample(sensor,
+						iio_buf, hw->tsample);
+			}
+		}
+		read_len += word_len;
+	}
 
 	return read_len;
 }
@@ -412,8 +404,9 @@
 	struct iio_dev *iio_dev = dev_get_drvdata(dev);
 	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
 	struct st_asm330lhh_hw *hw = sensor->hw;
-	s64 type, event;
+	s64 event;
 	int count;
+	s64 type;
 	s64 ts;
 
 	mutex_lock(&hw->fifo_lock);
@@ -421,9 +414,7 @@
 	hw->delta_ts = ts - hw->ts;
 	hw->ts = ts;
 	set_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);
-
 	count = st_asm330lhh_read_fifo(hw);
-
 	mutex_unlock(&hw->fifo_lock);
 
 	type = count > 0 ? CUSTOM_IIO_EV_DIR_FIFO_DATA : CUSTOM_IIO_EV_DIR_FIFO_EMPTY;
@@ -439,10 +430,8 @@
 	int err;
 
 	mutex_lock(&hw->fifo_lock);
-
 	st_asm330lhh_read_fifo(hw);
 	err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS);
-
 	mutex_unlock(&hw->fifo_lock);
 
 	return err;
@@ -468,8 +457,6 @@
 	if (err < 0)
 		goto out;
 
-	hw->odr = st_asm330lhh_ts_odr(hw);
-
 	if (enable && hw->fifo_mode == ST_ASM330LHH_FIFO_BYPASS) {
 		st_asm330lhh_reset_hwts(hw);
 		err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT);
@@ -491,6 +478,9 @@
 	hw->delta_ts = ts - hw->ts;
 	hw->ts = ts;
 
+	if (hw->asm330_hrtimer)
+		st_asm330lhh_hrtimer_reset(hw, hw->delta_ts);
+
 	return IRQ_WAKE_THREAD;
 }
 
@@ -499,12 +489,13 @@
 	struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private;
 
 	mutex_lock(&hw->fifo_lock);
-
 	st_asm330lhh_read_fifo(hw);
 	clear_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);
-
 	mutex_unlock(&hw->fifo_lock);
 
+	if (hw->asm330_hrtimer)
+		st_asm330lhh_set_cpu_idle_state(false);
+
 	return IRQ_HANDLED;
 }
 
@@ -548,6 +539,8 @@
 	int i, err;
 
 	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+	if (irq_type == IRQF_TRIGGER_NONE)
+		irq_type = IRQF_TRIGGER_HIGH;
 
 	switch (irq_type) {
 	case IRQF_TRIGGER_HIGH:
@@ -605,4 +598,3 @@
 
 	return st_asm330lhh_fifo_init(hw);
 }
-
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
index 623de5d..eca4659 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
@@ -17,6 +17,7 @@
 #include <linux/version.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/cpu.h>
 
 #include <linux/platform_data/st_sensors_pdata.h>
 
@@ -26,18 +27,24 @@
 #define ST_ASM330LHH_REG_INT2_ADDR		0x0e
 #define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR	0x0a
 #define ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK	BIT(3)
+
 #define ST_ASM330LHH_REG_WHOAMI_ADDR		0x0f
 #define ST_ASM330LHH_WHOAMI_VAL			0x6b
 #define ST_ASM330LHH_REG_CTRL1_XL_ADDR		0x10
 #define ST_ASM330LHH_REG_CTRL2_G_ADDR		0x11
+
 #define ST_ASM330LHH_REG_RESET_ADDR		0x12
 #define ST_ASM330LHH_REG_RESET_MASK		BIT(0)
+
 #define ST_ASM330LHH_REG_BDU_ADDR		0x12
 #define ST_ASM330LHH_REG_BDU_MASK		BIT(6)
-#define ST_ASM330LHH_REG_INT2_ON_INT1_ADDR	0x13
-#define ST_ASM330LHH_REG_INT2_ON_INT1_MASK	BIT(5)
+
+#define ST_ASM330LHH_REG_CTRL4_C_ADDR		0x13
+#define ST_ASM330LHH_REG_DRDY_MASK		BIT(3)
+
 #define ST_ASM330LHH_REG_ROUNDING_ADDR		0x14
 #define ST_ASM330LHH_REG_ROUNDING_MASK		GENMASK(6, 5)
+
 #define ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR	0x19
 #define ST_ASM330LHH_REG_TIMESTAMP_EN_MASK	BIT(5)
 
@@ -64,6 +71,8 @@
 #define ST_ASM330LHH_GYRO_FS_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
 #define ST_ASM330LHH_GYRO_FS_4000_GAIN		IIO_DEGREE_TO_RAD(140000)
 
+#define ST_ASM330LHH_INTERNAL_FREQ_FINE		0x63
+
 /* Temperature in uC */
 #define ST_ASM330LHH_TEMP_GAIN			256
 #define ST_ASM330LHH_TEMP_FS_GAIN		(1000000 / ST_ASM330LHH_TEMP_GAIN)
@@ -184,6 +193,33 @@
 	},
 };
 
+void st_asm330lhh_set_cpu_idle_state(bool value)
+{
+	cpu_idle_poll_ctrl(value);
+}
+static enum hrtimer_restart st_asm330lhh_timer_function(
+		struct hrtimer *timer)
+{
+	st_asm330lhh_set_cpu_idle_state(true);
+
+	return HRTIMER_NORESTART;
+}
+void st_asm330lhh_hrtimer_reset(struct st_asm330lhh_hw *hw,
+		s64 irq_delta_ts)
+{
+	hrtimer_cancel(&hw->st_asm330lhh_hrtimer);
+	/*forward HRTIMER just before 1ms of irq arrival*/
+	hrtimer_forward(&hw->st_asm330lhh_hrtimer, ktime_get(),
+			ns_to_ktime(irq_delta_ts - 1000000));
+	hrtimer_restart(&hw->st_asm330lhh_hrtimer);
+}
+static void st_asm330lhh_hrtimer_init(struct st_asm330lhh_hw *hw)
+{
+	hrtimer_init(&hw->st_asm330lhh_hrtimer, CLOCK_MONOTONIC,
+			HRTIMER_MODE_REL);
+	hw->st_asm330lhh_hrtimer.function = st_asm330lhh_timer_function;
+}
+
 int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
 				 u8 val)
 {
@@ -230,6 +266,30 @@
 	return 0;
 }
 
+static int st_asm330lhh_get_odr_calibration(struct st_asm330lhh_hw *hw)
+{
+	s64 odr_calib;
+	int err;
+	s8 data;
+
+	err = hw->tf->read(hw->dev,
+			   ST_ASM330LHH_INTERNAL_FREQ_FINE,
+			   sizeof(data), (u8 *)&data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to read %d register\n",
+				ST_ASM330LHH_INTERNAL_FREQ_FINE);
+		return err;
+	}
+
+	odr_calib = (data * 37500) / 1000;
+	hw->ts_delta_ns = ST_ASM330LHH_TS_DELTA_NS - odr_calib;
+
+	dev_info(hw->dev, "Freq Fine %lld (ts %lld)\n",
+			odr_calib, hw->ts_delta_ns);
+
+	return 0;
+}
+
 static int st_asm330lhh_set_full_scale(struct st_asm330lhh_sensor *sensor,
 				       u32 gain)
 {
@@ -507,8 +567,9 @@
 {
 	int i = 0;
 
+	sensor->buffer_asm_samples = false;
+
 	if (enable_read) {
-		sensor->buffer_asm_samples = false;
 		for (i = 0; i < sensor->bufsample_cnt; i++) {
 			dev_dbg(sensor->hw->dev,
 				"sensor:%d count:%d x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
@@ -535,7 +596,6 @@
 			for (i = 0; i < ASM_MAXSAMPLE; i++)
 				kmem_cache_free(sensor->asm_cachepool,
 					sensor->asm_samplist[i]);
-			kmem_cache_destroy(sensor->asm_cachepool);
 			sensor->bufsample_cnt = 0;
 		}
 
@@ -572,10 +632,15 @@
 				"Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+
+	mutex_lock(&sensor->sensor_buff);
 	err = asm_read_bootsampl(sensor, enable);
+	mutex_unlock(&sensor->sensor_buff);
 	if (err)
 		return err;
+
 	sensor->read_boot_sample = enable;
+
 	return count;
 
 }
@@ -607,10 +672,15 @@
 				"Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+
+	mutex_lock(&sensor->sensor_buff);
 	err = asm_read_bootsampl(sensor, enable);
+	mutex_unlock(&sensor->sensor_buff);
 	if (err)
 		return err;
+
 	sensor->read_boot_sample = enable;
+
 	return count;
 }
 #endif
@@ -775,6 +845,12 @@
 	if (err < 0)
 		return err;
 
+	/* enable DRDY MASK for filters settling time */
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_CTRL4_C_ADDR,
+					 ST_ASM330LHH_REG_DRDY_MASK, 1);
+	if (err < 0)
+		return err;
+
 	/* enable FIFO watermak interrupt */
 	err = st_asm330lhh_get_drdy_reg(hw, &drdy_int_reg);
 	if (err < 0)
@@ -996,6 +1072,8 @@
 
 	acc->buffer_asm_samples = true;
 	gyro->buffer_asm_samples = true;
+	mutex_init(&acc->sensor_buff);
+	mutex_init(&gyro->sensor_buff);
 
 	return 1;
 clean_exit5:
@@ -1043,6 +1121,7 @@
 
 	mutex_init(&hw->lock);
 	mutex_init(&hw->fifo_lock);
+	mutex_init(&hw->page_lock);
 
 	hw->dev = dev;
 	hw->irq = irq;
@@ -1062,11 +1141,18 @@
 		msleep(ST_ASM330LHH_TURN_ON_TIME);
 	}
 
+	/* use hrtimer if property is enabled */
+	hw->asm330_hrtimer = of_property_read_bool(np, "qcom,asm330_hrtimer");
+
 	dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION);
 	err = st_asm330lhh_check_whoami(hw);
 	if (err < 0)
 		return err;
 
+	err = st_asm330lhh_get_odr_calibration(hw);
+	if (err < 0)
+		return err;
+
 	err = st_asm330lhh_init_device(hw);
 	if (err < 0)
 		return err;
@@ -1096,6 +1182,9 @@
 	if (!err)
 		return err;
 
+	if (hw->asm330_hrtimer)
+		st_asm330lhh_hrtimer_init(hw);
+
 	st_asm330lhh_enable_acc_gyro(hw);
 
 	dev_info(hw->dev, "probe ok\n");
diff --git a/drivers/input/sensors/smi130/smi130_acc.c b/drivers/input/sensors/smi130/smi130_acc.c
index 8564850..27bcf58 100644
--- a/drivers/input/sensors/smi130/smi130_acc.c
+++ b/drivers/input/sensors/smi130/smi130_acc.c
@@ -1609,6 +1609,7 @@
 	int max_buffer_time;
 	struct input_dev *accbuf_dev;
 	int report_evt_cnt;
+	struct mutex acc_sensor_buff;
 #endif
 #ifdef SMI130_HRTIMER
 	struct hrtimer smi130_hrtimer;
@@ -6553,8 +6554,9 @@
 {
 	int i = 0;
 
+	client_data->acc_buffer_smi130_samples = false;
+
 	if (enable_read) {
-		client_data->acc_buffer_smi130_samples = false;
 		for (i = 0; i < client_data->acc_bufsample_cnt; i++) {
 			if (client_data->debug_level & 0x08)
 				PINFO("acc=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n",
@@ -6621,7 +6623,9 @@
 		PERR("Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+	mutex_lock(&smi130_acc->acc_sensor_buff);
 	err = smi_acc_read_bootsampl(smi130_acc, enable);
+	mutex_unlock(&smi130_acc->acc_sensor_buff);
 	if (err)
 		return err;
 
@@ -6961,6 +6965,7 @@
 static void store_acc_boot_sample(struct smi130_acc_data *client_data,
 				int x, int y, int z, struct timespec ts)
 {
+	mutex_lock(&client_data->acc_sensor_buff);
 	if (false == client_data->acc_buffer_smi130_samples)
 		return;
 	if (ts.tv_sec <  client_data->max_buffer_time) {
@@ -6985,6 +6990,7 @@
 			smi130_acc_set_mode(client_data->smi130_acc_client,
 					SMI_ACC2X2_MODE_SUSPEND, 1);
 	}
+	mutex_unlock(&client_data->acc_sensor_buff);
 }
 #else
 static void store_acc_boot_sample(struct smi130_acc_data *client_data,
@@ -7055,6 +7061,8 @@
 
 	smi130_set_cpu_idle_state(true);
 
+	mutex_init(&client_data->acc_sensor_buff);
+
 	smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1);
 	smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ);
 	smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G);
diff --git a/drivers/input/sensors/smi130/smi130_gyro_driver.c b/drivers/input/sensors/smi130/smi130_gyro_driver.c
index e497a0a8..51f55a4 100644
--- a/drivers/input/sensors/smi130/smi130_gyro_driver.c
+++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c
@@ -300,6 +300,7 @@
 	int max_buffer_time;
 	struct input_dev *gyrobuf_dev;
 	int report_evt_cnt;
+	struct mutex gyro_sensor_buff;
 #endif
 };
 
@@ -1521,8 +1522,8 @@
 {
 	int i = 0;
 
+	client_data->gyro_buffer_smi130_samples = false;
 	if (enable_read) {
-		client_data->gyro_buffer_smi130_samples = false;
 		for (i = 0; i < client_data->gyro_bufsample_cnt; i++) {
 			if (client_data->debug_level & 0x08)
 				PINFO("gyro=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n",
@@ -1588,7 +1589,9 @@
 		PERR("Invalid value of input, input=%ld\n", enable);
 		return -EINVAL;
 	}
+	mutex_lock(&client_data->gyro_sensor_buff);
 	err = smi_gyro_read_bootsampl(client_data, enable);
+	mutex_unlock(&client_data->gyro_sensor_buff);
 	if (err)
 		return err;
 	client_data->read_gyro_boot_sample = enable;
@@ -1738,6 +1741,7 @@
 static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data,
 			int x, int y, int z, struct timespec ts)
 {
+	mutex_lock(&client_data->gyro_sensor_buff);
 	if (false == client_data->gyro_buffer_smi130_samples)
 		return;
 	if (ts.tv_sec <  client_data->max_buffer_time) {
@@ -1763,6 +1767,7 @@
 			smi130_gyro_delay(5);
 		}
 	}
+	mutex_unlock(&client_data->gyro_sensor_buff);
 }
 #else
 static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data,
@@ -1832,6 +1837,7 @@
 	client_data->gyro_buffer_smi130_samples = true;
 	client_data->gyro_enable = false;
 
+	mutex_init(&client_data->gyro_sensor_buff);
 	smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL);
 	smi130_gyro_delay(5);
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index c9c8c50..1e620a9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1444,4 +1444,12 @@
 
 		  If unusre, say N.
 
+config TOUCHSCREEN_RAYDIUM_CHIPSET
+	bool "Raydium WT030 touchpanel CHIPSET"
+	depends on I2C
+	help
+	  Say Y here if you have a Raydium WT030 CHIPSET touchscreen.
+
+	  If unsure, say N.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a76b17f..59cf967 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -108,3 +108,4 @@
 obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28)		+= gt9xx_v2.8/
 obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET)	+= hxchipset/
 obj-$(CONFIG_TOUCHSCREEN_EKTF3XXX_CHIPSET) += ektf3xxx/
+obj-$(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET)  += raydium_wt030/
diff --git a/drivers/input/touchscreen/raydium_wt030/Makefile b/drivers/input/touchscreen/raydium_wt030/Makefile
new file mode 100644
index 0000000..982214b
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the touchscreen raydium drivers.
+#
+obj-$(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET) += raydium_driver.o raydium_sysfs.o raydium_fw_update.o
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.c b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c
new file mode 100644
index 0000000..c101c1f
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c
@@ -0,0 +1,2473 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_driver.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/device.h>
+#include <linux/kprobes.h>
+#include <asm/traps.h>
+#include <linux/firmware.h>
+#include <linux/of_gpio.h>
+#include "raydium_driver.h"
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif /*end of CONFIG_FB*/
+
+struct raydium_slot_status {
+	unsigned char pt_id;      /*Occupied point ID*/
+	unsigned char need_update;         /*Mark as info need to be updated*/
+	unsigned char pt_report_offset;    /*point info offset in report*/
+};
+/*The first 3 elements are currently occupied. therest is new coming points*/
+struct raydium_slot_status gst_slot[MAX_TOUCH_NUM * 2];
+struct raydium_slot_status gst_slot_init = {0xFF, 0, 0};
+
+unsigned char g_u8_addr;
+unsigned char g_u8_raydium_flag;
+unsigned char g_u8_i2c_mode;
+unsigned char g_u8_upgrade_type;
+unsigned char g_u8_raw_data_type;
+unsigned int g_u32_raw_data_len;    /* 72 bytes*/
+unsigned long g_u32_addr;
+unsigned int g_u32_length;
+unsigned int g_u32_driver_version;
+unsigned char *g_rad_fw_image, *g_rad_init_image;
+unsigned char *g_rad_boot_image, *g_rad_para_image;
+unsigned char *g_rad_testfw_image, *g_rad_testpara_image;
+unsigned char g_u8_table_setting, g_u8_table_init;
+unsigned char g_u8_resetflag;
+#ifdef ESD_SOLUTION_EN
+unsigned char g_u8_checkflag;
+#endif
+#ifdef ENABLE_DUMP_DATA
+unsigned char g_u8_dumpcount;
+unsigned char g_u8_dump_flag;
+unsigned char g_u8_palm_flag;
+unsigned long timeout;
+#endif
+struct raydium_ts_data *g_raydium_ts;
+
+/*****************************************************************************
+ *  Name: raydium_variable_init
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void raydium_variable_init(void)
+{
+	g_u8_addr = RAYDIUM_PDA2_PDA_CFG_ADDR;
+	g_u8_raydium_flag = 0;
+	g_u8_i2c_mode = PDA2_MODE;
+	g_u8_upgrade_type = 0;
+	g_u8_raw_data_type = RAYDIUM_FT_UPDATE;
+	g_u32_raw_data_len = 36 * 2;    /* 72 bytes*/
+	g_u32_addr = RAD_CHK_I2C_CMD;
+	g_u32_length = 1;
+	g_u8_table_setting = 0;
+	g_u8_table_init = 0;
+	g_rad_fw_image = NULL;
+	g_rad_init_image = NULL;
+	g_rad_boot_image = NULL;
+	g_rad_para_image = NULL;
+	g_rad_testfw_image = NULL;
+	g_rad_testpara_image = NULL;
+	g_u32_driver_version = ((RAD_MAIN_VERSION <<  24) |
+				(RAD_MINOR_VERSION << 16) |
+				(RAD_CUSTOMER_VERSION));
+	g_u8_resetflag = false;
+#ifdef ESD_SOLUTION_EN
+	g_u8_checkflag = false;
+#endif
+#ifdef ENABLE_DUMP_DATA
+	g_u8_dumpcount = 0;
+	g_u8_dump_flag = false;
+	g_u8_palm_flag = false;
+#endif
+}
+
+/*****************************************************************************
+ *  Name: raydium_gpio_configure
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int raydium_gpio_configure(bool on)
+{
+	int i32_err = 0;
+
+	if (on) {
+		if (gpio_is_valid(g_raydium_ts->irq_gpio)) {
+			i32_err = gpio_request(g_raydium_ts->irq_gpio,
+					   "raydium_irq_gpio");
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]irq gpio request failed");
+				goto err_irq_gpio_req;
+			}
+
+			i32_err = gpio_direction_input(g_raydium_ts->irq_gpio);
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]set_direction for irq gpio failed\n");
+				goto err_irq_gpio_dir;
+			}
+		}
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+			i32_err = gpio_request(g_raydium_ts->rst_gpio,
+					   "raydium_rst_gpio");
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]rst gpio request failed");
+				goto err_irq_gpio_req;
+			}
+
+			i32_err = gpio_direction_output(g_raydium_ts->rst_gpio,
+									1);
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]set_direction for irq gpio failed\n");
+				goto err_rst_gpio_dir;
+			}
+		}
+	} else {
+		if (gpio_is_valid(g_raydium_ts->irq_gpio))
+			gpio_free(g_raydium_ts->irq_gpio);
+	}
+
+	return 0;
+
+err_rst_gpio_dir:
+	if (gpio_is_valid(g_raydium_ts->rst_gpio))
+		gpio_free(g_raydium_ts->rst_gpio);
+	return i32_err;
+err_irq_gpio_dir:
+	if (gpio_is_valid(g_raydium_ts->irq_gpio))
+		gpio_free(g_raydium_ts->irq_gpio);
+err_irq_gpio_req:
+	return i32_err;
+}
+
+/*****************************************************************************
+ *  Name: raydium_ts_pinctrl_init
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+#ifdef MSM_NEW_VER
+static int raydium_ts_pinctrl_init(void)
+{
+	int i32_ret;
+
+	/* Get pinctrl if target uses pinctrl */
+	g_raydium_ts->ts_pinctrl = devm_pinctrl_get(&(g_raydium_ts->client->dev));
+	if (IS_ERR_OR_NULL(g_raydium_ts->ts_pinctrl)) {
+		i32_ret = PTR_ERR(g_raydium_ts->ts_pinctrl);
+		pr_err("[touch]target does not use pinctrl %d\n", i32_ret);
+		goto err_pinctrl_get;
+	}
+
+	g_raydium_ts->pinctrl_state_active
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl,
+						PINCTRL_STATE_ACTIVE);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_active)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_active);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+				PINCTRL_STATE_ACTIVE, i32_ret);
+		goto err_pinctrl_lookup;
+	}
+
+	g_raydium_ts->pinctrl_state_suspend
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl,
+					       PINCTRL_STATE_SUSPEND);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_suspend)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_suspend);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+				PINCTRL_STATE_SUSPEND, i32_ret);
+		goto err_pinctrl_lookup;
+	}
+
+	g_raydium_ts->pinctrl_state_release
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl,
+						PINCTRL_STATE_RELEASE);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_release);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+				PINCTRL_STATE_RELEASE, i32_ret);
+	}
+
+	return 0;
+
+err_pinctrl_lookup:
+	devm_pinctrl_put(g_raydium_ts->ts_pinctrl);
+err_pinctrl_get:
+	g_raydium_ts->ts_pinctrl = NULL;
+	return i32_ret;
+}
+#endif/*end of MSM_NEW_VER*/
+
+int wait_irq_state(struct i2c_client *client, unsigned int retry_time,
+				unsigned int u32_delay_us)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry;
+	unsigned int u32_irq_value;
+	unsigned int u32_min_delay_us = u32_delay_us - 500;
+	unsigned int u32_max_delay_us = u32_delay_us + 500;
+
+	u32_retry = retry_time;
+	u32_irq_value = 0;
+	while (u32_retry != 0 && u32_irq_value != 1) {
+		u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio);
+		usleep_range(u32_min_delay_us, u32_max_delay_us);
+		u32_retry--;
+	}
+	pr_debug("[touch]irq_value is %d\n", u32_irq_value);
+
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, FW not ready, retry error!\n", __func__);
+		i32_ret = ERROR;
+	}
+
+	return i32_ret;
+}
+
+#ifdef ESD_SOLUTION_EN
+static int raydium_hw_reset_fun(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+
+	pr_debug("[touch]HW reset\n");
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(DISABLE);
+
+	g_u8_resetflag = true;
+	/*HW reset*/
+	gpio_set_value(g_raydium_ts->rst_gpio, 1);
+	gpio_set_value(g_raydium_ts->rst_gpio, 0);
+	msleep(RAYDIUM_RESET_INTERVAL_MSEC);
+	gpio_set_value(g_raydium_ts->rst_gpio, 1);
+
+	g_u8_i2c_mode = PDA2_MODE;
+
+	i32_ret = wait_irq_state(client, 300, 2000);
+	if (i32_ret != ERROR)
+		msleep(25);
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(ENABLE);
+
+	pr_debug("[touch]Raydium HW reset : %d\n", i32_ret);
+	return i32_ret;
+}
+#endif
+int raydium_i2c_pda_set_address(unsigned int u32_address,
+				       unsigned char u8_mode)
+{
+	int i32_ret = 0;
+	unsigned char u8_retry;
+	unsigned char u8_buf[RAD_I2C_PDA_ADDRESS_LENGTH];
+	struct i2c_client *client = g_raydium_ts->client;
+
+	client->addr = RAYDIUM_I2C_EID;
+	u8_buf[0] = (u32_address & 0x0000FF00) >> 8;
+	u8_buf[1] = (u32_address & 0x00FF0000) >> 16;
+	u8_buf[2] = (u32_address & 0xFF000000) >> 24;
+	u8_buf[3] = u8_mode;
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		i32_ret = i2c_master_send(client, u8_buf,
+					 RAD_I2C_PDA_ADDRESS_LENGTH);
+		if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH) {
+			pr_err("[touch]%s: I2C retry %d\n",
+					__func__, u8_retry + 1);
+			usleep_range(500, 1500);
+		} else {
+			break;
+		}
+	}
+
+	return (i32_ret == RAD_I2C_PDA_ADDRESS_LENGTH) ? i32_ret : -EIO;
+}
+
+/*device attribute raydium_i2c_pda2_mode used*/
+int raydium_i2c_pda_read(struct i2c_client *client,
+				unsigned int u32_addr, unsigned char *u8_r_data,
+				unsigned short u16_length)
+{
+	int i32_ret;
+	unsigned char u8_retry;
+	unsigned char u8_mode = 0x00;
+	unsigned char u8_buf;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = 1,
+			.buf = &u8_buf,
+		},
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_READ,
+			.len = u16_length,
+			.buf = u8_r_data,
+		},
+	};
+
+	if (u16_length == 4)
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE |
+			RAD_I2C_PDA_MODE_WORD_MODE;
+	else
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE;
+
+	u8_mode |= 0x03;
+
+	u8_buf = u32_addr & MASK_8BIT;
+
+	i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode);
+	if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH)
+		goto exit;
+	usleep_range(50, 80);
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) {
+			i32_ret = u16_length;
+			break;
+		}
+		pr_err("%s: I2C retry %d\n", __func__, u8_retry + 1);
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("%s: I2C read over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+exit:
+	return i32_ret;
+}
+
+int raydium_i2c_pda_write(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_w_data,
+			unsigned short u16_length)
+{
+	int i32_ret;
+	unsigned char u8_retry;
+	unsigned char u8_mode = 0x00;
+	unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = u16_length + 1,
+			.buf = u8_buf,
+		},
+	};
+
+	if (u16_length > MAX_WRITE_PACKET_SIZE)
+		return -EINVAL;
+
+	if (u16_length == 4)
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE |
+			RAD_I2C_PDA_MODE_WORD_MODE;
+	else
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE;
+
+	u8_buf[0] = u32_addr & MASK_8BIT;
+	memcpy(&u8_buf[1], u8_w_data, u16_length);
+
+	i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode);
+	if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH)
+		goto exit;
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(client->adapter, msg, 1) == 1) {
+			i32_ret = u16_length;
+			break;
+		}
+		pr_err("[touch]%s: I2C retry %d\n", __func__, u8_retry + 1);
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+exit:
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_set_page(struct i2c_client *client,
+					unsigned int is_suspend,
+					unsigned char u8_page)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+	unsigned int u8_ret = (is_suspend) ? 10 : 2;
+	unsigned char u8_buf[RAYDIUM_I2C_PDA2_PAGE_LENGTH];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = RAYDIUM_I2C_PDA2_PAGE_LENGTH,
+			.buf = u8_buf,
+		},
+	};
+
+	u8_buf[0] = RAYDIUM_PDA2_PAGE_ADDR;
+	u8_buf[1] = u8_page;
+	for (; u8_ret > 0; u8_ret--) {
+		for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+			if (i2c_transfer(client->adapter, msg, 1) == 1) {
+				i32_ret = RAYDIUM_I2C_PDA2_PAGE_LENGTH;
+				break;
+			}
+			usleep_range(500, 1500);
+	}
+		if (i32_ret == RAYDIUM_I2C_PDA2_PAGE_LENGTH)
+			break;
+		usleep_range(2000, 5000);
+	}
+
+	if (u8_ret == 0) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_read(struct i2c_client *client,
+				 unsigned char u8_addr,
+				 unsigned char *u8_r_data,
+				 unsigned short u16_length)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = 1,
+			.buf = &u8_addr,
+		},
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_READ,
+			.len = u16_length,
+			.buf = u8_r_data,
+		},
+	};
+	g_u8_i2c_mode = PDA2_MODE;
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) {
+			i32_ret = u16_length;
+			break;
+		}
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C read over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_write(struct i2c_client *client,
+				  unsigned char u8_addr,
+				  unsigned char *u8_w_data,
+				  unsigned short u16_length)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+	unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = u16_length + 1,
+			.buf = u8_buf,
+		},
+	};
+
+	if (u16_length > MAX_WRITE_PACKET_SIZE)
+		return -EINVAL;
+	g_u8_i2c_mode = PDA2_MODE;
+	u8_buf[0] = u8_addr;
+	memcpy(&u8_buf[1], u8_w_data, u16_length);
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(client->adapter, msg, 1) == 1) {
+			i32_ret = u16_length;
+			break;
+		}
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+void raydium_irq_control(bool enable)
+{
+	if (enable) {
+		if (g_raydium_ts->irq_enabled) {
+			/*mutex_unlock(&ts->lock);*/
+			dev_info(&g_raydium_ts->client->dev,
+				"[touch]Already enable irq\n");
+			return;
+		}
+
+		/* Clear interrupts first */
+		if (g_raydium_ts->blank != FB_BLANK_POWERDOWN &&
+				g_u8_i2c_mode == PDA2_MODE) {
+			mutex_lock(&g_raydium_ts->lock);
+			if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0) < 0)
+				pr_err("[touch]set page fail%s\n",
+						__func__);
+			mutex_unlock(&g_raydium_ts->lock);
+			usleep_range(500, 1500);
+		}
+
+		while (g_raydium_ts->irq_desc->depth > 0) {
+			pr_debug("[touch]irq enable\n");
+			g_raydium_ts->irq_enabled = true;
+			enable_irq(g_raydium_ts->irq);
+		}
+	} else {
+		if (g_raydium_ts->irq_enabled &&
+			g_raydium_ts->irq_desc->depth == 0) {
+			disable_irq(g_raydium_ts->irq);
+			g_raydium_ts->irq_enabled = false;
+			pr_debug("[touch]irq disable\n");
+		}
+	}
+}
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+
+int raydium_i2c_mode_control(struct i2c_client *client,
+				    unsigned char u8_mode)
+{
+	unsigned char u8_buf[4];
+
+	switch (u8_mode) {
+	case 0:	/* Disable INT flag */
+		pr_debug("[touch]RAD INT flag : %d\n",
+				g_raydium_ts->irq_enabled);
+		disable_irq(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = false;
+		pr_debug("[touch]RAD irq disable\n");
+		break;
+	case 1:	/* Enable INT flag */
+		pr_debug("[touch]RAD INT flag : %d\n",
+				g_raydium_ts->irq_enabled);
+		enable_irq(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = true;
+		pr_debug("[touch]RAD irq enable\n");
+		break;
+	case 2: /* Disable INT by raydium_irq_control */
+		raydium_irq_control(DISABLE);
+		break;
+	case 3: /* Enable INT by raydium_irq_control */
+		raydium_irq_control(ENABLE);
+		break;
+	case 4: /* Show RAD INT depth */
+		pr_debug("[touch]RAD INT depth : %d\n",
+				g_raydium_ts->irq_desc->depth);
+		break;
+	case 7:
+		raydium_i2c_pda2_set_page(client,
+				g_raydium_ts->is_suspend, RAYDIUM_PDA2_2_PDA);
+		g_u8_i2c_mode = PDA_MODE;
+		pr_debug("[touch]Disable PDA2_MODE\n");
+		break;
+	case 8:
+		raydium_i2c_pda_read(client, RAD_PDA2_CTRL_CMD, u8_buf, 4);
+		u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2;
+		raydium_i2c_pda_write(client, RAD_PDA2_CTRL_CMD, u8_buf, 4);
+		raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+		g_u8_i2c_mode = PDA2_MODE;
+		pr_debug("[touch]Enable PDA2_MODE\n");
+		break;
+	}
+	return 0;
+}
+
+
+static const struct attribute_group raydium_attr_group = {
+	.attrs = raydium_attributes
+};
+
+/*create sysfs for debug update firmware*/
+static int raydium_create_sysfs(struct i2c_client *client)
+{
+	int ret = -1;
+
+	ret = sysfs_create_group(&(client->dev.kobj), &raydium_attr_group);
+	if (ret) {
+		pr_err("[touch]failed to register sysfs\n");
+		sysfs_remove_group(&client->dev.kobj, &raydium_attr_group);
+		ret = -EIO;
+	} else {
+		pr_debug("[touch]create raydium sysfs attr_group successful\n");
+	}
+	return ret;
+}
+
+static void raydium_release_sysfs(struct i2c_client *client)
+{
+	sysfs_remove_group(&client->dev.kobj, &raydium_attr_group);
+}
+#endif /*end of CONFIG_RM_SYSFS_DEBUG*/
+
+#ifdef ESD_SOLUTION_EN
+int raydium_esd_check(void)
+{
+	int i32_ret = 0;
+	unsigned char u8_esd_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_w_data[4];
+
+	mutex_lock(&g_raydium_ts->lock);
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+			g_raydium_ts->is_suspend,
+			RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit;
+		/*read esd status*/
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+				u8_esd_status, MAX_TCH_STATUS_PACKET_SIZE);
+		if (i32_ret < 0) {
+			pr_err("[touch]%s: failed to read data: %d\n",
+				__func__, __LINE__);
+			goto exit;
+		}
+
+		if (u8_esd_status[POS_FW_STATE] != 0x1A &&
+			u8_esd_status[POS_FW_STATE] != 0xAA) {
+			if (g_u8_resetflag == true) {
+				pr_err("[touch]%s -> filter abnormal irq\n"
+					, __func__);
+				goto exit;
+			}
+			pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n",
+			__func__, u8_esd_status[POS_FW_STATE]);
+			g_u8_resetflag = false;
+			i32_ret = -1;
+			goto exit;
+
+		}
+		u8_w_data[POS_SEQ] = 0;
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+					u8_w_data, 1);
+		if (i32_ret < 0) {
+			pr_err("[touch]%s: failed to clear seq: %d\n",
+				__func__, __LINE__);
+			goto exit;
+		}
+		g_u8_resetflag = false;
+	}
+exit:
+	mutex_unlock(&g_raydium_ts->lock);
+	pr_debug("[touch] raydium_esd_check\n");
+	return i32_ret;
+}
+#endif
+
+
+#ifdef ENABLE_DUMP_DATA
+int raydium_dump_data(unsigned char u8_frame, unsigned char u8_type)
+{
+	unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE*2];
+	short i16_data_buffer[MAX_READ_PACKET_SIZE*2];
+	unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH];
+	unsigned int u32_target_addr;
+	unsigned int u32_offset;
+	unsigned short u16_read_length;
+	int i32_ret = -1;
+	int i32_retry = 0;
+	unsigned char u8_i, u8_j, u8_k;
+	char write_string[1000];
+
+	pr_debug("[touch] %s -> type:%d\n", __func__, u8_type);
+
+	for (u8_i = 0; u8_i < u8_frame; u8_i++) {
+
+		u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+		u8_w_data[RAD_FT_CMD_POS] = u8_type;
+
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_HOST_CMD_ADDR,
+					u8_w_data, RAYDIUM_FT_CMD_LENGTH);
+
+		memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE*2);
+		/* make sure update flag was set*/
+		for (i32_retry = 0; i32_retry < 5; i32_retry++) {
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+							g_raydium_ts->is_suspend,
+							RAYDIUM_PDA2_PAGE_0);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer,
+						RAYDIUM_FT_CMD_LENGTH);
+			if (i32_ret < 0)
+				goto exit_flag_error;
+
+			if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE) ==
+					RAYDIUM_FT_UPDATE)
+				break;
+
+			usleep_range(4500, 5500);
+		}
+
+		if (i32_retry == 5) {
+			i32_ret = -EAGAIN;
+			pr_err("[touch] %s -> flag timeout\n", __func__);
+		}
+
+		u32_offset = 0;
+		u16_read_length = 0;
+#if DATA_MAP_5_5
+		g_u32_raw_data_len = 0x32;
+#else
+		g_u32_raw_data_len = 0x48;
+#endif
+		while (u32_offset < g_u32_raw_data_len) {
+			u16_read_length = g_u32_raw_data_len;
+
+			u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset;
+
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+							g_raydium_ts->is_suspend,
+							RAYDIUM_PDA2_PAGE_0);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			*(unsigned int *)u8_rbuffer =
+				(RAD_I2C_PDA_MODE_ENABLE << 24)
+				| ((u32_target_addr & (~MASK_8BIT)) >> 8);
+
+			/*using byte mode to read 4 bytes*/
+			i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_PDA_CFG_ADDR,
+					u8_rbuffer, 4);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_ENABLE_PDA);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+					(unsigned char)(u32_target_addr
+						& MASK_8BIT), u8_rbuffer,
+					u16_read_length);
+			if (i32_ret < 0)
+				goto exit_flag_error;
+
+			memcpy((i16_data_buffer + u32_offset),
+				u8_rbuffer,
+				u16_read_length);
+
+			u32_offset += u16_read_length;
+		}
+		pr_debug("[touch] frame%d\n", u8_i);
+#if DATA_MAP_5_5
+		for (u8_j = 0; u8_j < 25; u8_j += 5) {
+			pr_debug("[touch] %4d, %4d, %4d, %4d, %4d\r\n",
+			i16_data_buffer[u8_j], i16_data_buffer[u8_j+1],
+			i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3],
+			i16_data_buffer[u8_j+4]);
+		}
+#else
+		for (u8_j = 0; u8_j < 36; u8_j += 6) {
+			pr_debug("[touch] %4d, %4d, %4d, %4d, %4d, %4d\r\n",
+			i16_data_buffer[u8_j], i16_data_buffer[u8_j+1],
+			i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3],
+			i16_data_buffer[u8_j+4], i16_data_buffer[u8_j+5]);
+		}
+#endif
+		/* clear update flag to get next one*/
+		u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+		u8_rbuffer[RAD_FT_CMD_POS] = u8_type;
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_rbuffer, RAYDIUM_FT_CMD_LENGTH);
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+	}
+	return 0;
+exit_i2c_error:
+	pr_err("%s exit_i2c_error return %d\r\n", __func__, i32_ret);
+exit_flag_error:
+	return i32_ret;
+}
+
+static void raydium_dump_data_work(struct work_struct *work)
+{
+
+	int i32_ret = 0;
+	unsigned char u8_data_type;
+	unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH];
+
+	/* set mode */
+	memset(u8_w_data, 0x00, RAYDIUM_FT_CMD_LENGTH);
+	pr_debug("[touch] raydium_dump_data_work\n");
+
+	disable_irq_nosync(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = false;
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_FT_MODE;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, 1);
+	if (i32_ret < 0)
+		goto exit_error;
+	pr_debug("[touch] RAYDIUM_HOST_CMD_FT_MODE\n");
+
+	/*baseline*/
+	u8_data_type = 0x02;
+	raydium_dump_data(1, u8_data_type);
+	u8_data_type = 0x04;
+	raydium_dump_data(1, u8_data_type);
+	u8_data_type = 0x10;
+	raydium_dump_data(10, u8_data_type);
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_TP_MODE;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, 1);
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_w_data[RAD_FT_CMD_POS] = 0;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, RAD_FT_CMD_LENGTH);
+	if (i32_ret < 0)
+		goto exit_error;
+
+exit_error:
+	enable_irq(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = true;
+}
+
+#endif
+#ifdef FILTER_POINTS
+int raydium_pointer_filter(int i32_index,
+			unsigned short u16_diff_x,
+			unsigned short u16_diff_y)
+{
+	if (abs(ts->x_pos[i32_index] - ts->last_x_pos[i32_index]) > u16_diff_x)
+		return 0;
+	if (abs(ts->y_pos[i32_index] - ts->last_y_pos[i32_index]) > u16_diff_y)
+		return 0;
+
+	return 1;
+}
+#endif
+
+#ifdef HOST_NOTIFY_EN
+int raydium_notify_function(unsigned short u16_display_mode)
+{
+	int i32_ret = 0;
+	unsigned char u8_rbuffer[4];
+
+	mutex_lock(&g_raydium_ts->lock);
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit;
+		memset(u8_rbuffer, 0, sizeof(u8_rbuffer));
+
+		u8_rbuffer[0] = RAYDIUM_HOST_CMD_DISPLAY_MODE;
+		u8_rbuffer[2] = (unsigned char) (u16_display_mode & 0x00ff);
+		u8_rbuffer[3] = (unsigned char) ((u16_display_mode & 0xff00) >> 8);
+		pr_debug("[touch] display mode %d %d %d\r\n", u16_display_mode,
+					u8_rbuffer[2], u8_rbuffer[3]);
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_HOST_CMD_ADDR,
+					u8_rbuffer, 4);
+	}
+exit:
+	mutex_unlock(&g_raydium_ts->lock);
+	pr_debug("[touch] raydium_notify_function\n");
+	return i32_ret;
+}
+#endif
+static int raydium_touch_report(unsigned char *p_u8_buf,
+				unsigned char u8_points_amount)
+{
+	unsigned char u8_i, u8_j, u8_offset = 0, u8_pt_id;
+	signed short i16_wx, i16_wy;
+	/* number of touch points */
+	unsigned char u8_touch_count = 0;
+	DECLARE_BITMAP(ids, g_raydium_ts->u8_max_touchs);
+
+	bitmap_zero(ids, g_raydium_ts->u8_max_touchs);
+
+	for (u8_i = 0; u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) {
+		gst_slot[u8_i].need_update = 0;
+		gst_slot[u8_i].pt_report_offset = 0;
+	}
+
+	/*Check incoming point info*/
+	for (u8_i = 0; u8_i < u8_points_amount; u8_i++) {
+		u8_pt_id = p_u8_buf[POS_PT_ID + u8_i * LEN_PT];
+		/* Current*/
+		for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) {
+			if (u8_pt_id == gst_slot[u8_j].pt_id) {
+				gst_slot[u8_j].need_update = 1;
+				gst_slot[u8_j].pt_report_offset = u8_i;
+				break;
+			}
+		}
+		/* New coming*/
+		if (u8_j == g_raydium_ts->u8_max_touchs) {
+			for (u8_j = g_raydium_ts->u8_max_touchs;
+				u8_j < (g_raydium_ts->u8_max_touchs * 2); u8_j++) {
+				if (!gst_slot[u8_j].need_update) {
+					gst_slot[u8_j].pt_id = u8_pt_id;
+					gst_slot[u8_j].need_update = 1;
+					gst_slot[u8_j].pt_report_offset = u8_i;
+					pr_debug("[touch]x:%d,y:%d\n",
+					p_u8_buf[POS_X_L + u8_offset] |
+					p_u8_buf[POS_X_H + u8_offset] << 8,
+					p_u8_buf[POS_Y_L + u8_offset] |
+					p_u8_buf[POS_Y_H + u8_offset] << 8);
+					break;
+				}
+			}
+		}
+	}
+
+	/*Release slot with non-occupied point*/
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (!gst_slot[u8_i].need_update) {
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, false);
+			gst_slot[u8_i].pt_id = 0xFF;
+			gst_slot[u8_i].pt_report_offset = 0;
+			gst_slot[u8_i].need_update = 0;
+		}
+	}
+	/*Assign new one to non-occupied slot*/
+	for (u8_i = g_raydium_ts->u8_max_touchs;
+		u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) {
+				if (!gst_slot[u8_j].need_update) {
+					gst_slot[u8_j] = gst_slot[u8_i];
+					gst_slot[u8_i] = gst_slot_init;
+					break;
+				}
+			}
+		} else {
+			break;
+		}
+	}
+#ifdef FILTER_POINTS
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT;
+			g_raydium_ts->x_pos[i] =  p_u8_buf[POS_X_L + u8_offset] |
+				p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->y_pos[i] = p_u8_buf[POS_Y_L + u8_offset] |
+				p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] |
+			p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT;
+			i16_wx = p_u8_buf[POS_WX_L + u8_offset] |
+				p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT;
+			i16_wy = p_u8_buf[POS_WY_L + u8_offset] |
+				p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT;
+
+		if (!raydium_pointer_filter(g_raydium_ts, u8_i, DELTA_X, DELTA_Y)) {
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, true);
+			__set_bit(i, ids);
+
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_PRESSURE, g_raydium_ts->pressure);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy));
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy));
+			input_report_key(g_raydium_ts->input_dev,
+				BTN_TOUCH, 1);
+			input_report_key(g_raydium_ts->input_dev,
+				BTN_TOOL_FINGER, 1);
+			input_sync(g_raydium_ts->input_dev);
+			g_raydium_ts->last_x_pos[u8_i] = g_raydium_ts->x_pos[u8_i];
+			g_raydium_ts->last_y_pos[u8_i] = g_raydium_ts->y_pos[u8_i];
+		} else {
+			g_raydium_ts->x_pos[u8_i] = g_raydium_ts->last_x_pos[u8_i];
+			g_raydium_ts->y_pos[u8_i] = g_raydium_ts->last_y_pos[u8_i];
+		}
+		}
+	}
+
+	if ((gst_slot[0].need_update == 0) &&
+		(gst_slot[1].need_update == 0)) {
+		for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+			if (test_bit(u8_i, ids))
+				continue;
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, false);
+		}
+		input_report_key(g_raydium_ts->input_dev, BTN_TOUCH, 0);
+		input_report_key(g_raydium_ts->input_dev, BTN_TOOL_FINGER, 0);
+		input_sync(g_raydium_ts->input_dev);
+	}
+#else
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT;
+			g_raydium_ts->x_pos[u8_i] = p_u8_buf[POS_X_L + u8_offset] |
+				p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->y_pos[u8_i] = p_u8_buf[POS_Y_L + u8_offset] |
+				p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] |
+			p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT;
+			i16_wx = p_u8_buf[POS_WX_L + u8_offset] |
+				p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT;
+			i16_wy = p_u8_buf[POS_WY_L + u8_offset] |
+				p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT;
+
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, true);
+			__set_bit(u8_i, ids);
+
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_PRESSURE, g_raydium_ts->pressure);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy));
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy));
+
+			u8_touch_count++;
+		}
+	}
+	input_report_key(g_raydium_ts->input_dev,
+				BTN_TOUCH, u8_touch_count > 0);
+	input_report_key(g_raydium_ts->input_dev,
+				BTN_TOOL_FINGER, u8_touch_count > 0);
+
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (test_bit(u8_i, ids))
+			continue;
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+			MT_TOOL_FINGER, false);
+	}
+
+	input_sync(g_raydium_ts->input_dev);
+#endif
+	return 0;
+}
+int raydium_read_touchdata(unsigned char *p_u8_tp_status,
+		unsigned char *p_u8_buf)
+{
+	int i32_ret = 0;
+	unsigned char u8_points_amount;
+	static unsigned char u8_seq_no;
+	unsigned char u8_retry;
+
+	u8_retry = 3;
+
+	mutex_lock(&g_raydium_ts->lock);
+	while (u8_retry != 0) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0) {
+			msleep(250);
+			u8_retry--;
+		} else
+			break;
+	}
+	if (u8_retry == 0) {
+		pr_err("[touch]%s: failed to set page, hw reset\n", __func__);
+
+		goto reset_error;
+	}
+
+	memset(p_u8_buf, 0, MAX_REPORT_PACKET_SIZE);
+	memset(p_u8_tp_status, 0, MAX_TCH_STATUS_PACKET_SIZE);
+
+	/*read touch point information*/
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+			RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+			p_u8_tp_status, MAX_TCH_STATUS_PACKET_SIZE);
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: failed to read data: %d\n",
+				__func__, __LINE__);
+		goto exit_error;
+	}
+#ifdef ESD_SOLUTION_EN
+	if (p_u8_tp_status[POS_FW_STATE] != 0x1A &&
+		p_u8_tp_status[POS_FW_STATE] != 0xAA) {
+		if (g_u8_resetflag == true) {
+			pr_err("[touch]%s -> filter irq, FW state = 0x%x\n",
+					__func__, p_u8_tp_status[POS_FW_STATE]);
+			i32_ret = -1;
+			g_u8_resetflag = false;
+			goto exit_error;
+		}
+		pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n",
+				__func__, p_u8_tp_status[POS_FW_STATE]);
+		i32_ret = -1;
+		goto reset_error;
+
+	}
+#endif
+	/* inform IC to prepare next report*/
+	if (u8_seq_no == p_u8_tp_status[POS_SEQ]) {
+		pr_err("%s -> report not updated.\n", __func__);
+		goto exit_error;
+	}
+	u8_points_amount = p_u8_tp_status[POS_PT_AMOUNT];
+
+	if (u8_points_amount > MAX_TOUCH_NUM)
+		goto exit_error;
+
+	/*read touch point report*/
+	/*PDA2 only support word mode*/
+	if (u8_points_amount != 0)
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_TCH_RPT_ADDR, p_u8_buf,
+				u8_points_amount * LEN_PT);
+
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: failed to read data: %d\n",
+				__func__, __LINE__);
+		goto exit_error;
+	}
+
+	u8_seq_no = p_u8_tp_status[POS_SEQ];
+	p_u8_tp_status[POS_SEQ] = 0;
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+			RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, p_u8_tp_status, 1);
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: write data failed: %d\n", __func__, i32_ret);
+		goto exit_error;
+	}
+
+	raydium_touch_report(p_u8_buf, u8_points_amount);
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+
+	return i32_ret;
+
+reset_error:
+	mutex_unlock(&g_raydium_ts->lock);
+#ifdef ESD_SOLUTION_EN
+	u8_retry = 3;
+	while (u8_retry != 0) {
+		i32_ret = raydium_hw_reset_fun(g_raydium_ts->client);
+		if (i32_ret < 0) {
+			msleep(100);
+			u8_retry--;
+		} else
+			break;
+	}
+#endif
+	return i32_ret;
+}
+
+static void raydium_work_handler(struct work_struct *work)
+{
+	int i32_ret = 0;
+	unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_buf[MAX_REPORT_PACKET_SIZE];
+
+#ifdef GESTURE_EN
+	unsigned char u8_i;
+
+	if ((g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND ||
+			g_raydium_ts->blank == FB_BLANK_POWERDOWN) &&
+			(g_u8_resetflag == false)) {
+		input_mt_slot(g_raydium_ts->input_dev, 0);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+			MT_TOOL_FINGER, 1);
+		input_report_abs(g_raydium_ts->input_dev,
+					ABS_MT_POSITION_X, 100);
+		input_report_abs(g_raydium_ts->input_dev,
+					ABS_MT_POSITION_Y, 100);
+		input_sync(g_raydium_ts->input_dev);
+		usleep_range(9500, 10500);
+		input_mt_slot(g_raydium_ts->input_dev, 0);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+						MT_TOOL_FINGER, 0);
+		input_mt_report_pointer_emulation(g_raydium_ts->input_dev,
+						false);
+		input_sync(g_raydium_ts->input_dev);
+		input_report_key(g_raydium_ts->input_dev, KEY_POWER, true);
+		usleep_range(9500, 10500);
+		input_sync(g_raydium_ts->input_dev);
+
+		input_report_key(g_raydium_ts->input_dev, KEY_POWER, false);
+		input_sync(g_raydium_ts->input_dev);
+#ifdef ESD_SOLUTION_EN
+		g_u8_checkflag = true;
+#endif
+		pr_debug("[touch]display wake up with g_u8_resetflag false\n");
+	} else {
+
+		if (g_u8_i2c_mode == PDA2_MODE) {
+			i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf);
+			if (i32_ret < 0) {
+				pr_err("[touch]%s, read_touchdata error, ret:%d\n",
+					__func__, i32_ret);
+				return;
+			}
+		}
+		/*when display on can use palm to suspend*/
+		if (g_raydium_ts->blank == FB_BLANK_UNBLANK) {
+			if (u8_tp_status[POS_GES_STATUS] == RAD_PALM_ENABLE) {
+				if (g_raydium_ts->is_palm == 0) {
+					/* release all touches*/
+					for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs;
+						u8_i++) {
+						input_mt_slot(g_raydium_ts->input_dev,
+							       u8_i);
+					input_mt_report_slot_state(
+							       g_raydium_ts->input_dev,
+						MT_TOOL_FINGER, false);
+					}
+					input_mt_report_pointer_emulation(
+							g_raydium_ts->input_dev,
+							false);
+					/*press sleep key*/
+					input_report_key(g_raydium_ts->input_dev,
+						KEY_SLEEP, true);
+					input_sync(g_raydium_ts->input_dev);
+
+					pr_debug("[touch]palm_status = %d.\n",
+						u8_tp_status[POS_GES_STATUS]);
+
+					g_raydium_ts->is_palm = 1;
+					/*goto exit;*/
+				}
+			} else if ((u8_tp_status[POS_GES_STATUS]
+				== RAD_PALM_DISABLE)
+				&& (g_raydium_ts->is_palm == 1)) {
+				pr_debug("[touch]leave palm mode.\n");
+				input_report_key(g_raydium_ts->input_dev,
+						KEY_SLEEP, false);
+				input_sync(g_raydium_ts->input_dev);
+
+				/*raydium_irq_control(raydium_ts, DISABLE);*/
+				g_raydium_ts->is_palm = 0;
+				/*goto exit;*/
+			}
+		} else if (g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND ||
+				g_raydium_ts->blank == FB_BLANK_POWERDOWN) {
+			/*need check small area*/
+			if (u8_tp_status[POS_GES_STATUS] == RAD_WAKE_UP) {
+				input_mt_slot(g_raydium_ts->input_dev, 0);
+				input_mt_report_slot_state(g_raydium_ts->input_dev,
+					MT_TOOL_FINGER, 1);
+				input_report_abs(g_raydium_ts->input_dev,
+						ABS_MT_POSITION_X, 100);
+				input_report_abs(g_raydium_ts->input_dev,
+						ABS_MT_POSITION_Y, 100);
+				input_sync(g_raydium_ts->input_dev);
+				usleep_range(9500, 10500);
+				input_mt_slot(g_raydium_ts->input_dev, 0);
+				input_mt_report_slot_state(g_raydium_ts->input_dev,
+					MT_TOOL_FINGER, 0);
+				input_mt_report_pointer_emulation(
+							g_raydium_ts->input_dev,
+							false);
+				input_sync(g_raydium_ts->input_dev);
+				input_report_key(g_raydium_ts->input_dev, KEY_POWER, true);
+				usleep_range(9500, 10500);
+				input_sync(g_raydium_ts->input_dev);
+
+				input_report_key(g_raydium_ts->input_dev,
+							KEY_POWER, false);
+				input_sync(g_raydium_ts->input_dev);
+				pr_debug("[touch]display wake up with g_u8_resetflag true\n");
+				/*goto exit;*/
+			}
+		}
+	}
+#else
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf);
+		if (i32_ret < 0) {
+			pr_err("[touch]%s, read_touchdata error, ret:%d\n",
+				__func__, i32_ret);
+		}
+	}
+#endif
+}
+
+/*The raydium device will signal the host about TRIGGER_FALLING.
+ *Processed when the interrupt is asserted.
+ */
+static irqreturn_t raydium_ts_interrupt(int irq, void *dev_id)
+{
+	bool result = false;
+
+	/*For bootloader wrt/erase flash and software reset interrupt*/
+	if ((g_u8_raydium_flag & ENG_MODE) != 0) {
+		disable_irq_nosync(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = false;
+		pr_debug("[touch]RAD_ENG_MODE\n");
+		g_u8_raydium_flag |= INT_FLAG;
+	} else {
+		if (!work_pending(&g_raydium_ts->work)) {
+			/* Clear interrupts*/
+			result = queue_work(g_raydium_ts->workqueue,
+					&g_raydium_ts->work);
+			if (result == false) {
+				/*queue_work fail*/
+				pr_err("[touch]queue_work fail.\n");
+			}
+		} else {
+			/*work pending*/
+			mutex_lock(&g_raydium_ts->lock);
+			if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0) < 0) {
+				pr_err("[touch]%s: failed to set page in work_pending\n",
+						__func__);
+			}
+			mutex_unlock(&g_raydium_ts->lock);
+			pr_debug("[touch]work_pending\n");
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int raydium_check_i2c_ready(unsigned short *u16_i2c_data)
+{
+	unsigned char u8_buf[4];
+	int i32_ret = -1;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+				g_raydium_ts->is_suspend,
+				RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		*(unsigned int *)u8_buf =
+			(RAD_I2C_PDA_MODE_ENABLE << 24) |
+			((RAD_CHK_I2C_CMD & (~MASK_8BIT)) >> 8);
+		/*using byte mode to read 4 bytes*/
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					     RAYDIUM_PDA2_PDA_CFG_ADDR,
+					     u8_buf,
+					     4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_read(
+				g_raydium_ts->client,
+				(unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT),
+				u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_error;
+		if (u8_buf[3] != 0xF3) {
+			pr_err("[touch]PDA2 read i2c fail\n");
+			g_u8_i2c_mode = PDA_MODE;
+			i32_ret = raydium_i2c_pda_read(g_raydium_ts->client,
+					   RAD_CHK_I2C_CMD, u8_buf,
+					   4);
+			if (i32_ret < 0)
+				goto exit_error;
+		}
+
+	} else {
+		i32_ret = raydium_i2c_pda_read(g_raydium_ts->client,
+					   RAD_CHK_I2C_CMD, u8_buf,
+					   4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+	}
+
+	*u16_i2c_data = u8_buf[3] << 8 | u8_buf[2];
+
+	pr_debug("[touch]RAD check I2C : 0x%02X%02X\n", u8_buf[3], u8_buf[2]);
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+
+#if defined(CONFIG_PM)
+static void raydium_ts_do_suspend(void)
+{
+	unsigned char u8_i = 0;
+
+	g_u8_resetflag = false;
+	if (g_raydium_ts->is_suspend == 1) {
+		pr_info("[touch]Already in suspend state\n");
+		return;
+	}
+
+	/*#ifndef GESTURE_EN*/
+	raydium_irq_control(DISABLE);
+	/*#endif*/
+
+	/*clear workqueue*/
+	if (!cancel_work_sync(&g_raydium_ts->work))
+		pr_info("[touch]workqueue is empty!\n");
+
+	pr_debug("[touch]%s.\n", __func__);
+
+	/* release all touches */
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+					   MT_TOOL_FINGER,
+					   false);
+	}
+	input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false);
+	input_sync(g_raydium_ts->input_dev);
+#ifdef ENABLE_DUMP_DATA
+	if (!g_u8_dumpcount)
+		timeout = jiffies + 2*HZ;
+	if (g_u8_dumpcount < 5)
+		g_u8_dumpcount++;
+	if (g_u8_palm_flag || (time_is_before_jiffies(timeout))) {
+		g_u8_dumpcount = 0;
+		g_u8_palm_flag = false;
+	}
+	if (g_u8_dumpcount == 5) {
+		g_u8_dump_flag = true;
+		g_u8_dumpcount = 0;
+	}
+#endif
+
+#ifdef GESTURE_EN
+	if (device_may_wakeup(&g_raydium_ts->client->dev)) {
+		pr_debug("[touch]Device may wakeup\n");
+		if (!enable_irq_wake(g_raydium_ts->irq))
+			g_raydium_ts->irq_wake = 1;
+
+	} else
+		pr_debug("[touch]Device not wakeup\n");
+	raydium_irq_control(ENABLE);
+#endif
+
+	g_raydium_ts->is_suspend = 1;
+}
+
+static void raydium_ts_do_resume(void)
+{
+#ifdef ESD_SOLUTION_EN
+	int i32_ret = 0;
+	unsigned char u8_retry = 0;
+#endif
+	unsigned char u8_w_data[4];
+
+	pr_debug("[touch]%s, %d.\n", __func__, g_raydium_ts->is_suspend);
+	if (g_raydium_ts->is_suspend == 0) {
+		pr_info("[touch]Already in resume state\n");
+		return;
+	}
+
+	/* clear interrupts*/
+	mutex_lock(&g_raydium_ts->lock);
+	if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0) < 0) {
+		pr_err("[ raydium ]%s: failed to set page\n", __func__);
+		mutex_unlock(&g_raydium_ts->lock);
+		return;
+	}
+	/* clear seq num*/
+	u8_w_data[POS_SEQ] = 0;
+	if (raydium_i2c_pda2_write(g_raydium_ts->client,
+		RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, u8_w_data, 1) < 0) {
+		pr_err("[ raydium ]%s: failed to clear seq\n", __func__);
+		mutex_unlock(&g_raydium_ts->lock);
+		return;
+	}
+
+	mutex_unlock(&g_raydium_ts->lock);
+
+	/* clear workqueue*/
+	if (!cancel_work_sync(&g_raydium_ts->work))
+		pr_info("[ raydium ]workqueue is empty!\n");
+#ifdef ESD_SOLUTION_EN
+	if (g_u8_checkflag == true) {
+		i32_ret = raydium_esd_check();
+		if (i32_ret < 0) {
+			u8_retry = 3;
+			while (u8_retry != 0) {
+				i32_ret = raydium_hw_reset_fun(g_raydium_ts->client);
+				if (i32_ret < 0) {
+					msleep(100);
+					u8_retry--;
+				} else
+					break;
+			}
+
+		}
+		g_u8_checkflag = false;
+	}
+#endif
+	raydium_irq_control(ENABLE);
+#ifdef ENABLE_DUMP_DATA
+	if (g_u8_dump_flag) {
+		schedule_delayed_work(&g_raydium_ts->dump_work, HZ);
+		g_u8_dump_flag = false;
+	}
+#endif
+#ifdef GESTURE_EN
+	if (device_may_wakeup(&g_raydium_ts->client->dev)) {
+		pr_debug("[touch]Device may wakeup\n");
+		if (g_raydium_ts->irq_wake) {
+			disable_irq_wake(g_raydium_ts->irq);
+			g_raydium_ts->irq_wake = 0;
+		}
+	} else
+		pr_debug("[touch]Device not wakeup\n");
+#endif
+
+	g_raydium_ts->is_suspend = 0;
+}
+
+static int raydium_ts_suspend(struct device *dev)
+{
+	raydium_ts_do_suspend();
+	return 0;
+}
+
+static int raydium_ts_resume(struct device *dev)
+{
+	raydium_ts_do_resume();
+	return 0;
+}
+
+static const struct dev_pm_ops raydium_ts_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+	.suspend    = raydium_ts_suspend,
+	.resume        = raydium_ts_resume,
+#endif /*end of CONFIG_PM*/
+};
+
+/*used for touch lock feature*/
+static int raydium_ts_open(struct input_dev *input_dev)
+{
+	int i32_ret = 0;
+
+	pr_debug("[touch]%s()+\n", __func__);
+
+	pr_debug("[touch]ts->blank:%x\n", g_raydium_ts->blank);
+
+	if (g_raydium_ts->is_sleep == 1) {
+		mutex_lock(&g_raydium_ts->lock);
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+
+			g_u8_resetflag = true;
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			gpio_set_value(g_raydium_ts->rst_gpio, 0);
+			msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/
+			g_u8_i2c_mode = PDA2_MODE;
+		}
+		mutex_unlock(&g_raydium_ts->lock);
+		raydium_irq_control(ENABLE);
+		g_raydium_ts->is_sleep = 0;
+		pr_debug("[touch]disable touch lock.\n");
+	}
+	return i32_ret;
+}
+
+static void raydium_ts_close(struct input_dev *input_dev)
+{
+	int i32_ret = 0;
+	unsigned char u8_i = 0;
+	unsigned char u8_wbuffer[1];
+
+	pr_debug("[touch]%s()+\n", __func__);
+
+	if (g_raydium_ts->is_sleep == 1) {
+		pr_debug("[touch]touch lock already enabled.\n");
+		return;
+	}
+
+	raydium_irq_control(DISABLE);
+
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+			MT_TOOL_FINGER,
+			false);
+	}
+	input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false);
+	input_sync(g_raydium_ts->input_dev);
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0) {
+		pr_err("[touch]ret:%d\n", i32_ret);
+		goto exit_i2c_error;
+	}
+	u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP;
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+		RAYDIUM_PDA2_HOST_CMD_ADDR,
+		u8_wbuffer,
+		1);
+	if (i32_ret < 0) {
+		pr_err("[touch]ret:%d\n", i32_ret);
+		goto exit_i2c_error;
+	}
+
+	mutex_unlock(&g_raydium_ts->lock);
+	g_raydium_ts->is_sleep = 1;
+	pr_debug("[touch]enable touch lock.\n");
+	return;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+}
+
+#else
+static int raydium_ts_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int raydium_ts_resume(struct device *dev)
+{
+	return 0;
+}
+#endif /*end of CONFIG_FB*/
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+				unsigned long event,
+				void *data)
+{
+	struct fb_event *evdata = data;
+	int *blank;
+
+	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+	    g_raydium_ts && g_raydium_ts->client) {
+		blank = evdata->data;
+		g_raydium_ts->blank = (*blank);
+		switch (*blank) {
+
+		/*screen on*/
+		case FB_BLANK_UNBLANK:
+			pr_debug("[touch]FB_BLANK_UNBLANK\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(ACTIVE_MODE);
+#endif
+			raydium_ts_resume(&g_raydium_ts->client->dev);
+			break;
+
+		/*screen off*/
+		case FB_BLANK_POWERDOWN:
+			pr_debug("[touch]FB_BLANK_POWERDOWN\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(SLEEP_MODE);
+#endif
+			raydium_ts_suspend(&g_raydium_ts->client->dev);
+			break;
+
+		/*ambient mode*/
+		case FB_BLANK_VSYNC_SUSPEND:
+			pr_debug("[touch]FB_BLANK_VSYNC_SUSPEND\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(AMBIENT_MODE);
+#endif
+			raydium_ts_suspend(&g_raydium_ts->client->dev);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void raydium_register_notifier(void)
+{
+	memset(&g_raydium_ts->fb_notif, 0, sizeof(g_raydium_ts->fb_notif));
+	g_raydium_ts->fb_notif.notifier_call = fb_notifier_callback;
+
+	/* register on the fb notifier and work with fb*/
+	if (fb_register_client(&g_raydium_ts->fb_notif))
+		pr_err("[touch]register notifier failed\n");
+}
+
+static void raydium_unregister_notifier(void)
+{
+	fb_unregister_client(&g_raydium_ts->fb_notif);
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void raydium_ts_early_suspend(struct early_suspend *handler)
+{
+
+	raydium_ts_do_suspend();
+}
+
+static void raydium_ts_late_resume(struct early_suspend *handler)
+{
+	raydium_ts_do_resume();
+}
+#endif /*end of CONFIG_FB*/
+
+#ifdef CONFIG_OF
+static int raydium_get_dt_coords(struct device *dev, char *name,
+				 struct raydium_ts_platform_data *pdata)
+{
+	u32 coords[COORDS_ARR_SIZE];
+	struct property *prop;
+	struct device_node *np = dev->of_node;
+	int coords_size, rc;
+
+	prop = of_find_property(np, name, NULL);
+	if (!prop)
+		return -EINVAL;
+
+	if (!prop->value)
+		return -ENODATA;
+
+
+	coords_size = prop->length / sizeof(u32);
+	if (coords_size != COORDS_ARR_SIZE) {
+		pr_err("[touch]invalid %s\n", name);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_array(np, name, coords, coords_size);
+	if (rc && (rc != -EINVAL)) {
+		pr_err("[touch]unable to read %s\n", name);
+		return rc;
+	}
+
+	if (!strcmp(name, "raydium,display-coords")) {
+		pdata->x_min = coords[0];
+		pdata->y_min = coords[1];
+		pdata->x_max = coords[2];
+		pdata->y_max = coords[3];
+	} else {
+		pr_err("[touch]unsupported property %s\n", name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int raydium_parse_dt(struct device *dev,
+			    struct raydium_ts_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	int rc = 0;
+	u32 temp_val = 0;
+
+	pdata->name = RAYDIUM_NAME;
+
+	rc = raydium_get_dt_coords(dev, "raydium,display-coords", pdata);
+	if (rc)
+		return rc;
+
+
+	/* reset, irq gpio info */
+	pdata->reset_gpio = of_get_named_gpio_flags(np,
+			    "raydium,reset-gpio",
+			    0,
+			    &pdata->reset_gpio_flags);
+	if (pdata->reset_gpio < 0)
+		return pdata->reset_gpio;
+
+
+	pdata->irq_gpio = of_get_named_gpio_flags(np,
+			  "raydium,irq-gpio",
+			  0,
+			  &pdata->irq_gpio_flags);
+	if (pdata->irq_gpio < 0)
+		return pdata->irq_gpio;
+
+
+	rc = of_property_read_u32(np,
+			"raydium,hard-reset-delay-ms", &temp_val);
+	if (!rc)
+		pdata->hard_rst_dly = temp_val;
+	else
+		return rc;
+
+
+	rc = of_property_read_u32(np,
+			"raydium,soft-reset-delay-ms", &temp_val);
+	if (!rc)
+		pdata->soft_rst_dly = temp_val;
+	else
+		return rc;
+
+
+	rc = of_property_read_u32(np, "raydium,num-max-touches", &temp_val);
+	if (!rc)
+		pdata->num_max_touches = temp_val;
+	else
+		return rc;
+
+#ifdef FW_MAPPING_BYID_EN
+	rc = of_property_read_u32(np, "raydium,fw_id", &temp_val);
+	if (!rc)
+		pdata->fw_id = temp_val;
+	else
+		return rc;
+#endif
+	return 0;
+}
+#else
+static int raydium_parse_dt(struct device *dev,
+			    struct raydium_ts_platform_data *pdata)
+{
+	return -ENODEV;
+}
+#endif /*end of CONFIG_OF*/
+
+static void raydium_input_set(struct input_dev *input_dev)
+{
+	int ret = 0;
+	unsigned char i;
+
+	input_dev->name = "raydium_ts";/*name need same with .idc*/
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &g_raydium_ts->client->dev;
+	input_dev->open = raydium_ts_open;/*touch lock*/
+	input_dev->close = raydium_ts_close;
+	input_set_drvdata(input_dev, g_raydium_ts);
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+	pr_debug("[touch]set abs prarams x[%d], y[%d]\n",
+		g_raydium_ts->x_max, g_raydium_ts->y_max);
+
+	/* Multitouch input params setup */
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+				g_raydium_ts->x_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+				g_raydium_ts->y_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0);
+	input_set_abs_params(input_dev,
+		ABS_MT_TOUCH_MAJOR, 0, WIDTH_MAX, 0, 0);
+	input_set_abs_params(input_dev,
+		ABS_MT_TOUCH_MINOR, 0, WIDTH_MAX, 0, 0);
+
+	ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM,
+				  INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (ret)
+		pr_err("[touch]failed to initialize MT slots: %d\n", ret);
+
+	for (i = 0; i < (MAX_TOUCH_NUM * 2); i++)
+		gst_slot[i] = gst_slot_init;
+
+}
+static int raydium_set_resolution(void)
+{
+	unsigned char u8_buf[4];
+	int i32_ret = -1;
+	unsigned int u32_x, u32_y;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+			g_raydium_ts->is_suspend,
+			RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_DISPLAY_INFO_ADDR,
+				u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	u32_x = u8_buf[3] << 8 | u8_buf[2];
+	u32_y = u8_buf[1] << 8 | u8_buf[0];
+
+	pr_debug("[touch]RAD display info x:%d, y:%d\n", u32_x, u32_y);
+
+	if (u32_x > 300 && u32_y > 300 &&
+			u32_x < 600 && u32_y < 600) {
+		g_raydium_ts->x_max = u32_x - 1;
+		g_raydium_ts->y_max = u32_y - 1;
+	}
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+
+static int raydium_get_regulators(struct raydium_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int rc;
+
+	ts->vdd = devm_regulator_get(dev, "vdd_ana");
+	if (IS_ERR(ts->vdd)) {
+		rc = PTR_ERR(ts->vdd);
+		dev_err(dev, "Failed to get 'vdd_ana' regulator: %d\n", rc);
+		return rc;
+	}
+
+	ts->vcc_i2c = devm_regulator_get(dev, "vcc_i2c");
+	if (IS_ERR(ts->vcc_i2c)) {
+		rc = PTR_ERR(ts->vcc_i2c);
+		dev_err(dev, "Failed to get 'vcc_i2c' regulator: %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int raydium_config_regulators(struct raydium_ts_data *ts, bool enable)
+{
+	int retval = 0;
+
+	if (!enable)
+		goto hw_shutdown;
+
+	if (ts->vdd) {
+		if (regulator_count_voltages(ts->vdd) > 0) {
+			retval = regulator_set_voltage(ts->vdd,
+					VDD_VTG_MIN_UV, VDD_VTG_MAX_UV);
+			if (retval) {
+				dev_err(&ts->client->dev,
+					"regulator set_vtg failed retval =%d\n",
+					retval);
+				return retval;
+			}
+		}
+	}
+
+	if (ts->vcc_i2c) {
+		if (regulator_count_voltages(ts->vcc_i2c) > 0) {
+			retval = regulator_set_voltage(ts->vcc_i2c,
+				I2C_VTG_MIN_UV, I2C_VTG_MAX_UV);
+			if (retval) {
+				dev_err(&ts->client->dev,
+					"regulator set_vtg failed retval =%d\n",
+					retval);
+				goto err_set_vtg_bus;
+			}
+		}
+	}
+
+	return 0;
+
+hw_shutdown:
+	if (ts->vcc_i2c &&
+		regulator_count_voltages(ts->vcc_i2c) > 0)
+		regulator_set_voltage(ts->vcc_i2c, 0, I2C_VTG_MAX_UV);
+err_set_vtg_bus:
+	if (ts->vdd &&
+		regulator_count_voltages(ts->vdd) > 0)
+		regulator_set_voltage(ts->vdd, 0, VDD_VTG_MAX_UV);
+
+	return retval;
+}
+
+static int raydium_enable_regulators(struct raydium_ts_data *ts, bool enable)
+{
+	int retval = 0;
+
+	if (!enable)
+		goto disable_vdd;
+
+	if (ts->vcc_i2c) {
+		retval = regulator_enable(ts->vcc_i2c);
+		if (retval < 0) {
+			dev_err(&ts->client->dev,
+					"%s: Failed to enable vcc regulator\n",
+					__func__);
+			return retval;
+		}
+	}
+
+	if (ts->vdd) {
+		retval = regulator_enable(ts->vdd);
+		if (retval < 0) {
+			dev_err(&ts->client->dev,
+					"%s: Failed to enable vdd regulator\n",
+					__func__);
+			goto disable_vcc_i2c;
+		}
+	}
+
+	return 0;
+disable_vdd:
+	if (ts->vdd)
+		regulator_disable(ts->vdd);
+disable_vcc_i2c:
+	if (ts->vcc_i2c)
+		regulator_disable(ts->vcc_i2c);
+
+	return retval;
+}
+
+static int raydium_power_on(struct raydium_ts_data *ts, bool on)
+{
+	int retval = 0;
+
+	if (!on)
+		goto disable_reg;
+
+	retval = raydium_config_regulators(ts, true);
+	if (retval) {
+		dev_err(&ts->client->dev,
+				"%s: Failed to config regulator\n",
+				__func__);
+		return retval;
+	}
+
+	retval = raydium_enable_regulators(ts, true);
+	if (retval) {
+		dev_err(&ts->client->dev,
+				"%s: Failed to enable regulator\n",
+				__func__);
+		goto err_config_reg;
+	}
+
+	return 0;
+disable_reg:
+	raydium_enable_regulators(ts, false);
+err_config_reg:
+	raydium_config_regulators(ts, false);
+	return retval;
+}
+
+static int raydium_ts_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct raydium_ts_platform_data *pdata =
+		(struct raydium_ts_platform_data *)client->dev.platform_data;
+
+	struct input_dev *input_dev;
+	unsigned short u16_i2c_data;
+	int ret = 0;
+
+	pr_debug("[touch] probe\n");
+
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+				     sizeof(struct raydium_ts_platform_data),
+				     GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev,
+				"[touch]failed to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		ret = raydium_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev,
+				"[touch]device tree parsing failed\n");
+			goto parse_dt_failed;
+		}
+	} else
+		pdata = client->dev.platform_data;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		ret = -ENODEV;
+		goto exit_check_functionality_failed;
+	}
+
+	g_raydium_ts = devm_kzalloc(&client->dev,
+				  sizeof(struct raydium_ts_data),
+				  GFP_KERNEL);
+	if (!g_raydium_ts) {
+		pr_err("[touch]failed to allocate input driver data\n");
+		return -ENOMEM;
+	}
+
+	raydium_variable_init();
+
+	mutex_init(&g_raydium_ts->lock);
+
+	i2c_set_clientdata(client, g_raydium_ts);
+	g_raydium_ts->irq_enabled = false;
+	g_raydium_ts->irq_wake = false;
+
+	g_raydium_ts->irq_gpio = pdata->irq_gpio;
+	g_raydium_ts->rst_gpio = pdata->reset_gpio;
+	client->irq = g_raydium_ts->irq_gpio;
+	g_raydium_ts->u8_max_touchs = pdata->num_max_touches;
+	g_raydium_ts->client = client;
+	g_raydium_ts->x_max = pdata->x_max - 1;
+	g_raydium_ts->y_max = pdata->y_max - 1;
+	g_raydium_ts->is_suspend = 0;
+	g_raydium_ts->is_sleep = 0;
+#ifdef GESTURE_EN
+	g_raydium_ts->is_palm = 0;
+#endif
+	g_raydium_ts->fw_version = 0;
+	device_init_wakeup(&client->dev, 1);
+
+#ifdef MSM_NEW_VER
+	ret = raydium_ts_pinctrl_init();
+	if (!ret && g_raydium_ts->ts_pinctrl) {
+		/*
+		 * Pinctrl handle is optional. If pinctrl handle is found
+		 * let pins to be configured in active state. If not
+		 * found continue further without error.
+		 */
+		ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl,
+					   g_raydium_ts->pinctrl_state_active);
+		if (ret < 0)
+			pr_err("[touch]failed to set pin to active state\n");
+	}
+#endif /*end of MSM_NEW_VER*/
+
+	ret = raydium_get_regulators(g_raydium_ts);
+	if (ret < 0) {
+		pr_err("[touch]failed to get regulators\n");
+		return -EINVAL;
+	}
+
+	ret = raydium_power_on(g_raydium_ts, true);
+	if (ret < 0) {
+		pr_err("[touch]failed to power on\n");
+		goto err_reg_req;
+	}
+
+	ret = raydium_gpio_configure(true);
+	if (ret < 0) {
+		pr_err("[touch]failed to configure the gpios\n");
+		goto err_gpio_req;
+	}
+	/*modify dtsi to 360*/
+	msleep(pdata->soft_rst_dly);
+
+	/*print touch i2c ready*/
+	ret = raydium_check_i2c_ready(&u16_i2c_data);
+	if (ret < 0) {
+		pr_err("[touch]Check I2C failed\n");
+		ret = -ENODEV;
+		goto exit_check_i2c;
+	}
+
+	/*input device initialization*/
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		ret = -ENOMEM;
+		pr_err("[touch]failed to allocate input device\n");
+		goto exit_input_dev_alloc_failed;
+	}
+
+	raydium_set_resolution();
+
+	g_raydium_ts->input_dev = input_dev;
+	raydium_input_set(input_dev);
+
+	ret = input_register_device(input_dev);
+	if (ret) {
+		pr_err("[touch]failed to register input device: %s\n",
+			dev_name(&client->dev));
+		goto exit_input_register_device_failed;
+	}
+
+#ifdef GESTURE_EN
+	input_set_capability(input_dev, EV_KEY, KEY_SLEEP);
+	input_set_capability(input_dev, EV_KEY, KEY_POWER);
+#endif
+
+	/*suspend/resume routine*/
+#if defined(CONFIG_FB)
+	raydium_register_notifier();
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	/*Early-suspend level*/
+	g_raydium_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	g_raydium_ts->early_suspend.suspend = raydium_ts_early_suspend;
+	g_raydium_ts->early_suspend.resume = raydium_ts_late_resume;
+	register_early_suspend(&g_raydium_ts->early_suspend);
+#endif/*end of CONFIG_FB*/
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+	raydium_create_sysfs(client);
+#endif/*end of CONFIG_RM_SYSFS_DEBUG*/
+
+	INIT_WORK(&g_raydium_ts->work, raydium_work_handler);
+
+	g_raydium_ts->workqueue = create_singlethread_workqueue("raydium_ts");
+#ifdef ENABLE_DUMP_DATA
+	INIT_DELAYED_WORK(&g_raydium_ts->dump_work, raydium_dump_data_work);
+#endif
+	/*irq_gpio = 13 irqflags = 108*/
+	pr_debug("[touch]pdata irq : %d\n", g_raydium_ts->irq_gpio);
+	pr_debug("[touch]client irq : %d, pdata flags : %d\n",
+		client->irq, pdata->irqflags);
+
+	g_raydium_ts->irq = gpio_to_irq(pdata->irq_gpio);
+	ret = request_threaded_irq(g_raydium_ts->irq, NULL, raydium_ts_interrupt,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_SUSPEND,
+			client->dev.driver->name, g_raydium_ts);
+
+	if (ret < 0) {
+		pr_err("[touch]raydium_probe: request irq failed\n");
+		goto exit_irq_request_failed;
+	}
+
+	g_raydium_ts->irq_desc = irq_to_desc(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = true;
+
+	/*disable_irq then enable_irq for avoid Unbalanced enable for IRQ */
+
+	/*raydium_irq_control(ts, ENABLE);*/
+
+	pr_info("[touch]RAD Touch driver ver :0x%X\n", g_u32_driver_version);
+
+#ifdef FW_UPDATE_EN
+	/*fw update check*/
+	ret = raydium_fw_update_check(u16_i2c_data);
+	if (ret < 0) {
+		pr_err("[touch]FW update check failed\n");
+		ret = -ENODEV;
+		goto exit_irq_request_failed;
+	}
+#endif
+	return 0;
+
+exit_irq_request_failed:
+#if defined(CONFIG_FB)
+	raydium_unregister_notifier();
+#endif/*end of CONFIG_FB*/
+
+	cancel_work_sync(&g_raydium_ts->work);
+	input_unregister_device(input_dev);
+
+exit_input_register_device_failed:
+	input_free_device(input_dev);
+
+exit_input_dev_alloc_failed:
+exit_check_i2c:
+	if (gpio_is_valid(pdata->reset_gpio))
+		gpio_free(pdata->reset_gpio);
+
+	if (gpio_is_valid(pdata->irq_gpio))
+		gpio_free(pdata->irq_gpio);
+
+err_gpio_req:
+#ifdef MSM_NEW_VER
+	if (g_raydium_ts->ts_pinctrl) {
+		if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) {
+			devm_pinctrl_put(g_raydium_ts->ts_pinctrl);
+			g_raydium_ts->ts_pinctrl = NULL;
+		} else {
+			ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl,
+					g_raydium_ts->pinctrl_state_release);
+			if (ret)
+				pr_err("[touch]pinctrl_select_state failed\n");
+		}
+	}
+#endif/*end of MSM_NEW_VER*/
+
+err_reg_req:
+	raydium_power_on(g_raydium_ts, false);
+parse_dt_failed:
+exit_check_functionality_failed:
+	return ret;
+
+}
+
+static int raydium_ts_remove(struct i2c_client *client)
+{
+
+#if defined(CONFIG_FB)
+	raydium_unregister_notifier();
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	unregister_early_suspend(&g_raydium_ts->early_suspend);
+#endif/*end of CONFIG_FB*/
+	input_unregister_device(g_raydium_ts->input_dev);
+	input_free_device(g_raydium_ts->input_dev);
+	gpio_free(g_raydium_ts->rst_gpio);
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+	raydium_release_sysfs(client);
+#endif /*end of CONFIG_RM_SYSFS_DEBUG*/
+
+	free_irq(client->irq, g_raydium_ts);
+
+	if (gpio_is_valid(g_raydium_ts->rst_gpio))
+		gpio_free(g_raydium_ts->rst_gpio);
+
+	if (gpio_is_valid(g_raydium_ts->irq_gpio))
+		gpio_free(g_raydium_ts->irq_gpio);
+
+	cancel_work_sync(&g_raydium_ts->work);
+	destroy_workqueue(g_raydium_ts->workqueue);
+
+
+	kfree(g_raydium_ts);
+
+	i2c_set_clientdata(client, NULL);
+	return 0;
+}
+
+static const struct i2c_device_id raydium_ts_id[] = {
+	{RAYDIUM_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, raydium_ts_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id raydium_match_table[] = {
+	{ .compatible = "raydium,raydium-ts",},
+	{ },
+};
+#else
+#define raydium_match_table NULL
+#endif/*end of CONFIG_OF*/
+
+static struct i2c_driver raydium_ts_driver = {
+	.probe = raydium_ts_probe,
+	.remove = raydium_ts_remove,
+	.id_table = raydium_ts_id,
+	.driver = {
+		.name = RAYDIUM_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = raydium_match_table,
+#if defined(CONFIG_PM)
+		.pm    = &raydium_ts_pm_ops,
+#endif/*end of CONFIG_PM*/
+	},
+};
+
+static int __init raydium_ts_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&raydium_ts_driver);
+	return ret;
+}
+
+static void __exit raydium_ts_exit(void)
+{
+	i2c_del_driver(&raydium_ts_driver);
+}
+
+module_init(raydium_ts_init);
+module_exit(raydium_ts_exit);
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.h b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h
new file mode 100644
index 0000000..e604a59
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h
@@ -0,0 +1,378 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_driver.h
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __LINUX_RAYDIUM_H
+#define __LINUX_RAYDIUM_H
+#define RAYDIUM_NAME "raydium_ts"
+#define COORDS_ARR_SIZE    4
+#define I2C_VTG_MIN_UV		1650000
+#define I2C_VTG_MAX_UV		1950000
+#define VDD_VTG_MIN_UV		1650000
+#define VDD_VTG_MAX_UV		1950000
+#define RAD_MAIN_VERSION	0x01
+#define RAD_MINOR_VERSION	0x07
+#define RAD_CUSTOMER_VERSION	0x0100
+
+#if defined(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET)
+/* IC timing control arguments */
+#define RAYDIUM_POWERON_DELAY_USEC    500
+#define RAYDIUM_RESET_INTERVAL_MSEC   5
+#define RAYDIUM_RESET_RESTORE_USEC    200
+#define RAYDIUM_RESET_DELAY_MSEC      100
+
+/* I2C bus slave address(ID) */
+#define RAYDIUM_I2C_EID    (0x5A)
+#define RAYDIUM_I2C_NID    (0x39)
+
+/* I2C R/W configuration literal */
+#define RAYDIUM_I2C_WRITE       I2C_SMBUS_WRITE
+#define RAYDIUM_I2C_READ        I2C_SMBUS_READ
+#define SYN_I2C_RETRY_TIMES     2
+#define MAX_WRITE_PACKET_SIZE   64
+#define MAX_READ_PACKET_SIZE    64
+
+/* PDA address and bit definition*/
+#define RAD_READ_FT_DATA_CMD        0x2000019C
+/* 1byte, disable:0x00 ; enable:0x20*/
+#define RAD_GESTURE_STATE_CMD       0x200005F4
+#define RAD_GESTURE_DISABLE         0x00
+#define RAD_GESTURE_ENABLE          0x20
+/* 4bytes, [0]:ready ; [1]:type ; [2]:direction*/
+#define RAD_GESTURE_RESULT_CMD      0x200005F0
+#define RAD_CHK_I2C_CMD				0x500009BC
+#define RAD_PDA2_CTRL_CMD           0x50000628
+#define RAD_ENABLE_PDA2             0x04
+#define RAD_ENABLE_SI2				0x02
+
+/* PDA literal */
+#define MASK_8BIT    0xFF
+#define RAD_I2C_PDA_ADDRESS_LENGTH    4
+#define PDA_MODE     1
+#define PDA2_MODE    2
+#define RAD_I2C_PDA_MODE_DISABLE      0x00
+#define RAD_I2C_PDA_MODE_ENABLE       0x80
+/* Using byte mode due to data might be not word-aligment */
+#define RAD_I2C_PDA_MODE_WORD_MODE    0x40
+#define RAD_I2C_PDA_2_MODE_DISABLE    0x20
+#define RAD_PALM_DISABLE    0x00
+#define RAD_PALM_ENABLE     0x01
+#define RAD_WAKE_UP			0x02
+#define RAYDIUM_TEST_FW	0x80
+#define RAYDIUM_TEST_PARA	0x40
+#define RAYDIUM_BOOTLOADER	0x20
+#define RAYDIUM_FIRMWARE	0x10
+#define RAYDIUM_PARA		0x08
+#define RAYDIUM_COMP		0x04
+#define RAYDIUM_BASELINE	0x02
+#define RAYDIUM_INIT		0x01
+#define FAIL          0
+#define ERROR        -1
+#define SUCCESS       1
+#define DISABLE       0
+#define ENABLE        1
+
+/* PDA2 setting */
+/* Page 0 ~ Page A */
+#define MAX_PAGE_AMOUNT    11
+
+/* PDA2 address and setting definition*/
+#define RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR    0x00    /* only in Page 0 */
+#define RAYDIUM_PDA2_TCH_RPT_ADDR           0x01    /* only in Page 0 */
+#define RAYDIUM_PDA2_HOST_CMD_ADDR          0x02    /* only in Page 0 */
+#define RAYDIUM_PDA2_PALM_AREA_ADDR         0x03    /* only in Page 0 */
+#define RAYDIUM_PDA2_GESTURE_RPT_ADDR       0x04    /* only in Page 0 */
+#define RAYDIUM_PDA2_PALM_STATUS_ADDR       0x05    /* only in Page 0 */
+#define RAYDIUM_PDA2_FW_VERSION_ADDR        0x06    /* only in Page 0 */
+#define RAYDIUM_PDA2_PANEL_VERSION_ADDR     0x07    /* only in Page 0 */
+#define RAYDIUM_PDA2_DISPLAY_INFO_ADDR		0x08    /* only in Page 0 */
+#define RAYDIUM_PDA2_PDA_CFG_ADDR           0x09    /* only in Page 0 */
+#define RAYDIUM_PDA2_RAWDATA_ADDR           0x0B    /* only in Page 0 */
+/* Page 0 ~ Page 9 will be directed to Page 0 */
+#define RAYDIUM_PDA2_PAGE_ADDR              0x0A
+#define RAYDIUM_PDA2_PAGE_0                 0x00
+/* temporary switch to PDA once */
+#define RAYDIUM_PDA2_ENABLE_PDA             0x0A
+/* permanently switch to PDA mode */
+#define RAYDIUM_PDA2_2_PDA                  (MAX_PAGE_AMOUNT + 2)
+
+/* Raydium host cmd */
+#define RAYDIUM_HOST_CMD_NO_OP              0x00
+#define RAYDIUM_HOST_CMD_PWR_SLEEP          0x30
+#define RAYDIUM_HOST_CMD_DISPLAY_MODE	0x33
+#define RAYDIUM_HOST_CMD_CALIBRATION        0x5C
+#define RAYDIUM_HOST_CMD_TP_MODE            0x60
+#define RAYDIUM_HOST_CMD_FT_MODE            0x61
+
+/* PDA2 literal */
+/* entry byte + target page byte */
+#define RAYDIUM_I2C_PDA2_PAGE_LENGTH        2
+
+
+/* Touch report */
+#define MAX_TOUCH_NUM                 2
+#define MAX_REPORT_PACKET_SIZE        35
+#define MAX_TCH_STATUS_PACKET_SIZE    4
+#define PRESS_MAX                     0xFFFF
+#define WIDTH_MAX                     0xFFFF
+#define BYTE_SHIFT         8
+
+/* FW update literal */
+#define RAYDIUM_FW_BIN_PATH_LENGTH    256
+
+#define RAD_BOOT_1X_SIZE		0x800
+#define RAD_INIT_1X_SIZE		0x200
+#define RAD_FW_1X_SIZE			0x5000
+#define RAD_PARA_1X_SIZE		0xE4
+#define RAD_TESTFW_1X_SIZE		0x5600
+
+#define RAD_BOOT_2X_SIZE		0x800
+#define RAD_INIT_2X_SIZE		0x200
+#define RAD_FW_2X_SIZE			0x6200
+#define RAD_PARA_2X_SIZE		0x15C
+#define RAD_TESTFW_2X_SIZE		(RAD_FW_2X_SIZE + RAD_PARA_2X_SIZE + 4)
+
+#define RAD_CMD_UPDATE_BIN		0x80
+#define RAD_CMD_UPDATE_END		0x81
+#define RAD_CMD_BURN_FINISH		0x82
+
+/* FT APK literal */
+#define RAD_HOST_CMD_POS    0x00
+#define RAD_FT_CMD_POS      0x01
+#define RAD_FT_CMD_LENGTH   0x02
+
+/* FT APK data type */
+#define RAYDIUM_FT_UPDATE    0x01
+
+/*Raydium system flag*/
+#define INT_FLAG	0x01
+#define ENG_MODE	0x02
+
+/* define display mode */
+#define ACTIVE_MODE     0x00
+#define AMBIENT_MODE    0x01
+#define SLEEP_MODE      0x02
+
+#define RAD_20 0x2209
+
+/* Enable sysfs */
+#define CONFIG_RM_SYSFS_DEBUG
+
+/* Gesture switch */
+#define GESTURE_EN
+
+/* Enable FW update */
+/* #define FW_UPDATE_EN */
+/* #define FW_MAPPING_EN */
+#define HOST_NOTIFY_EN
+#define MSM_NEW_VER
+
+/* enable ESD */
+/* #define ESD_SOLUTION_EN */
+/* #define ENABLE_DUMP_DATA */
+/* #define ENABLE_FLASHLOG_BACKUP */
+#ifdef ENABLE_DUMP_DATA
+#define DATA_MAP_5_5 0
+#endif
+
+
+
+#define PINCTRL_STATE_ACTIVE     "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND    "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE    "pmx_ts_release"
+
+#if defined(CONFIG_TOUCHSCREEN_RM_TS_SELFTEST)
+#define RAD_SELFTEST
+#endif
+
+struct raydium_ts_data {
+	unsigned int irq;
+	unsigned int irq_gpio;
+	unsigned int rst_gpio;
+	unsigned int x_max;
+	unsigned int y_max;
+#ifdef FILTER_POINTS
+	unsigned int x_pos[2];
+	unsigned int y_pos[2];
+	unsigned int last_x_pos[2];
+	unsigned int last_y_pos[2];
+#else
+	unsigned int x_pos[2];
+	unsigned int y_pos[2];
+#endif
+	unsigned int pressure;
+	unsigned int is_suspend;
+	unsigned int is_sleep;
+#ifdef GESTURE_EN
+	unsigned int is_palm;
+#endif
+	unsigned char u8_max_touchs;
+
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct mutex lock;
+	struct work_struct  work;
+	struct workqueue_struct *workqueue;
+	struct irq_desc *irq_desc;
+	bool irq_enabled;
+	bool irq_wake;
+
+#if defined(CONFIG_FB)
+	struct notifier_block fb_notif;
+	int blank;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	struct early_suspend early_suspend;
+#endif /*end of CONFIG_FB*/
+
+	struct regulator *vdd;
+	struct regulator *vcc_i2c;
+	unsigned int fw_version;
+	unsigned short id;
+	char *vcc_name;
+#ifdef MSM_NEW_VER
+	struct pinctrl *ts_pinctrl;
+	struct pinctrl_state *pinctrl_state_active;
+	struct pinctrl_state *pinctrl_state_suspend;
+	struct pinctrl_state *pinctrl_state_release;
+#endif /*end of MSM_NEW_VER*/
+
+#ifdef ENABLE_DUMP_DATA
+	struct delayed_work dump_work;
+
+#endif /*end of ENABLE_DUMP_DATA*/
+
+};
+struct raydium_platform_data {
+	char *vdd_name;
+	int irq_gpio_number;
+	int reset_gpio_number;
+	int x_max;
+	int y_max;
+};
+
+struct raydium_ts_platform_data {
+	char *name;
+	u32 irqflags;
+	u32 irq_gpio;
+	u32 irq_gpio_flags;
+	u32 reset_gpio;
+	u32 reset_gpio_flags;
+	u32 x_max;
+	u32 y_max;
+	u32 x_min;
+	u32 y_min;
+	u32 hard_rst_dly;
+	u32 soft_rst_dly;
+	u32 num_max_touches;
+	u32 fw_id;
+};
+
+/* TODO: Using struct+memcpy instead of array+offset*/
+enum raydium_pt_report_status {
+	POS_SEQ = 0,/*1:touch, 0:no touch*/
+	POS_PT_AMOUNT,
+	POS_GES_STATUS,
+	POS_FW_STATE,
+};
+
+enum raydium_pt_report_idx {
+	POS_PT_ID = 0,
+	POS_X_L,
+	POS_X_H,
+	POS_Y_L,
+	POS_Y_H,
+	POS_PRESSURE_L,
+	POS_PRESSURE_H,
+	POS_WX_L,
+	POS_WX_H,
+	POS_WY_L,
+	POS_WY_H,
+	LEN_PT = 11
+};
+
+extern int raydium_read_touchdata(unsigned char *tp_status,  unsigned char *buf);
+extern unsigned char raydium_mem_table_setting(void);
+extern int wait_fw_state(struct i2c_client *client, unsigned int u32_addr,
+			 unsigned int u32_state, unsigned long u32_delay_us,
+			 unsigned short u16_retry);
+extern int wait_irq_state(struct i2c_client *client,
+				unsigned int u32_retry_time,
+				unsigned int u32_delay_us);
+extern void raydium_irq_control(bool enable);
+
+extern int raydium_i2c_mode_control(struct i2c_client *client,
+				    unsigned char u8_mode);
+extern int raydium_i2c_pda_read(struct i2c_client *client,
+				unsigned int u32_addr, unsigned char *u8_r_data,
+				unsigned short u16_length);
+extern int raydium_i2c_pda_write(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_w_data,
+			unsigned short u16_length);
+extern int raydium_i2c_pda2_read(struct i2c_client *client,
+				 unsigned char u8_addr,
+				 unsigned char *u8_r_data,
+				 unsigned short u16_length);
+extern int raydium_i2c_pda2_write(struct i2c_client *client,
+				  unsigned char u8_addr,
+				  unsigned char *u8_w_data,
+				  unsigned short u16_length);
+extern int raydium_i2c_pda2_set_page(struct i2c_client *client,
+				unsigned int is_suspend,
+				unsigned char u8_page);
+extern unsigned char raydium_selftest_stop_mcu(struct i2c_client *client);
+extern int raydium_burn_comp(struct i2c_client *client);
+extern int raydium_burn_fw(struct i2c_client *client);
+extern int raydium_fw_upgrade_with_bin_file(struct i2c_client *client,
+		char *arguments,
+		size_t count,
+		struct device *dev);
+extern int raydium_load_test_fw(struct i2c_client *client);
+extern int raydium_fw_update_check(unsigned short u16_i2c_data);
+extern int raydium_i2c_pda_set_address(unsigned int u32_address,
+				       unsigned char u8_mode);
+extern unsigned char raydium_mem_table_init(unsigned short u16_id);
+extern unsigned char raydium_id_init(unsigned char u8_type);
+
+#ifdef RAD_SELFTEST
+extern int raydium_do_selftest(void);
+#endif
+int raydium_esd_check(void);
+
+extern struct attribute *raydium_attributes[];
+
+extern unsigned char g_u8_raydium_flag;
+extern unsigned char g_u8_addr;
+extern unsigned char g_u8_i2c_mode;
+extern unsigned char g_u8_upgrade_type;
+extern unsigned char g_u8_raw_data_type;
+extern unsigned int g_u32_raw_data_len;    /* 72 bytes*/
+extern unsigned int g_u32_length;
+extern unsigned long g_u32_addr;
+extern unsigned char *g_rad_fw_image, *g_rad_init_image;
+extern unsigned char *g_rad_boot_image, *g_rad_para_image;
+extern unsigned char *g_rad_testfw_image, *g_rad_testpara_image;
+extern unsigned char g_u8_table_setting, g_u8_table_init;
+extern unsigned int g_u32_driver_version;
+extern unsigned char g_u8_resetflag;
+extern struct raydium_ts_data *g_raydium_ts;
+
+#endif
+#endif  /*__LINUX_RAYDIUM_H*/
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
new file mode 100644
index 0000000..e4a3005
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
@@ -0,0 +1,1815 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <asm/traps.h>
+#include <linux/firmware.h>
+#include "raydium_driver.h"
+#if defined(FW_MAPPING_EN)
+#include "rad_fw_image_21.h"
+#endif
+
+#ifdef FW_UPDATE_EN
+
+#ifdef ENABLE_FLASHLOG_BACKUP
+unsigned char raydium_turn_on_flash_2X(struct i2c_client *client)
+{
+	unsigned int u32_read = 0;
+	unsigned char u8_buf[4];
+
+	/*Turn on Flash*/
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] = 0x20;
+	if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	return SUCCESS;
+}
+
+unsigned char  raydium_read_fpc_flash(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_r_data)
+{
+	unsigned int u32_read;
+	unsigned char u8_buf[4];
+
+	pr_debug("[touch]raydium_read_fpc_flash\n");
+
+	if (raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] |= 0x40;
+	if (raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] =  (u32_addr & 0x000000FF);
+	u8_buf[1] = ((u32_addr & 0x0000FF00) >> 8);
+	u8_buf[2] = ((u32_addr & 0x00FF0000) >> 16);
+	u8_buf[3] = ((u32_addr & 0xFF000000) >> 24);
+
+	if (raydium_i2c_pda_write(client, 0x50000910, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	u8_buf[0] = 0x40;
+
+	if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	usleep_range(950, 1050);
+
+	if (raydium_i2c_pda_read(client, 0x5000093C, u8_r_data, 4) == ERROR)
+		return ERROR;
+
+	return SUCCESS;
+}
+
+unsigned char raydium_read_flash_log(void)
+{
+	unsigned char u8_buf[4];
+	unsigned int u32_readbuf;
+	unsigned char u8_ret = 0;
+	unsigned char u8_logcount = 0;
+	unsigned int u32_temp = 0;
+	unsigned char u8_i = 0, u8_j = 0;
+
+	raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_2_PDA);
+	g_u8_i2c_mode = PDA_MODE;
+	pr_debug("[touch]Disable PDA2_MODE\n");
+
+	if ((g_raydium_ts->id  & 0x2000) != 0)
+		raydium_turn_on_flash_2X(g_raydium_ts->client);
+
+	for (u8_i = 0; u8_i < 4; u8_i++) {
+		u32_temp = (0x9000 +  (u8_i*4));
+		raydium_read_fpc_flash(g_raydium_ts->client, u32_temp,
+						&u32_readbuf);
+		if (u8_i == 0 && u32_readbuf == 0xFFFFFFFF) {
+			pr_err("[touch]Raydium flash no log\n");
+			return FAIL;
+		}
+		pr_debug("[touch]Raydium flash 0x%x = 0x%x\n",
+			u32_temp, u32_readbuf);
+		u32_readbuf = u32_readbuf & (~u32_readbuf + 1);
+		pr_debug("[touch]Raydium flash reverse = 0x%x\n",
+			u32_readbuf);
+		u32_temp = 1;
+		u8_j = 0;
+		while (u32_readbuf != u32_temp) {
+			u8_j++;
+			u32_temp <<= 1;
+			if (u8_j == 32)
+				break;
+		}
+		if (u8_i == 0) {
+			if ((u8_j > 0) && (u8_j < 32)) {
+				u8_logcount = u8_i*32 + u8_j;
+				pr_debug("[touch]logcount = Log%d\n",
+						(u8_logcount - 1));
+				break;
+			}
+		} else {
+			if (u8_j < 32) {
+				u8_logcount = u8_i*32 + u8_j;
+				pr_debug("[touch]logcount = Log%d\n",
+						(u8_logcount - 1));
+				break;
+			}
+		}
+	}
+
+	if (u8_logcount != 0) {
+		u32_temp = (0x9014 + (u8_logcount-1) * 48);
+		raydium_read_fpc_flash(g_raydium_ts->client, u32_temp, u8_buf);
+		pr_info("[touch]Rad log fw version 0x%x.0x%x.0x%x.0x%x\n",
+				u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]);
+		if ((g_raydium_ts->id  & 0x2000) != 0)
+			g_raydium_ts->id = 0x2000 | ((u8_buf[0] & 0xF) << 8)
+						| u8_buf[1];
+
+		return SUCCESS;
+	}
+	return FAIL;
+}
+#endif
+unsigned char raydium_mem_table_init(unsigned short u16_id)
+{
+	unsigned int u8_ret = 0;
+
+	pr_info("[touch]Raydium table init 0x%x\n", u16_id);
+
+	if ((u16_id & 0x2000) != 0) {
+		g_rad_boot_image = kzalloc(RAD_BOOT_2X_SIZE, GFP_KERNEL);
+		g_rad_init_image = kzalloc(RAD_INIT_2X_SIZE, GFP_KERNEL);
+		g_rad_fw_image = kzalloc(RAD_FW_2X_SIZE, GFP_KERNEL);
+		g_rad_para_image = kzalloc(RAD_PARA_2X_SIZE + 4, GFP_KERNEL);
+		g_rad_testfw_image = kzalloc(RAD_TESTFW_2X_SIZE, GFP_KERNEL);
+		g_rad_testpara_image = kzalloc(RAD_PARA_2X_SIZE + 4,
+								GFP_KERNEL);
+		g_u8_table_init = SUCCESS;
+		u8_ret = SUCCESS;
+	}
+
+	return u8_ret;
+}
+
+unsigned char raydium_mem_table_setting(void)
+{
+	unsigned char u8_ret = SUCCESS;
+#ifdef ENABLE_FLASHLOG_BACKUP
+	unsigned char u8_buf[4];
+	static unsigned char u8_readflash;
+#endif
+
+	pr_info("[touch]Raydium ID is 0x%x\n", g_raydium_ts->id);
+	switch (g_raydium_ts->id) {
+	case RAD_20:
+		memcpy(g_rad_boot_image, u8_rad_boot_20, RAD_BOOT_2X_SIZE);
+		memcpy(g_rad_init_image, u8_rad_init_20, RAD_INIT_2X_SIZE);
+		memcpy(g_rad_fw_image, u8_rad_fw_20, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image, u8_rad_testfw_20, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+			u8_rad_testpara_20, RAD_PARA_2X_SIZE + 4);
+		if (g_rad_boot_image[0x82] >= 4) {
+			memcpy(g_rad_para_image,
+				u8_rad_para_20,
+				RAD_PARA_2X_SIZE + 4);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE + 4);
+		} else {
+			memcpy(g_rad_para_image,
+				u8_rad_para_20,
+				RAD_PARA_2X_SIZE);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE);
+		}
+		break;
+#if defined(FW_MAPPING_EN)
+	case RAD_21:
+		memcpy(g_rad_boot_image, u8_rad_boot_21, RAD_BOOT_2X_SIZE);
+		memcpy(g_rad_init_image, u8_rad_init_21, RAD_INIT_2X_SIZE);
+		memcpy(g_rad_fw_image, u8_rad_fw_21, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image, u8_rad_testfw_21, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+			u8_rad_testpara_21,
+			RAD_PARA_2X_SIZE + 4);
+		if (g_rad_boot_image[0x82] >= 4) {
+			memcpy(g_rad_para_image,
+				u8_rad_para_21,
+				RAD_PARA_2X_SIZE + 4);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_21,
+				RAD_PARA_2X_SIZE + 4);
+		} else {
+			memcpy(g_rad_para_image,
+				u8_rad_para_21,
+				RAD_PARA_2X_SIZE);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_21,
+				RAD_PARA_2X_SIZE);
+		}
+		break;
+#endif
+	default:
+		pr_info("[touch]mapping ic setting use default fw\n");
+#ifdef ENABLE_FLASHLOG_BACKUP
+		if (!u8_readflash) {
+			u8_ret = raydium_read_flash_log();
+			u8_readflash = true;
+
+			raydium_i2c_pda_read(g_raydium_ts->client,
+					RAD_PDA2_CTRL_CMD,
+					u8_buf,
+					4);
+			u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2;
+			raydium_i2c_pda_write(g_raydium_ts->client,
+					RAD_PDA2_CTRL_CMD,
+					u8_buf,
+					4);
+			raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+			g_u8_i2c_mode = PDA2_MODE;
+			pr_debug("[touch]Enable PDA2_MODE\n");
+			raydium_mem_table_setting();
+		} else {
+			if ((g_raydium_ts->id & 0x2000) != 0) {
+				memcpy(g_rad_boot_image,
+					u8_rad_boot_20,
+					RAD_BOOT_2X_SIZE);
+				memcpy(g_rad_init_image,
+					u8_rad_init_20,
+					RAD_INIT_2X_SIZE);
+				memcpy(g_rad_fw_image,
+					u8_rad_fw_20,
+					RAD_FW_2X_SIZE);
+				memcpy(g_rad_testfw_image,
+					u8_rad_testfw_20,
+					RAD_FW_2X_SIZE);
+				memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE + 4);
+				if (g_rad_boot_image[0x82] >= 4) {
+					memcpy(g_rad_para_image,
+						u8_rad_para_20,
+						RAD_PARA_2X_SIZE + 4);
+					memcpy(g_rad_testpara_image,
+						u8_rad_testpara_20,
+						RAD_PARA_2X_SIZE + 4);
+				} else {
+					memcpy(g_rad_para_image,
+						u8_rad_para_20,
+						RAD_PARA_2X_SIZE);
+					memcpy(g_rad_testpara_image,
+						u8_rad_testpara_20,
+						RAD_PARA_2X_SIZE);
+				}
+				g_raydium_ts->id = RAD_20;
+			}
+		}
+		u8_ret = SUCCESS;
+		break;
+#else
+		if ((g_raydium_ts->id & 0x2000) != 0) {
+			memcpy(g_rad_boot_image,
+				u8_rad_boot_20,
+				RAD_BOOT_2X_SIZE);
+			memcpy(g_rad_init_image,
+				u8_rad_init_20,
+				RAD_INIT_2X_SIZE);
+			memcpy(g_rad_fw_image,
+				u8_rad_fw_20,
+				RAD_FW_2X_SIZE);
+			memcpy(g_rad_testfw_image,
+				u8_rad_testfw_20,
+				RAD_FW_2X_SIZE);
+			memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE + 4);
+			if (g_rad_boot_image[0x82] >= 4) {
+				memcpy(g_rad_para_image,
+					u8_rad_para_20,
+					RAD_PARA_2X_SIZE + 4);
+				memcpy(g_rad_testpara_image,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE + 4);
+			} else {
+				memcpy(g_rad_para_image,
+					u8_rad_para_20,
+					RAD_PARA_2X_SIZE);
+				memcpy(g_rad_testpara_image,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE);
+			}
+			g_raydium_ts->id = RAD_20;
+		}
+		u8_ret = SUCCESS;
+		break;
+#endif
+	}
+
+	g_u8_table_setting = 0;
+	return u8_ret;
+}
+
+unsigned char raydium_id_init(unsigned char u8_type)
+{
+	unsigned int u8_ret = 0;
+
+	switch (u8_type) {
+	case 0:
+		g_raydium_ts->id = RAD_20;
+		u8_ret = SUCCESS;
+		break;
+#if defined(FW_MAPPING_EN)
+	case 1:
+		g_raydium_ts->id = RAD_21;
+		u8_ret = SUCCESS;
+		break;
+#endif
+	}
+
+
+	return u8_ret;
+}
+
+static unsigned int bits_reverse(unsigned int u32_num, unsigned int bit_num)
+{
+	unsigned int reverse = 0, u32_i;
+
+	for (u32_i = 0; u32_i < bit_num; u32_i++) {
+		if (u32_num & (1 << u32_i))
+			reverse |= 1 << ((bit_num - 1) - u32_i);
+	}
+	return reverse;
+}
+
+static unsigned int rc_crc32(const char *buf, unsigned int u32_len,
+			     unsigned int u32_crc)
+{
+	unsigned int u32_i;
+	unsigned char u8_flash_byte, u8_current, u8_j;
+
+	for (u32_i = 0; u32_i < u32_len; u32_i++) {
+		u8_flash_byte = buf[u32_i];
+		u8_current = (unsigned char)bits_reverse(u8_flash_byte, 8);
+		for (u8_j = 0; u8_j < 8; u8_j++) {
+			if ((u32_crc ^ u8_current) & 0x01)
+				u32_crc = (u32_crc >> 1) ^ 0xedb88320;
+			else
+				u32_crc >>= 1;
+			u8_current >>= 1;
+		}
+	}
+	return u32_crc;
+}
+
+int wait_fw_state(struct i2c_client *client, unsigned int u32_addr,
+			 unsigned int u32_state, unsigned long u32_delay_us,
+			 unsigned short u16_retry)
+{
+	unsigned char u8_buf[4];
+	unsigned int u32_read_data;
+	unsigned int u32_min_delay_us = u32_delay_us - 500;
+	unsigned int u32_max_delay_us = u32_delay_us + 500;
+
+	do {
+		if (raydium_i2c_pda_read(client, u32_addr, u8_buf, 4) == ERROR)
+			return ERROR;
+
+		memcpy(&u32_read_data, u8_buf, 4);
+		u16_retry--;
+		usleep_range(u32_min_delay_us, u32_max_delay_us);
+	} while ((u32_read_data != u32_state) && (u16_retry != 0));
+
+	if (u32_read_data != u32_state) {
+		pr_err("[touch]confirm data error : 0x%x\n", u32_read_data);
+		return ERROR;
+	}
+
+	return SUCCESS;
+}
+
+int raydium_do_software_reset(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+
+	unsigned char u8_buf[4];
+
+	/*SW reset*/
+	g_u8_resetflag = true;
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x01;
+	pr_info("[touch]SW reset\n");
+	i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit;
+
+	if ((g_raydium_ts->id & 0x2000) != 0)
+		msleep(25);
+exit:
+	return i32_ret;
+}
+
+static int raydium_check_fw_ready(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry = 400;
+	unsigned char u8_buf[4];
+
+	u8_buf[1] = 0;
+	while (u8_buf[1] != 0x40 && u32_retry != 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit;
+
+		u32_retry--;
+		usleep_range(4500, 5500);
+	}
+
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, FW not ready, retry error!\n", __func__);
+		i32_ret = ERROR;
+	} else {
+		pr_info("[touch]%s, FW is ready!!\n", __func__);
+		usleep_range(4500, 5500);
+	}
+
+exit:
+	return i32_ret;
+}
+
+int set_skip_load(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry_time = 1000;
+	unsigned char u8_buf[4];
+
+	/*Skip load*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x10;
+	u8_buf[1] = 0x08;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_do_software_reset(client);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, SW reset error!\n", __func__);
+
+	i32_ret = wait_fw_state(client, 0x20000214, 0x82, 2000, u32_retry_time);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, wait_fw_state error!\n", __func__);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/*check pram crc32*/
+static int raydium_check_pram_crc_2X(struct i2c_client *client,
+		unsigned int u32_addr,
+		unsigned int u32_len)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_crc_addr = u32_addr + u32_len;
+	unsigned int u32_end_addr = u32_crc_addr - 1;
+	unsigned int u32_crc_result, u32_read_data;
+	unsigned int u32_retry = 400;
+	unsigned char u8_buf[4], u8_retry = 3;
+
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = (unsigned char)(u32_addr & 0xFF);
+	u8_buf[1] = (unsigned char)((u32_addr & 0xFF00) >> 8);
+	u8_buf[2] = (unsigned char)(u32_end_addr & 0xFF);
+	u8_buf[3] = (unsigned char)((u32_end_addr & 0xFF00) >> 8);
+
+	i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[3] |= 0x81;
+	i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+
+	while (u8_buf[3] != 0x80 && u32_retry != 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		u32_retry--;
+		usleep_range(4500, 5500);
+	}
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, Cal CRC not ready, retry error!\n",
+			__func__);
+		i32_ret = ERROR;
+	}
+
+	i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	memcpy(&u32_crc_result, u8_buf, 4);
+	i32_ret = raydium_i2c_pda_read(client, u32_crc_addr, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	memcpy(&u32_read_data, u8_buf, 4);
+
+	while (u32_read_data != u32_crc_result && u8_retry > 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		usleep_range(1500, 2500);
+		u8_retry--;
+	}
+	if (u32_read_data != u32_crc_result) {
+		pr_err("[touch]check pram crc fail!!\n");
+		pr_err("[touch]u32_read_data 0x%x\n", u32_read_data);
+		pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+		i32_ret = ERROR;
+		goto exit_upgrade;
+	} else if (u8_retry != 3) {
+		pr_err("[touch]check pram crc pass!!\n");
+		pr_err("[touch]u8_retry : %d\n", u8_retry);
+		pr_err("[touch]u32_read_data 0x%x\n", u32_read_data);
+		pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+		i32_ret = ERROR;
+		goto exit_upgrade;
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/* upgrade firmware with image file */
+static int raydium_write_to_pram_2X(struct i2c_client *client,
+		unsigned int u32_fw_addr,
+		unsigned char u8_type)
+{
+	int i32_ret = ERROR;
+	unsigned int u32_fw_size = 0;
+	unsigned char *p_u8_firmware_data = NULL;
+	unsigned int u32_write_offset = 0;
+	unsigned short u16_write_length = 0;
+
+	switch (u8_type) {
+	case RAYDIUM_INIT:
+		u32_fw_size = 0x200;
+		p_u8_firmware_data = g_rad_init_image;
+		break;
+
+	case RAYDIUM_PARA:
+		u32_fw_size = 0x160;
+		p_u8_firmware_data = g_rad_para_image;
+		break;
+
+	case RAYDIUM_FIRMWARE:
+		u32_fw_size = 0x6200;
+		p_u8_firmware_data = g_rad_fw_image;
+		break;
+
+	case RAYDIUM_BOOTLOADER:
+		u32_fw_size = 0x800;
+		p_u8_firmware_data = g_rad_boot_image;
+		break;
+
+	case RAYDIUM_TEST_FW:
+		u32_fw_size = 0x6360;
+		p_u8_firmware_data = g_rad_testfw_image;
+		break;
+	}
+
+	u32_write_offset = 0;
+	while (u32_write_offset < u32_fw_size) {
+		if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size)
+			u16_write_length = MAX_WRITE_PACKET_SIZE;
+		else
+			u16_write_length =
+			(unsigned short)(u32_fw_size - u32_write_offset);
+
+		i32_ret = raydium_i2c_pda_write(
+			      client,
+			      (u32_fw_addr + u32_write_offset),
+			      (p_u8_firmware_data + u32_write_offset),
+			      u16_write_length);
+		if (i32_ret < 0)
+			goto exit_upgrate;
+
+		u32_write_offset += (unsigned long)u16_write_length;
+	}
+	u32_fw_addr += u32_write_offset;
+
+exit_upgrate:
+	if (i32_ret < 0) {
+		pr_err("[touch]upgrade failed\n");
+		return i32_ret;
+	}
+	pr_info("[touch]upgrade success\n");
+	return 0;
+}
+
+/* upgrade firmware with image file */
+static int raydium_fw_upgrade_with_image(struct i2c_client *client,
+		unsigned int u32_fw_addr,
+		unsigned char u8_type)
+{
+	int i32_ret = ERROR;
+	unsigned int u32_fw_size = 0;
+	unsigned char *p_u8_firmware_data = NULL;
+	unsigned int u32_write_offset = 0;
+	unsigned short u16_write_length = 0;
+	unsigned int u32_checksum = 0xFFFFFFFF;
+
+	switch (u8_type) {
+	case RAYDIUM_INIT:
+		u32_fw_size = 0x1fc;
+		p_u8_firmware_data = g_rad_init_image;
+		break;
+	case RAYDIUM_PARA:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x158;
+		p_u8_firmware_data = g_rad_para_image;
+		break;
+	case RAYDIUM_FIRMWARE:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x61fc;
+		p_u8_firmware_data = g_rad_fw_image;
+		break;
+	case RAYDIUM_BOOTLOADER:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x7FC;
+		p_u8_firmware_data = g_rad_boot_image;
+		break;
+	case RAYDIUM_TEST_FW:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x635C;
+		p_u8_firmware_data = g_rad_testfw_image;
+		break;
+	}
+
+	pr_debug("[touch]CRC 0x%08X\n",
+		*(unsigned int *)(p_u8_firmware_data + u32_fw_size));
+
+	u32_checksum = rc_crc32(p_u8_firmware_data,
+		u32_fw_size, u32_checksum);
+	u32_checksum = bits_reverse(u32_checksum, 32);
+	memcpy((p_u8_firmware_data + u32_fw_size), &u32_checksum, 4);
+	pr_debug("[touch]CRC result 0x%08X\n", u32_checksum);
+	u32_fw_size += 4;
+
+	u32_write_offset = 0;
+	while (u32_write_offset < u32_fw_size) {
+		if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size)
+			u16_write_length = MAX_WRITE_PACKET_SIZE;
+		else
+			u16_write_length =
+				(unsigned short)
+				(u32_fw_size - u32_write_offset);
+
+		i32_ret = raydium_i2c_pda_write(
+			      client,
+			      (u32_fw_addr + u32_write_offset),
+			      (p_u8_firmware_data + u32_write_offset),
+			      u16_write_length);
+		if (i32_ret < 0)
+			goto exit_upgrate;
+
+		u32_write_offset += (unsigned long)u16_write_length;
+	}
+	u32_fw_addr += u32_write_offset;
+
+exit_upgrate:
+	if (i32_ret < 0) {
+		pr_err("[touch]upgrade failed\n");
+		return i32_ret;
+	}
+	pr_info("[touch]upgrade success\n");
+	return 0;
+}
+static int raydium_boot_upgrade_2X(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned char u8_buf[4];
+
+	/*set mcu hold*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x20;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[0] = 0x01;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	msleep(25);
+
+	/*WRT boot-loader to PRAM first*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4);
+
+	/*Sending bootloader*/
+	i32_ret = raydium_write_to_pram_2X(client, 0x0000,
+					    RAYDIUM_BOOTLOADER);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	i32_ret = raydium_check_pram_crc_2X(client, 0x000, 0x7FC);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	/*release mcu hold*/
+	/*Skip load*/
+	i32_ret = set_skip_load(client);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, set skip_load error!\n", __func__);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/* Raydium fireware upgrade flow */
+static int raydium_fw_upgrade_2X(struct i2c_client *client,
+			      unsigned char u8_type,
+			      unsigned char u8_check_crc)
+{
+	int i32_ret = 0;
+	unsigned char u8_buf[4];
+	unsigned short u16_retry = 1000;
+
+	/*##### wait for boot-loader start #####*/
+	pr_debug("[touch]Type is %x\n", u8_type);
+
+	/*read Boot version*/
+	if (raydium_i2c_pda_read(client, 0x80, u8_buf, 4) == ERROR)
+		return ERROR;
+	pr_debug("[touch]Boot version is %x\n", u8_buf[2]);
+
+	if (u8_buf[2] >= 4) {
+		if (u8_type != RAYDIUM_COMP) {
+			/*set mcu hold*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x20;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x50000918,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x40000004,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			msleep(25);
+		}
+
+		/*#start write data to PRAM*/
+		if (u8_type == RAYDIUM_FIRMWARE) {
+			/* unlock PRAM */
+			u8_buf[0] = 0x27;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x50000900,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x800,
+							    RAYDIUM_FIRMWARE);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_write_to_pram_2X(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_check_pram_crc_2X(client, 0x800,
+				0x635C);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			/* unlock PRAM */
+			u8_buf[0] = 0x0E;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000900,
+							u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x0800,
+							    RAYDIUM_BOOTLOADER);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x1000,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_check_pram_crc_2X(client, 0x800,
+				0x7FC);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_check_pram_crc_2X(client, 0x1000,
+				0x1FC);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		if (u8_type != RAYDIUM_COMP) {
+			/*release mcu hold*/
+			/*Skip load*/
+			i32_ret = set_skip_load(client);
+			if (i32_ret < 0)
+				pr_err("[touch]%s, set skip_load error!\n",
+					__func__);
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#confirm in burn mode*/
+		if (wait_fw_state(client, 0x20000214, 255,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm in burn mode\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*Clear BL_CRC*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x10;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = u8_type;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#set PRAM length (at 'h5000_090C)*/
+		if (u8_type == RAYDIUM_COMP) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x60;
+			u8_buf[1] = 0x6b;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x9c;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x63;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x0A;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*#set sync_data(0x20000200) = 0 as WRT data finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait for input unlock key*/
+		if (wait_fw_state(client, 0x20000210, 168, 1000,
+				 u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait for input unlock key\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#unlock key*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xd7;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wrt return data as unlock value*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa8;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*pr_debug("[touch]ready burn flash\n");*/
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/* wait erase/wrt finish
+		 * confirm burning_state result (gu8I2CSyncData.burning_state =
+		 * BURNING_WRT_FLASH_FINISH at 0x2000020C)
+		 */
+		if (wait_fw_state(client, 0x2000020c, 6, 2000,
+				 u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait erase/wrt finish\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+		pr_info("[touch]Burn flash ok\n");
+
+		if (u8_check_crc) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			i32_ret = raydium_i2c_pda_write(client, 0x20000200,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait software reset finish*/
+			msleep(25);
+
+			/* wait sw reset finished 0x20000214 = 0x82 */
+			if (wait_fw_state(client, 0x20000214, 130, 2000,
+					 u16_retry) == ERROR) {
+				pr_err("[touch]Error, wait sw reset finished\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#set test_mode = 1*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x20000218,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait crc check finish*/
+			if (wait_fw_state(client, 0x20000208, 2,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, wait crc check finish\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#crc check pass 0x20000214 = 0x81*/
+			if (wait_fw_state(client, 0x20000214, 0x81,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, confirm crc result\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+		}
+
+	} else {
+		/*#set main state as burning mode, normal init state*/
+		/* #sync_data:200h
+		 * main_state:204h
+		 * normal_state:208h
+		 * burning_state:20Ch
+		 */
+		/* #sync_data:210h
+		 * cmd_type:210h
+		 * ret_data:214h
+		 * test_mode:218h
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#confirm in burn mode*/
+		if (wait_fw_state(client, 0x50000900, 63,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm in burn mode\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*Clear BL_CRC*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x10;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*
+		 * #set PRAM type (at 0x50000904), wrt param code
+		 * #write PRAM relative data
+		 * #init_code:0x01,
+		 * baseline:0x02
+		 * COMP:0x04
+		 * param:0x08
+		 * FW:0x10
+		 * bootloader:0x20
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = u8_type;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*
+		 * #set PRAM addr (at 'h5000_0908)
+		 * #init_code:0x800
+		 * Baseline:0xA00
+		 * COMP:0xCD4
+		 * para:0xF1C
+		 * FW:0x1000
+		 * BOOT:0x5000
+		 *
+		 * #set PRAM length (at 'h5000_090C)
+		 */
+		if (u8_type == RAYDIUM_INIT) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x6e;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BASELINE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0xcc;
+			u8_buf[1] = 0x6c;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x30;
+			u8_buf[1] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_COMP) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x60;
+			u8_buf[1] = 0x6b;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x9c;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_PARA) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x6a;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x63;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x0A;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*#set sync_data(0x20000200) = 0 as WRT data finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#Wait bootloader check addr and PRAM unlock*/
+		/*#Confirm ret_data at 0x20000214 is SET_ADDR_READY*/
+		if (wait_fw_state(client, 0x20000214, 161,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, SET_ADDR_READY\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#Confirm cmd_type at 0x20000210 is WRT_PRAM_DATA*/
+		if (wait_fw_state(client, 0x20000210, 163,
+				 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, WRT_PRAM_DATA\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#start write data to PRAM*/
+		if (u8_type == RAYDIUM_INIT) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6E00,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}  else if (u8_type == RAYDIUM_PARA) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x800,
+							    RAYDIUM_FIRMWARE);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x0800,
+							    RAYDIUM_BOOTLOADER);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x1000,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*
+		 *set sync_data(0x20000200) = 0 as WRT data finish
+		 *bootloader check checksum
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*
+		 * wait(checksum okay) ACK cmd
+		 * (gu8I2CSyncData.cmd_type=0xa5 at 0x20000210)
+		 */
+		if (wait_fw_state(client, 0x20000210,
+				 165, 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, WRT_CHECKSUM_OK\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#confirm ACK cmd result(ret_data=0xa5 at 0x20000214)*/
+		if (wait_fw_state(client, 0x20000214,
+				 165, 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm ACK cmd result\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*
+		 * set ACK return data = 0x5A
+		 * adb shell "echo 20000210 1 A5 > /sys/bus/i2c/drivers/
+		 * raydium_ts/1-0039 raydium_i2c_pda_access"
+		 * above command can be ignored, due to previous while loop
+		 * has check its value.
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x5a;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait for input unlock key*/
+		if (wait_fw_state(client, 0x20000210,
+				 168, 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait for input unlock key\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#unlock key*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xd7;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wrt return data as unlock value*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa8;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*pr_info("[touch]ready burn flash\n");*/
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/* wait erase/wrt finish
+		 * confirm burning_state result (gu8I2CSyncData.burning_state =
+		 * BURNING_WRT_FLASH_FINISH at 0x2000020C)
+		 */
+		if (wait_fw_state(client, 0x2000020c,
+				 6, 2000, u16_retry) == ERROR) {
+			dev_err(&g_raydium_ts->client->dev,
+				"[touch]Error, wait erase/wrt finish\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+		pr_info("[touch]Burn flash ok\n");
+
+
+		if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x10;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000918,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait software reset finish*/
+		msleep(25);
+
+		/* wait sw reset finished 0x20000214 = 0x82 */
+		if (wait_fw_state(client, 0x20000214,
+				 130, 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait sw reset finished\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		if (u8_type == RAYDIUM_BASELINE || u8_type == RAYDIUM_COMP ||
+		    u8_type == RAYDIUM_FIRMWARE || u8_check_crc == 1) {
+			/*#set test_mode = 1*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x20000218,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait crc check finish*/
+			if (wait_fw_state(client, 0x20000208, 2,
+					 2000, u16_retry) == ERROR) {
+				pr_err("[touch]Error, wait crc check finish\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#crc check pass 0x20000214 = 0x81*/
+			if (wait_fw_state(client, 0x20000214, 0x81,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, confirm crc result\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+		}
+	}
+
+	/*#run to next step*/
+		pr_info("[touch]Type 0x%x => Pass\n", u8_type);
+
+	if (u8_check_crc) {
+		/*#clr sync para*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		usleep_range(4500, 5500);
+		raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+		g_u8_i2c_mode = PDA2_MODE;
+
+		pr_info("[touch]Burn FW finish!\n");
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_burn_fw(struct i2c_client *client)
+{
+	int i32_ret = 0;
+
+	g_u8_resetflag = true;
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		pr_debug("[touch]start burn function!\n");
+		i32_ret = raydium_boot_upgrade_2X(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_BOOTLOADER, 0);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_FIRMWARE, 1);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_fw_update_check(unsigned short u16_i2c_data)
+{
+
+	unsigned char u8_rbuffer[4];
+	unsigned int u32_fw_version, u32_image_version;
+	int i32_ret = ERROR;
+	unsigned char u8_mode_change;
+
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+				g_raydium_ts->is_suspend,
+				RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				    RAYDIUM_PDA2_FW_VERSION_ADDR,
+				    u8_rbuffer,
+				    4);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	mutex_unlock(&g_raydium_ts->lock);
+
+	u32_fw_version = (u8_rbuffer[0] << 24) | (u8_rbuffer[1] << 16) |
+		(u8_rbuffer[2] << 8) | u8_rbuffer[3];
+	pr_info("[touch]RAD FW ver 0x%.8x\n", u32_fw_version);
+
+	g_raydium_ts->fw_version = u32_fw_version;
+
+	g_raydium_ts->id = ((u16_i2c_data & 0xF) << 12) |
+		((u8_rbuffer[0] & 0xF) << 8) | u8_rbuffer[1];
+
+	raydium_mem_table_init(g_raydium_ts->id);
+	if (raydium_mem_table_setting()) {
+
+		u32_image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+		pr_info("[touch]RAD Image FW ver : 0x%x\n", u32_image_version);
+	} else {
+		pr_err("[touch]Mem setting failed, Stop fw upgrade!\n");
+		return FAIL;
+	}
+
+	if (u32_fw_version != u32_image_version) {
+		pr_info("[touch]FW need update.\n");
+		raydium_irq_control(DISABLE);
+		if ((g_u8_raydium_flag & ENG_MODE) == 0) {
+			g_u8_raydium_flag |= ENG_MODE;
+			u8_mode_change = 1;
+		}
+		i32_ret = raydium_burn_fw(g_raydium_ts->client);
+		if (i32_ret < 0)
+			pr_err("[touch]FW update fail:%d\n", i32_ret);
+
+		if (u8_mode_change) {
+			g_u8_raydium_flag &= ~ENG_MODE;
+			u8_mode_change = 0;
+		}
+		raydium_irq_control(ENABLE);
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+					    RAYDIUM_PDA2_FW_VERSION_ADDR,
+					    u8_rbuffer,
+					    4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		mutex_unlock(&g_raydium_ts->lock);
+		u32_fw_version = (u8_rbuffer[0] << 24) |
+			     (u8_rbuffer[1] << 16) |
+			     (u8_rbuffer[2] << 8) |
+			     u8_rbuffer[3];
+		pr_info("[touch]RAD FW ver is 0x%x\n",
+			 u32_fw_version);
+		g_raydium_ts->fw_version = u32_fw_version;
+	} else
+		pr_info("[touch]FW is the latest version.\n");
+
+	return i32_ret;
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+int raydium_burn_comp(struct i2c_client *client)
+{
+	int i32_ret = FAIL;
+
+	i32_ret = set_skip_load(client);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_COMP, 1);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+	}
+
+	i32_ret = SUCCESS;
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_load_test_fw(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned char u8_buf[4];
+	unsigned int u32_crc_result, u32_read_data;
+
+	/*set mcu hold*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x20;
+	raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	raydium_i2c_pda_read(client, 0x40000004, u8_buf, 4);
+	u8_buf[0] |= 0x01;
+	raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	msleep(25);
+
+	i32_ret = raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	u8_buf[3] |= 0x40;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	i32_ret = raydium_i2c_pda_read(client, 0x40000014, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	u8_buf[0] |= 0x04;
+	u8_buf[1] |= 0x04;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000014, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	memset(u8_buf, 0, sizeof(u8_buf));
+	pr_debug("[touch]Raydium WRT test_fw to PRAM\n");
+
+	i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	/*Sending test fw*/
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		i32_ret = raydium_fw_upgrade_with_image(client,
+			0x800, RAYDIUM_TEST_FW);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+	}
+
+	/*check pram crc data*/
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[1] = 0x08;
+		u8_buf[2] = 0x5B;
+		u8_buf[3] = 0x6B;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		u8_buf[3] |= 0x81;
+		i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+		usleep_range(9500, 10500);
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		i32_ret = raydium_i2c_pda_read(client, 0x6B5C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_read_data, u8_buf, 4);
+		if (u32_read_data != u32_crc_result) {
+			pr_err("[touch]check pram fw crc fail, result=0x%x\n",
+					u32_crc_result);
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x60;
+		u8_buf[1] = 0x6B;
+		u8_buf[2] = 0xFB;
+		u8_buf[3] = 0x6D;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		u8_buf[3] |= 0x81;
+		i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+		usleep_range(1000, 2000);
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		i32_ret = raydium_i2c_pda_read(client, 0x6DFC, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_read_data, u8_buf, 4);
+		if (u32_read_data != u32_crc_result) {
+			pr_err("[touch]check pram CB crc fail, result=0x%x\n",
+					u32_crc_result);
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		i32_ret = raydium_i2c_pda_read(client, 0x80, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		if (u8_buf[2] > 2) {
+			pr_err("[touch]bootloader version %x,!!\n", u8_buf[2]);
+			memset(u8_buf, 0, sizeof(u8_buf));
+
+			u8_buf[1] = 0x04;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000918,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+	}
+
+	/*Skip load*/
+	pr_info("[touch]Raydium skip load\n");
+	i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[0] = 0x10;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_do_software_reset(client);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	pr_debug("[touch]0x5000918 = 0x%x, 0x%x, 0x%x, 0x%x\n",
+		u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]);
+	i32_ret = raydium_check_fw_ready(client);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+#endif /* FW_UPDATE_EN */
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
new file mode 100644
index 0000000..439c19b
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
@@ -0,0 +1,1402 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include "raydium_driver.h"
+
+static ssize_t raydium_touch_calibration_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[1];
+	int i32_ret = -1;
+	unsigned char u8_retry = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+
+	u8_rbuffer[0] = RAYDIUM_HOST_CMD_CALIBRATION;
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+				     u8_rbuffer, 1);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+
+	do {
+		if (u8_rbuffer[0] == RAYDIUM_HOST_CMD_NO_OP)
+			break;
+
+		msleep(1000);
+
+		i32_ret = raydium_i2c_pda2_read(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer, 1);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		pr_debug("[touch]RAD %s return 0x%02x!!\n",
+				__func__, u8_rbuffer[0]);
+	} while (u8_retry++ < (SYN_I2C_RETRY_TIMES * 2));
+
+	i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, "0x%02x\n", u8_rbuffer[0]);
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	return i32_ret;
+}
+
+static ssize_t raydium_i2c_pda_access_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_u32_length > 4)
+		return -EINVAL;
+
+	memset(u8_rbuffer, 0x00, 4);
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda_read(client,
+				g_u32_addr,
+				u8_rbuffer,
+				g_u32_length);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return scnprintf(p_i8_buf, PAGE_SIZE, "0x%08X : 0x%02X%02X%02X%02X\n",
+		 (unsigned int)g_u32_addr, u8_rbuffer[3], u8_rbuffer[2],
+		 u8_rbuffer[1], u8_rbuffer[0]);
+}
+
+static ssize_t raydium_check_i2c_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						 g_raydium_ts->is_suspend,
+						 RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		/*using byte mode to read 4 bytes*/
+		*(unsigned long *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24)
+						| ((RAD_CHK_I2C_CMD &
+						(~MASK_8BIT)) >> 8);
+
+		i32_ret = raydium_i2c_pda2_write(client,
+						RAYDIUM_PDA2_PDA_CFG_ADDR,
+						u8_rbuffer,
+						4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		i32_ret = raydium_i2c_pda2_read(client,
+				(unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT),
+				u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+	} else {
+		i32_ret = raydium_i2c_pda_read(client, RAD_CHK_I2C_CMD,
+					   u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+	}
+
+	i32_ret = scnprintf(p_i8_buf, PAGE_SIZE,
+			"[touch]RAD Touch check i2c: %02X%02X\n",
+			u8_rbuffer[3], u8_rbuffer[2]);
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+	return i32_ret;
+}
+
+static ssize_t raydium_hw_reset_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	int i32_ret = SUCCESS;
+
+	pr_debug("[touch]HW reset\n");
+	g_u8_resetflag = true;
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(DISABLE);
+
+	/*HW reset*/
+	if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+		gpio_set_value(g_raydium_ts->rst_gpio, 1);
+		gpio_set_value(g_raydium_ts->rst_gpio, 0);
+		msleep(RAYDIUM_RESET_INTERVAL_MSEC);
+		gpio_set_value(g_raydium_ts->rst_gpio, 1);
+	}
+
+	g_u8_i2c_mode = PDA2_MODE;
+
+	i32_ret = wait_irq_state(client, 1000, 2000);
+	if (i32_ret != ERROR)
+		msleep(25);
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(ENABLE);
+
+	pr_debug("Raydium HW Reset : %d\n", i32_ret);
+	return scnprintf(p_i8_buf, PAGE_SIZE,
+			"Raydium HW Reset : %d\n", i32_ret);
+}
+
+static ssize_t raydium_reset_control_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_high;
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_high);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	g_u8_i2c_mode = PDA2_MODE;
+	g_u8_resetflag = true;
+
+	if (u8_high) {
+		pr_debug("[touch]RAD %s set reset gpio to high!!\n", __func__);
+		gpio_set_value(g_raydium_ts->rst_gpio, 1);
+	} else {
+		pr_debug("[touch]RAD %s set reset gpio to low!!\n",  __func__);
+		gpio_set_value(g_raydium_ts->rst_gpio, 0);
+	}
+
+	return count;
+}
+
+static ssize_t raydium_palm_status_show(struct device *dev,
+					struct device_attribute *attr,
+					char *p_i8_buf)
+{
+	unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_tp_buf[MAX_REPORT_PACKET_SIZE];
+
+	raydium_read_touchdata(u8_tp_status, u8_tp_buf);
+	return scnprintf(p_i8_buf, PAGE_SIZE, "[touch] palm_status : %d\n",
+				u8_tp_status[POS_GES_STATUS]);
+}
+
+
+static ssize_t raydium_palm_area_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned char w_data[1];
+	unsigned char palm_area = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count > 3)
+		return -EINVAL;
+
+	ret = kstrtou8(buf, 16, &palm_area);
+	pr_debug("[touch] input palm area = %d\n", palm_area);
+
+	mutex_lock(&g_raydium_ts->lock);
+	/* unlock PARM */
+
+	ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend,
+			RAYDIUM_PDA2_PAGE_0);
+	if (ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	w_data[0] = palm_area;
+	ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_PALM_AREA_ADDR,
+				w_data, 1);
+	if (ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	mutex_unlock(&g_raydium_ts->lock);
+
+exit_error:
+	return count;
+}
+
+static ssize_t raydium_palm_area_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_PALM_AREA_ADDR,
+				    u8_rbuffer, 4);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, "RAD Palm area : %02X\n",
+					u8_rbuffer[0]);
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	return i32_ret;
+}
+
+static ssize_t raydium_irq_state_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	unsigned int u32_irq_value;
+
+	u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio);
+
+	pr_debug("%d\n", u32_irq_value);
+	return scnprintf(p_i8_buf, PAGE_SIZE, "%d", u32_irq_value);
+}
+
+
+static ssize_t raydium_touch_lock_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_mode;
+	unsigned char u8_wbuffer[1];
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	switch (u8_mode) {
+	case 0: /* Disable Touch lock */
+
+		if (g_raydium_ts->is_sleep != 1)
+			break;
+		g_u8_resetflag = true;
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			gpio_set_value(g_raydium_ts->rst_gpio, 0);
+			msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/
+		}
+		pr_debug("[touch]RAD %s disable touch lock!!\n", __func__);
+
+		g_raydium_ts->is_sleep = 0;
+		break;
+
+	case 1: /* Enable Touch lock */
+
+		if (g_raydium_ts->is_sleep == 1)
+			break;
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						 g_raydium_ts->is_suspend,
+						 RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		/*fw enter sleep mode*/
+		u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP;
+		i32_ret = raydium_i2c_pda2_write(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_wbuffer,
+						1);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		pr_debug("[touch]RAD %s enable touch lock!!\n", __func__);
+		g_raydium_ts->is_sleep = 1;
+		break;
+	}
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+	return count;
+}
+
+static ssize_t raydium_check_driver_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	return scnprintf(p_i8_buf, PAGE_SIZE, "RAD Driver Ver: 0x%X\n",
+			g_u32_driver_version);
+}
+
+static ssize_t raydium_check_fw_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	unsigned int fw_version;
+#ifdef FW_UPDATE_EN
+	unsigned int image_version;
+#endif
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_FW_VERSION_ADDR,
+				    u8_rbuffer, 4);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = scnprintf(p_i8_buf, PAGE_SIZE,
+			"RAD Touch FW Ver : %02X%02X%02X%02X\n",
+			u8_rbuffer[0], u8_rbuffer[1],
+			u8_rbuffer[2], u8_rbuffer[3]);
+
+	fw_version = (u8_rbuffer[0] << 24)
+		| (u8_rbuffer[1] << 16)
+		| (u8_rbuffer[2] << 8)
+		| u8_rbuffer[3];
+	pr_debug("[touch]RAD FW ver : 0x%x\n", fw_version);
+
+#ifdef FW_UPDATE_EN
+	image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+	pr_debug("[touch]RAD Image FW ver : 0x%x\n", image_version);
+
+	if (fw_version != image_version)
+		pr_debug("[touch]%s, FW need upgrade.\n", __func__);
+#endif
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	return i32_ret;
+}
+
+static ssize_t raydium_check_panel_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[8];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client,
+					RAYDIUM_PDA2_PANEL_VERSION_ADDR,
+					u8_rbuffer, 8);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = scnprintf(p_i8_buf, PAGE_SIZE,
+			"RAD Touch Panel Version : %02X%02X%02X%02X%02X%02X\n",
+			u8_rbuffer[0], u8_rbuffer[1], u8_rbuffer[2],
+			u8_rbuffer[3], u8_rbuffer[4], u8_rbuffer[5]);
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+	return i32_ret;
+}
+
+#ifdef FW_UPDATE_EN
+static ssize_t raydium_fw_upgrade_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &g_u8_upgrade_type);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return count;
+}
+
+static ssize_t raydium_fw_upgrade_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *p_i8_buf)
+{
+	int i32_ret = 0, i32_result = FAIL;
+	unsigned char u8_mode_change;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	raydium_irq_control(DISABLE);
+
+	pr_debug("[touch]RAD burn type is %d\n", g_u8_upgrade_type);
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0) {
+		g_u8_raydium_flag |= ENG_MODE;
+		u8_mode_change = 1;
+	}
+
+	if ((g_u8_table_setting == 1) && (g_u8_table_init == 1))
+		raydium_mem_table_setting();
+
+	if (g_u8_upgrade_type == 1) {
+		i32_ret = raydium_burn_fw(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	} else if (g_u8_upgrade_type == 2) {
+		i32_ret = raydium_burn_comp(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	} else if (g_u8_upgrade_type == 4) {
+		i32_ret = raydium_load_test_fw(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	}
+
+exit_upgrade:
+	if (u8_mode_change) {
+		pr_debug("[touch]g_u8_raydium_flag : %d", g_u8_raydium_flag);
+		g_u8_raydium_flag &= ~ENG_MODE;
+		u8_mode_change = 0;
+	}
+	raydium_irq_control(ENABLE);
+	g_u8_upgrade_type = 0;
+
+	return scnprintf(p_i8_buf, PAGE_SIZE,
+			"FW Upgrade result : %d\n", i32_result);
+}
+#endif
+
+static ssize_t raydium_i2c_pda2_page_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_page = 0;
+	char *temp_buf, *token;
+	const char *delim = " ,";
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	if (temp_buf) {
+		pr_err("[touch]input error, extra auguments!n");
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+	i32_ret = kstrtou8(token, 16, &u8_page);
+
+	if (i32_ret < 0)
+		goto exit_error;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend,
+						u8_page);
+	if (i32_ret < 0)
+		goto exit_set_error;
+
+	/* TODO: Page check, Due to ISR will change page back to Page_0.
+	 *  Or disable IRQ during PDA2 access period
+	 */
+
+exit_set_error:
+	mutex_unlock(&g_raydium_ts->lock);
+
+exit_error:
+	kfree(token);
+	kfree(temp_buf);
+	return count;
+}
+
+static ssize_t raydium_flag_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *p_i8_buf)
+{
+	pr_debug("[touch]RAD flag : %d\n", g_u8_raydium_flag);
+	return scnprintf(p_i8_buf, PAGE_SIZE, "%d", g_u8_raydium_flag);
+}
+
+static ssize_t raydium_flag_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_flag = 0;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_flag);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	g_u8_raydium_flag = u8_flag;
+	return count;
+}
+
+#ifdef FW_UPDATE_EN
+static ssize_t raydium_mem_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_type = 0;
+	unsigned int u32_image_version;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	pr_debug("[touch]%s\n", __func__);
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_type);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	if (u8_type > 3) {
+		pr_debug("[touch]Input invalid value!!\n");
+		return ERROR;
+	}
+
+	if (g_rad_boot_image != NULL)
+		kfree(g_rad_boot_image);
+	if (g_rad_init_image != NULL)
+		kfree(g_rad_init_image);
+	if (g_rad_fw_image != NULL)
+		kfree(g_rad_fw_image);
+	if (g_rad_para_image != NULL)
+		kfree(g_rad_para_image);
+	if (g_rad_testfw_image != NULL)
+		kfree(g_rad_testfw_image);
+	if (g_rad_testpara_image != NULL)
+		kfree(g_rad_testpara_image);
+
+	if (!raydium_id_init(u8_type)) {
+		pr_debug("[touch]Set Raydium id failed!\n");
+		return count;
+	}
+
+	raydium_mem_table_init(g_raydium_ts->id);
+	if (raydium_mem_table_setting()) {
+		u32_image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+		pr_debug("[touch]RAD Image FW ver : 0x%x\n", u32_image_version);
+	} else
+		pr_debug("[touch]Mem init failed!\n");
+
+	return count;
+}
+#endif
+
+static ssize_t raydium_i2c_raw_data_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[RAD_FT_CMD_LENGTH];
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf  == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token  == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtou8(token, 16, &g_u8_raw_data_type);
+
+	token = strsep(&temp_buf, delim);
+	if (token) {
+		i32_ret = kstrtouint(token, 16, &g_u32_raw_data_len);
+		if (i32_ret < 0)
+			goto exit_error;
+
+
+	} else { /* without length info*/
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	if (temp_buf) { /* too much arguments*/
+		i32_ret = -E2BIG;
+		goto exit_error;
+	}
+
+	memset(u8_w_data, 0x00, RAD_FT_CMD_LENGTH);
+
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	g_u8_resetflag = true;
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_w_data[RAD_FT_CMD_POS] = g_u8_raw_data_type;
+
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_w_data, RAD_FT_CMD_LENGTH);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	if (g_u8_raw_data_type == 0) {
+		usleep_range(10000, 20000);
+		g_u8_resetflag = false;
+	}
+exit_error:
+	kfree(token);
+	kfree(temp_buf);
+
+	return count;
+}
+static ssize_t raydium_i2c_raw_data_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE];
+	unsigned int u32_target_addr;
+	unsigned int u32_offset;
+	unsigned short u16_read_length;
+
+	int i32_ret = -1;
+	int i32_retry = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct raydium_ts_data *ts =
+		(struct raydium_ts_data *)i2c_get_clientdata(client);
+	unsigned char u8_retry_limit = (ts->is_suspend) ? 30 : 3;
+
+	memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE);
+
+	/* make sure update flag was set*/
+	for (i32_retry = 0; i32_retry < u8_retry_limit; i32_retry++) {
+		mutex_lock(&ts->lock);
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_read(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer,
+						RAD_FT_CMD_LENGTH);
+		mutex_unlock(&ts->lock);
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+		if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE)
+				== RAYDIUM_FT_UPDATE)
+			break;
+
+		usleep_range(4500, 5500);
+	}
+
+	if (i32_retry == u8_retry_limit) {
+		i32_ret = -EAGAIN;
+		goto exit_flag_error;
+	}
+
+	u32_offset = 0;
+	u16_read_length = 0;
+	while (u32_offset < g_u32_raw_data_len) {
+		if ((u32_offset + MAX_READ_PACKET_SIZE) <
+				g_u32_raw_data_len)
+			u16_read_length = MAX_READ_PACKET_SIZE;
+		else
+			u16_read_length =
+				(unsigned short)(g_u32_raw_data_len
+							- u32_offset);
+
+		u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset;
+
+		mutex_lock(&(ts->lock));
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		*(unsigned int *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24)
+						| ((u32_target_addr
+						& (~MASK_8BIT)) >> 8);
+
+		/*using byte mode to read 4 bytes*/
+		i32_ret = raydium_i2c_pda2_write(client,
+				RAYDIUM_PDA2_PDA_CFG_ADDR, u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_set_page(client,
+				ts->is_suspend,
+				RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_read(client,
+				(unsigned char)(u32_target_addr & MASK_8BIT),
+				u8_rbuffer,
+				u16_read_length);
+
+		mutex_unlock(&(ts->lock));
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+		memcpy((p_i8_buf + u32_offset), u8_rbuffer, u16_read_length);
+
+		u32_offset += u16_read_length;
+	}
+
+	/* clear update flag to get next one*/
+	u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_rbuffer[RAD_FT_CMD_POS] = g_u8_raw_data_type;
+	mutex_lock(&ts->lock);
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+				     u8_rbuffer, RAD_FT_CMD_LENGTH);
+	mutex_unlock(&ts->lock);
+	if (i32_ret < 0)
+		goto exit_flag_error;
+
+	return g_u32_raw_data_len;
+exit_i2c_error:
+	mutex_unlock(&(ts->lock));
+exit_flag_error:
+	return i32_ret;
+}
+static ssize_t raydium_i2c_pda_access_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE];
+	unsigned int u32_data_count = 0;
+	unsigned int u32_data_index = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtoul(token, 16, &g_u32_addr);
+
+	token = strsep(&temp_buf, delim);
+	if (token)
+		i32_ret = kstrtouint(token, 16, &u32_data_count);
+	else
+		goto exit_error;
+
+	if (g_u32_length > MAX_WRITE_PACKET_SIZE)
+		goto exit_error;
+
+	g_u32_length = u32_data_count;
+
+	memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE);
+
+	if (temp_buf && u32_data_count) {
+		u32_data_index = 0;
+		while (u32_data_count) {
+			token = strsep(&temp_buf, delim);
+			i32_ret = kstrtou8(token, 16,
+					&u8_w_data[u32_data_index++]);
+			if (i32_ret < 0)
+				goto exit_error;
+			u32_data_count--;
+		}
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda_write(client, g_u32_addr,
+					       u8_w_data, g_u32_length);
+		mutex_unlock(&g_raydium_ts->lock);
+	}
+
+exit_error:
+	kfree(token);
+	kfree(temp_buf);
+	return count;
+}
+
+static ssize_t raydium_i2c_pda2_mode_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_mode;
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_debug("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	i32_ret = raydium_i2c_mode_control(client, u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return count;
+}
+
+static ssize_t raydium_i2c_pda2_access_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_u32_length > 4)
+		return -EINVAL;
+
+	memset(u8_rbuffer, 0x00, 4);
+
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_read(client, g_u8_addr,
+					u8_rbuffer, g_u32_length);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return scnprintf(p_i8_buf, PAGE_SIZE, "0x%04X : 0x%02X%02X%02X%02X\n",
+			g_u8_addr, u8_rbuffer[3], u8_rbuffer[2],
+			u8_rbuffer[1], u8_rbuffer[0]);
+}
+
+static ssize_t raydium_i2c_pda2_access_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE];
+	unsigned int u32_data_count = 0;
+	unsigned int u32_data_index = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf  == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token  == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtou8(token, 16, &g_u8_addr);
+
+	token = strsep(&temp_buf, delim);
+	if (token)
+		i32_ret = kstrtouint(token, 16, &u32_data_count);
+	else {
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	if (u32_data_count > MAX_WRITE_PACKET_SIZE) {
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE);
+
+	g_u32_length = u32_data_count;
+
+	if (temp_buf && u32_data_count) {
+		u32_data_index = 0;
+		while (u32_data_count) {
+			token = strsep(&temp_buf, delim);
+			i32_ret = kstrtou8(token, 16,
+					 &u8_w_data[u32_data_index++]);
+			if (i32_ret < 0)
+				goto exit_error;
+			u32_data_count--;
+		}
+
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda2_write(client, g_u8_addr,
+						u8_w_data, g_u32_length);
+		mutex_unlock(&g_raydium_ts->lock);
+		if (i32_ret < 0)
+			goto exit_error;
+	}
+
+exit_error:
+	kfree(token);
+	kfree(temp_buf);
+	return count;
+}
+
+#ifdef FW_UPDATE_EN
+static ssize_t raydium_receive_fw_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	const char *delim = " ,";
+	char *token, *temp_buf;
+	static unsigned char *p_u8_firmware_data;
+
+	unsigned char u8_cmd;
+	unsigned long u32_len;
+	static unsigned char u8_type;
+	static unsigned int u32_index;
+
+	if (count == 20) { /*check FW type*/
+		temp_buf = kzalloc(32, GFP_KERNEL);
+		if (temp_buf  == NULL) {
+			pr_err("[touch]kzalloc temp_buf failed\n");
+			return -ENOMEM;
+		}
+
+		token = kzalloc(32, GFP_KERNEL);
+		if (token == NULL) {
+			kfree(temp_buf);
+			return -ENOMEM;
+		}
+
+		snprintf(temp_buf, PAGE_SIZE, "%s", p_i8_buf);
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtou8(token, 16, &u8_cmd);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			goto exit_error;
+		}
+
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtou8(token, 16, &u8_type);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			goto exit_error;
+		}
+
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtoul(token, 16, &u32_len);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			goto exit_error;
+		}
+
+		pr_debug("[touch]uc_cmd=0x%x, uc_type=0x%x, u16_len=0x%x\n",
+			u8_cmd, u8_type, (unsigned int)u32_len);
+
+		if (u8_cmd == RAD_CMD_UPDATE_BIN) { /*check FW length*/
+			u32_index = 0;
+			if (u8_type == RAYDIUM_BOOTLOADER) {
+				memset(g_rad_boot_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_boot_image;
+			} else if (u8_type == RAYDIUM_INIT) {
+				memset(g_rad_init_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_init_image;
+			} else if (u8_type == RAYDIUM_PARA) {
+				memset(g_rad_para_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_para_image;
+			} else if (u8_type == RAYDIUM_FIRMWARE) {
+				memset(g_rad_fw_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_fw_image;
+			} else if (u8_type == RAYDIUM_TEST_PARA) {
+				memset(g_rad_testpara_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_testpara_image;
+			} else if (u8_type == RAYDIUM_TEST_FW) {
+				memset(g_rad_testfw_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_testfw_image;
+			}
+
+		} else if (u8_cmd == RAD_CMD_UPDATE_END) { /*set buffer finish*/
+			if (((g_raydium_ts->id & 0x2000) == 0x2000)
+					&& (u8_type == RAYDIUM_TEST_FW)) {
+				memcpy((g_rad_testfw_image + RAD_FW_2X_SIZE),
+						g_rad_testpara_image,
+						RAD_PARA_2X_SIZE + 4);
+			}
+
+			u32_index = 0;
+			g_u8_table_setting = 0;
+
+		} else if (u8_cmd == RAD_CMD_BURN_FINISH) { /*free buffer*/
+			u8_type = 0;
+			u32_index = 0;
+			g_u8_table_setting = 1;
+		}
+
+	} else  if (count > 10) {	/*start copy FW to array*/
+		memcpy((p_u8_firmware_data + u32_index), p_i8_buf, count);
+		u32_index += count;
+	} else
+		pr_debug("[touch]other case, count=%d\n", count);
+
+exit_error:
+	kfree(temp_buf);
+	kfree(token);
+	return count;
+}
+#endif
+
+#ifdef RAD_SELFTEST
+static ssize_t raydium_selftest_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	int i32_ret = SUCCESS;
+
+	pr_debug("[touch]do selftest\n");
+
+	i32_ret = raydium_do_selftest();
+
+	return scnprintf(p_i8_buf, PAGE_SIZE,
+			"Raydium do selftest : %d\n", i32_ret);
+}
+
+#endif
+/* panel calibration cmd (R)
+ *  example:cat raydium_ic_verion
+ */
+static DEVICE_ATTR(raydium_touch_calibration, 0644,
+		   raydium_touch_calibration_show,
+		   NULL);
+
+/* check the i2c (R)
+ *  example:cat raydium_check_i2c
+ */
+static DEVICE_ATTR(raydium_check_i2c, 0644,
+		   raydium_check_i2c_show,
+		   NULL);
+
+#ifdef FW_UPDATE_EN
+/* upgrade configurate and algo firmware from app.bin (W)
+ *  example:echo "offset num_of_bin length *_app.bin [length *_app.bin]"
+ *  > raydium_fw_upgrade_mode
+ */
+static DEVICE_ATTR(raydium_fw_upgrade, 0644,
+		   raydium_fw_upgrade_show,
+		   raydium_fw_upgrade_store);
+#endif
+
+/* change I2C communication mode (W)
+ *  example:echo 1 > raydium_i2c_pda2_mode ==> enable pda2 mode
+ *        echo 0 > raydium_i2c_pda2_mode ==> disable pda2 mode
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_mode, 0644,
+		   NULL,
+		   raydium_i2c_pda2_mode_store);
+
+/* I2C pda mode (R/W)
+ *  example:    cat raydium_i2c_pda_access ==> read pda address provided by the
+ *		following cmd
+ *		echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda_access ==> write
+ *		pda address [data]
+ */
+static DEVICE_ATTR(raydium_i2c_pda_access, 0644,
+		   raydium_i2c_pda_access_show,
+		   raydium_i2c_pda_access_store);
+
+/* I2C pda2 mode (R/W)
+ *  example:    cat raydium_i2c_pda2_access ==> read pda2 address provided by
+ *		the following cmd
+ *		echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda2_access ==>
+ *		write pda2 address [data]
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_access, 0644,
+		   raydium_i2c_pda2_access_show,
+		   raydium_i2c_pda2_access_store);
+
+/* I2C pda2 mode page (W)
+ *  example:    echo PAGEinHEX > raydium_i2c_pda2_page ==> write pda2 page
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_page, 0644,
+		   NULL,
+		   raydium_i2c_pda2_page_store);
+
+/* I2C read/set FT raw data (R/W)
+ *  example:    cat raydium_i2c_raw_data ==> read raw data with specific length
+ *		of corresponding type provided by the following cmd
+ *              echo DataTypeinHEX RawDataLengthinHEX > raydium_i2c_raw_data
+ *		==> set raw data type and its length
+ */
+static DEVICE_ATTR(raydium_i2c_raw_data, 0644,
+		   raydium_i2c_raw_data_show,
+		   raydium_i2c_raw_data_store);
+
+/* Read interrupt flag cmd (R)
+ *  example:cat raydium_flag
+ */
+static DEVICE_ATTR(raydium_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Read interrupt flag cmd (R)
+ *  example:cat raydium_int_flag
+ */
+static DEVICE_ATTR(raydium_int_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Read selftest flag cmd (R)
+ *  example:cat raydium_int_flag
+ */
+static DEVICE_ATTR(raydium_selftest_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Touch lock (W)
+ *  example:    echo 1 > raydium_i2c_touch_lock ==> enable touch lock
+ *            echo 0 > raydium_i2c_touch_lock ==> disable touch lock
+ */
+static DEVICE_ATTR(raydium_i2c_touch_lock, 0644,
+		   NULL,
+		   raydium_touch_lock_store);
+
+/* show the fw version (R)
+ *  example:cat raydium_fw_version
+ */
+static DEVICE_ATTR(raydium_check_fw_version, 0644,
+		   raydium_check_fw_version_show,
+		   NULL);
+
+/* show the driver version (R)
+ *  example:cat raydium_check_driver_version
+ */
+static DEVICE_ATTR(raydium_check_driver_version, 0644,
+		   raydium_check_driver_version_show,
+		   NULL);
+/* show the panel version (R)
+ *  example:cat raydium_panel_version
+ */
+static DEVICE_ATTR(raydium_check_panel_version, 0644,
+		   raydium_check_panel_version_show,
+		   NULL);
+
+static DEVICE_ATTR(raydium_hw_reset, 0644,
+		   raydium_hw_reset_show,
+		   NULL);
+
+static DEVICE_ATTR(raydium_irq_state, 0644,
+		   raydium_irq_state_show,
+		   NULL);
+static DEVICE_ATTR(raydium_palm_status, 0644,
+		   raydium_palm_status_show,
+		   NULL);
+static DEVICE_ATTR(raydium_palm_area, 0644,
+		   raydium_palm_area_show,
+		   raydium_palm_area_store);
+static DEVICE_ATTR(raydium_reset_control, 0644,
+		   NULL,
+		   raydium_reset_control_store);
+#ifdef FW_UPDATE_EN
+static DEVICE_ATTR(raydium_receive_fw_control, 0644,
+		   NULL,
+		   raydium_receive_fw_store);
+static DEVICE_ATTR(raydium_mem_setting, 0644,
+		   NULL,
+		   raydium_mem_store);
+#endif
+#ifdef RAD_SELFTEST
+static DEVICE_ATTR(raydium_do_selftest, 0644,
+		   raydium_selftest_show,
+		   NULL);
+#endif
+/*add your attr in here*/
+struct attribute *raydium_attributes[] = {
+	&dev_attr_raydium_touch_calibration.attr,
+	&dev_attr_raydium_check_i2c.attr,
+	&dev_attr_raydium_i2c_pda2_mode.attr,
+	&dev_attr_raydium_i2c_pda_access.attr,
+	&dev_attr_raydium_i2c_pda2_access.attr,
+	&dev_attr_raydium_i2c_pda2_page.attr,
+	&dev_attr_raydium_i2c_raw_data.attr,
+	&dev_attr_raydium_flag.attr,
+	&dev_attr_raydium_i2c_touch_lock.attr,
+	&dev_attr_raydium_check_fw_version.attr,
+	&dev_attr_raydium_check_panel_version.attr,
+	&dev_attr_raydium_hw_reset.attr,
+	&dev_attr_raydium_irq_state.attr,
+	&dev_attr_raydium_palm_status.attr,
+	&dev_attr_raydium_palm_area.attr,
+	&dev_attr_raydium_int_flag.attr,
+	&dev_attr_raydium_selftest_flag.attr,
+	&dev_attr_raydium_check_driver_version.attr,
+	&dev_attr_raydium_reset_control.attr,
+#ifdef FW_UPDATE_EN
+	&dev_attr_raydium_fw_upgrade.attr,
+	&dev_attr_raydium_receive_fw_control.attr,
+	&dev_attr_raydium_mem_setting.attr,
+#endif
+#ifdef RAD_SELFTEST
+	&dev_attr_raydium_do_selftest.attr,
+#endif
+	NULL
+};
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
index 21236e9..dd72261 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
@@ -1471,7 +1471,7 @@
 		input_mt_sync(rmi4_data->input_dev);
 #endif
 
-		if (rmi4_data->stylus_enable) {
+		if (rmi4_data->stylus_enable && rmi4_data->stylus_dev) {
 			stylus_presence = 0;
 			input_report_key(rmi4_data->stylus_dev,
 					BTN_TOUCH, 0);
@@ -3624,7 +3624,7 @@
 #endif
 	input_sync(rmi4_data->input_dev);
 
-	if (rmi4_data->stylus_enable) {
+	if (rmi4_data->stylus_enable && rmi4_data->stylus_dev) {
 		input_report_key(rmi4_data->stylus_dev,
 				BTN_TOUCH, 0);
 		input_report_key(rmi4_data->stylus_dev,
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f931a2c..c42c846 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -705,6 +705,15 @@
 	  variable brightness.  It also supports outputting the Avdd supply for
 	  AMOLED displays.
 
+config LEDS_MSM_GPIO_FLASH
+	tristate "Support for GPIO Flash LEDs"
+	help
+	  This driver supports the leds functionality of GPIO Flash LED. It
+	  includes flash mode and torch mode.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called leds-gpio-flash.
+
 config LEDS_QPNP_HAPTICS
 	tristate "Haptics support for QPNP PMIC"
 	depends on LEDS_CLASS && MFD_SPMI_PMIC
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 31d29f0..e53ef7e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -61,6 +61,7 @@
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
+obj-$(CONFIG_LEDS_MSM_GPIO_FLASH)	+= leds-msm-gpio-flash.o
 obj-$(CONFIG_LEDS_QTI_TRI_LED)		+= leds-qti-tri-led.o
 obj-$(CONFIG_LEDS_SYSCON)		+= leds-syscon.o
 obj-$(CONFIG_LEDS_VERSATILE)		+= leds-versatile.o
diff --git a/drivers/leds/leds-msm-gpio-flash.c b/drivers/leds/leds-msm-gpio-flash.c
new file mode 100644
index 0000000..6a5332e
--- /dev/null
+++ b/drivers/leds/leds-msm-gpio-flash.c
@@ -0,0 +1,516 @@
+/* Copyright (c) 2013-2014, 2017, 2020, 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/printk.h>
+#include <linux/list.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/clk/msm-clk-provider.h>
+#include <linux/pinctrl/consumer.h>
+
+/* #define CONFIG_GPIO_FLASH_DEBUG */
+#undef CDBG
+#ifdef CONFIG_GPIO_FLASH_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+#define LED_GPIO_FLASH_DRIVER_NAME	"qcom,leds-gpio-flash"
+#define LED_TRIGGER_DEFAULT		"none"
+
+#define GPIO_OUT_LOW          (0 << 1)
+#define GPIO_OUT_HIGH         (1 << 1)
+
+#define DUTY_CYCLE_BASE       100
+
+enum msm_flash_seq_type_t {
+	FLASH_EN,
+	FLASH_NOW,
+};
+
+enum msm_flash_gpio_type_t {
+	NORMAL_GPIO,
+	CLK_GPIO,
+};
+
+struct msm_flash_ctrl_seq {
+	enum msm_flash_seq_type_t seq_type;
+	uint8_t flash_on_val;
+	uint8_t torch_on_val;
+};
+
+struct led_gpio_flash_data {
+	int flash_en;
+	int flash_now;
+	struct clk *flash_en_clk;
+	struct clk *flash_now_clk;
+	int brightness;
+	atomic_t clk_enabled[2];
+	uint32_t clk_freq[2];
+	uint32_t duty_cycle[2];
+	enum msm_flash_gpio_type_t gpio_type[2];
+	struct led_classdev cdev;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *gpio_state_default;
+	struct msm_flash_ctrl_seq ctrl_seq[2];
+};
+
+static const struct of_device_id led_gpio_flash_of_match[] = {
+	{.compatible = LED_GPIO_FLASH_DRIVER_NAME,},
+	{},
+};
+
+static void led_gpio_brightness_set(struct led_classdev *led_cdev,
+				    enum led_brightness value)
+{
+	int rc = 0;
+	int brightness = value;
+	int flash_en = 0;
+	int flash_now = 0;
+	struct led_gpio_flash_data *flash_led =
+	    container_of(led_cdev, struct led_gpio_flash_data, cdev);
+
+	if (brightness > LED_HALF) {
+		flash_en =
+			flash_led->ctrl_seq[FLASH_EN].flash_on_val;
+		flash_now =
+			flash_led->ctrl_seq[FLASH_NOW].flash_on_val;
+	} else if (brightness > LED_OFF) {
+		flash_en =
+			flash_led->ctrl_seq[FLASH_EN].torch_on_val;
+		flash_now =
+			flash_led->ctrl_seq[FLASH_NOW].torch_on_val;
+	} else {
+		flash_en = 0;
+		flash_now = 0;
+	}
+
+	CDBG("%s:flash_en=%d, flash_now=%d\n", __func__, flash_en, flash_now);
+
+	if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO) {
+		rc = gpio_direction_output(flash_led->flash_en, flash_en);
+	} else {
+		if (flash_en == GPIO_OUT_HIGH &&
+			!atomic_read(&flash_led->clk_enabled[FLASH_EN])) {
+			rc = clk_prepare_enable(flash_led->flash_en_clk);
+			atomic_set(&flash_led->clk_enabled[FLASH_EN], 1);
+		} else if (flash_en == GPIO_OUT_LOW &&
+			atomic_read(&flash_led->clk_enabled[FLASH_EN])) {
+			clk_disable_unprepare(flash_led->flash_en_clk);
+			atomic_set(&flash_led->clk_enabled[FLASH_EN], 0);
+		}
+	}
+
+	if (rc) {
+		pr_err("%s: Failed to set flash en.\n", __func__);
+		return;
+	}
+
+	if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO) {
+		rc = gpio_direction_output(flash_led->flash_now, flash_now);
+	} else {
+		if (flash_now == GPIO_OUT_HIGH &&
+			!atomic_read(&flash_led->clk_enabled[FLASH_NOW])) {
+			rc = clk_prepare_enable(flash_led->flash_now_clk);
+			atomic_set(&flash_led->clk_enabled[FLASH_NOW], 1);
+		} else if (flash_now == GPIO_OUT_LOW &&
+			atomic_read(&flash_led->clk_enabled[FLASH_NOW]))  {
+			clk_disable_unprepare(flash_led->flash_now_clk);
+			atomic_set(&flash_led->clk_enabled[FLASH_NOW], 0);
+		}
+	}
+
+	if (rc) {
+		pr_err("%s: Failed to set flash now.\n", __func__);
+		return;
+	}
+
+	flash_led->brightness = brightness;
+}
+
+static enum led_brightness led_gpio_brightness_get(struct led_classdev
+						   *led_cdev)
+{
+	struct led_gpio_flash_data *flash_led =
+	    container_of(led_cdev, struct led_gpio_flash_data, cdev);
+	return flash_led->brightness;
+}
+
+static int led_gpio_get_dt_data(struct device *dev,
+			struct led_gpio_flash_data *flash_led)
+{
+	int rc = 0;
+	int i = 0;
+	const char *temp_str = NULL;
+	const char *seq_name = NULL;
+	uint32_t array_flash_seq[2];
+	uint32_t array_torch_seq[2];
+	struct device_node *node = dev->of_node;
+
+	flash_led->cdev.default_trigger = LED_TRIGGER_DEFAULT;
+	rc = of_property_read_string(node, "linux,default-trigger",
+			&temp_str);
+	if (!rc)
+		flash_led->cdev.default_trigger = temp_str;
+
+	rc = of_property_read_string(node, "linux,name", &flash_led->cdev.name);
+	if (rc) {
+		pr_err("Failed to read linux name. rc = %d\n", rc);
+		return rc;
+	}
+
+	/* Configure the gpio type as NORMAL_GPIO by default,
+	 * the gpio type should be CLK_GPIO if the frequency
+	 * is not 0.
+	 */
+	flash_led->gpio_type[FLASH_EN] = NORMAL_GPIO;
+	flash_led->gpio_type[FLASH_NOW] = NORMAL_GPIO;
+	rc = of_property_read_u32_array(node, "qcom,clk-freq",
+			flash_led->clk_freq, 2);
+	if (!rc) {
+		if (flash_led->clk_freq[FLASH_EN])
+			flash_led->gpio_type[FLASH_EN] = CLK_GPIO;
+
+		if (flash_led->clk_freq[FLASH_NOW])
+			flash_led->gpio_type[FLASH_NOW] = CLK_GPIO;
+	}
+
+	if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO) {
+		flash_led->flash_en =
+			of_get_named_gpio(node, "qcom,flash-en", 0);
+		if (flash_led->flash_en < 0) {
+			pr_err("Read flash-en property failed. rc = %d\n",
+				flash_led->flash_en);
+			return -EINVAL;
+		}
+		rc = gpio_request(flash_led->flash_en, "FLASH_EN");
+		if (rc) {
+			pr_err("%s: Failed to request gpio %d,rc = %d\n",
+				__func__, flash_led->flash_en, rc);
+			return rc;
+		}
+	} else {
+		flash_led->flash_en_clk =
+			devm_clk_get(dev, "flash_en_clk");
+		if (IS_ERR(flash_led->flash_en_clk)) {
+			pr_err("Failed to get flash-en clk.\n");
+			return -EINVAL;
+		}
+
+		flash_led->clk_freq[FLASH_EN] =
+			clk_round_rate(flash_led->flash_en_clk,
+			flash_led->clk_freq[FLASH_EN]);
+		rc = clk_set_rate(flash_led->flash_en_clk,
+				flash_led->clk_freq[FLASH_EN]);
+		if (rc) {
+			pr_err("%s: Failed to set rate for flash en.\n",
+				__func__);
+			return rc;
+		}
+	}
+
+	if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO) {
+		flash_led->flash_now =
+			of_get_named_gpio(node, "qcom,flash-now", 0);
+		if (flash_led->flash_now < 0) {
+			pr_err("Read flash-now property failed. rc = %d\n",
+				flash_led->flash_now);
+			return -EINVAL;
+		}
+		rc = gpio_request(flash_led->flash_now, "FLASH_NOW");
+		if (rc) {
+			pr_err("%s: Failed to request gpio %d,rc = %d\n",
+				__func__, flash_led->flash_now, rc);
+			return rc;
+		}
+	} else {
+		flash_led->flash_now_clk =
+			devm_clk_get(dev, "flash_now_clk");
+		if (IS_ERR(flash_led->flash_now_clk)) {
+			pr_err("Failed to get flash-now clk.\n");
+			return -EINVAL;
+		}
+
+		flash_led->clk_freq[FLASH_NOW] =
+			clk_round_rate(flash_led->flash_now_clk,
+			flash_led->clk_freq[FLASH_NOW]);
+		rc = clk_set_rate(flash_led->flash_now_clk,
+				flash_led->clk_freq[FLASH_NOW]);
+		if (rc) {
+			pr_err("%s: Failed to set rate for flash now.\n",
+				__func__);
+			return rc;
+		}
+	}
+
+	/* Configure the duty cycle if need. */
+	if (flash_led->gpio_type[FLASH_EN] == CLK_GPIO ||
+		flash_led->gpio_type[FLASH_NOW] == CLK_GPIO) {
+		rc = of_property_read_u32_array(node, "qcom,duty-cycle",
+				flash_led->duty_cycle, 2);
+		if (!rc &&
+			flash_led->duty_cycle[FLASH_EN] >= DUTY_CYCLE_BASE &&
+			flash_led->duty_cycle[FLASH_NOW] >= DUTY_CYCLE_BASE) {
+			pr_err("%s: the duty cycle value is invalid.\n",
+				__func__);
+			return -EINVAL;
+		}
+	}
+
+	/* Based on clk protocol, only RCG clks support duty cycle
+	 * configuration, so if the used clk doesn't support set duty
+	 * cycle, we use the clk's parent rcg clk to configure the
+	 * duty cycle.
+	 */
+	if (flash_led->duty_cycle[FLASH_EN]) {
+		struct clk *flash_en_duty_cycle_clk = NULL;
+
+		flash_en_duty_cycle_clk = devm_clk_get(dev,
+			"flash_en_duty_cycle_clk");
+		if (!IS_ERR(flash_en_duty_cycle_clk)) {
+			rc = clk_set_duty_cycle(flash_en_duty_cycle_clk,
+					flash_led->duty_cycle[FLASH_EN],
+					DUTY_CYCLE_BASE);
+			clk_put(flash_en_duty_cycle_clk);
+		} else {
+			rc = clk_set_duty_cycle(flash_led->flash_en_clk,
+					flash_led->duty_cycle[FLASH_EN],
+					DUTY_CYCLE_BASE);
+		}
+
+		if (rc) {
+			pr_err("Failed to set duty cycle for flash en.\n");
+			return rc;
+		}
+	}
+
+	if (flash_led->duty_cycle[FLASH_NOW]) {
+		struct clk *flash_now_duty_cycle_clk = NULL;
+
+		flash_now_duty_cycle_clk = devm_clk_get(dev,
+			"flash_now_duty_cycle_clk");
+		if (!IS_ERR(flash_now_duty_cycle_clk)) {
+			rc = clk_set_duty_cycle(flash_now_duty_cycle_clk,
+					flash_led->duty_cycle[FLASH_NOW],
+					DUTY_CYCLE_BASE);
+			clk_put(flash_now_duty_cycle_clk);
+		} else {
+			rc = clk_set_duty_cycle(flash_led->flash_now_clk,
+					flash_led->duty_cycle[FLASH_NOW],
+					DUTY_CYCLE_BASE);
+		}
+
+		if (rc) {
+			pr_err("Failed to set duty cycle for flash now.\n");
+			return rc;
+		}
+	}
+
+	rc = of_property_read_u32_array(node, "qcom,flash-seq-val",
+			array_flash_seq, 2);
+	if (rc < 0) {
+		pr_err("Failed to get flash op seq, rc = %d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32_array(node, "qcom,torch-seq-val",
+			array_torch_seq, 2);
+	if (rc < 0) {
+		pr_err("Failed to get torch op seq, rc = %d\n", rc);
+		return rc;
+	}
+
+	pr_debug("%s: seq: flash: %d, %d torch:%d, %d\n", __func__,
+		array_flash_seq[0], array_flash_seq[1],
+		array_torch_seq[0], array_torch_seq[1]);
+
+	for (i = 0; i < 2; i++) {
+		rc = of_property_read_string_index(node,
+				"qcom,op-seq", i,
+				&seq_name);
+		CDBG("%s seq_name[%d] = %s\n", __func__, i,
+				seq_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			return rc;
+		}
+
+		if (!strcmp(seq_name, "flash_en")) {
+			flash_led->ctrl_seq[FLASH_EN].seq_type =
+				FLASH_EN;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, flash_led->ctrl_seq[FLASH_EN].seq_type);
+			if (array_flash_seq[i] == 0)
+				flash_led->ctrl_seq[FLASH_EN].flash_on_val =
+					GPIO_OUT_LOW;
+			else
+				flash_led->ctrl_seq[FLASH_EN].flash_on_val =
+					GPIO_OUT_HIGH;
+
+			if (array_torch_seq[i] == 0)
+				flash_led->ctrl_seq[FLASH_EN].torch_on_val =
+					GPIO_OUT_LOW;
+			else
+				flash_led->ctrl_seq[FLASH_EN].torch_on_val =
+					GPIO_OUT_HIGH;
+		} else if (!strcmp(seq_name, "flash_now")) {
+			flash_led->ctrl_seq[FLASH_NOW].seq_type =
+				FLASH_NOW;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, flash_led->ctrl_seq[FLASH_NOW].seq_type);
+			if (array_flash_seq[i] == 0)
+				flash_led->ctrl_seq[FLASH_NOW].flash_on_val =
+					GPIO_OUT_LOW;
+			else
+				flash_led->ctrl_seq[FLASH_NOW].flash_on_val =
+					GPIO_OUT_HIGH;
+
+			if (array_torch_seq[i] == 0)
+				flash_led->ctrl_seq[FLASH_NOW].torch_on_val =
+					GPIO_OUT_LOW;
+			else
+				flash_led->ctrl_seq[FLASH_NOW].torch_on_val =
+					GPIO_OUT_HIGH;
+		}
+	}
+
+	return rc;
+}
+
+static int led_gpio_flash_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct led_gpio_flash_data *flash_led = NULL;
+
+	flash_led = devm_kzalloc(&pdev->dev, sizeof(struct led_gpio_flash_data),
+				 GFP_KERNEL);
+	if (flash_led == NULL)
+		return -ENOMEM;
+
+	flash_led->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(flash_led->pinctrl)) {
+		pr_err("%s:failed to get pinctrl\n", __func__);
+		rc = PTR_ERR(flash_led->pinctrl);
+		goto error;
+	}
+
+	flash_led->gpio_state_default = pinctrl_lookup_state(flash_led->pinctrl,
+		"flash_default");
+	if (IS_ERR(flash_led->gpio_state_default)) {
+		pr_err("%s:can not get active pinstate\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	rc = pinctrl_select_state(flash_led->pinctrl,
+		flash_led->gpio_state_default);
+	if (rc) {
+		pr_err("%s:set state failed!\n", __func__);
+		goto error;
+	}
+
+	rc = led_gpio_get_dt_data(&pdev->dev, flash_led);
+	if (rc) {
+		pr_err("%s: get device tree data failed.\n",
+				__func__);
+		goto error;
+	}
+
+	/* Add these atomic variables to make sure clk is disabled
+	 * just after the clk has been enabled.
+	 */
+	atomic_set(&flash_led->clk_enabled[FLASH_EN], 0);
+	atomic_set(&flash_led->clk_enabled[FLASH_NOW], 0);
+
+	platform_set_drvdata(pdev, flash_led);
+	flash_led->cdev.max_brightness = LED_FULL;
+	flash_led->cdev.brightness_set = led_gpio_brightness_set;
+	flash_led->cdev.brightness_get = led_gpio_brightness_get;
+
+	rc = led_classdev_register(&pdev->dev, &flash_led->cdev);
+	if (rc) {
+		pr_err("%s: Failed to register led dev. rc = %d\n",
+			__func__, rc);
+		goto error;
+	}
+	pr_err("%s:probe successfully!\n", __func__);
+	return 0;
+
+error:
+	if (flash_led->gpio_type[FLASH_EN] == CLK_GPIO &&
+		IS_ERR(flash_led->flash_en_clk))
+		devm_clk_put(&pdev->dev, flash_led->flash_en_clk);
+	else if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO &&
+		flash_led->flash_en)
+		gpio_free(flash_led->flash_en);
+
+	if (flash_led->gpio_type[FLASH_NOW] == CLK_GPIO &&
+		IS_ERR(flash_led->flash_now_clk))
+		devm_clk_put(&pdev->dev, flash_led->flash_now_clk);
+	else if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO &&
+		flash_led->flash_now)
+		gpio_free(flash_led->flash_now);
+
+	if (IS_ERR(flash_led->pinctrl))
+		devm_pinctrl_put(flash_led->pinctrl);
+
+	devm_kfree(&pdev->dev, flash_led);
+	return rc;
+}
+
+static int led_gpio_flash_remove(struct platform_device *pdev)
+{
+	struct led_gpio_flash_data *flash_led =
+	    (struct led_gpio_flash_data *)platform_get_drvdata(pdev);
+	if (IS_ERR(flash_led->pinctrl))
+		devm_pinctrl_put(flash_led->pinctrl);
+	led_classdev_unregister(&flash_led->cdev);
+	devm_kfree(&pdev->dev, flash_led);
+	return 0;
+}
+
+static struct platform_driver led_gpio_flash_driver = {
+	.probe = led_gpio_flash_probe,
+	.remove = led_gpio_flash_remove,
+	.driver = {
+		   .name = LED_GPIO_FLASH_DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   .of_match_table = led_gpio_flash_of_match,
+	}
+};
+
+static int __init led_gpio_flash_init(void)
+{
+	return platform_driver_register(&led_gpio_flash_driver);
+}
+
+static void __exit led_gpio_flash_exit(void)
+{
+	return platform_driver_unregister(&led_gpio_flash_driver);
+}
+
+late_initcall(led_gpio_flash_init);
+module_exit(led_gpio_flash_exit);
+
+MODULE_DESCRIPTION("QTI GPIO LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("leds:leds-msm-gpio-flash");
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index e418fa9..0dce0fa 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, 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
@@ -511,8 +511,8 @@
 		}
 	}
 
-	priority = evt_handler->priority;
 	if (found) {
+		priority = evt_handler->priority;
 		for (i = 0; i < controller->num_registers; i++) {
 			irq_register = &controller->irq_register_arr[i];
 			irq_register->top_half_enable_mask[priority] &=
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index c5808d4..e6a0e01 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, 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
@@ -511,8 +511,8 @@
 		}
 	}
 
-	priority = evt_handler->priority;
 	if (found) {
+		priority = evt_handler->priority;
 		for (i = 0; i < controller->num_registers; i++) {
 			irq_register = &controller->irq_register_arr[i];
 			irq_register->top_half_enable_mask[priority] &=
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
index 56b86d7..7d711aa 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 2020, 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
@@ -40,8 +40,8 @@
 #define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1)
 #define MAX_DEBUGFS_NAME 50
 #define DEFAULT_TIMEOUT 3
-#define DEFAULT_HEIGHT 1088
-#define DEFAULT_WIDTH 1920
+#define DEFAULT_HEIGHT 480
+#define DEFAULT_WIDTH 720
 #define MIN_SUPPORTED_WIDTH 32
 #define MIN_SUPPORTED_HEIGHT 32
 #define DEFAULT_FPS 15
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index cf5764e..c0b5390 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -282,6 +282,36 @@
 	  to maintain PMIC register and RTC state in the absence of
 	  external power.
 
+config QCOM_XR_SMRTVWR_MISC
+	tristate "QTI XR SmartVwr Misc driver support"
+	default n
+	help
+	  This driver supports the misc chips power up such as
+	  USB bridge chip, Display Port bridgechip, MIPI switches etc.
+	  This driver initializes gpios, turns on and off gpios, and
+          enables/disables LDOs that are part of XR  Smart Viewer
+	  reference device.
+
+config TUSB1064_XR_MISC
+	tristate "I2C driver for TI TUSB1064 chip for XR"
+	default n
+	help
+	  This i2c driver allows applications to communicate with TI
+	  TUSB1064 USB redriver chip. This redriver chip could be configured
+	  to USB3.1 mode, Display Port 4lane and USB2.0 Mode, and Display Port
+	  2-lane and USB 3.1 modes. This driver allows the XR smart viewer to
+	  put in any one of the above three modes.
+
+config VXR200_XR_MISC
+	tristate "I2C driver for Synaptics VXR7200 chip for XR"
+	default n
+	help
+	  This i2c driver allows applications to communicate with Synaptics
+	  VXR7200 DP2DSI bridge chip. This driver enables the display data
+	  from Display Port and move the data to DSI data path. Thus enabling
+	  the display data from DP to be shown on the display of the XR smart
+	  viewer reference device.
+
 config SGI_GRU
 	tristate "SGI GRU driver"
 	depends on X86_UV && SMP
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 6494a66..0331572 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,6 +62,10 @@
 
 obj-$(CONFIG_UID_SYS_STATS)	+= uid_sys_stats.o
 obj-$(CONFIG_MEMORY_STATE_TIME)	+= memory_state_time.o
+obj-$(CONFIG_QCOM_XR_SMRTVWR_MISC) += qcom-xr-smrtvwr-misc.o
+obj-$(CONFIG_TUSB1064_XR_MISC) += tusb1064.o
+obj-$(CONFIG_VXR200_XR_MISC) += vxr7200.o
+
 
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o
diff --git a/drivers/misc/qcom-xr-smrtvwr-misc.c b/drivers/misc/qcom-xr-smrtvwr-misc.c
new file mode 100644
index 0000000..fc8796f
--- /dev/null
+++ b/drivers/misc/qcom-xr-smrtvwr-misc.c
@@ -0,0 +1,159 @@
+/* Copyright (c) 2020, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+struct qcom_xr_smrtvwr {
+	struct device	*dev;
+};
+
+
+static int qcom_xr_smrtvwr_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct regulator *reg1, *reg2, *reg3;
+	int dp3p3_en_gpio = 142;
+	int wcd_en_gpio = 93;
+	int switch_gpio = 112;
+	int rgb_tck_oe_en_gpio = 108;
+
+	reg1 = devm_regulator_get(&pdev->dev, "pm660l_l6");
+	if (!IS_ERR(reg1)) {
+		regulator_set_load(reg1, 600000);
+		rc = regulator_enable(reg1);
+		if (rc < 0) {
+			pr_err("%s pm660l_l6 failed\n", __func__);
+			goto reg1_fail;
+		}
+	}
+
+	reg2 = devm_regulator_get(&pdev->dev, "pm660_l6");
+	if (!IS_ERR(reg2)) {
+		regulator_set_load(reg2, 600000);
+		rc = regulator_enable(reg2);
+		if (rc < 0) {
+			pr_err("%s pm660_l6 failed\n", __func__);
+			goto reg2_fail;
+		}
+	}
+
+	reg3 = devm_regulator_get(&pdev->dev, "pm660_l7");
+	if (!IS_ERR(reg3)) {
+		regulator_set_load(reg3, 600000);
+		rc = regulator_enable(reg3);
+		if (rc < 0) {
+			pr_err("%s pm660_l7 failed\n", __func__);
+			goto reg3_fail;
+		}
+	}
+
+	rc = gpio_request(dp3p3_en_gpio, "ti-dp-3v3-en-gpio");
+	if (rc) {
+		pr_err("%s dp3p3_en gpio request failed\n", __func__);
+		goto gpio3p3_fail;
+	}
+	rc = gpio_direction_output(dp3p3_en_gpio, 0);
+	if (rc) {
+		pr_err("%s dp3p3_en_gpio direction failed\n", __func__);
+		goto gpio3p3_fail;
+	}
+	gpio_set_value(dp3p3_en_gpio, 1);
+	msleep(20);
+
+	rc = gpio_request(wcd_en_gpio, "wcd9340_en_gpio");
+	if (rc) {
+		pr_err("%s wcd9340_en_gpio request failed\n", __func__);
+		goto gpiowcd_fail;
+	}
+	rc = gpio_direction_output(wcd_en_gpio, 0);
+	if (rc) {
+		pr_err("%s wcd9340_en_gpio direction failed\n", __func__);
+		goto gpiowcd_fail;
+	}
+	gpio_set_value(wcd_en_gpio, 1);
+	msleep(20);
+
+	rc = gpio_request(switch_gpio, "1p8_en_gpio");
+	if (rc) {
+		pr_err("%s 1p8_switch_gpio request failed\n", __func__);
+		goto gpio_switch_fail;
+	}
+	rc = gpio_direction_output(switch_gpio, 0);
+	if (rc) {
+		pr_err("%s 1p8_switch_gpio direction failed\n", __func__);
+		goto gpio_switch_fail;
+	}
+	gpio_set_value(switch_gpio, 1);
+	msleep(20);
+
+	rc = gpio_request(rgb_tck_oe_en_gpio, "rgb_tck_oe_en_gpio");
+	if (rc) {
+		pr_err("%s rgb_tck_oe_en_gpio request failed\n", __func__);
+		goto gpio_oe_en_fail;
+	}
+	rc = gpio_direction_output(rgb_tck_oe_en_gpio, 0);
+	if (rc) {
+		pr_err("%s rgb_tck_oe_en_gpio direction failed\n", __func__);
+		goto gpio_oe_en_fail;
+	}
+	gpio_set_value(rgb_tck_oe_en_gpio, 0);
+	msleep(20);
+
+	pr_debug("%s success\n", __func__);
+	return 0;
+
+gpio_oe_en_fail:
+	gpio_free(rgb_tck_oe_en_gpio);
+gpio_switch_fail:
+	gpio_free(switch_gpio);
+gpiowcd_fail:
+	gpio_free(wcd_en_gpio);
+gpio3p3_fail:
+	gpio_free(dp3p3_en_gpio);
+reg3_fail:
+	devm_regulator_put(reg3);
+reg2_fail:
+	devm_regulator_put(reg2);
+reg1_fail:
+	devm_regulator_put(reg1);
+
+	return rc;
+}
+
+static const struct of_device_id qcom_xr_smrtvwr_match_table[] = {
+	{ .compatible = "qcom,xr-smrtvwr-misc", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_xr_smrtvwr_match_table);
+
+static struct platform_driver qcom_xr_smrtvwr_driver = {
+	.driver	= {
+		.name		= "qcom-xr-smrtvwr-misc",
+		.of_match_table	= qcom_xr_smrtvwr_match_table,
+	},
+	.probe		= qcom_xr_smrtvwr_probe,
+};
+
+module_platform_driver(qcom_xr_smrtvwr_driver);
+
+MODULE_DESCRIPTION("QTI XR SMRTVWR MISC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/tusb1064.c b/drivers/misc/tusb1064.c
new file mode 100644
index 0000000..234e21a
--- /dev/null
+++ b/drivers/misc/tusb1064.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2020, 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.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+struct tusb1064 {
+	struct device *dev;
+	struct device_node *host_node;
+	u8 i2c_addr;
+	u32 dp_3v3_en;
+	struct i2c_client *i2c_client;
+	bool power_on;
+};
+
+static struct tusb1064 *pdata;
+static bool standalone_mode;
+
+static int tusb1064_read(struct i2c_client *client, u8 reg, char *buf, u32 size)
+{
+	struct i2c_msg msg[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = size,
+			.buf = buf,
+		}
+	};
+
+	if (i2c_transfer(client->adapter, msg, 2) != 2) {
+		pr_err("%s i2c read failed\n", __func__);
+		return -EIO;
+	}
+	pr_debug("%s, reg:%x buf[0]:%x\n", __func__, reg, buf[0]);
+
+	return 0;
+}
+
+static int tusb1064_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	u8 buf[2] = {reg, val};
+	struct i2c_msg msg = {
+		.addr = client->addr,
+		.flags = 0,
+		.len = 2,
+		.buf = buf,
+	};
+
+	pr_debug("%s, reg:%x, val:%x\n", __func__, reg, val);
+	if (i2c_transfer(client->adapter, &msg, 1) < 1) {
+		pr_err("i2c write failed\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+void tusb1064_flip(bool flip)
+{
+	if (pdata) {
+		if (flip) {
+			pr_debug("%s flipping the switch\n", __func__);
+			/*AUXn->SBU2, AUXp->SBU1*/
+			tusb1064_write(pdata->i2c_client, 0x13, 0x2F);
+		} else {
+			pr_debug("%s not flipping the switch\n", __func__);
+			/*AUXn->SBU2, AUXp->SBU1*/
+			tusb1064_write(pdata->i2c_client, 0x13, 0x1F);
+		}
+	}
+}
+EXPORT_SYMBOL(tusb1064_flip);
+
+static int tusb1064_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	char buf[2];
+
+	if (!client || !client->dev.of_node) {
+		pr_err("%s invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s device doesn't support I2C\n", __func__);
+		return -ENODEV;
+	}
+
+	pdata = devm_kzalloc(&client->dev,
+		sizeof(struct tusb1064), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = &client->dev;
+	pdata->i2c_client = client;
+	pr_debug("%s I2C address is %x\n", __func__, client->addr);
+
+	i2c_set_clientdata(client, pdata);
+	dev_set_drvdata(&client->dev, pdata);
+
+	tusb1064_read(pdata->i2c_client, 0x0A, buf, 2);
+	tusb1064_read(pdata->i2c_client, 0x13, buf, 2);
+	/*Enable 4-lane DP with FLip and enable EQ_OVERRIDe*/
+	/*tusb1064_write(pdata, 0x0A, 0x13); */
+	/*written usb sideEnable 4-lane DP with FLip and enable EQ_OVERRIDe */
+	/*tusb1064_write(pdata, 0x0A, 0x12); */
+
+	if (standalone_mode) {
+		/*Enable 3.1 USB, no DP */
+		if (tusb1064_write(pdata->i2c_client, 0x0A, 0x01) < 0)
+			goto fail;
+	} else {
+		/*Enable 4-lane DP with Flip and enable EQ_OVERRIDe */
+		if (tusb1064_write(pdata->i2c_client, 0x0A, 0x02) < 0)
+			goto fail;
+
+		pr_debug("%s setting SBU1 to AUXN, SBU2 to AUXP\n", __func__);
+		/*AUXn->SBU2, AUXp->SBU1 */
+		if (tusb1064_write(pdata->i2c_client, 0x13, 0x1F) < 0)
+			goto fail;
+		//tusb1064_write(pdata, 0x13, 0x01);//AUXn->SBU1, AUXp->SBU2
+
+		/*Enable 4-lane DP */
+		if (tusb1064_write(pdata->i2c_client, 0x10, 0x55) < 0)
+			goto fail;
+		/*Enable 4-lane DP */
+		if (tusb1064_write(pdata->i2c_client, 0x11, 0x55) < 0)
+			goto fail;
+		//pr_err("setting SBU1 to AUXp and SBU2 to AUXN\n");
+		//tusb1064_write(pdata, 0x13, 0x8F);//Enable 4-lane DP
+	}
+	tusb1064_read(pdata->i2c_client, 0x0A, buf, 2);
+	tusb1064_read(pdata->i2c_client, 0x13, buf, 2);
+	tusb1064_read(pdata->i2c_client, 0x10, buf, 2);
+	tusb1064_read(pdata->i2c_client, 0x11, buf, 2);
+
+	pr_debug("%s probe successfully\n", __func__);
+	return 0;
+fail:
+	devm_kfree(&client->dev, pdata);
+	return -EINVAL;
+}
+
+static int tusb1064_remove(struct i2c_client *client)
+{
+	struct tusb1064 *pdata = i2c_get_clientdata(client);
+
+	if (pdata)
+		devm_kfree(&client->dev, pdata);
+	return 0;
+}
+
+static void tusb1064_shutdown(struct i2c_client *client)
+{
+	dev_info(&(client->dev), "shutdown");
+}
+
+static int tusb1064_suspend(struct device *dev, pm_message_t state)
+{
+	dev_info(dev, "suspend");
+	return 0;
+}
+
+static int tusb1064_resume(struct device *dev)
+{
+	dev_info(dev, "resume");
+	return 0;
+}
+
+static const struct i2c_device_id tusb1064_id_table[] = {
+	{"tusb1064", 0},
+	{}
+};
+
+static struct i2c_driver tusb1064_i2c_driver = {
+	.probe = tusb1064_probe,
+	.remove = tusb1064_remove,
+	.shutdown = tusb1064_shutdown,
+	.driver = {
+		.name = "tusb1064",
+		.owner = THIS_MODULE,
+		.suspend = tusb1064_suspend,
+		.resume = tusb1064_resume,
+	},
+	.id_table = tusb1064_id_table,
+};
+
+static int __init tusb1064_init(void)
+{
+	char *cmdline;
+
+	cmdline = strnstr(boot_command_line,
+			"msm_drm.dsi_display0=dsi_sim_vid_display",
+				strlen(boot_command_line));
+	if (cmdline) {
+		pr_debug("%s tethered mode cmdline:%s\n",
+				__func__, cmdline);
+		standalone_mode = false;
+	} else {
+		pr_debug("%s standalone mode cmdline:%s\n",
+				__func__, cmdline);
+		standalone_mode = true;
+	}
+
+	return 0;
+}
+
+device_initcall(tusb1064_init);
+module_i2c_driver(tusb1064_i2c_driver);
+MODULE_DEVICE_TABLE(i2c, tusb1064_id_table);
+MODULE_DESCRIPTION("TUSB1064 USB Bridge");
diff --git a/drivers/misc/vxr7200.c b/drivers/misc/vxr7200.c
new file mode 100644
index 0000000..ad1c82c
--- /dev/null
+++ b/drivers/misc/vxr7200.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2020, 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.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/kernel.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/rwlock.h>
+#include <linux/leds.h>
+
+struct vxr7200 {
+	struct device *dev;
+	struct device_node *host_node;
+
+	u8 i2c_addr;
+	int irq;
+	u32 vxr_3v3_en;
+	u32 led_5v_en;
+	u32 led_drive_en1;
+	u32 led_drive_en2;
+	u32 display_1v8_en;
+	u32 mipi_sw_1v8_en;
+	u32 display_res1;
+	u32 selab_gpio;
+	u32 oenab_gpio;
+	bool gpioInit;
+
+	struct i2c_client *i2c_client;
+
+	struct regulator *vddio;
+	struct regulator *lab;
+	struct regulator *ibb;
+
+	bool power_on;
+};
+
+static bool dsi_way;
+
+static int vxr7200_read(struct vxr7200 *pdata, u8 *reg, u8 *buf, u32 size)
+{
+	struct i2c_client *client = pdata->i2c_client;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 4,
+			.buf = reg,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = size,
+			.buf = buf,
+		}
+	};
+
+	if (i2c_transfer(client->adapter, msg, 2) != 2) {
+		pr_err("i2c read failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int turnGpio(struct vxr7200 *pdata, int gpio, char *name, bool on)
+{
+	int ret = -1;
+
+	pr_info("%s vxr7200 gpio:%d, name:%s, on:%d\n", __func__, gpio,
+						name, on);
+	if (!pdata->gpioInit) {
+		ret = gpio_request(gpio, name);
+		if (ret) {
+			pr_err("vxr7200 %s gpio request failed\n", name);
+			goto error;
+		}
+	}
+	if (on) {
+		ret = gpio_direction_output(gpio, 0);
+		if (ret) {
+			pr_err("vxr7200 gpio direction failed\n");
+			goto error;
+		}
+		gpio_set_value(gpio, 1);
+		pr_debug("%s vxr7200 gpio:%d set to high\n", __func__, gpio);
+	} else {
+		ret = gpio_direction_output(gpio, 1);
+		if (ret) {
+			pr_err("vxr7200 gpio direction failed\n");
+			goto error;
+		}
+		gpio_set_value(gpio, 0);
+		pr_debug("%s vxr7200 gpio:%d set to low\n", __func__, gpio);
+	}
+	return 0;
+error:
+	return -EINVAL;
+}
+
+static void vxr7200_set_gpios(struct vxr7200 *pdata, bool turnOn)
+{
+	int rc;
+
+	pr_debug("%s, turnOn:%d\n", __func__, turnOn);
+	if (pdata) {
+		rc = turnGpio(pdata, pdata->vxr_3v3_en, "vxr_3v3_en", turnOn);
+		if (rc)
+			goto gpio1Fail;
+		rc = turnGpio(pdata, pdata->led_5v_en, "led_5v_en", turnOn);
+		if (rc)
+			goto gpio2Fail;
+		rc = turnGpio(pdata, pdata->led_drive_en1,
+					"led_drive_en1", turnOn);
+		if (rc)
+			goto gpio3Fail;
+		rc = turnGpio(pdata, pdata->led_drive_en2,
+					 "led_drive_en2", turnOn);
+		if (rc)
+			goto gpio4Fail;
+		rc = turnGpio(pdata, pdata->display_1v8_en,
+					 "disp_1v8_en", turnOn);
+		if (rc)
+			goto gpio5Fail;
+		pdata->mipi_sw_1v8_en += 1100;
+		rc = turnGpio(pdata, pdata->mipi_sw_1v8_en,
+						 "mipi_sw1v8_en", turnOn);
+		if (rc)
+			goto gpio6Fail;
+		rc = turnGpio(pdata, pdata->display_res1,
+						 "display_res1", turnOn);
+		if (rc)
+			goto gpio7Fail;
+	}
+
+gpio7Fail:
+	gpio_free(pdata->display_res1);
+gpio6Fail:
+	gpio_free(pdata->mipi_sw_1v8_en);
+gpio5Fail:
+	gpio_free(pdata->display_1v8_en);
+gpio4Fail:
+	gpio_free(pdata->led_drive_en2);
+gpio3Fail:
+	gpio_free(pdata->led_drive_en1);
+gpio2Fail:
+	gpio_free(pdata->led_5v_en);
+gpio1Fail:
+	gpio_free(pdata->vxr_3v3_en);
+}
+
+static void vxr7200_free_gpios(struct vxr7200 *pdata)
+{
+	if (pdata) {
+		gpio_free(pdata->vxr_3v3_en);
+		gpio_free(pdata->led_5v_en);
+		gpio_free(pdata->led_drive_en1);
+		gpio_free(pdata->led_drive_en2);
+		gpio_free(pdata->display_1v8_en);
+		gpio_free(pdata->mipi_sw_1v8_en);
+		gpio_free(pdata->display_res1);
+	}
+}
+
+
+static int vxr7200_parse_dt(struct device *dev,
+				struct vxr7200 *pdata)
+{
+	struct device_node *np = dev->of_node;
+	int rc = 0;
+
+	pdata->vxr_3v3_en =
+		of_get_named_gpio(np, "qcom,vxr_3v3_en", 0);
+	if (!gpio_is_valid(pdata->vxr_3v3_en)) {
+		pr_err("vxr_3v3_en gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->led_5v_en =
+		of_get_named_gpio(np, "qcom,led-5v-en-gpio", 0);
+	if (!gpio_is_valid(pdata->led_5v_en)) {
+		pr_err("led_5v_en gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->led_drive_en1 =
+		of_get_named_gpio(np, "qcom,led-driver-en1-gpio", 0);
+	if (!gpio_is_valid(pdata->led_drive_en1)) {
+		pr_err("led_drive_en1 gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->led_drive_en2 =
+		of_get_named_gpio(np, "qcom,led-driver-en2-gpio", 0);
+	if (!gpio_is_valid(pdata->led_drive_en2)) {
+		pr_err("led_drive_en2 gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->display_1v8_en =
+		of_get_named_gpio(np, "qcom,1p8-en-gpio", 0);
+	if (!gpio_is_valid(pdata->display_1v8_en)) {
+		pr_err("display_1v8_en gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->mipi_sw_1v8_en =
+		of_get_named_gpio(np, "qcom,switch-power-gpio", 0);
+	if (!gpio_is_valid(pdata->mipi_sw_1v8_en)) {
+		pr_err("mipi_sw_1v8_en gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	pdata->display_res1 =
+		of_get_named_gpio(np, "qcom,platform-reset-gpio", 0);
+	if (!gpio_is_valid(pdata->display_res1)) {
+		pr_err("display_res1 gpio not specified\n");
+		rc = -EINVAL;
+	}
+
+	if (!rc)
+		vxr7200_set_gpios(pdata, true);
+
+	pdata->selab_gpio = of_get_named_gpio(np, "qcom,selab-gpio", 0);
+	if (!gpio_is_valid(pdata->selab_gpio)) {
+		pr_err("selab_gpio gpio not specified\n");
+		rc = -EINVAL;
+		goto gpio_selab_fail;
+	} else
+		turnGpio(pdata, pdata->selab_gpio, "selab_gpio", 0);
+
+	pdata->oenab_gpio = of_get_named_gpio(np, "qcom,oenab-gpio", 0);
+	if (!gpio_is_valid(pdata->oenab_gpio)) {
+		pr_err("oenab_gpio gpio not specified\n");
+		rc = -EINVAL;
+		goto gpio_oenab_fail;
+	} else
+		turnGpio(pdata, pdata->oenab_gpio, "oenab_gpio", 0);
+
+	if (!pdata->gpioInit)
+		pdata->gpioInit = true;
+
+	return rc;
+
+gpio_oenab_fail:
+	gpio_free(pdata->oenab_gpio);
+gpio_selab_fail:
+	gpio_free(pdata->selab_gpio);
+	vxr7200_free_gpios(pdata);
+	return rc;
+}
+
+static void vxr7200_display_pwr_enable_vregs(struct vxr7200 *pdata)
+{
+	int rc = 0;
+
+	pdata->vddio = devm_regulator_get(pdata->dev, "pm660_l11");
+	rc = PTR_RET(pdata->vddio);
+	if (rc) {
+		pr_err("Failed to get pm660_l11 regulator %s\n", __func__);
+		goto vddio_fail;
+	}
+	rc = regulator_set_load(pdata->vddio, 62000);
+	if (rc < 0) {
+		pr_err("Load setting failed for vddio %s\n", __func__);
+		goto vddio_fail;
+	}
+	rc = regulator_set_voltage(pdata->vddio, 1800000, 1800000);
+	if (rc) {
+		pr_err("Set voltage(vddio) fail, rc=%d %s\n", rc, __func__);
+		goto vddio_fail;
+	}
+	rc = regulator_enable(pdata->vddio);
+	if (rc) {
+		pr_err("enable failed for vddio, rc=%d %s\n", rc, __func__);
+		goto vddio_fail;
+	}
+
+	pdata->lab = devm_regulator_get(pdata->dev, "lcdb_ldo");
+	rc = PTR_RET(pdata->lab);
+	if (rc) {
+		pr_err("Failed to get lcdb_ldo_vreg regulator %s\n", __func__);
+		goto lab_fail;
+	}
+	rc = regulator_set_load(pdata->lab, 100000);
+	if (rc < 0) {
+		pr_err("Load Setting failed for lab %s\n", __func__);
+		goto lab_fail;
+	}
+	rc = regulator_set_voltage(pdata->lab, 4600000, 6000000);
+	if (rc) {
+		pr_err("Set voltage(lab) fail, rc=%d %s\n", rc, __func__);
+		goto lab_fail;
+	}
+	rc = regulator_enable(pdata->lab);
+	if (rc) {
+		pr_err("enable failed for lab, rc=%d %s\n", rc, __func__);
+		goto lab_fail;
+	}
+
+	pdata->ibb = devm_regulator_get(pdata->dev, "lcdb_ncp");
+	rc = PTR_RET(pdata->ibb);
+	if (rc) {
+		pr_err("Failed to get lcdb_ncp_vreg regulator %s\n", __func__);
+		goto ibb_fail;
+	}
+	rc = regulator_set_load(pdata->ibb, 100000);
+	if (rc < 0) {
+		pr_err("Load Setting failed for ibb %s\n", __func__);
+		goto ibb_fail;
+	}
+	rc = regulator_set_voltage(pdata->ibb, 4600000, 6000000);
+	if (rc) {
+		pr_err("Set voltage(ibb) fail, rc=%d %s\n", rc, __func__);
+		goto ibb_fail;
+	}
+	rc = regulator_enable(pdata->ibb);
+	if (rc) {
+		pr_err("enable failed for ibb, rc=%d %s\n", rc, __func__);
+		goto ibb_fail;
+	}
+
+	return;
+
+ibb_fail:
+	devm_regulator_put(pdata->ibb);
+	(void)regulator_set_load(pdata->ibb, 100);
+	(void)regulator_set_voltage(pdata->ibb, 0, 6000000);
+
+lab_fail:
+	(void)regulator_set_voltage(pdata->lab, 0, 6000000);
+	(void)regulator_set_load(pdata->lab, 100);
+	devm_regulator_put(pdata->lab);
+
+vddio_fail:
+	(void)regulator_set_load(pdata->vddio, 100);
+	(void)regulator_set_voltage(pdata->vddio, 0, 1800000);
+	devm_regulator_put(pdata->vddio);
+}
+
+static int vxr7200_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc;
+	struct vxr7200 *pdata;
+	u8 reg[4] = {0x00, 0x20, 0x01, 0x60};
+	u8 buf[4] = {0x00, 0x0, 0x0, 0x0};
+
+	if (!client || !client->dev.of_node) {
+		pr_err("%s invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s device doesn't support I2C\n", __func__);
+		return -ENODEV;
+	}
+
+	if (dsi_way)
+		return -EINVAL;
+
+	pdata = devm_kzalloc(&client->dev,
+		sizeof(struct vxr7200), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->gpioInit = false;
+
+	rc = vxr7200_parse_dt(&client->dev, pdata);
+	if (rc) {
+		pr_err("%s failed to parse device tree\n", __func__);
+		goto err_dt_parse;
+	}
+	pdata->dev = &client->dev;
+	pdata->i2c_client = client;
+
+	vxr7200_display_pwr_enable_vregs(pdata);
+
+	i2c_set_clientdata(client, pdata);
+	dev_set_drvdata(&client->dev, pdata);
+
+	//vxr7200_write(pdata, 0x0A, 0x02);//Enable 4-lane DP
+	vxr7200_read(pdata, reg, buf, 4);//Enable 4-lane DP
+
+err_dt_parse:
+	devm_kfree(&client->dev, pdata);
+
+	return rc;
+}
+
+static int vxr7200_remove(struct i2c_client *client)
+{
+	struct vxr7200 *pdata = i2c_get_clientdata(client);
+
+	if (pdata)
+		devm_kfree(&client->dev, pdata);
+	return 0;
+}
+
+
+static void vxr7200_shutdown(struct i2c_client *client)
+{
+	dev_info(&(client->dev), "shutdown");
+}
+
+static int vxr7200_pm_freeze(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vxr7200 *pdata = i2c_get_clientdata(client);
+
+	dev_info(dev, "freeze");
+	vxr7200_set_gpios(pdata, false);
+	return 0;
+}
+static int vxr7200_pm_restore(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vxr7200 *pdata = i2c_get_clientdata(client);
+
+	dev_info(dev, "restore");
+	vxr7200_set_gpios(pdata, true);
+	return 0;
+}
+static int vxr7200_pm_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vxr7200 *pdata = i2c_get_clientdata(client);
+
+	dev_info(dev, "suspend");
+	vxr7200_set_gpios(pdata, false);
+	return 0;
+}
+
+static int vxr7200_pm_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vxr7200 *pdata = i2c_get_clientdata(client);
+
+	dev_info(dev, "resume");
+	vxr7200_set_gpios(pdata, true);
+	return 0;
+}
+
+static const struct dev_pm_ops vxr7200_dev_pm_ops = {
+	.suspend	= vxr7200_pm_suspend,
+	.resume	 = vxr7200_pm_resume,
+	.freeze	 = vxr7200_pm_freeze,
+	.restore	= vxr7200_pm_restore,
+	.thaw	   = vxr7200_pm_restore,
+	.poweroff       = vxr7200_pm_suspend,
+};
+
+static const struct i2c_device_id vxr7200_id_table[] = {
+	{"vxr7200", 0},
+	{}
+};
+
+static struct i2c_driver vxr7200_i2c_driver = {
+	.probe = vxr7200_probe,
+	.remove = vxr7200_remove,
+	.shutdown = vxr7200_shutdown,
+	.driver = {
+		.name = "vxr7200",
+		.owner = THIS_MODULE,
+		.pm    = &vxr7200_dev_pm_ops,
+	},
+	.id_table = vxr7200_id_table,
+};
+
+static int __init vxr7200_init(void)
+{
+	char *cmdline;
+
+	cmdline = strnstr(boot_command_line,
+			 "msm_drm.dsi_display0=dsi_sim_vid_display",
+						strlen(boot_command_line));
+	if (cmdline) {
+		pr_debug("%s DSI SIM mode, going to dp init cmdline:%s\n",
+					__func__, cmdline);
+		dsi_way = false;
+	} else {
+		pr_debug("%s DSI WAY, going to dsi init cmdline:%s\n",
+					__func__, cmdline);
+		dsi_way = true;
+	}
+
+	return 0;
+
+}
+
+device_initcall(vxr7200_init);
+module_i2c_driver(vxr7200_i2c_driver);
+MODULE_DEVICE_TABLE(i2c, vxr7200_id_table);
+MODULE_DESCRIPTION("VXR7200 DP2DSI Bridge");
diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c
index fdc6188..d8c1048 100644
--- a/drivers/net/can/spi/qti-can.c
+++ b/drivers/net/can/spi/qti-can.c
@@ -46,8 +46,8 @@
 #define DRIVER_MODE_AMB			2
 #define QUERY_FIRMWARE_TIMEOUT_MS	300
 #define EUPGRADE			140
-#define TIME_OFFSET_MAX_THD		5
-#define TIME_OFFSET_MIN_THD		-5
+#define TIME_OFFSET_MAX_THD		30
+#define TIME_OFFSET_MIN_THD		-30
 
 struct qti_can {
 	struct net_device	**netdev;
@@ -326,7 +326,7 @@
 	if (ts_offset_corrected > 0) {
 		if (disp_disc_cntr == 1) {
 			dev_info(&priv_data->spidev->dev,
-				 "No of buff frames discarded is %lld\n",
+				 "No of buff frames discarded is %d\n",
 				 buff_frames_disc_cntr);
 			disp_disc_cntr = 0;
 		}
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index dc49be3..607369d 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -2155,8 +2155,8 @@
 		mhi_ctrl->iova_stop = pci_priv->smmu_iova_start +
 					pci_priv->smmu_iova_len;
 	} else {
-		mhi_ctrl->iova_start = memblock_start_of_DRAM();
-		mhi_ctrl->iova_stop = memblock_end_of_DRAM();
+		mhi_ctrl->iova_start = 0;
+		mhi_ctrl->iova_stop = (dma_addr_t)U64_MAX;
 	}
 
 	mhi_ctrl->link_status = cnss_mhi_link_status;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 23e0bf7..4b6922b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -629,75 +629,74 @@
 		)
 {
 	int ep_index = -1, i;
+	int pair_id = 0;
 
-	ep_info->num_ep_pairs = 0;
 	for (i = 0; i < ep_info->max_ep_pairs; i++) {
 		pair_info[i].consumer_pipe_num = -1;
 		pair_info[i].producer_pipe_num = -1;
 		pair_info[i].ep_id = -1;
 	}
-	ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD);
 
-	if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
-		pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
-		ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS);
-		if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
-			pair_info[ep_info->num_ep_pairs].producer_pipe_num =
-				ep_index;
-			pair_info[ep_info->num_ep_pairs].ep_id =
-				IPA_USB1_EP_ID;
+	if ((!ep_info->teth_prot_valid) || (ep_info->teth_prot_valid &&
+		ep_info->teth_prot == IPA_PROT_RMNET_CV2X)) {
+		ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD);
 
-			IPADBG("ep_pair_info consumer_pipe_num %d",
-				pair_info[ep_info->num_ep_pairs].
-				consumer_pipe_num);
-			IPADBG(" producer_pipe_num %d ep_id %d\n",
-				pair_info[ep_info->num_ep_pairs].
-				producer_pipe_num,
-				pair_info[ep_info->num_ep_pairs].ep_id);
-			ep_info->num_ep_pairs++;
-		} else {
-			pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
-			IPADBG("ep_pair_info consumer_pipe_num %d",
-				pair_info[ep_info->num_ep_pairs].
-				consumer_pipe_num);
-			IPADBG(" producer_pipe_num %d ep_id %d\n",
-				pair_info[ep_info->num_ep_pairs].
-				producer_pipe_num,
-				pair_info[ep_info->num_ep_pairs].ep_id);
+		if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+			pair_info[pair_id].consumer_pipe_num = ep_index;
+			ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS);
+
+			if ((ep_index != -1) &&
+				(ipa3_ctx->ep[ep_index].valid)) {
+				pair_info[pair_id].producer_pipe_num = ep_index;
+				pair_info[pair_id].ep_id = IPA_USB1_EP_ID;
+
+				IPADBG("ep_pair_info consumer_pipe_num %d",
+					pair_info[pair_id].consumer_pipe_num);
+				IPADBG(" producer_pipe_num %d ep_id %d\n",
+					pair_info[pair_id].producer_pipe_num,
+					pair_info[pair_id].ep_id);
+				pair_id++;
+			} else {
+				pair_info[pair_id].consumer_pipe_num = -1;
+				IPADBG("ep_pair_info consumer_pipe_num %d",
+					pair_info[pair_id].consumer_pipe_num);
+				IPADBG(" producer_pipe_num %d ep_id %d\n",
+					pair_info[pair_id].producer_pipe_num,
+					pair_info[pair_id].ep_id);
+			}
 		}
 	}
 
+	if ((!ep_info->teth_prot_valid) || (ep_info->teth_prot_valid &&
+		ep_info->teth_prot == IPA_PROT_RMNET)) {
+		ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
 
-	ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
+		if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+			pair_info[pair_id].consumer_pipe_num = ep_index;
+			ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS);
 
-	if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
-		pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
-		ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS);
-		if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
-			pair_info[ep_info->num_ep_pairs].producer_pipe_num =
-				ep_index;
-			pair_info[ep_info->num_ep_pairs].ep_id =
-				IPA_USB0_EP_ID;
+			if ((ep_index != -1) &&
+				(ipa3_ctx->ep[ep_index].valid)) {
+				pair_info[pair_id].producer_pipe_num = ep_index;
+				pair_info[pair_id].ep_id = IPA_USB0_EP_ID;
 
-			IPADBG("ep_pair_info consumer_pipe_num %d",
-				pair_info[ep_info->num_ep_pairs].
-				consumer_pipe_num);
-			IPADBG(" producer_pipe_num %d ep_id %d\n",
-				pair_info[ep_info->num_ep_pairs].
-				producer_pipe_num,
-				pair_info[ep_info->num_ep_pairs].ep_id);
-			ep_info->num_ep_pairs++;
-		} else {
-			pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
-			IPADBG("ep_pair_info consumer_pipe_num %d",
-				pair_info[ep_info->num_ep_pairs].
-				consumer_pipe_num);
-			IPADBG(" producer_pipe_num %d ep_id %d\n",
-				pair_info[ep_info->num_ep_pairs].
-				producer_pipe_num,
-				pair_info[ep_info->num_ep_pairs].ep_id);
+				IPADBG("ep_pair_info consumer_pipe_num %d",
+					pair_info[pair_id].consumer_pipe_num);
+				IPADBG(" producer_pipe_num %d ep_id %d\n",
+					pair_info[pair_id].producer_pipe_num,
+					pair_info[pair_id].ep_id);
+				pair_id++;
+			} else {
+				pair_info[pair_id].consumer_pipe_num = -1;
+				IPADBG("ep_pair_info consumer_pipe_num %d",
+					pair_info[pair_id].consumer_pipe_num);
+				IPADBG(" producer_pipe_num %d ep_id %d\n",
+					pair_info[pair_id].producer_pipe_num,
+					pair_info[pair_id].ep_id);
+			}
 		}
 	}
+	ep_info->num_ep_pairs = pair_id;
 
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 50dc080..672f721 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, 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
@@ -32,6 +32,8 @@
 #define IPA_READ_WRITE_MODE 0664
 #define IPA_WRITE_ONLY_MODE 0220
 
+#define DEBUG_BUF_MAX_LEN(nbytes) (nbytes < IPA_MAX_MSG_LEN ? 1 : 0)
+
 struct ipa3_debugfs_file {
 	const char *name;
 	umode_t mode;
@@ -392,26 +394,34 @@
 			ipa3_hdr_l2_type_name[entry->type]);
 
 		if (entry->is_hdr_proc_ctx) {
-			nbytes += scnprintf(
-				dbg_buff + nbytes,
-				IPA_MAX_MSG_LEN - nbytes,
-				"phys_base=0x%pa ",
-				&entry->phys_base);
+			if (DEBUG_BUF_MAX_LEN(nbytes)) {
+				nbytes += scnprintf(
+					dbg_buff + nbytes,
+					IPA_MAX_MSG_LEN - nbytes,
+					"phys_base=0x%pa ",
+					&entry->phys_base);
+			}
 		} else {
-			nbytes += scnprintf(
-				dbg_buff + nbytes,
-				IPA_MAX_MSG_LEN - nbytes,
-				"ofst=%u ",
-				entry->offset_entry->offset >> 2);
+			if (DEBUG_BUF_MAX_LEN(nbytes)) {
+				nbytes += scnprintf(
+					dbg_buff + nbytes,
+					IPA_MAX_MSG_LEN - nbytes,
+					"ofst=%u ",
+					entry->offset_entry->offset >> 2);
+			}
 		}
 		for (i = 0; i < entry->hdr_len; i++) {
-			scnprintf(dbg_buff + nbytes + i * 2,
-				  IPA_MAX_MSG_LEN - nbytes - i * 2,
-				  "%02x", entry->hdr[i]);
+			if (DEBUG_BUF_MAX_LEN(nbytes + i * 2)) {
+				scnprintf(dbg_buff + nbytes + i * 2,
+					  IPA_MAX_MSG_LEN - nbytes - i * 2,
+					  "%02x", entry->hdr[i]);
+			}
 		}
-		scnprintf(dbg_buff + nbytes + entry->hdr_len * 2,
-			  IPA_MAX_MSG_LEN - nbytes - entry->hdr_len * 2,
-			  "\n");
+		if (DEBUG_BUF_MAX_LEN(nbytes + entry->hdr_len * 2)) {
+			scnprintf(dbg_buff + nbytes + entry->hdr_len * 2,
+				  IPA_MAX_MSG_LEN - nbytes - entry->hdr_len * 2,
+				  "\n");
+		}
 		pr_err("%s", dbg_buff);
 	}
 	mutex_unlock(&ipa3_ctx->lock);
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.c b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
index dad3ec9..1db9ce9 100644
--- a/drivers/platform/msm/ipa/test/ipa_ut_framework.c
+++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, 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
@@ -439,9 +439,11 @@
 		for (i = 0 ; i < suite->tests_cnt ; i++) {
 			if (!suite->tests[i].run_in_regression)
 				continue;
-			nbytes += scnprintf(buf + nbytes,
-				IPA_UT_DEBUG_READ_BUF_SIZE - nbytes,
-				"\t\t%s\n", suite->tests[i].name);
+			if (nbytes < IPA_UT_DEBUG_READ_BUF_SIZE) {
+				nbytes += scnprintf(buf + nbytes,
+					IPA_UT_DEBUG_READ_BUF_SIZE - nbytes,
+					"\t\t%s\n", suite->tests[i].name);
+			}
 		}
 	}
 
diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c
index 5118318..7880457 100644
--- a/drivers/soc/qcom/bgcom_interface.c
+++ b/drivers/soc/qcom/bgcom_interface.c
@@ -73,6 +73,7 @@
 	bool pending_bg_twm_wear_load;
 	struct workqueue_struct *bgdaemon_wq;
 	struct work_struct bgdaemon_load_twm_bg_work;
+	bool bg_twm_wear_load;
 };
 
 struct bg_event {
@@ -132,6 +133,7 @@
 		dev->pil_h = NULL;
 		bg_soft_reset();
 	} else {
+		dev->bg_twm_wear_load = true;
 		dev->pil_h = subsystem_get_with_fwname("bg-wear",
 							"bg-twm-wear");
 		if (!dev->pil_h)
@@ -425,7 +427,7 @@
 			ret = -EFAULT;
 			break;
 		}
-
+		dev->bg_twm_wear_load = false;
 		dev->pil_h = subsystem_get_with_fwname("bg-wear", "bg-wear");
 		if (!dev->pil_h) {
 			pr_err("failed to load bg-wear\n");
@@ -624,7 +626,10 @@
 		}
 		break;
 	case SUBSYS_AFTER_POWERUP:
-		bge.e_type = BG_AFTER_POWER_UP;
+		if (dev->bg_twm_wear_load)
+			bge.e_type = TWM_BG_AFTER_POWER_UP;
+		else
+			bge.e_type = BG_AFTER_POWER_UP;
 		bgdaemon_ldowork(DISABLE_LDO03);
 		bgdaemon_ldowork(DISABLE_LDO09);
 		bgcom_set_spi_state(BGCOM_SPI_FREE);
diff --git a/drivers/soc/qcom/sdx_ext_ipc.c b/drivers/soc/qcom/sdx_ext_ipc.c
index 2b18017..dadc63c 100644
--- a/drivers/soc/qcom/sdx_ext_ipc.c
+++ b/drivers/soc/qcom/sdx_ext_ipc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, 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
@@ -240,6 +240,7 @@
 
 static const struct of_device_id sdx_ext_ipc_of_match[] = {
 	{ .compatible = "qcom,sdx-ext-ipc"},
+	{ .compatible = "qcom,sa415m-ccard"},
 	{},
 };
 
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 29f4205..6b4bba8 100755
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/utsname.h>
+#include <soc/qcom/boot_stats.h>
 
 #include <linux/usb/composite.h>
 #include <linux/usb/otg.h>
@@ -923,6 +924,7 @@
 	if (!c)
 		goto done;
 
+	place_marker("M - USB Device is enumerated");
 	usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
 	cdev->config = c;
 	c->num_ineps_used = 0;
@@ -2495,6 +2497,7 @@
 	 * suspend/resume callbacks?
 	 */
 	DBG(cdev, "resume\n");
+	place_marker("M - USB device is resumed");
 	if (cdev->driver->resume)
 		cdev->driver->resume(cdev);
 
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 92127ab..1a7ebc5 100755
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -18,8 +18,6 @@
 #include <function/u_ncm.h>
 #endif
 
-#include <soc/qcom/boot_stats.h>
-
 #ifdef CONFIG_USB_CONFIGFS_F_ACC
 extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
 				const struct usb_ctrlrequest *ctrl);
@@ -1460,7 +1458,6 @@
 		kobject_uevent_env(&gi->dev->kobj,
 					KOBJ_CHANGE, configured);
 		pr_info("%s: sent uevent %s\n", __func__, configured[0]);
-		place_marker("M - USB enumeration complete");
 		uevent_sent = true;
 	}
 
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index f252d32..2524146 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -73,6 +73,7 @@
 static void gsi_free_trb_buffer(struct f_gsi *gsi);
 static struct gsi_ctrl_pkt *gsi_ctrl_pkt_alloc(unsigned int len, gfp_t flags);
 static void gsi_ctrl_pkt_free(struct gsi_ctrl_pkt *pkt);
+static int gsi_ctrl_send_cpkt_tomodem(struct f_gsi *gsi, void *buf, size_t len);
 
 static inline bool is_ext_prot_ether(int prot_id)
 {
@@ -740,6 +741,12 @@
 			ipa_out_channel_out_params.db_reg_phs_addr_msb;
 	}
 
+	/* Send 0 byte packet to QTI only if DTR linetstate is HIGH already */
+	if (gsi->rmnet_dtr_status &&
+			(gsi->prot_id == USB_PROT_RMNET_IPA ||
+			 gsi->prot_id == USB_PROT_RMNET_V2X_IPA))
+		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
+
 	return ret;
 
 end_xfer_ep_out:
@@ -2220,6 +2227,14 @@
 			queue_work(gsi->c_port.uevent_wq,
 					&gsi->c_port.uevent_work);
 
+		/* Send 0 byte packet to QTI only if IPA connect is done */
+		if (gsi->rmnet_dtr_status) {
+			if (gsi->prot_id == USB_PROT_RMNET_ETHER)
+				gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
+			else if (gsi->d_port.in_channel_handle != -EINVAL)
+				gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
+		}
+
 		value = 0;
 		break;
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -2624,10 +2639,7 @@
 	if (gsi->prot_id == USB_PROT_DIAG_IPA ||
 				gsi->prot_id == USB_PROT_DPL_ETHER ||
 				gsi->prot_id == USB_PROT_GPS_CTRL ||
-				gsi->prot_id == USB_PROT_MBIM_IPA ||
-				gsi->prot_id == USB_PROT_RMNET_IPA ||
-				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
-				gsi->prot_id == USB_PROT_RMNET_ETHER)
+				gsi->prot_id == USB_PROT_MBIM_IPA)
 		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
 
 	if (gsi->c_port.uevent_wq)
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 34869b8..d4bb61a 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -1325,19 +1325,37 @@
 	/*Map the splash addr for VIDEO mode panel before smmu attach*/
 	if ((mfd->panel.type == MIPI_VIDEO_PANEL) &&
 				(mdp3_session->in_splash_screen)) {
+		rc = mdss_smmu_set_attribute(MDSS_IOMMU_DOMAIN_UNSECURE,
+							EARLY_MAP, 1);
+		if (rc) {
+			pr_err("mdp3 set attribute failed for early map\n");
+			goto reset_error;
+		}
+		rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+		if (IS_ERR_VALUE((unsigned long)rc)) {
+			pr_err("mdp3 iommu attach failed\n");
+			goto reset_error;
+		}
 		rc = mdss_smmu_map(MDSS_IOMMU_DOMAIN_UNSECURE,
 				mdp3_res->splash_mem_addr,
 				mdp3_res->splash_mem_addr,
 				mdp3_res->splash_mem_size,
 				IOMMU_READ | IOMMU_NOEXEC);
-	}
+		if (rc)
+			pr_err("iommu memory mapping failed ret=%d\n", rc);
+		else
+			pr_info("iommu map passed for PA=VA\n");
 
-	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
-	if (rc) {
-		pr_err("fail to attach dma iommu\n");
-		if (mdp3_res->idle_pc)
-			mdp3_clk_enable(0, 0);
-		goto reset_error;
+		rc = mdss_smmu_set_attribute(MDSS_IOMMU_DOMAIN_UNSECURE,
+							EARLY_MAP, 0);
+	} else {
+		rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+		if (rc) {
+			pr_err("fail to attach dma iommu\n");
+			if (mdp3_res->idle_pc)
+				mdp3_clk_enable(0, 0);
+			goto reset_error;
+		}
 	}
 
 	vsync_client = mdp3_dma->vsync_client;
@@ -1831,8 +1849,13 @@
 
 	mdp3_session->vsync_before_commit = 0;
 	if (!splash_done || mdp3_session->esd_recovery == true) {
-		if (panel && panel->set_backlight)
-			panel->set_backlight(panel, panel->panel_info.bl_max);
+		if (panel && panel->set_backlight) {
+			if (mfd->bl_level > 0)
+				panel->set_backlight(panel, mfd->bl_level);
+			else
+				panel->set_backlight(panel,
+						panel->panel_info.bl_max);
+		}
 		splash_done = true;
 		mdp3_session->esd_recovery = false;
 	}
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index e46cbfe..7d3009b 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, 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
@@ -425,6 +425,11 @@
 		return rc;
 	}
 
+	if (pinfo->skip_panel_reset && !pinfo->cont_splash_enabled) {
+		pr_debug("%s: skip_panel_reset is set\n", __func__);
+		return 0;
+	}
+
 	pr_debug("%s: enable = %d\n", __func__, enable);
 
 	if (enable) {
@@ -2942,6 +2947,9 @@
 	pinfo->mipi.force_clk_lane_hs = of_property_read_bool(np,
 		"qcom,mdss-dsi-force-clock-lane-hs");
 
+	pinfo->skip_panel_reset =
+		of_property_read_bool(np, "qcom,mdss-skip-panel-reset");
+
 	rc = mdss_dsi_parse_panel_features(np, ctrl_pdata);
 	if (rc) {
 		pr_err("%s: failed to parse panel features\n", __func__);
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 0c71e24..d1bce46 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1914,7 +1914,10 @@
 		if (mfd->disp_thread)
 			mdss_fb_stop_disp_thread(mfd);
 		mutex_lock(&mfd->bl_lock);
-		current_bl = mfd->bl_level;
+		if (mfd->unset_bl_level != U32_MAX)
+			current_bl = mfd->unset_bl_level;
+		else
+			current_bl = mfd->bl_level;
 		mfd->allow_bl_update = true;
 		mdss_fb_set_backlight(mfd, 0);
 		mfd->allow_bl_update = false;
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 0fa242e..e79ae1d 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2020, 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
@@ -774,6 +774,12 @@
 	/* persistence mode on/off */
 	bool persist_mode;
 
+	/*
+	 * Skip panel reset during panel on/off.
+	 * Set for some in-cell panels
+	 */
+	bool skip_panel_reset;
+
 	/* HDR properties of display panel*/
 	struct mdss_panel_hdr_properties hdr_properties;
 };
diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.c b/drivers/video/fbdev/msm/mdss_spi_panel.c
index e95dcd5..5cff450 100644
--- a/drivers/video/fbdev/msm/mdss_spi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_spi_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 2020, 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
@@ -1122,10 +1122,10 @@
 
 	if (level == 0) {
 		if (ctrl->pwm_enabled) {
-			ret = pwm_config_us(ctrl->pwm_bl, level,
-					ctrl->pwm_period);
+			ret = pwm_config(ctrl->pwm_bl, 0,
+				ctrl->pwm_period * NSEC_PER_USEC);
 			if (ret)
-				pr_err("%s: pwm_config_us() failed err=%d.\n",
+				pr_err("%s: pwm_config() failed err=%d.\n",
 						__func__, ret);
 			pwm_disable(ctrl->pwm_bl);
 		}
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 961156a..0acf72e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -126,6 +126,12 @@
 	unsigned int bpc;
 
 	/**
+	 * @bpc: Maximum bits per color channel for YCbCr420 modes.
+	 * Used by HDMI and DP outputs.
+	 */
+	unsigned int y420_bpc;
+
+	/**
 	 * @subpixel_order: Subpixel order of LCD panels.
 	 */
 	enum subpixel_order subpixel_order;
@@ -133,6 +139,8 @@
 #define DRM_COLOR_FORMAT_RGB444		(1<<0)
 #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
 #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
+#define DRM_COLOR_FORMAT_DC_RGB444	(1<<3)
+#define DRM_COLOR_FORMAT_DC_YCRCB444	(1<<4)
 
 	/**
 	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
diff --git a/include/linux/clk/msm-clk.h b/include/linux/clk/msm-clk.h
index baa8e52..f442538 100644
--- a/include/linux/clk/msm-clk.h
+++ b/include/linux/clk/msm-clk.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009, 2012-2017, 2020, 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
@@ -55,6 +55,11 @@
 /* Set clock-specific configuration parameters */
 int clk_set_flags(struct clk *clk, unsigned long flags);
 
+/* Set clock duty-cycle as a ratio of numerator/denominator for the desired
+ * duty cycle
+ */
+int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator);
+
 /* returns the mux selection index associated with a particular parent */
 int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p);
 
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index ae72202..9e9408d 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -148,7 +148,7 @@
  * a new RANGE of SSIDs to the msg_mask_tbl.
  */
 #define MSG_MASK_TBL_CNT		26
-#define APPS_EVENT_LAST_ID		0xCB9
+#define APPS_EVENT_LAST_ID		0xCC1
 
 #define MSG_SSID_0			0
 #define MSG_SSID_0_LAST			132
@@ -925,7 +925,7 @@
 /* LOG CODES */
 static const uint32_t log_code_last_tbl[] = {
 	0x0,	/* EQUIP ID 0 */
-	0x1CCA,	/* EQUIP ID 1 */
+	0x1CD6,	/* EQUIP ID 1 */
 	0x0,	/* EQUIP ID 2 */
 	0x0,	/* EQUIP ID 3 */
 	0x4910,	/* EQUIP ID 4 */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9560fda..fbbe3e8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -73,6 +73,9 @@
 /* Indicate backport support for DH IE creation/update*/
 #define CFG80211_EXTERNAL_DH_UPDATE_SUPPORT 1
 
+/* Indicate backport support for supported AKM advertisement per interface*/
+#define CFG80211_IFTYPE_AKM_SUITES_SUPPORT 1
+
 /**
  * DOC: Introduction
  *
@@ -3557,6 +3560,21 @@
 };
 
 /**
+ * struct wiphy_iftype_akm_suites - This structure encapsulates supported akm
+ * suites for interface types defined in @iftypes_mask. Each type in the
+ * @iftypes_mask must be unique across all instances of iftype_akm_suites.
+ *
+ * @iftypes_mask: bitmask of interfaces types
+ * @akm_suites: points to an array of supported akm suites
+ * @n_akm_suites: number of supported AKM suites
+ */
+struct wiphy_iftype_akm_suites {
+	u16 iftypes_mask;
+	const u32 *akm_suites;
+	int n_akm_suites;
+};
+
+/**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback,
  *	note that if your driver uses wiphy_apply_custom_regulatory()
@@ -3568,6 +3586,12 @@
  * @signal_type: signal type reported in &struct cfg80211_bss.
  * @cipher_suites: supported cipher suites
  * @n_cipher_suites: number of supported cipher suites
+ * @iftype_akm_suites: array of supported akm suites info per interface type.
+ *	Note that the bits in @iftypes_mask inside this structure cannot
+ *	overlap (i.e. only one occurrence of each type is allowed across all
+ *	instances of iftype_akm_suites).
+ * @num_iftype_akm_suites: number of interface types for which supported akm
+ *	suites are specified separately.
  * @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
  * @retry_long: Retry limit for long frames (dot11LongRetryLimit)
  * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
@@ -3754,6 +3778,9 @@
 	int n_cipher_suites;
 	const u32 *cipher_suites;
 
+	const struct wiphy_iftype_akm_suites *iftype_akm_suites;
+	unsigned int num_iftype_akm_suites;
+
 	u8 retry_short;
 	u8 retry_long;
 	u32 frag_threshold;
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 9c927a5..b420f2a 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -78,7 +78,29 @@
 #define  DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF	(8<<14)
 #define  DRM_MODE_FLAG_SEAMLESS			(1<<19)
 #define  DRM_MODE_FLAG_SUPPORTS_RGB		(1<<20)
-#define  DRM_MODE_FLAG_SUPPORTS_YUV		(1<<21)
+#define  DRM_MODE_FLAG_SUPPORTS_YUV422		(1<<21)
+#define  DRM_MODE_FLAG_SUPPORTS_YUV420		(1<<22)
+
+
+/* Picture aspect ratio options */
+#define DRM_MODE_PICTURE_ASPECT_NONE		0
+#define DRM_MODE_PICTURE_ASPECT_4_3		1
+#define DRM_MODE_PICTURE_ASPECT_16_9		2
+#define DRM_MODE_PICTURE_ASPECT_64_27		3
+#define DRM_MODE_PICTURE_ASPECT_256_135		4
+
+/* Aspect ratio flag bitmask (4 bits 27:24) */
+#define DRM_MODE_FLAG_PIC_AR_MASK		(0x0F<<24)
+#define  DRM_MODE_FLAG_PIC_AR_NONE \
+			(DRM_MODE_PICTURE_ASPECT_NONE<<24)
+#define  DRM_MODE_FLAG_PIC_AR_4_3 \
+			(DRM_MODE_PICTURE_ASPECT_4_3<<24)
+#define  DRM_MODE_FLAG_PIC_AR_16_9 \
+			(DRM_MODE_PICTURE_ASPECT_16_9<<24)
+#define  DRM_MODE_FLAG_PIC_AR_64_27 \
+			(DRM_MODE_PICTURE_ASPECT_64_27<<24)
+#define  DRM_MODE_FLAG_PIC_AR_256_135 \
+			(DRM_MODE_PICTURE_ASPECT_256_135<<24)
 
 /* DPMS flags */
 /* bit compatible with the xorg definitions. */
@@ -94,11 +116,6 @@
 #define DRM_MODE_SCALE_CENTER		2 /* Centered, no scaling */
 #define DRM_MODE_SCALE_ASPECT		3 /* Full screen, preserve aspect */
 
-/* Picture aspect ratio options */
-#define DRM_MODE_PICTURE_ASPECT_NONE	0
-#define DRM_MODE_PICTURE_ASPECT_4_3	1
-#define DRM_MODE_PICTURE_ASPECT_16_9	2
-
 /* Dithering mode options */
 #define DRM_MODE_DITHERING_OFF	0
 #define DRM_MODE_DITHERING_ON	1
diff --git a/include/uapi/linux/bgcom_interface.h b/include/uapi/linux/bgcom_interface.h
index b2ac56d..17130ec 100644
--- a/include/uapi/linux/bgcom_interface.h
+++ b/include/uapi/linux/bgcom_interface.h
@@ -44,6 +44,7 @@
 	MODEM_AFTER_POWER_UP,
 	ADSP_BEFORE_POWER_DOWN,
 	ADSP_AFTER_POWER_UP,
+	TWM_BG_AFTER_POWER_UP,
 };
 
 #define REG_READ \
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index 864943f..078672b 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -1838,6 +1838,12 @@
 	IPA_DATA_EP_TYP_BAM_DMUX,
 };
 
+enum ipa_data_ep_prot_type {
+	IPA_PROT_RMNET = 0,
+	IPA_PROT_RMNET_CV2X = 1,
+	IPA_PROT_MAX
+};
+
 struct ipa_ep_pair_info {
 	uint32_t consumer_pipe_num;
 	uint32_t producer_pipe_num;
@@ -1852,6 +1858,8 @@
  * @num_ep_pairs: number of ep_pairs - o/p param
  * @ep_pair_size: sizeof(ipa_ep_pair_info) * max_ep_pairs
  * @info: structure contains ep pair info
+ * @teth_prot : RMNET/CV2X --i/p param
+ * @teth_prot_valid - validity of i/p param protocol
  */
 struct ipa_ioc_get_ep_info {
 	enum ipa_peripheral_ep_type ep_type;
@@ -1859,6 +1867,8 @@
 	uint8_t num_ep_pairs;
 	uint32_t ep_pair_size;
 	uintptr_t info;
+	enum ipa_data_ep_prot_type teth_prot;
+	uint8_t teth_prot_valid;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 31817b8..17f1635 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2191,6 +2191,80 @@
  *	may offload authentication processing to user space if this capability
  *	is indicated in the respective requests from the user space.
  *
+ * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
+ *	u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
+ *
+ * @NL80211_ATTR_TXQ_STATS: TXQ statistics (nested attribute, see &enum
+ *      nl80211_txq_stats)
+ * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy.
+ *      The smaller of this and the memory limit is enforced.
+ * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the
+ *      TXQ queues for this phy. The smaller of this and the packet limit is
+ *      enforced.
+ * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
+ *      a flow is assigned on each round of the DRR scheduler.
+ * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
+ *	association request when used with NL80211_CMD_NEW_STATION). Can be set
+ *	only if %NL80211_STA_FLAG_WME is set.
+ *
+ * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
+ *      in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
+ *      measurement (FTM) responder functionality and containing parameters as
+ *      possible, see &enum nl80211_ftm_responder_attr
+ *
+ * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
+ *      statistics, see &enum nl80211_ftm_responder_stats.
+ *
+ * @NL80211_ATTR_TIMEOUT: Timeout for the given operation in milliseconds (u32),
+ *      if the attribute is not given no timeout is requested. Note that 0 is an
+ *      invalid value.
+ *
+ * @NL80211_ATTR_PEER_MEASUREMENTS: peer measurements request (and result)
+ *      data, uses nested attributes specified in
+ *      &enum nl80211_peer_measurement_attrs.
+ *      This is also used for capability advertisement in the wiphy information,
+ *      with the appropriate sub-attributes.
+ *
+ * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime
+ *      scheduler.
+ *
+ * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for
+ *      station associated with the AP. See &enum nl80211_tx_power_setting for
+ *      possible values.
+ * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This
+ *      allows to set Tx power for a station. If this attribute is not included,
+ *      the default per-interface tx power setting will be overriding. Driver
+ *      should be picking up the lowest tx power, either tx power per-interface
+ *      or per-station.
+ *
+ * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It
+ *      is used with %NL80211_CMD_CONNECT to provide password for offloading
+ *      SAE authentication for WPA3-Personal networks.
+ *
+ * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support.
+ *
+ * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection
+ *      functionality.
+ *
+ * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz
+ *      channel(s) that are allowed to be used for EDMG transmissions.
+ *      Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute)
+ * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
+ *      the allowed channel bandwidth configurations. (u8 attribute)
+ *      Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+ *
+ * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
+ *      (u16).
+ *
+ * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings.
+ *
+ * @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry
+ *	using attributes from &enum nl80211_iftype_akm_attributes. This
+ *	attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating
+ *	supported AKM suites capability per interface. AKMs advertised in
+ *	%NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not
+ *	advertised for a specific interface type.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2620,6 +2694,45 @@
 	NL80211_ATTR_EXTERNAL_AUTH_ACTION,
 	NL80211_ATTR_EXTERNAL_AUTH_SUPPORT,
 
+	NL80211_ATTR_NSS,
+	NL80211_ATTR_ACK_SIGNAL,
+
+	NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
+
+	NL80211_ATTR_TXQ_STATS,
+	NL80211_ATTR_TXQ_LIMIT,
+	NL80211_ATTR_TXQ_MEMORY_LIMIT,
+	NL80211_ATTR_TXQ_QUANTUM,
+
+	NL80211_ATTR_HE_CAPABILITY,
+
+	NL80211_ATTR_FTM_RESPONDER,
+
+	NL80211_ATTR_FTM_RESPONDER_STATS,
+
+	NL80211_ATTR_TIMEOUT,
+
+	NL80211_ATTR_PEER_MEASUREMENTS,
+
+	NL80211_ATTR_AIRTIME_WEIGHT,
+	NL80211_ATTR_STA_TX_POWER_SETTING,
+	NL80211_ATTR_STA_TX_POWER,
+
+	NL80211_ATTR_SAE_PASSWORD,
+
+	NL80211_ATTR_TWT_RESPONDER,
+
+	NL80211_ATTR_HE_OBSS_PD,
+
+	NL80211_ATTR_WIPHY_EDMG_CHANNELS,
+	NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+
+	NL80211_ATTR_VLAN_ID,
+
+	NL80211_ATTR_HE_BSS_COLOR,
+
+	NL80211_ATTR_IFTYPE_AKM_SUITES,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -5578,4 +5691,28 @@
 	NL80211_EXTERNAL_AUTH_ABORT,
 };
 
+/**
+ * enum nl80211_iftype_akm_attributes - interface type AKM attributes
+ * @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid
+ *
+ * @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag
+ *	attribute for each interface type that supports AKM suites specified in
+ *	%NL80211_IFTYPE_AKM_ATTR_SUITES
+ * @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported
+ *	AKM suites for the specified interface types.
+ *
+ * @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal
+ * @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute.
+ */
+enum nl80211_iftype_akm_attributes {
+	__NL80211_IFTYPE_AKM_ATTR_INVALID,
+
+	NL80211_IFTYPE_AKM_ATTR_IFTYPES,
+	NL80211_IFTYPE_AKM_ATTR_SUITES,
+
+	/* keep last */
+	__NL80211_IFTYPE_AKM_ATTR_LAST,
+	NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index 20431fe..fad6e6f 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -409,6 +409,13 @@
 	__u32 nap;
 };
 
+/** struct snd_dec_dsd - codec for DSD format
+ * @blk_size - dsd channel block size
+ */
+struct snd_dec_dsd {
+	__u32 blk_size;
+};
+
 /** struct snd_dec_pcm - codec options for PCM format
  * @num_channels: Number of channels
  * @ch_map: Channel map for the above corresponding channels
@@ -435,6 +442,7 @@
 	struct snd_dec_aptx aptx_dec;
 	struct snd_dec_pcm pcm_dec;
 	struct snd_dec_amrwb_plus amrwbplus;
+	struct snd_dec_dsd dsd_dec;
 };
 
 /** struct snd_codec_desc - description of codec capabilities
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 0e5571d..8b432ae 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2020, 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
@@ -2793,6 +2793,33 @@
 				     hdr->control_flag, hdr->src_node_id,
 				     hdr->src_port_id, hdr->dst_node_id,
 				     hdr->dst_port_id);
+			/**
+			 * update forwarding port information as well in routing
+			 * table which will help to cleanup clients/services
+			 * running in modem when MSM goes down
+			 */
+			rport_ptr = ipc_router_get_rport_ref(hdr->src_node_id,
+							     hdr->src_port_id);
+			if (!rport_ptr) {
+				rport_ptr =
+				ipc_router_create_rport(hdr->src_node_id,
+							hdr->src_port_id,
+							xprt_info);
+				if (!rport_ptr) {
+					IPC_RTR_ERR(
+					"%s: Rmt Prt %08x:%08x create failed\n",
+					__func__, hdr->src_node_id,
+					hdr->src_port_id);
+				}
+			}
+			/**
+			 * just to fail safe check is added, if rport
+			 * allocation failed above we still forward the
+			 * packet to remote.
+			 */
+			if (rport_ptr)
+				kref_put(&rport_ptr->ref,
+					 ipc_router_release_rport);
 			forward_msg(xprt_info, pkt);
 			goto read_next_pkt1;
 		}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9ebd99e..94b537f 100755
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1377,6 +1377,46 @@
 	return 0;
 }
 
+static int
+nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
+			      struct sk_buff *msg)
+{
+	int i;
+	struct nlattr *nested, *nested_akms;
+	const struct wiphy_iftype_akm_suites *iftype_akms;
+
+	if (!rdev->wiphy.num_iftype_akm_suites ||
+	    !rdev->wiphy.iftype_akm_suites)
+		return 0;
+
+	nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
+	if (!nested)
+		return -ENOBUFS;
+
+	for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
+		nested_akms = nla_nest_start(msg, i + 1);
+		if (!nested_akms)
+			return -ENOBUFS;
+
+		iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
+
+		if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
+					iftype_akms->iftypes_mask))
+			return -ENOBUFS;
+
+		if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
+			    sizeof(u32) * iftype_akms->n_akm_suites,
+			    iftype_akms->akm_suites)) {
+			return -ENOBUFS;
+		}
+		nla_nest_end(msg, nested_akms);
+	}
+
+	nla_nest_end(msg, nested);
+
+	return 0;
+}
+
 struct nl80211_dump_wiphy_state {
 	s64 filter_wiphy;
 	long start;
@@ -1677,6 +1717,7 @@
 				CMD(add_tx_ts, ADD_TX_TS);
 			CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
 			CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
+			CMD(update_ft_ies, UPDATE_FT_IES);
 		}
 		/* add into the if now */
 #undef CMD
@@ -1921,6 +1962,13 @@
 			}
 		}
 
+		state->split_start++;
+		break;
+	case 14:
+
+		if (nl80211_put_iftype_akm_suites(rdev, msg))
+			goto nla_put_failure;
+
 		/* done */
 		state->split_start = 0;
 		break;
@@ -8930,6 +8978,7 @@
 
 	if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
 		if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+			kzfree(connkeys);
 			return -EINVAL;
 		}
 		connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;