Merge "defconfig: msm: Enable CNSS_UTILS for SA415m"
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/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 9ce2354..6c151af 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -500,6 +500,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 +574,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
diff --git a/arch/arm/configs/sa415m-perf_defconfig b/arch/arm/configs/sa415m-perf_defconfig
index ef66336..8c32b03 100644
--- a/arch/arm/configs/sa415m-perf_defconfig
+++ b/arch/arm/configs/sa415m-perf_defconfig
@@ -375,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 537509c..50e8098 100644
--- a/arch/arm/configs/sa415m_defconfig
+++ b/arch/arm/configs/sa415m_defconfig
@@ -392,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_defconfig b/arch/arm/configs/sdm429-bg_defconfig
index c76c09b..6ead97a 100644
--- a/arch/arm/configs/sdm429-bg_defconfig
+++ b/arch/arm/configs/sdm429-bg_defconfig
@@ -574,6 +574,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/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/msm8905-qrd-skub.dtsi b/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi
index a94f887..1ac0640 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 */
@@ -456,3 +564,11 @@
 &actuator0 {
 	status = "disabled";
 };
+
+&pm8909_conga_dig {
+	status = "disabled";
+};
+
+&pm8909_conga_analog {
+	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..4a635a4 100644
--- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
@@ -177,3 +177,42 @@
 		};
 	};
 };
+
+&msm_gpu {
+	qcom,initial-pwrlevel = <0>;
+	qcom,gpu-pwrlevels {
+		qcom,gpu-pwrlevel@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 =
+		<   769 /*  100.8 MHz */ >,
+		<  1611 /*  211.2 MHz */ >,     /*Low SVS*/
+		<  2124 /*  278.4 MHz */ >,
+		<  2929 /*  384   MHz */ >,     /* SVS */
+		<  3221 /*  422.4 MHz */ >,
+		<  4248 /*  556.8 MHz */ >,
+		<  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-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
index 32ae531..438cc8a 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts
@@ -177,3 +177,41 @@
 		};
 	};
 };
+
+&msm_gpu {
+	qcom,initial-pwrlevel = <0>;
+	qcom,gpu-pwrlevels {
+		qcom,gpu-pwrlevel@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 =
+		<   769 /*  100.8 MHz */ >,
+		<  1611 /*  211.2 MHz */ >,     /*Low SVS*/
+		<  2124 /*  278.4 MHz */ >,
+		<  2929 /*  384   MHz */ >,     /* SVS */
+		<  3221 /*  422.4 MHz */ >,
+		<  4248 /*  556.8 MHz */ >,
+		<  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/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/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/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..a6aaf52
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c
@@ -0,0 +1,2320 @@
+/* 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_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_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*/
+
+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..e47eb78
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h
@@ -0,0 +1,376 @@
+/* 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    1800000
+#define I2C_VTG_MAX_UV    1800000
+#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/media/platform/msm/vidc_3x/msm_vidc_internal.h b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
index 56b86d7..5533c62 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 720
+#define DEFAULT_WIDTH 1280
 #define MIN_SUPPORTED_WIDTH 32
 #define MIN_SUPPORTED_HEIGHT 32
 #define DEFAULT_FPS 15
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/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 34869b8..7c1b7d9 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -1831,8 +1831,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_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/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/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/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/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3e9b136..fd7a83c 100755
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1671,6 +1671,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