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