aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bestas <mkbestas@lineageos.org>2018-06-19 23:12:57 +0300
committerMichael Bestas <mkbestas@lineageos.org>2018-06-19 23:12:57 +0300
commitde6dac6df6807f901bac8e29de24a6a7981aea2d (patch)
treea70d6303c33a857e730b5d920bfe7dc1047999dc
parented9b46f6268d2abcbb9079bf44261e3b6e8c424f (diff)
parent44ff472b917252c55c8e96ce7e0612aed13269cb (diff)
Merge tag 'LA.UM.6.6.r1-08900-89xx.0' of kernel/msm-3.18 into lineage-15.1-caf-8996
Conflicts: net/sctp/socket.c Change-Id: I90c45f914ac4d11bbeee3722ede5ea55e52898e1
-rw-r--r--Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt1
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/himax.txt22
-rw-r--r--Documentation/devicetree/bindings/qseecom/qseecom.txt3
-rw-r--r--arch/arm/boot/dts/qcom/Makefile1
-rw-r--r--arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi130
-rw-r--r--arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi29
-rw-r--r--arch/arm/boot/dts/qcom/apq8053.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts185
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi27
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-gpu.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-ion.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi29
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-qrd.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi29
-rw-r--r--arch/arm/boot/dts/qcom/msm8909.dtsi2
-rw-r--r--arch/arm/configs/msmcortex-perf_defconfig8
-rw-r--r--arch/arm/configs/msmcortex_defconfig8
-rw-r--r--drivers/bluetooth/bluetooth-power.c3
-rw-r--r--drivers/cpuidle/lpm-levels-of.c33
-rw-r--r--drivers/gpu/msm/adreno.c4
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c4
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c42
-rw-r--r--drivers/gpu/msm/kgsl_iommu.h15
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i0
-rw-r--r--drivers/input/touchscreen/hxchipset/HX_CRC_124.i0
-rw-r--r--drivers/input/touchscreen/hxchipset/HX_CRC_128.i0
-rw-r--r--drivers/input/touchscreen/hxchipset/HX_CRC_60.i0
-rw-r--r--drivers/input/touchscreen/hxchipset/HX_CRC_64.i0
-rw-r--r--drivers/input/touchscreen/hxchipset/Kconfig21
-rw-r--r--drivers/input/touchscreen/hxchipset/Makefile3
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_common.c1936
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_common.h395
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_debug.c2329
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_debug.h181
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_ic.c2118
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_ic.h82
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_platform.c796
-rw-r--r--drivers/input/touchscreen/hxchipset/himax_platform.h135
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp_util.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c18
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c26
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c17
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c15
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c6
-rw-r--r--drivers/misc/qseecom.c17
-rw-r--r--drivers/mmc/core/core.c12
-rw-r--r--drivers/mmc/core/quirks.c10
-rw-r--r--drivers/mmc/core/sd.c5
-rw-r--r--drivers/mmc/core/sdio.c3
-rw-r--r--drivers/net/can/spi/qti-can.c4
-rw-r--r--drivers/net/wireless/cnss/cnss_sdio.c47
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c58
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c75
-rw-r--r--drivers/platform/msm/mhi_dev/mhi.c89
-rw-r--r--drivers/power/qcom/lpm-stats.c9
-rw-r--r--drivers/soc/qcom/rpm_stats.c5
-rw-r--r--drivers/video/msm/mdss/mdp3_ctrl.c3
-rw-r--r--include/linux/ipc_router_xprt.h4
-rw-r--r--include/linux/mmc/card.h7
-rw-r--r--include/linux/mmc/host.h1
-rw-r--r--net/ipc_router/ipc_router_core.c60
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c2
72 files changed, 8905 insertions, 239 deletions
diff --git a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
index 7b89497f4638..49233d46a877 100644
--- a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
+++ b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
@@ -6,6 +6,7 @@ Required properties:
- compatible: Should be set to one of the following:
qca,ar3002
qca,qca6174
+ qca,qca9379
qca,wcn3990
- qca,bt-reset-gpio: GPIO pin to bring BT Controller out of reset
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax.txt b/Documentation/devicetree/bindings/input/touchscreen/himax.txt
new file mode 100644
index 000000000000..b54c85971927
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/himax.txt
@@ -0,0 +1,22 @@
+Himax touch controller
+
+Required properties:
+
+ - compatible : Should be "himax,hxcommon"
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - himax,irq-gpio : irq gpio.
+ - himax,reset-gpio : reset gpio.
+ - vdd-supply : Power supply needed to power up the device.
+ - avdd-supply : Power source required to power up i2c bus.
+ - himax,panel-coords : panel coordinates for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+ - himax,display-coords : display coordinates in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values
+
+Optional properties:
+ - himax,3v3-gpio : gpio acting as 3.3 v supply.
+ - report_type : Multi-touch protocol type. Default 0.
+ 0 for protocol A, 1 for protocol B.
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
index dfc62b78f58d..1d48c7136a3e 100644
--- a/Documentation/devicetree/bindings/qseecom/qseecom.txt
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -27,6 +27,7 @@ Optional properties:
- qcom,qsee-reentrancy-support: indicates the qsee reentrancy phase supported by the target
- qcom,commonlib64-loaded-by-uefi: indicates commonlib64 is loaded by uefi already
- qcom,fde-key-size: indicates which FDE key size is used in device.
+ - qcom,enable-key-wrap-in-ks: enables wrapping of ICE key with KS key.
Example:
qcom,qseecom@fe806000 {
@@ -40,6 +41,7 @@ Example:
qcom,hlos-ce-hw-instance = <1 2>;
qcom,qsee-ce-hw-instance = <0>;
qcom,support-fde;
+ qcom,enable-key-wrap-in-ks;
qcom,support-pfe;
qcom,msm_bus,name = "qseecom-noc";
qcom,msm_bus,num_cases = <4>;
@@ -64,6 +66,7 @@ Example: The following dts setup is the same as the example above.
reg = <0x7f00000 0x500000>;
reg-names = "secapp-region";
qcom,support-fde;
+ qcom,enable-key-wrap-in-ks;
qcom,full-disk-encrypt-info = <0 1 2>, <0 2 2>;
qcom,support-pfe;
qcom,per-file-encrypt-info = <0 1 0>, <0 2 0>;
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index db2682ff39b3..0ee9e79bf3e8 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -149,6 +149,7 @@ dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-sim.dtb \
mdm9650-emmc-mtp.dtb \
mdm9650-nand-mtp.dtb \
mdm9650-ttp.dtb \
+ mdm9650-pcie-ep-ttp.dtb \
mdm9650-nand-dualwifi-mtp.dtb \
mdm9650-v1.1-emmc-cdp.dtb \
mdm9650-v1.1-nand-cdp.dtb \
diff --git a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi
index 3b5225f50907..8230eab26da2 100644
--- a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2018 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
@@ -36,6 +36,109 @@
qcom,cam-vreg-op-mode = <80000>;
};
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ compatible = "qcom,eeprom";
+ reg = <0x0>;
+ qcom,cci-master = <0>;
+ cam_vio-supply = <&pm8953_l6>;
+ cam_vdig-supply = <&pm8953_l2>;
+ cam_vana-supply = <&pm8953_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+ "cam_vana";
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default
+ &cam_sensor_rear_vana>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+ &cam_sensor_rear_vana_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ compatible = "qcom,eeprom";
+ reg = <0x1>;
+ qcom,cci-master = <0>;
+ cam_vio-supply = <&pm8953_l6>;
+ cam_vdig-supply = <&pm8953_l2>;
+ cam_vana-supply = <&pm8953_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+ "cam_vana";
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk1_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 27 0>,
+ <&tlmm 129 0>,
+ <&tlmm 130 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_STANDBY1";
+ clocks = <&clock_gcc clk_mclk1_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ compatible = "qcom,eeprom";
+ reg = <0x2>;
+ qcom,cci-master = <0>;
+ cam_vio-supply = <&pm8953_l6>;
+ cam_vdig-supply = <&pm8953_l2>;
+ cam_vana-supply = <&pm8953_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+ "cam_vana";
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 131 0>,
+ <&tlmm 132 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
camera0: qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -45,13 +148,14 @@
qcom,mount-angle = <0>;
/*qcom,led-flash-src = <&led_flash0>;*/
qcom,actuator-src = <&actuator0>;
+ qcom,eeprom-src = <&eeprom0>;
cam_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&eldo_cam0_vreg>;
+ cam_vdig-supply = <&pm8953_l2>;
cam_vana-supply = <&pm8953_l17>;
qcom,cam-vreg-name = "cam_vio", "cam_vdig",
"cam_vana";
- qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>;
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
qcom,cam-vreg-op-mode = <105000 0 100000>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_default
@@ -86,14 +190,15 @@
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
qcom,mount-angle = <0>;
- qcom,actuator-src = <&actuator1>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,eeprom-src = <&eeprom1>;
cam_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&eldo_cam1_vreg>;
+ cam_vdig-supply = <&pm8953_l2>;
cam_vana-supply = <&pm8953_l17>;
qcom,cam-vreg-name = "cam_vio", "cam_vdig",
"cam_vana";
- qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>;
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
qcom,cam-vreg-op-mode = <105000 0 100000>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_default
@@ -110,7 +215,7 @@
qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
"CAM_RESET1",
"CAM_STANDBY1";
- qcom,sensor-position = <0>;
+ qcom,sensor-position = <1>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
status = "ok";
@@ -128,13 +233,14 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <0>;
qcom,actuator-src = <&actuator0>;
+ qcom,eeprom-src = <&eeprom2>;
cam_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&eldo_cam2_vreg>;
+ cam_vdig-supply = <&pm8953_l2>;
cam_vana-supply = <&pm8953_l17>;
qcom,cam-vreg-name = "cam_vio", "cam_vdig",
"cam_vana";
- qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>;
+ qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
qcom,cam-vreg-op-mode = <105000 0 100000>;
/*qcom,gpio-no-mux = <0>;*/
pinctrl-names = "cam_default", "cam_suspend";
diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi
index 6286015ae2c2..8649b2000e70 100644
--- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2018 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
@@ -173,6 +173,23 @@
/delete-property/ qcom,msm-vdd-wsa-switch-current;
};
+&pm8953_l2 {
+ status = "okay";
+ regulator-always-on;
+};
+
+&camera0 {
+ qcom,mount-angle = <90>;
+};
+
+&camera1 {
+ qcom,mount-angle = <90>;
+};
+
+&camera2{
+ qcom,mount-angle = <90>;
+};
+
&pm8953_diangu_dig {
status = "ok";
};
@@ -537,3 +554,13 @@
status = "ok";
};
};
+
+&soc {
+ qcom,wcnss-wlan@0a000000 {
+ status = "disabled";
+ };
+
+ qcom,pronto@a21b000 {
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/apq8053.dtsi b/arch/arm/boot/dts/qcom/apq8053.dtsi
index 48529b041afc..b4aa9ae8b644 100644
--- a/arch/arm/boot/dts/qcom/apq8053.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8053.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
@@ -52,3 +52,7 @@
&secure_mem {
status = "disabled";
};
+
+&qcom_seecom {
+ qcom,enable-key-wrap-in-ks;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts
new file mode 100644
index 000000000000..be1876886d6d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "mdm9650-v1.1-mtp.dtsi"
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9650 PCIE EP TTP";
+ compatible = "qcom,mdm9650-ttp", "qcom,mdm9650", "qcom,ttp";
+ qcom,board-id = <0x1e 2>;
+};
+
+&pmd9650_l13 {
+ regulator-always-on;
+};
+
+&i2c_1 {
+ status = "ok";
+ bmi160@68{
+ compatible = "bosch-sensortec,bmi160";
+ reg = <0x68>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bmi160_int1_default &bmi160_int2_default>;
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <0x0 0x2002>;
+ bmi,init-interval = <200>;
+ bmi,place = <1>;
+ bmi,gpio_irq = <&tlmm_pinmux 0x0 0x2002>;
+ };
+};
+
+&i2c_3 {
+ status = "ok";
+ smb1351_otg_supply: smb1351-charger@55{
+ status = "disabled";
+ };
+};
+
+&soc {
+ tlmm_pinmux: pinctrl@1000000 {
+ i2c_1 {
+ i2c_1_active {
+ config {
+ pins = "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+ };
+
+ usb_detect {
+ compatible = "qcom,gpio-usbdetect";
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x0 0x0d 0x0>; /* PMD9655 VBUS DETECT */
+ interrupt-names = "vbus_det_irq";
+ };
+};
+
+&usb3 {
+ cpe-gpio = <&tlmm_pinmux 87 0>;
+};
+
+&spi_2 {
+ status = "ok";
+
+ can-controller@0 {
+ compatible = "fsl,k61";
+ spi-max-frequency = <4800000>;
+ reg = <0>;
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <84 0>;
+ reset-gpio = <&tlmm_pinmux 68 0x1>;
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&can_rst_on>;
+ pinctrl-1 = <&can_rst_off>;
+ };
+};
+
+&blsp1_uart4b_hs {
+ status = "ok";
+};
+
+&blsp1_uart2_hs {
+ status = "disabled";
+};
+
+&snd_tasha {
+ pinctrl-names =
+ "all_off",
+ "pri_mi2s_aux_master_active",
+ "pri_mi2s_aux_slave_active",
+ "invalid_state_1",
+ "sec_mi2s_aux_master_active",
+ "pri_master_active_sec_master_active",
+ "pri_slave_active_sec_master_active",
+ "invalid_state_2",
+ "sec_mi2s_aux_slave_active",
+ "pri_master_active_sec_slave_active",
+ "pri_slave_active_sec_slave_active";
+ pinctrl-0 = <&pri_ws_sleep &pri_sck_sleep
+ &pri_dout_sleep &pri_din_sleep
+ &sec_ws_b_sleep &sec_sck_b_sleep
+ &sec_dout_b_sleep &sec_din_b_sleep>;
+ pinctrl-1 = <&pri_ws_active_master &pri_sck_active_master
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_sleep &sec_sck_b_sleep
+ &sec_dout_b_sleep &sec_din_b_sleep>;
+ pinctrl-2 = <&pri_ws_active_slave &pri_sck_active_slave
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_sleep &sec_sck_b_sleep
+ &sec_dout_b_sleep &sec_din_b_sleep>;
+ pinctrl-3 = <&pri_ws_sleep &pri_sck_sleep
+ &pri_dout_sleep &pri_din_sleep
+ &sec_ws_b_sleep &sec_sck_b_sleep
+ &sec_dout_b_sleep &sec_din_b_sleep>;
+ pinctrl-4 = <&pri_ws_sleep &pri_sck_sleep
+ &pri_dout_sleep &pri_din_sleep
+ &sec_ws_b_active_master &sec_sck_b_active_master
+ &sec_dout_b_active &sec_din_b_active>;
+ pinctrl-5 = <&pri_ws_active_master &pri_sck_active_master
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_active_master &sec_sck_b_active_master
+ &sec_dout_b_active &sec_din_b_active>;
+ pinctrl-6 = <&pri_ws_active_slave &pri_sck_active_slave
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_active_master &sec_sck_b_active_master
+ &sec_dout_b_active &sec_din_b_active>;
+ pinctrl-7 = <&pri_ws_sleep &pri_sck_sleep
+ &pri_dout_sleep &pri_din_sleep
+ &sec_ws_b_sleep &sec_sck_b_sleep
+ &sec_dout_b_sleep &sec_din_b_sleep>;
+ pinctrl-8 = <&pri_ws_sleep &pri_sck_sleep
+ &pri_dout_sleep &pri_din_sleep
+ &sec_ws_b_active_slave &sec_sck_b_active_slave
+ &sec_dout_b_active &sec_din_b_active>;
+ pinctrl-9 = <&pri_ws_active_master &pri_sck_active_master
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_active_slave &sec_sck_b_active_slave
+ &sec_dout_b_active &sec_din_b_active>;
+ pinctrl-10 = <&pri_ws_active_slave &pri_sck_active_slave
+ &pri_dout_active &pri_din_active
+ &sec_ws_b_active_slave &sec_sck_b_active_slave
+ &sec_dout_b_active &sec_din_b_active>;
+};
+
+&pcie_ep {
+ status = "ok";
+ mdm2apstatus-gpio = <&tlmm_pinmux 85 0>;
+};
+
+&pcie0 {
+ status = "disabled";
+};
+
+&cnss_pcie {
+ status = "disabled";
+};
+
+&mhi_device {
+ status = "ok";
+};
+
+&pcie0_mdm2apstatus_default {
+ mux {
+ pins = "gpio85";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio85";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts
index bcc2b9049657..9e522bc8387e 100644
--- a/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts
+++ b/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016,2018, 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
@@ -15,6 +15,7 @@
#include "msm8909-cdp.dtsi"
#include "msm8909-pm8909.dtsi"
#include "msm8909-pm8909-cdp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB CDP";
diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts
index 3853148057d2..14606fa11713 100644
--- a/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts
+++ b/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016,2018, 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
@@ -15,6 +15,7 @@
#include "msm8909-mtp.dtsi"
#include "msm8909-pm8909.dtsi"
#include "msm8909-pm8909-mtp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB MTP";
diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts
index a15d8c91287f..7a46da8db1c6 100644
--- a/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts
+++ b/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016,2018, 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
@@ -16,6 +16,7 @@
#include "msm8909-cdp.dtsi"
#include "msm8909-pm8909.dtsi"
#include "msm8909-pm8909-cdp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB RCM";
diff --git a/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi b/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi
index 8a67a01cfa63..9e64171a7173 100644
--- a/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-18 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,17 +11,20 @@
* GNU General Public License for more details.
*/
&soc {
- SY7803_default: SY7803_default {
- mux {
- /* CLK, DATA */
- pins = "gpio31", "gpio32";
- function = "gpio";
- };
- config {
- pins = "gpio31", "gpio32";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
+ msm_gpio: pinctrl@1000000 {
+ SY7803_default: SY7803_default {
+ mux {
+ /* CLK, DATA */
+ pins = "gpio31", "gpio32";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio31", "gpio32";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
};
};
@@ -33,7 +36,7 @@
qcom,flash-en = <&msm_gpio 31 0>;
qcom,flash-now = <&msm_gpio 32 0>;
qcom,op-seq = "flash_en", "flash_now";
- qcom,torch-seq-val = <1 0>;
+ qcom,torch-seq-val = <0 1>;
qcom,flash-seq-val = <1 1>;
linux,name = "flashlight";
linux,default-trigger = "flashlight-trigger";
diff --git a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi
index ba87d663a8d4..51529a2ee8b2 100644
--- a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi
@@ -19,26 +19,15 @@
/* To use BIMC based bus governor */
gpubw: qcom,gpubw {
compatible = "qcom,devbw";
- governor = "bw_hwmon";
+ governor = "bw_vbif";
qcom,src-dst-ports = <26 512>;
qcom,bw-tbl =
< 0 >, /* 9.6 MHz */
- < 381 >, /* 50.0 MHz */
- < 762 >, /* 100.0 MHz */
< 1525 >, /* 200.0 MHz */
< 3051 >, /* 400.0 MHz */
< 4066 >; /* 533.0 MHz */
};
- qcom,gpu-bwmon@410000 {
- compatible = "qcom,bimc-bwmon2";
- reg = <0x00410000 0x300>, <0x00401000 0x200>;
- reg-names = "base", "global_base";
- interrupts = <0 183 4>;
- qcom,mport = <2>;
- qcom,target-dev = <&gpubw>;
- };
-
msm_gpu: qcom,kgsl-3d0@01c00000 {
label = "kgsl-3d0";
compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
@@ -105,24 +94,32 @@
reg = <0>;
qcom,gpu-freq = <456000000>;
qcom,bus-freq = <3>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <3>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
qcom,gpu-freq = <307200000>;
qcom,bus-freq = <2>;
+ qcom,bus-min = <2>;
+ qcom,bus-max = <3>;
};
qcom,gpu-pwrlevel@2 {
reg = <2>;
qcom,gpu-freq = <200000000>;
- qcom,bus-freq = <1>;
+ qcom,bus-freq = <2>;
+ qcom,bus-min = <1>;
+ qcom,bus-max = <2>;
};
qcom,gpu-pwrlevel@3 {
reg = <3>;
qcom,gpu-freq = <19200000>;
qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi
index 4655b758f8e5..98561498c82e 100644
--- a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, 2016-2017, Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2016-2018, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*/
&soc {
- qcom,ion {
+ ion: qcom,ion {
compatible = "qcom,msm-ion";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi b/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi
new file mode 100644
index 000000000000..67dca943a51f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&reserved_mem {
+ secure_display_memory: secure_region {
+ compatible = "shared-dma-pool";
+ label = "secure_display_mem";
+ size = <0 0x1400000>;
+ reusable;
+ };
+};
+
+&ion {
+ secure_display_heap: qcom,ion-heap@10 { /* SECURE DISPLAY HEAP */
+ reg = <10>;
+ memory-region = <&secure_display_memory>;
+ qcom,ion-heap-type = "SECURE_DMA";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts b/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts
index a80bd89c5c03..3c05965f9b90 100644
--- a/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts
+++ b/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2018, 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
@@ -15,6 +15,7 @@
#include "msm8909-cdp.dtsi"
#include "msm8909-pm8916-cdp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909-PM8916 1GB RCM";
diff --git a/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts b/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts
index fb37873cc661..5c5adb73a998 100644
--- a/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts
+++ b/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016,2018, 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
@@ -16,6 +16,7 @@
#include "msm8909-mtp.dtsi"
#include "msm8909-pm8916.dtsi"
#include "msm8909-pm8916-mtp.dtsi"
+#include "msm8909-mtp_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909-PM8916 1GB MTP";
diff --git a/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi
index f4b41b4f38ba..56d22b2045d2 100644
--- a/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016,2018, 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
@@ -13,6 +13,7 @@
#include "msm8909.dtsi"
#include "msm8909-pm8909.dtsi"
#include "msm8909-pinctrl.dtsi"
+#include "msm8909-qrd_qseev4.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8909 QRD";
diff --git a/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi b/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi
new file mode 100644
index 000000000000..8c58d4689b77
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&reserved_mem {
+ secure_display_memory: secure_region {
+ compatible = "shared-dma-pool";
+ label = "secure_display_mem";
+ size = <0 0x800000>;
+ reusable;
+ };
+};
+
+&ion {
+ secure_display_heap: qcom,ion-heap@10 { /* SECURE DISPLAY HEAP */
+ reg = <10>;
+ memory-region = <&secure_display_memory>;
+ qcom,ion-heap-type = "SECURE_DMA";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm8909.dtsi b/arch/arm/boot/dts/qcom/msm8909.dtsi
index fd10716b1c6e..b14f0cb89ed2 100644
--- a/arch/arm/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8909.dtsi
@@ -132,7 +132,7 @@
};
};
- reserved-memory {
+ reserved_mem: reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
diff --git a/arch/arm/configs/msmcortex-perf_defconfig b/arch/arm/configs/msmcortex-perf_defconfig
index 1d28f3770f0d..378119e357a0 100644
--- a/arch/arm/configs/msmcortex-perf_defconfig
+++ b/arch/arm/configs/msmcortex-perf_defconfig
@@ -285,7 +285,9 @@ CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_CNSS_CRYPTO=y
CONFIG_ATH_CARDS=y
-CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+CONFIG_CLD_HL_SDIO_CORE=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
CONFIG_INPUT_KEYRESET=y
@@ -305,6 +307,10 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_TOUCHSCREEN_MAXIM_STI=y
+CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
+CONFIG_TOUCHSCREEN_HIMAX_I2C=y
+CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
+CONFIG_HMX_DB=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_KEYCHORD=y
diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig
index 1f27382f2f43..2400e9efbf3f 100644
--- a/arch/arm/configs/msmcortex_defconfig
+++ b/arch/arm/configs/msmcortex_defconfig
@@ -228,7 +228,6 @@ CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
-CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_INTERNAL_REGDB=y
CONFIG_RFKILL=y
CONFIG_NFC_NQ=y
@@ -288,6 +287,9 @@ CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_CNSS_CRYPTO=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+CONFIG_CLD_HL_SDIO_CORE=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
@@ -306,6 +308,10 @@ CONFIG_SECURE_TOUCH=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_TOUCHSCREEN_MAXIM_STI=y
+CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
+CONFIG_TOUCHSCREEN_HIMAX_I2C=y
+CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
+CONFIG_HMX_DB=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_UINPUT=y
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index 3f2d53fa5a90..8485481d0c89 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, 2013-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2010, 2013-2018 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
@@ -36,6 +36,7 @@
static struct of_device_id bt_power_match_table[] = {
{ .compatible = "qca,ar3002" },
{ .compatible = "qca,qca6174" },
+ { .compatible = "qca,qca9379" },
{ .compatible = "qca,wcn3990" },
{}
};
diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c
index 41fcee399eed..df60c3ea077f 100644
--- a/drivers/cpuidle/lpm-levels-of.c
+++ b/drivers/cpuidle/lpm-levels-of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -423,10 +423,6 @@ static int parse_legacy_cluster_params(struct device_node *node,
return 0;
failed:
pr_err("%s(): Failed reading %s\n", __func__, key);
- kfree(c->name);
- kfree(c->lpm_dev);
- c->name = NULL;
- c->lpm_dev = NULL;
return ret;
}
@@ -612,8 +608,6 @@ static int parse_cluster_level(struct device_node *node,
return 0;
failed:
pr_err("Failed %s() key = %s ret = %d\n", __func__, key, ret);
- kfree(level->mode);
- level->mode = NULL;
return ret;
}
@@ -808,19 +802,12 @@ static int parse_cpu_levels(struct device_node *node, struct lpm_cluster *c)
return 0;
failed:
- for (i = 0; i < c->cpu->nlevels; i++) {
- kfree(c->cpu->levels[i].name);
- c->cpu->levels[i].name = NULL;
- }
- kfree(c->cpu);
- c->cpu = NULL;
pr_err("%s(): Failed with error code:%d\n", __func__, ret);
return ret;
}
void free_cluster_node(struct lpm_cluster *cluster)
{
- int i;
struct lpm_cluster *cl, *m;
list_for_each_entry_safe(cl, m, &cluster->child, list) {
@@ -828,22 +815,6 @@ void free_cluster_node(struct lpm_cluster *cluster)
free_cluster_node(cl);
};
- if (cluster->cpu) {
- for (i = 0; i < cluster->cpu->nlevels; i++) {
- kfree(cluster->cpu->levels[i].name);
- cluster->cpu->levels[i].name = NULL;
- }
- }
- for (i = 0; i < cluster->nlevels; i++) {
- kfree(cluster->levels[i].mode);
- cluster->levels[i].mode = NULL;
- }
- kfree(cluster->cpu);
- kfree(cluster->name);
- kfree(cluster->lpm_dev);
- cluster->cpu = NULL;
- cluster->name = NULL;
- cluster->lpm_dev = NULL;
cluster->ndevices = 0;
}
@@ -957,9 +928,7 @@ failed_parse_cluster:
list_del(&c->list);
free_cluster_node(c);
failed_parse_params:
- c->parent = NULL;
pr_err("Failed parse params\n");
- kfree(c);
return NULL;
}
struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6355831b34bb..0a44f538f192 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1368,7 +1368,7 @@ static void _set_secvid(struct kgsl_device *device)
adreno_writereg64(adreno_dev,
ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE,
ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI,
- KGSL_IOMMU_SECURE_BASE);
+ KGSL_IOMMU_SECURE_BASE(&device->mmu));
adreno_writereg(adreno_dev,
ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE,
KGSL_IOMMU_SECURE_SIZE);
@@ -1790,7 +1790,7 @@ static int adreno_getproperty(struct kgsl_device *device,
* anything to mmap().
*/
shadowprop.gpuaddr =
- (unsigned int) device->memstore.gpuaddr;
+ (unsigned long)device->memstore.gpuaddr;
shadowprop.size = device->memstore.size;
/* GSL needs this to be set, even if it
appears to be meaningless */
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index b112b041e8b9..002489226884 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -2441,8 +2441,8 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev,
adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_CNTL,
A5XX_CP_RB_CNTL_DEFAULT);
- adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE,
- rb->buffer_desc.gpuaddr);
+ adreno_writereg64(adreno_dev, ADRENO_REG_CP_RB_BASE,
+ ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc.gpuaddr);
ret = a5xx_microcode_load(adreno_dev);
if (ret)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 0e9fa9ffdf12..2fe1fdc0baa0 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -38,9 +38,10 @@
#define _IOMMU_PRIV(_mmu) (&((_mmu)->priv.iommu))
-#define ADDR_IN_GLOBAL(_a) \
- (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \
- ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE)))
+#define ADDR_IN_GLOBAL(_mmu, _a) \
+ (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu)) && \
+ ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) + \
+ KGSL_IOMMU_GLOBAL_MEM_SIZE)))
static struct kgsl_mmu_pt_ops iommu_pt_ops;
static bool need_iommu_sync;
@@ -197,7 +198,7 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu,
BUG_ON(global_pt_count >= GLOBAL_PT_ENTRIES);
BUG_ON((global_pt_alloc + memdesc->size) >= KGSL_IOMMU_GLOBAL_MEM_SIZE);
- memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE + global_pt_alloc;
+ memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + global_pt_alloc;
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
global_pt_alloc += memdesc->size;
@@ -210,7 +211,7 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu,
void kgsl_add_global_secure_entry(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
{
- memdesc->gpuaddr = KGSL_IOMMU_SECURE_BASE;
+ memdesc->gpuaddr = KGSL_IOMMU_SECURE_BASE(&device->mmu);
kgsl_global_secure_pt_entry = memdesc;
}
@@ -631,7 +632,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr,
/* Set the maximum possible size as an initial value */
nextentry->gpuaddr = (uint64_t) -1;
- if (ADDR_IN_GLOBAL(faultaddr)) {
+ if (ADDR_IN_GLOBAL(mmu, faultaddr)) {
_get_global_entries(faultaddr, preventry, nextentry);
} else if (context) {
private = context->proc_priv;
@@ -1001,14 +1002,14 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu,
unsigned int secure_global_size = kgsl_global_secure_pt_entry != NULL ?
kgsl_global_secure_pt_entry->size : 0;
if (mmu->secured && pagetable->name == KGSL_MMU_SECURE_PT) {
- pt->compat_va_start = KGSL_IOMMU_SECURE_BASE +
+ pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu) +
secure_global_size;
- pt->compat_va_end = KGSL_IOMMU_SECURE_END;
- pt->va_start = KGSL_IOMMU_SECURE_BASE + secure_global_size;
- pt->va_end = KGSL_IOMMU_SECURE_END;
+ pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu);
+ pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size;
+ pt->va_end = KGSL_IOMMU_SECURE_END(mmu);
} else {
pt->compat_va_start = KGSL_IOMMU_SVM_BASE32;
- pt->compat_va_end = KGSL_IOMMU_SVM_END32;
+ pt->compat_va_end = KGSL_IOMMU_SECURE_BASE(mmu);
pt->va_start = KGSL_IOMMU_VA_BASE64;
pt->va_end = KGSL_IOMMU_VA_END64;
}
@@ -1017,7 +1018,7 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu,
pagetable->name != KGSL_MMU_SECURE_PT) {
if ((BITS_PER_LONG == 32) || is_compat_task()) {
pt->svm_start = KGSL_IOMMU_SVM_BASE32;
- pt->svm_end = KGSL_IOMMU_SVM_END32;
+ pt->svm_end = KGSL_IOMMU_SECURE_BASE(mmu);
} else {
pt->svm_start = KGSL_IOMMU_SVM_BASE64;
pt->svm_end = KGSL_IOMMU_SVM_END64;
@@ -1033,22 +1034,22 @@ static void setup_32bit_pagetable(struct kgsl_mmu *mmu,
kgsl_global_secure_pt_entry->size : 0;
if (mmu->secured) {
if (pagetable->name == KGSL_MMU_SECURE_PT) {
- pt->compat_va_start = KGSL_IOMMU_SECURE_BASE +
+ pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu) +
secure_global_size;
- pt->compat_va_end = KGSL_IOMMU_SECURE_END;
- pt->va_start = KGSL_IOMMU_SECURE_BASE +
+ pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu);
+ pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu) +
secure_global_size;
- pt->va_end = KGSL_IOMMU_SECURE_END;
+ pt->va_end = KGSL_IOMMU_SECURE_END(mmu);
} else {
pt->va_start = KGSL_IOMMU_SVM_BASE32;
- pt->va_end = KGSL_IOMMU_SECURE_BASE +
+ pt->va_end = KGSL_IOMMU_SECURE_BASE(mmu) +
secure_global_size;
pt->compat_va_start = pt->va_start;
pt->compat_va_end = pt->va_end;
}
} else {
pt->va_start = KGSL_IOMMU_SVM_BASE32;
- pt->va_end = KGSL_IOMMU_GLOBAL_MEM_BASE;
+ pt->va_end = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu);
pt->compat_va_start = pt->va_start;
pt->compat_va_end = pt->va_end;
}
@@ -2203,7 +2204,8 @@ static int kgsl_iommu_set_svm_region(struct kgsl_pagetable *pagetable,
struct rb_node *node;
/* Make sure the requested address doesn't fall in the global range */
- if (ADDR_IN_GLOBAL(gpuaddr) || ADDR_IN_GLOBAL(gpuaddr + size))
+ if (ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr) ||
+ ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr + size))
return -ENOMEM;
spin_lock(&pagetable->lock);
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index 457522986fce..097dfe798bbe 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016,2018 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
@@ -24,12 +24,17 @@
* are mapped into all pagetables.
*/
#define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_8M
-#define KGSL_IOMMU_GLOBAL_MEM_BASE 0xf8000000
+#define KGSL_IOMMU_GLOBAL_MEM_BASE32 0xf8000000
+#define KGSL_IOMMU_GLOBAL_MEM_BASE64 0xfc000000
+
+#define KGSL_IOMMU_GLOBAL_MEM_BASE(__mmu) \
+ (MMU_FEATURE(__mmu, KGSL_MMU_64BIT) ? \
+ KGSL_IOMMU_GLOBAL_MEM_BASE64 : KGSL_IOMMU_GLOBAL_MEM_BASE32)
#define KGSL_IOMMU_SECURE_SIZE SZ_256M
-#define KGSL_IOMMU_SECURE_END KGSL_IOMMU_GLOBAL_MEM_BASE
-#define KGSL_IOMMU_SECURE_BASE \
- (KGSL_IOMMU_GLOBAL_MEM_BASE - KGSL_IOMMU_SECURE_SIZE)
+#define KGSL_IOMMU_SECURE_END(_mmu) KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu)
+#define KGSL_IOMMU_SECURE_BASE(_mmu) \
+ (KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) - KGSL_IOMMU_SECURE_SIZE)
#define KGSL_IOMMU_SVM_BASE32 0x300000
#define KGSL_IOMMU_SVM_END32 (0xC0000000 - SZ_16M)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index dd9b928e3694..769849d2e43c 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1137,4 +1137,16 @@ config TOUCHSCREEN_MAXIM_STI
source "drivers/input/touchscreen/gt9xx/Kconfig"
+config TOUCHSCREEN_HIMAX_CHIPSET
+ bool "Himax touchpanel CHIPSET"
+ depends on I2C
+ help
+ Say Y here if you have a Himax CHIPSET touchscreen.
+ HIMAX controllers are multi touch controllers which can
+ report 10 touches at a time.
+
+ If unsure, say N.
+
+source "drivers/input/touchscreen/hxchipset/Kconfig"
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index be0eb9b34f5b..499b8110fe6c 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -90,3 +90,4 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset/
diff --git a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig
new file mode 100644
index 000000000000..ebf3aa478af5
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/Kconfig
@@ -0,0 +1,21 @@
+#
+# Himax Touchscreen driver configuration
+#
+
+config TOUCHSCREEN_HIMAX_I2C
+ tristate "HIMAX chipset i2c touchscreen"
+ depends on TOUCHSCREEN_HIMAX_CHIPSET
+ help
+ This enables support for HIMAX CHIPSET over I2C based touchscreens.
+
+config TOUCHSCREEN_HIMAX_DEBUG
+ tristate "HIMAX debug function"
+ depends on TOUCHSCREEN_HIMAX_I2C
+ help
+ This enables support for HIMAX debug function.
+
+config HMX_DB
+ tristate "HIMAX driver test over Dragon Board"
+ depends on TOUCHSCREEN_HIMAX_I2C
+ help
+ This enables support for HIMAX driver test over Dragon Board.
diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile
new file mode 100644
index 000000000000..509d4913bc39
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/Makefile
@@ -0,0 +1,3 @@
+# Makefile for the Himax touchscreen drivers.
+
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C) += himax_platform.o himax_ic.o himax_common.o himax_debug.o
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c
new file mode 100644
index 000000000000..417b0c08e361
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_common.c
@@ -0,0 +1,1936 @@
+/* Himax Android Driver Sample Code for Himax chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_common.h"
+#include "himax_ic.h"
+
+#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F
+#define TS_WAKE_LOCK_TIMEOUT (2 * HZ)
+#define FRAME_COUNT 5
+
+#if defined(HX_AUTO_UPDATE_FW)
+ static unsigned char i_CTPM_FW[]=
+ {
+ #include "HX83100_Amber_0901_030B.i"
+ };
+#endif
+
+#ifdef HX_ESD_WORKAROUND
+ extern void HX_report_ESD_event(void);
+ unsigned char ESD_00_counter = 0;
+ unsigned char ESD_00_Flag = 0;
+#endif
+
+//static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; // for Virtual key array
+
+struct himax_ts_data *private_ts;
+struct himax_ic_data* ic_data;
+
+static int HX_TOUCH_INFO_POINT_CNT;
+
+#ifdef HX_AUTO_UPDATE_FW
+extern unsigned long FW_VER_MAJ_FLASH_ADDR;
+extern unsigned long FW_VER_MIN_FLASH_ADDR;
+extern unsigned long CFG_VER_MAJ_FLASH_ADDR;
+extern unsigned long CFG_VER_MIN_FLASH_ADDR;
+#endif
+extern unsigned long FW_VER_MAJ_FLASH_LENG;
+extern unsigned long FW_VER_MIN_FLASH_LENG;
+extern unsigned long CFG_VER_MAJ_FLASH_LENG;
+extern unsigned long CFG_VER_MIN_FLASH_LENG;
+extern unsigned char IC_TYPE;
+extern unsigned char IC_CHECKSUM;
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+extern int himax_touch_proc_init(void);
+extern void himax_touch_proc_deinit(void);
+//PROC-START
+#ifdef HX_TP_PROC_FLASH_DUMP
+extern void himax_ts_flash_func(void);
+extern void setFlashBuffer(void);
+extern bool getFlashDumpGoing(void);
+extern uint8_t getSysOperation(void);
+extern void setSysOperation(uint8_t operation);
+#endif
+
+#ifdef HX_TP_PROC_HITOUCH
+extern bool hitouch_is_connect;
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ extern int touch_monitor_stop_flag;
+ extern int touch_monitor_stop_limit;
+ extern void himax_ts_diag_func(void);
+ extern int16_t *getMutualBuffer(void);
+ extern int16_t *getMutualNewBuffer(void);
+ extern int16_t *getMutualOldBuffer(void);
+ extern int16_t *getSelfBuffer(void);
+ extern uint8_t getXChannel(void);
+ extern uint8_t getYChannel(void);
+ extern uint8_t getDiagCommand(void);
+ extern void setXChannel(uint8_t x);
+ extern void setYChannel(uint8_t y);
+ extern void setMutualBuffer(void);
+ extern void setMutualNewBuffer(void);
+ extern void setMutualOldBuffer(void);
+ extern uint8_t coordinate_dump_enable;
+ extern struct file *coordinate_fn;
+ extern uint8_t diag_coor[128];
+#ifdef HX_TP_PROC_2T2R
+ extern int16_t *getMutualBuffer_2(void);
+ extern uint8_t getXChannel_2(void);
+ extern uint8_t getYChannel_2(void);
+ extern void setXChannel_2(uint8_t x);
+ extern void setYChannel_2(uint8_t y);
+ extern void setMutualBuffer_2(void);
+#endif
+#endif
+//PROC-END
+#endif
+
+extern int himax_parse_dt(struct himax_ts_data *ts,
+ struct himax_i2c_platform_data *pdata);
+extern int himax_ts_pinctrl_init(struct himax_ts_data *ts);
+
+static uint8_t vk_press;
+static uint8_t AA_press;
+static uint8_t EN_NoiseFilter;
+static uint8_t Last_EN_NoiseFilter;
+static int hx_point_num; // for himax_ts_work_func use
+static int p_point_num = 0xFFFF;
+static int tpd_key;
+static int tpd_key_old;
+static int probe_fail_flag;
+static bool config_load;
+static struct himax_config *config_selected;
+
+//static int iref_number = 11;
+//static bool iref_found = false;
+
+#ifdef HX_USB_DETECT2
+extern bool USB_Flag;
+#endif
+
+#if defined(CONFIG_FB)
+int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void himax_ts_early_suspend(struct early_suspend *h);
+static void himax_ts_late_resume(struct early_suspend *h);
+#endif
+
+int himax_input_register(struct himax_ts_data *ts)
+{
+ int ret;
+ ts->input_dev = input_allocate_device();
+ if (ts->input_dev == NULL) {
+ ret = -ENOMEM;
+ E("%s: Failed to allocate input device\n", __func__);
+ return ret;
+ }
+ ts->input_dev->name = "himax-touchscreen";
+
+ set_bit(EV_SYN, ts->input_dev->evbit);
+ set_bit(EV_ABS, ts->input_dev->evbit);
+ set_bit(EV_KEY, ts->input_dev->evbit);
+
+ set_bit(KEY_BACK, ts->input_dev->keybit);
+ set_bit(KEY_HOME, ts->input_dev->keybit);
+ set_bit(KEY_MENU, ts->input_dev->keybit);
+ set_bit(KEY_SEARCH, ts->input_dev->keybit);
+#if defined(HX_SMART_WAKEUP)
+ set_bit(KEY_POWER, ts->input_dev->keybit);
+ set_bit(KEY_CUST_01, ts->input_dev->keybit);
+ set_bit(KEY_CUST_02, ts->input_dev->keybit);
+ set_bit(KEY_CUST_03, ts->input_dev->keybit);
+ set_bit(KEY_CUST_04, ts->input_dev->keybit);
+ set_bit(KEY_CUST_05, ts->input_dev->keybit);
+ set_bit(KEY_CUST_06, ts->input_dev->keybit);
+ set_bit(KEY_CUST_07, ts->input_dev->keybit);
+ set_bit(KEY_CUST_08, ts->input_dev->keybit);
+ set_bit(KEY_CUST_09, ts->input_dev->keybit);
+ set_bit(KEY_CUST_10, ts->input_dev->keybit);
+ set_bit(KEY_CUST_11, ts->input_dev->keybit);
+ set_bit(KEY_CUST_12, ts->input_dev->keybit);
+ set_bit(KEY_CUST_13, ts->input_dev->keybit);
+ set_bit(KEY_CUST_14, ts->input_dev->keybit);
+ set_bit(KEY_CUST_15, ts->input_dev->keybit);
+#endif
+ set_bit(BTN_TOUCH, ts->input_dev->keybit);
+
+ set_bit(KEY_F10, ts->input_dev->keybit);
+
+ set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ //ts->input_dev->mtsize = ts->nFinger_support;
+ input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
+ 0, 3, 0, 0);
+ } else {/* PROTOCOL_TYPE_B */
+ set_bit(MT_TOOL_FINGER, ts->input_dev->keybit);
+ input_mt_init_slots(ts->input_dev, ts->nFinger_support,0);
+ }
+
+ I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
+ ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0);
+
+// input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);
+// input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);
+
+ return input_register_device(ts->input_dev);
+}
+
+static void calcDataSize(uint8_t finger_num)
+{
+ struct himax_ts_data *ts_data = private_ts;
+ ts_data->coord_data_size = 4 * finger_num;
+ ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4;
+ ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1;
+ ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel +
+ ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size +
+ (((uint32_t)ts_data->x_channel * ts_data->y_channel +
+ ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size)? 1 : 0;
+ I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes);
+}
+
+static void calculate_point_number(void)
+{
+ HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4 ;
+
+ if ( (ic_data->HX_MAX_PT % 4) == 0)
+ HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4 ;
+ else
+ HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) +1) * 4 ;
+}
+
+#if 0
+static int himax_read_Sensor_ID(struct i2c_client *client)
+{
+ uint8_t val_high[1], val_low[1], ID0=0, ID1=0;
+ char data[3];
+ const int normalRetry = 10;
+ int sensor_id;
+
+ data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High*/
+ i2c_himax_master_write(client, &data[0],3,normalRetry);
+ usleep_range(1000, 2000);
+
+ //read id pin high
+ i2c_himax_read(client, 0x57, val_high, 1, normalRetry);
+
+ data[0] = 0x56; data[1] = 0x01; data[2] = 0x01;/*ID pin PULL Low*/
+ i2c_himax_master_write(client, &data[0],3,normalRetry);
+ usleep_range(1000, 2000);
+
+ //read id pin low
+ i2c_himax_read(client, 0x57, val_low, 1, normalRetry);
+
+ if((val_high[0] & 0x01) ==0)
+ ID0=0x02;/*GND*/
+ else if((val_low[0] & 0x01) ==0)
+ ID0=0x01;/*Floating*/
+ else
+ ID0=0x04;/*VCC*/
+
+ if((val_high[0] & 0x02) ==0)
+ ID1=0x02;/*GND*/
+ else if((val_low[0] & 0x02) ==0)
+ ID1=0x01;/*Floating*/
+ else
+ ID1=0x04;/*VCC*/
+ if((ID0==0x04)&&(ID1!=0x04))
+ {
+ data[0] = 0x56; data[1] = 0x02; data[2] = 0x01;/*ID pin PULL High,Low*/
+ i2c_himax_master_write(client, &data[0],3,normalRetry);
+ usleep_range(1000, 2000);
+
+ }
+ else if((ID0!=0x04)&&(ID1==0x04))
+ {
+ data[0] = 0x56; data[1] = 0x01; data[2] = 0x02;/*ID pin PULL Low,High*/
+ i2c_himax_master_write(client, &data[0],3,normalRetry);
+ usleep_range(1000, 2000);
+
+ }
+ else if((ID0==0x04)&&(ID1==0x04))
+ {
+ data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High,High*/
+ i2c_himax_master_write(client, &data[0],3,normalRetry);
+ usleep_range(1000, 2000);
+
+ }
+ sensor_id=(ID1<<4)|ID0;
+
+ data[0] = 0xE4; data[1] = sensor_id;
+ i2c_himax_master_write(client, &data[0],2,normalRetry);/*Write to MCU*/
+ usleep_range(1000, 2000);
+
+ return sensor_id;
+
+}
+#endif
+static void himax_power_on_initCMD(struct i2c_client *client)
+{
+ I("%s:\n", __func__);
+
+ himax_touch_information(client);
+
+ //himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+}
+
+#ifdef HX_AUTO_UPDATE_FW
+static int i_update_FW(void)
+{
+ int upgrade_times = 0;
+ unsigned char* ImageBuffer = i_CTPM_FW;
+ int fullFileLength = sizeof(i_CTPM_FW);
+ int i_FW_VER = 0, i_CFG_VER = 0;
+ uint8_t ret = -1, result = 0;
+// uint8_t tmp_addr[4];
+// uint8_t tmp_data[4];
+ int CRC_from_FW = 0;
+ int CRC_Check_result = 0;
+
+ i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR];
+ i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR];
+
+ I("%s: i_fullFileLength = %d\n", __func__,fullFileLength);
+
+ himax_sense_off(private_ts->client);
+ msleep(500);
+
+ CRC_from_FW = himax_check_CRC(private_ts->client,fw_image_64k);
+ CRC_Check_result = Calculate_CRC_with_AP(ImageBuffer, CRC_from_FW,fw_image_64k);
+ I("%s: Check sum result = %d\n", __func__,CRC_Check_result);
+ //I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", __func__,ic_data->vendor_fw_ver, i_FW_VER);
+ //I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", __func__,ic_data->vendor_config_ver, i_CFG_VER);
+
+ if ((CRC_Check_result == 0)|| ( ic_data->vendor_fw_ver < i_FW_VER ) || ( ic_data->vendor_config_ver < i_CFG_VER ))
+ {
+ himax_int_enable(private_ts->client->irq,0);
+update_retry:
+ if(fullFileLength == FW_SIZE_60k){
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,ImageBuffer,fullFileLength,false);
+ }else if (fullFileLength == FW_SIZE_64k){
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,ImageBuffer,fullFileLength,false);
+ }else if (fullFileLength == FW_SIZE_124k){
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,ImageBuffer,fullFileLength,false);
+ }else if (fullFileLength == FW_SIZE_128k){
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,ImageBuffer,fullFileLength,false);
+ }
+ if(ret == 0){
+ upgrade_times++;
+ E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times);
+ if(upgrade_times < 3)
+ goto update_retry;
+ else
+ {
+ himax_sense_on(private_ts->client, 0x01);
+ msleep(120);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+ result = -1;//upgrade fail
+ }
+ }
+ else if(ret == 1){
+/*
+ // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
+
+ // 2. Write driver initial code condition
+ // write value from AHB I2C : 0x8001_C603 = 0x000000FF
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xFF;
+ himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
+
+ // 1. Set DDREG_Req = 0 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
+*/
+ himax_sense_on(private_ts->client, 0x01);
+ msleep(120);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+
+ ic_data->vendor_fw_ver = i_FW_VER;
+ ic_data->vendor_config_ver = i_CFG_VER;
+ result = 1;//upgrade success
+ I("%s: TP upgrade OK\n", __func__);
+ }
+
+ himax_int_enable(private_ts->client->irq,1);
+ return result;
+ }
+ else
+ {
+ himax_sense_on(private_ts->client, 0x01);
+ return 0;//NO upgrade
+ }
+}
+#endif
+
+#ifdef HX_RST_PIN_FUNC
+void himax_HW_reset(uint8_t loadconfig,uint8_t int_off)
+{
+ struct himax_ts_data *ts = private_ts;
+ int ret = 0;
+
+ return;
+ if (ts->rst_gpio) {
+ if(int_off)
+ {
+ if (ts->use_irq)
+ himax_int_enable(private_ts->client->irq,0);
+ else {
+ hrtimer_cancel(&ts->timer);
+ ret = cancel_work_sync(&ts->work);
+ }
+ }
+
+ I("%s: Now reset the Touch chip.\n", __func__);
+
+ himax_rst_gpio_set(ts->rst_gpio, 0);
+ msleep(20);
+ himax_rst_gpio_set(ts->rst_gpio, 1);
+ msleep(20);
+
+ if(loadconfig)
+ himax_loadSensorConfig(private_ts->client,private_ts->pdata);
+
+ if(int_off)
+ {
+ if (ts->use_irq)
+ himax_int_enable(private_ts->client->irq,1);
+ else
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ }
+}
+#endif
+
+int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata)
+{
+
+ if (!client) {
+ E("%s: Necessary parameters client are null!\n", __func__);
+ return -EINVAL;
+ }
+
+ if(config_load == false)
+ {
+ config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL);
+ if (config_selected == NULL) {
+ E("%s: alloc config_selected fail!\n", __func__);
+ return -ENOMEM;
+ }
+ }
+
+ himax_power_on_initCMD(client);
+
+ himax_int_enable(client->irq,0);
+ himax_read_FW_ver(client);
+#ifdef HX_RST_PIN_FUNC
+ himax_HW_reset(true,false);
+#endif
+ himax_int_enable(client->irq,1);
+ I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+
+ ic_data->vendor_sensor_id=0x2602;
+ I("sensor_id=%x.\n",ic_data->vendor_sensor_id);
+
+ himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+ msleep(120);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+ I("%s: initialization complete\n", __func__);
+
+ return 1;
+}
+
+#ifdef HX_ESD_WORKAROUND
+void ESD_HW_REST(void)
+{
+ I("START_Himax TP: ESD - Reset\n");
+
+ HX_report_ESD_event();
+ ESD_00_counter = 0;
+ ESD_00_Flag = 0;
+ /*************************************/
+ if (private_ts->protocol_type == PROTOCOL_TYPE_A)
+ input_mt_sync(private_ts->input_dev);
+ input_report_key(private_ts->input_dev, BTN_TOUCH, 0);
+ input_sync(private_ts->input_dev);
+ /*************************************/
+
+ I("END_Himax TP: ESD - Reset\n");
+}
+#endif
+#ifdef HX_HIGH_SENSE
+void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable)
+{
+ uint8_t tmp_data[4];
+
+ if(HSEN_enable)
+ {
+ I(" %s in", __func__);
+ HSEN_bit_retry:
+ himax_set_HSEN_enable(client,HSEN_enable);
+ msleep(20);
+ himax_get_HSEN_enable(client,tmp_data);
+ I("%s: Read HSEN bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
+ ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+ if(tmp_data[0]!= 0x01)
+ {
+ I("%s: retry HSEN bit write data[0]=%x \n",__func__,tmp_data[0]);
+ goto HSEN_bit_retry;
+ }
+ }
+}
+
+static void himax_HSEN_func(struct work_struct *work)
+{
+ struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
+ hsen_work.work);
+
+ himax_set_HSEN_func(ts->client, ts->HSEN_enable);
+}
+
+#endif
+
+#ifdef HX_SMART_WAKEUP
+#ifdef HX_GESTURE_TRACK
+static void gest_pt_log_coordinate(int rx, int tx)
+{
+ //driver report x y with range 0 - 255 , we scale it up to x/y pixel
+ gest_pt_x[gest_pt_cnt] = rx*(ic_data->HX_X_RES)/255;
+ gest_pt_y[gest_pt_cnt] = tx*(ic_data->HX_Y_RES)/255;
+}
+#endif
+static int himax_parse_wake_event(struct himax_ts_data *ts)
+{
+ uint8_t buf[64];
+ unsigned char check_sum_cal = 0;
+#ifdef HX_GESTURE_TRACK
+ int tmp_max_x=0x00,tmp_min_x=0xFFFF,tmp_max_y=0x00,tmp_min_y=0xFFFF;
+ int gest_len;
+#endif
+ int i=0, check_FC = 0, gesture_flag = 0;
+
+ himax_burst_enable(ts->client, 0);
+ himax_read_event_stack(ts->client,buf,56);
+
+ for(i=0;i<GEST_PTLG_ID_LEN;i++)
+ {
+ if (check_FC==0)
+ {
+ if((buf[0]!=0x00)&&((buf[0]<=0x0F)||(buf[0]==0x80)))
+ {
+ check_FC = 1;
+ gesture_flag = buf[i];
+ }
+ else
+ {
+ check_FC = 0;
+ I("ID START at %x , value = %x skip the event\n", i, buf[i]);
+ break;
+ }
+ }
+ else
+ {
+ if(buf[i]!=gesture_flag)
+ {
+ check_FC = 0;
+ I("ID NOT the same %x != %x So STOP parse event\n", buf[i], gesture_flag);
+ break;
+ }
+ }
+
+ I("0x%2.2X ", buf[i]);
+ if (i % 8 == 7)
+ I("\n");
+ }
+ I("Himax gesture_flag= %x\n",gesture_flag );
+ I("Himax check_FC is %d\n", check_FC);
+
+ if (check_FC == 0)
+ return 0;
+ if(buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 ||
+ buf[GEST_PTLG_ID_LEN+1] != GEST_PTLG_HDR_ID2)
+ return 0;
+ for(i=0;i<(GEST_PTLG_ID_LEN+GEST_PTLG_HDR_LEN);i++)
+ {
+ I("P[%x]=0x%2.2X \n", i, buf[i]);
+ I("checksum=0x%2.2X \n", check_sum_cal);
+ check_sum_cal += buf[i];
+ }
+ if ((check_sum_cal != 0x00) )
+ {
+ I(" %s : check_sum_cal: 0x%02X\n",__func__ ,check_sum_cal);
+ return 0;
+ }
+#ifdef HX_GESTURE_TRACK
+ if(buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 &&
+ buf[GEST_PTLG_ID_LEN+1] == GEST_PTLG_HDR_ID2)
+ {
+ gest_len = buf[GEST_PTLG_ID_LEN+2];
+
+ I("gest_len = %d ",gest_len);
+
+ i = 0;
+ gest_pt_cnt = 0;
+ I("gest doornidate start \n %s",__func__);
+ while(i<(gest_len+1)/2)
+ {
+ gest_pt_log_coordinate(buf[GEST_PTLG_ID_LEN+4+i*2],buf[GEST_PTLG_ID_LEN+4+i*2+1]);
+ i++;
+
+ I("gest_pt_x[%d]=%d \n",gest_pt_cnt,gest_pt_x[gest_pt_cnt]);
+ I("gest_pt_y[%d]=%d \n",gest_pt_cnt,gest_pt_y[gest_pt_cnt]);
+
+ gest_pt_cnt +=1;
+ }
+ if(gest_pt_cnt)
+ {
+ for(i=0; i<gest_pt_cnt; i++)
+ {
+ if(tmp_max_x<gest_pt_x[i])
+ tmp_max_x=gest_pt_x[i];
+ if(tmp_min_x>gest_pt_x[i])
+ tmp_min_x=gest_pt_x[i];
+ if(tmp_max_y<gest_pt_y[i])
+ tmp_max_y=gest_pt_y[i];
+ if(tmp_min_y>gest_pt_y[i])
+ tmp_min_y=gest_pt_y[i];
+ }
+ I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n",tmp_min_x,tmp_max_x,tmp_min_y,tmp_max_y);
+ gest_start_x=gest_pt_x[0];
+ gn_gesture_coor[0] = gest_start_x;
+ gest_start_y=gest_pt_y[0];
+ gn_gesture_coor[1] = gest_start_y;
+ gest_end_x=gest_pt_x[gest_pt_cnt-1];
+ gn_gesture_coor[2] = gest_end_x;
+ gest_end_y=gest_pt_y[gest_pt_cnt-1];
+ gn_gesture_coor[3] = gest_end_y;
+ gest_width = tmp_max_x - tmp_min_x;
+ gn_gesture_coor[4] = gest_width;
+ gest_height = tmp_max_y - tmp_min_y;
+ gn_gesture_coor[5] = gest_height;
+ gest_mid_x = (tmp_max_x + tmp_min_x)/2;
+ gn_gesture_coor[6] = gest_mid_x;
+ gest_mid_y = (tmp_max_y + tmp_min_y)/2;
+ gn_gesture_coor[7] = gest_mid_y;
+ gn_gesture_coor[8] = gest_mid_x;//gest_up_x
+ gn_gesture_coor[9] = gest_mid_y-gest_height/2;//gest_up_y
+ gn_gesture_coor[10] = gest_mid_x;//gest_down_x
+ gn_gesture_coor[11] = gest_mid_y+gest_height/2; //gest_down_y
+ gn_gesture_coor[12] = gest_mid_x-gest_width/2; //gest_left_x
+ gn_gesture_coor[13] = gest_mid_y; //gest_left_y
+ gn_gesture_coor[14] = gest_mid_x+gest_width/2; //gest_right_x
+ gn_gesture_coor[15] = gest_mid_y; //gest_right_y
+
+ }
+
+ }
+#endif
+ if(gesture_flag != 0x80)
+ {
+ if(!ts->gesture_cust_en[gesture_flag])
+ {
+ I("%s NOT report customer key \n ",__func__);
+ return 0;//NOT report customer key
+ }
+ }
+ else
+ {
+ if(!ts->gesture_cust_en[0])
+ {
+ I("%s NOT report report double click \n",__func__);
+ return 0;//NOT report power key
+ }
+ }
+
+ if(gesture_flag == 0x80)
+ return EV_GESTURE_PWR;
+ else
+ return gesture_flag;
+}
+
+void himax_wake_check_func(void)
+{
+ int ret_event = 0, KEY_EVENT = 0;
+
+ ret_event = himax_parse_wake_event(private_ts);
+ switch (ret_event) {
+ case EV_GESTURE_PWR:
+ KEY_EVENT = KEY_POWER;
+ break;
+ case EV_GESTURE_01:
+ KEY_EVENT = KEY_CUST_01;
+ break;
+ case EV_GESTURE_02:
+ KEY_EVENT = KEY_CUST_02;
+ break;
+ case EV_GESTURE_03:
+ KEY_EVENT = KEY_CUST_03;
+ break;
+ case EV_GESTURE_04:
+ KEY_EVENT = KEY_CUST_04;
+ break;
+ case EV_GESTURE_05:
+ KEY_EVENT = KEY_CUST_05;
+ break;
+ case EV_GESTURE_06:
+ KEY_EVENT = KEY_CUST_06;
+ break;
+ case EV_GESTURE_07:
+ KEY_EVENT = KEY_CUST_07;
+ break;
+ case EV_GESTURE_08:
+ KEY_EVENT = KEY_CUST_08;
+ break;
+ case EV_GESTURE_09:
+ KEY_EVENT = KEY_CUST_09;
+ break;
+ case EV_GESTURE_10:
+ KEY_EVENT = KEY_CUST_10;
+ break;
+ case EV_GESTURE_11:
+ KEY_EVENT = KEY_CUST_11;
+ break;
+ case EV_GESTURE_12:
+ KEY_EVENT = KEY_CUST_12;
+ break;
+ case EV_GESTURE_13:
+ KEY_EVENT = KEY_CUST_13;
+ break;
+ case EV_GESTURE_14:
+ KEY_EVENT = KEY_CUST_14;
+ break;
+ case EV_GESTURE_15:
+ KEY_EVENT = KEY_CUST_15;
+ break;
+ }
+ if(ret_event)
+ {
+ I(" %s SMART WAKEUP KEY event %x press\n",__func__,KEY_EVENT);
+ input_report_key(private_ts->input_dev, KEY_EVENT, 1);
+ input_sync(private_ts->input_dev);
+ //msleep(100);
+ I(" %s SMART WAKEUP KEY event %x release\n",__func__,KEY_EVENT);
+ input_report_key(private_ts->input_dev, KEY_EVENT, 0);
+ input_sync(private_ts->input_dev);
+ FAKE_POWER_KEY_SEND=true;
+#ifdef HX_GESTURE_TRACK
+ I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n",gest_start_x,gest_start_y,
+ gest_end_x,gest_end_y);
+ I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n",gest_width,gest_height,
+ gest_mid_x,gest_mid_y);
+ I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n",gn_gesture_coor[8],gn_gesture_coor[9],
+ gn_gesture_coor[10],gn_gesture_coor[11]);
+ I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n",gn_gesture_coor[12],gn_gesture_coor[13],
+ gn_gesture_coor[14],gn_gesture_coor[15]);
+#endif
+ }
+}
+
+#endif
+static void himax_ts_button_func(int tp_key_index,struct himax_ts_data *ts)
+{
+ uint16_t x_position = 0, y_position = 0;
+if ( tp_key_index != 0x00)
+ {
+ I("virtual key index =%x\n",tp_key_index);
+ if ( tp_key_index == 0x01) {
+ vk_press = 1;
+ I("back key pressed\n");
+ if (ts->pdata->virtual_key)
+ {
+ if (ts->button[0].index) {
+ x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2;
+ y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2;
+ }
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ 1);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ }
+ }
+ else
+ input_report_key(ts->input_dev, KEY_BACK, 1);
+ }
+ else if ( tp_key_index == 0x02) {
+ vk_press = 1;
+ I("home key pressed\n");
+ if (ts->pdata->virtual_key)
+ {
+ if (ts->button[1].index) {
+ x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2;
+ y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2;
+ }
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ 1);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ }
+ }
+ else
+ input_report_key(ts->input_dev, KEY_HOME, 1);
+ }
+ else if ( tp_key_index == 0x04) {
+ vk_press = 1;
+ I("APP_switch key pressed\n");
+ if (ts->pdata->virtual_key)
+ {
+ if (ts->button[2].index) {
+ x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2;
+ y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2;
+ }
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ 1);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ y_position);
+ }
+ }
+ else
+ input_report_key(ts->input_dev, KEY_F10, 1);
+ }
+ input_sync(ts->input_dev);
+ }
+else/*tp_key_index =0x00*/
+ {
+ I("virtual key released\n");
+ vk_press = 0;
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_mt_sync(ts->input_dev);
+ }
+ else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+ }
+ input_report_key(ts->input_dev, KEY_BACK, 0);
+ input_report_key(ts->input_dev, KEY_HOME, 0);
+ input_report_key(ts->input_dev, KEY_F10, 0);
+ input_sync(ts->input_dev);
+ }
+}
+
+void himax_ts_work(struct himax_ts_data *ts)
+{
+ int ret = 0;
+ uint8_t finger_num, hw_reset_check[2];
+ uint8_t buf[128];
+ uint8_t finger_on = 0;
+ int32_t loop_i;
+ uint16_t check_sum_cal = 0;
+ int raw_cnt_max ;
+ int raw_cnt_rmd ;
+ int hx_touch_info_size;
+ uint8_t coordInfoSize = ts->coord_data_size + ts->area_data_size + 4;
+
+#ifdef HX_TP_PROC_DIAG
+ int16_t *mutual_data;
+ int16_t *self_data;
+ uint8_t diag_cmd;
+ int i;
+ int mul_num;
+ int self_num;
+ int RawDataLen = 0;
+ //coordinate dump start
+ char coordinate_char[15+(ic_data->HX_MAX_PT+5)*2*5+2];
+ //coordinate dump end
+#endif
+
+ memset(buf, 0x00, sizeof(buf));
+ memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
+
+ raw_cnt_max = ic_data->HX_MAX_PT/4;
+ raw_cnt_rmd = ic_data->HX_MAX_PT%4;
+
+#if defined(HX_USB_DETECT2)
+ himax_cable_detect_func();
+#endif
+
+ if (raw_cnt_rmd != 0x00) //more than 4 fingers
+ {
+ RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
+ hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+2)*4;
+ }
+ else //less than 4 fingers
+ {
+ RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
+ hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+1)*4;
+ }
+
+#ifdef HX_TP_PROC_DIAG
+ diag_cmd = getDiagCommand();
+ if( diag_cmd ){
+ ret = read_event_stack(ts->client, buf, 128);
+ }
+ else{
+ if(touch_monitor_stop_flag != 0){
+ ret = read_event_stack(ts->client, buf, 128);
+ touch_monitor_stop_flag-- ;
+ }
+ else{
+ ret = read_event_stack(ts->client, buf, hx_touch_info_size);
+ }
+ }
+
+ if (!ret)
+#else
+ if(!read_event_stack(ts->client, buf, hx_touch_info_size))
+#endif
+ {
+ E("%s: can't read data from chip!\n", __func__);
+ goto err_workqueue_out;
+ }
+ post_read_event_stack(ts->client);
+#ifdef HX_ESD_WORKAROUND
+ for(i = 0; i < hx_touch_info_size; i++)
+ {
+ if(buf[i] == 0xED)/*case 1 ESD recovery flow*/
+ {
+ check_sum_cal = 1;
+
+ }else if(buf[i] == 0x00)
+ {
+ ESD_00_Flag = 1;
+ }
+ else
+ {
+ check_sum_cal = 0;
+ ESD_00_counter = 0;
+ ESD_00_Flag = 0;
+ i = hx_touch_info_size;
+ break;
+ }
+ }
+ if (ESD_00_Flag == 1){
+ ESD_00_counter ++;
+ }
+ if (ESD_00_counter > 1){
+ check_sum_cal = 2;
+ }
+
+ if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0)
+ {
+ I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
+ ESD_HW_REST();
+ return;
+ }
+
+ if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0)
+ {
+ I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n");
+ ESD_HW_REST();
+ return;
+ }
+ else if (HX_ESD_RESET_ACTIVATE)
+ {
+#ifdef HX_SMART_WAKEUP
+ queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(50));
+#endif
+#ifdef HX_HIGH_SENSE
+ queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(50));
+#endif
+ HX_ESD_RESET_ACTIVATE = 0;/*drop 1st interrupts after chip reset*/
+ I("[HIMAX TP MSG]:%s: Back from reset, ready to serve.\n", __func__);
+ }
+#endif
+ for (loop_i = 0, check_sum_cal = 0; loop_i < hx_touch_info_size; loop_i++)
+ check_sum_cal += buf[loop_i];
+
+ if ((check_sum_cal % 0x100 != 0) )
+ {
+ I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal);
+ return;
+ }
+
+ if (ts->debug_log_level & BIT(0)) {
+ I("%s: raw data:\n", __func__);
+ for (loop_i = 0; loop_i < hx_touch_info_size; loop_i++) {
+ I("P %d = 0x%2.2X ", loop_i, buf[loop_i]);
+ if (loop_i % 8 == 7)
+ I("\n");
+ }
+ }
+
+ //touch monitor raw data fetch
+#ifdef HX_TP_PROC_DIAG
+ diag_cmd = getDiagCommand();
+ if (diag_cmd >= 1 && diag_cmd <= 6)
+ {
+ //Check 124th byte CRC
+ if(!diag_check_sum(hx_touch_info_size, buf))
+ {
+ goto bypass_checksum_failed_packet;
+ }
+#ifdef HX_TP_PROC_2T2R
+ if(Is_2T2R && diag_cmd == 4)
+ {
+ mutual_data = getMutualBuffer_2();
+ self_data = getSelfBuffer();
+
+ // initiallize the block number of mutual and self
+ mul_num = getXChannel_2() * getYChannel_2();
+
+#ifdef HX_EN_SEL_BUTTON
+ self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM;
+#else
+ self_num = getXChannel_2() + getYChannel_2();
+#endif
+ }
+ else
+#endif
+ {
+ mutual_data = getMutualBuffer();
+ self_data = getSelfBuffer();
+
+ // initiallize the block number of mutual and self
+ mul_num = getXChannel() * getYChannel();
+
+#ifdef HX_EN_SEL_BUTTON
+ self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM;
+#else
+ self_num = getXChannel() + getYChannel();
+#endif
+ }
+
+ diag_parse_raw_data(hx_touch_info_size, RawDataLen, mul_num, self_num, buf, diag_cmd, mutual_data, self_data);
+
+ }
+ else if (diag_cmd == 7)
+ {
+ memcpy(&(diag_coor[0]), &buf[0], 128);
+ }
+ //coordinate dump start
+ if (coordinate_dump_enable == 1)
+ {
+ for(i=0; i<(15 + (ic_data->HX_MAX_PT+5)*2*5); i++)
+ {
+ coordinate_char[i] = 0x20;
+ }
+ coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5] = 0xD;
+ coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5 + 1] = 0xA;
+ }
+ //coordinate dump end
+bypass_checksum_failed_packet:
+#endif
+ EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>3);
+ //I("EN_NoiseFilter=%d\n",EN_NoiseFilter);
+ EN_NoiseFilter = EN_NoiseFilter & 0x01;
+ //I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);
+
+#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON)
+ tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>4);
+ if (tpd_key == 0x0F)/*All (VK+AA)leave*/
+ {
+ tpd_key = 0x00;
+ }
+ //I("[DEBUG] tpd_key: %x\r\n", tpd_key);
+#else
+ tpd_key = 0x00;
+#endif
+
+ p_point_num = hx_point_num;
+
+ if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
+ hx_point_num = 0;
+ else
+ hx_point_num= buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f;
+
+ // Touch Point information
+ if (hx_point_num != 0 ) {
+ if(vk_press == 0x00)
+ {
+ uint16_t old_finger = ts->pre_finger_mask;
+ ts->pre_finger_mask = 0;
+ finger_num = buf[coordInfoSize - 4] & 0x0F;
+ finger_on = 1;
+ AA_press = 1;
+ for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
+ int base = loop_i * 4;
+ int x = buf[base] << 8 | buf[base + 1];
+ int y = (buf[base + 2] << 8 | buf[base + 3]);
+ int w = buf[(ts->nFinger_support * 4) + loop_i];
+ if(x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max){
+ finger_num--;
+
+ if ((ts->debug_log_level & BIT(3)) > 0)
+ {
+ if (old_finger >> loop_i == 0)
+ {
+ if (ts->useScreenRes)
+ {
+ I("status: Screen:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
+ loop_i+1, x * ts->widthFactor >> SHIFTBITS,
+ y * ts->heightFactor >> SHIFTBITS, w, EN_NoiseFilter);
+ }
+ else
+ {
+ I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
+ loop_i+1, x, y, w, EN_NoiseFilter);
+ }
+ }
+ }
+
+ if (ts->protocol_type == PROTOCOL_TYPE_B)
+ {
+ input_mt_slot(ts->input_dev, loop_i);
+ }
+
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
+
+ if (ts->protocol_type == PROTOCOL_TYPE_A)
+ {
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, loop_i);
+ input_mt_sync(ts->input_dev);
+ }
+ else
+ {
+ ts->last_slot = loop_i;
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
+ }
+
+ if (!ts->first_pressed)
+ {
+ ts->first_pressed = 1;
+ I("S1@%d, %d\n", x, y);
+ }
+
+ ts->pre_finger_data[loop_i][0] = x;
+ ts->pre_finger_data[loop_i][1] = y;
+
+
+ if (ts->debug_log_level & BIT(1))
+ I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, N:%d\n",
+ loop_i + 1, x, y, w, w, loop_i + 1, EN_NoiseFilter);
+
+ ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i);
+
+ } else {
+ if (ts->protocol_type == PROTOCOL_TYPE_B)
+ {
+ input_mt_slot(ts->input_dev, loop_i);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+ }
+
+ if (loop_i == 0 && ts->first_pressed == 1)
+ {
+ ts->first_pressed = 2;
+ I("E1@%d, %d\n",
+ ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
+ }
+ if ((ts->debug_log_level & BIT(3)) > 0)
+ {
+ if (old_finger >> loop_i == 1)
+ {
+ if (ts->useScreenRes)
+ {
+ I("status: Screen:F:%02d Up, X:%d, Y:%d, N:%d\n",
+ loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
+ ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
+ }
+ else
+ {
+ I("status: Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",
+ loop_i+1, ts->pre_finger_data[loop_i][0],
+ ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
+ }
+ }
+ }
+ }
+ }
+
+ }else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
+ //temp_x[0] = 0xFFFF;
+ //temp_y[0] = 0xFFFF;
+ //temp_x[1] = 0xFFFF;
+ //temp_y[1] = 0xFFFF;
+ himax_ts_button_func(tpd_key,ts);
+ finger_on = 0;
+ }
+ input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+ input_sync(ts->input_dev);
+ } else if (hx_point_num == 0){
+ if(AA_press)
+ {
+ // leave event
+ finger_on = 0;
+ AA_press = 0;
+ if (ts->protocol_type == PROTOCOL_TYPE_A)
+ input_mt_sync(ts->input_dev);
+
+ for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
+ if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
+ if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, loop_i);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+ }
+ }
+ }
+ if (ts->pre_finger_mask > 0) {
+ for (loop_i = 0; loop_i < ts->nFinger_support && (ts->debug_log_level & BIT(3)) > 0; loop_i++) {
+ if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
+ if (ts->useScreenRes) {
+ I("status:%X, Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", 0, loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
+ ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
+ } else {
+ I("status:%X, Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",0, loop_i+1, ts->pre_finger_data[loop_i][0],ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
+ }
+ }
+ }
+ ts->pre_finger_mask = 0;
+ }
+
+ if (ts->first_pressed == 1) {
+ ts->first_pressed = 2;
+ I("E1@%d, %d\n",ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
+ }
+
+ if (ts->debug_log_level & BIT(1))
+ I("All Finger leave\n");
+
+ }
+ else if (tpd_key != 0x00) {
+ himax_ts_button_func(tpd_key,ts);
+ finger_on = 1;
+ }
+ else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
+ himax_ts_button_func(tpd_key,ts);
+ finger_on = 0;
+ }
+ input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+ input_sync(ts->input_dev);
+ }
+ tpd_key_old = tpd_key;
+ Last_EN_NoiseFilter = EN_NoiseFilter;
+
+workqueue_out:
+ return;
+
+err_workqueue_out:
+ I("%s: Now reset the Touch chip.\n", __func__);
+
+#ifdef HX_RST_PIN_FUNC
+ himax_HW_reset(true,false);
+#endif
+
+ goto workqueue_out;
+}
+enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer)
+{
+ struct himax_ts_data *ts;
+
+ ts = container_of(timer, struct himax_ts_data, timer);
+ queue_work(ts->himax_wq, &ts->work);
+ hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+#if defined(HX_USB_DETECT)
+static void himax_cable_tp_status_handler_func(int connect_status)
+{
+ struct himax_ts_data *ts;
+ I("Touch: cable change to %d\n", connect_status);
+ ts = private_ts;
+ if (ts->cable_config) {
+ if (!atomic_read(&ts->suspend_mode)) {
+ if ((!!connect_status) != ts->usb_connected) {
+ if (!!connect_status) {
+ ts->cable_config[1] = 0x01;
+ ts->usb_connected = 0x01;
+ } else {
+ ts->cable_config[1] = 0x00;
+ ts->usb_connected = 0x00;
+ }
+
+ i2c_himax_master_write(ts->client, ts->cable_config,
+ sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES);
+
+ I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]);
+ } else
+ I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+ } else {
+ if (connect_status)
+ ts->usb_connected = 0x01;
+ else
+ ts->usb_connected = 0x00;
+ I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected);
+ }
+ }
+}
+
+static struct t_cable_status_notifier himax_cable_status_handler = {
+ .name = "usb_tp_connected",
+ .func = himax_cable_tp_status_handler_func,
+};
+
+#endif
+
+#if defined(HX_USB_DETECT2)
+void himax_cable_detect_func(void)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[128];
+ struct himax_ts_data *ts;
+ u32 connect_status = 0;
+
+ connect_status = USB_Flag;//upmu_is_chr_det();
+ ts = private_ts;
+ //I("Touch: cable status=%d, cable_config=%p, usb_connected=%d \n", connect_status,ts->cable_config, ts->usb_connected);
+ if (ts->cable_config) {
+ if ((!!connect_status) != ts->usb_connected) {
+ //notify USB plug/unplug
+ // 0x9008_8060 ==> 0x0000_0000/0001
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x60;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00;
+
+ if (!!connect_status) {
+ tmp_data[0] = 0x01;
+ ts->usb_connected = 0x01;
+ } else {
+ tmp_data[0] = 0x00;
+ ts->usb_connected = 0x00;
+ }
+
+ himax_flash_write_burst(ts->client, tmp_addr, tmp_data);
+
+ I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected);
+ }
+ //else
+ //I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+ }
+}
+#endif
+
+#ifdef CONFIG_FB
+int himax_fb_register(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ I(" %s in", __func__);
+ ts->fb_notif.notifier_call = fb_notifier_callback;
+ ret = fb_register_client(&ts->fb_notif);
+ if (ret)
+ E(" Unable to register fb_notifier: %d\n", ret);
+
+ return ret;
+}
+#endif
+
+#ifdef HX_SMART_WAKEUP
+void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable)
+{
+ uint8_t tmp_data[4];
+
+ if(SMWP_enable)
+ {
+ SMWP_bit_retry:
+ himax_set_SMWP_enable(client, SMWP_enable);
+ msleep(20);
+ himax_get_SMWP_enable(client,tmp_data);
+ I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
+ ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+ if(tmp_data[0]!= 0x01)
+ {
+ I("%s: retry SMWP bit write data[0]=%x \n",__func__,tmp_data[0]);
+ goto SMWP_bit_retry;
+ }
+ }
+}
+
+static void himax_SMWP_work(struct work_struct *work)
+{
+ struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
+ smwp_work.work);
+ I(" %s in", __func__);
+
+ himax_set_SMWP_func(ts->client,ts->SMWP_enable);
+
+}
+#endif
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+static void himax_ts_flash_work_func(struct work_struct *work)
+{
+ himax_ts_flash_func();
+}
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+static void himax_ts_diag_work_func(struct work_struct *work)
+{
+ himax_ts_diag_func();
+}
+#endif
+
+void himax_ts_init(struct himax_ts_data *ts)
+{
+ int ret = 0, err = 0;
+ struct himax_i2c_platform_data *pdata;
+ struct i2c_client *client;
+
+ client = ts->client;
+ pdata = ts->pdata;
+
+ I("%s: Start.\n", __func__);
+
+ /* Set pinctrl in active state */
+ if (ts->ts_pinctrl) {
+ ret = pinctrl_select_state(ts->ts_pinctrl,
+ ts->pinctrl_state_active);
+ if (ret < 0) {
+ E("Failed to set pin in active state %d",ret);
+ }
+ }
+
+ himax_burst_enable(client, 0);
+
+ //Get Himax IC Type / FW information / Calculate the point number
+ if (himax_check_chip_version(ts->client) == false) {
+ E("Himax chip doesn NOT EXIST");
+ goto err_ic_package_failed;
+ }
+ if (himax_ic_package_check(ts->client) == false) {
+ E("Himax chip doesn NOT EXIST");
+ goto err_ic_package_failed;
+ }
+
+ if (pdata->virtual_key)
+ ts->button = pdata->virtual_key;
+#ifdef HX_TP_PROC_FLASH_DUMP
+ ts->flash_wq = create_singlethread_workqueue("himax_flash_wq");
+ if (!ts->flash_wq)
+ {
+ E("%s: create flash workqueue failed\n", __func__);
+ err = -ENOMEM;
+ goto err_create_wq_failed;
+ }
+
+ INIT_WORK(&ts->flash_work, himax_ts_flash_work_func);
+
+ setSysOperation(0);
+ setFlashBuffer();
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ ts->himax_diag_wq = create_singlethread_workqueue("himax_diag");
+ if (!ts->himax_diag_wq)
+ {
+ E("%s: create diag workqueue failed\n", __func__);
+ err = -ENOMEM;
+ goto err_create_wq_failed;
+ }
+ INIT_DELAYED_WORK(&ts->himax_diag_delay_wrok, himax_ts_diag_work_func);
+#endif
+
+himax_read_FW_ver(client);
+
+#ifdef HX_AUTO_UPDATE_FW
+ I(" %s in", __func__);
+ if(i_update_FW() == false)
+ I("NOT Have new FW=NOT UPDATE=\n");
+ else
+ I("Have new FW=UPDATE=\n");
+#endif
+
+ //Himax Power On and Load Config
+ if (himax_loadSensorConfig(client, pdata) < 0) {
+ E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__);
+ goto err_detect_failed;
+ }
+
+ calculate_point_number();
+#ifdef HX_TP_PROC_DIAG
+ setXChannel(ic_data->HX_RX_NUM); // X channel
+ setYChannel(ic_data->HX_TX_NUM); // Y channel
+
+ setMutualBuffer();
+ setMutualNewBuffer();
+ setMutualOldBuffer();
+ if (getMutualBuffer() == NULL) {
+ E("%s: mutual buffer allocate fail failed\n", __func__);
+ return;
+ }
+#ifdef HX_TP_PROC_2T2R
+ if(Is_2T2R){
+ setXChannel_2(ic_data->HX_RX_NUM_2); // X channel
+ setYChannel_2(ic_data->HX_TX_NUM_2); // Y channel
+
+ setMutualBuffer_2();
+
+ if (getMutualBuffer_2() == NULL) {
+ E("%s: mutual buffer 2 allocate fail failed\n", __func__);
+ return;
+ }
+ }
+#endif
+#endif
+#ifdef CONFIG_OF
+ ts->power = pdata->power;
+#endif
+ ts->pdata = pdata;
+
+ ts->x_channel = ic_data->HX_RX_NUM;
+ ts->y_channel = ic_data->HX_TX_NUM;
+ ts->nFinger_support = ic_data->HX_MAX_PT;
+ //calculate the i2c data size
+ calcDataSize(ts->nFinger_support);
+ I("%s: calcDataSize complete\n", __func__);
+#ifdef CONFIG_OF
+ ts->pdata->abs_pressure_min = 0;
+ ts->pdata->abs_pressure_max = 200;
+ ts->pdata->abs_width_min = 0;
+ ts->pdata->abs_width_max = 200;
+ pdata->cable_config[0] = 0x90;
+ pdata->cable_config[1] = 0x00;
+#endif
+ ts->suspended = false;
+#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+ ts->usb_connected = 0x00;
+ ts->cable_config = pdata->cable_config;
+#endif
+ ts->protocol_type = pdata->protocol_type;
+ I("%s: Use Protocol Type %c\n", __func__,
+ ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B');
+
+ ret = himax_input_register(ts);
+ if (ret) {
+ E("%s: Unable to register %s input device\n",
+ __func__, ts->input_dev->name);
+ goto err_input_register_device_failed;
+ }
+#ifdef HX_SMART_WAKEUP
+ ts->SMWP_enable=0;
+ wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, HIMAX_common_NAME);
+
+ ts->himax_smwp_wq = create_singlethread_workqueue("HMX_SMWP_WORK");
+ if (!ts->himax_smwp_wq) {
+ E(" allocate himax_smwp_wq failed\n");
+ err = -ENOMEM;
+ goto err_smwp_wq_failed;
+ }
+ INIT_DELAYED_WORK(&ts->smwp_work, himax_SMWP_work);
+#endif
+#ifdef HX_HIGH_SENSE
+ ts->HSEN_enable=0;
+ ts->himax_hsen_wq = create_singlethread_workqueue("HMX_HSEN_WORK");
+ if (!ts->himax_hsen_wq) {
+ E(" allocate himax_hsen_wq failed\n");
+ err = -ENOMEM;
+ goto err_hsen_wq_failed;
+ }
+ INIT_DELAYED_WORK(&ts->hsen_work, himax_HSEN_func);
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+ himax_touch_proc_init();
+#endif
+
+#if defined(HX_USB_DETECT)
+ if (ts->cable_config)
+ cable_detect_register_notifier(&himax_cable_status_handler);
+#endif
+
+ err = himax_ts_register_interrupt(ts->client);
+ if (err)
+ goto err_register_interrupt_failed;
+ return;
+
+err_register_interrupt_failed:
+#ifdef HX_HIGH_SENSE
+err_hsen_wq_failed:
+#endif
+#ifdef HX_SMART_WAKEUP
+err_smwp_wq_failed:
+ wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+#endif
+err_input_register_device_failed:
+ input_free_device(ts->input_dev);
+err_detect_failed:
+#ifdef HX_TP_PROC_FLASH_DUMP
+err_create_wq_failed:
+#endif
+err_ic_package_failed:
+
+return;
+}
+
+int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct himax_ts_data *ts;
+ struct himax_i2c_platform_data *pdata;
+
+ //Check I2C functionality
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ E("%s: i2c check functionality error\n", __func__);
+ err = -ENODEV;
+ goto err_check_functionality_failed;
+ }
+
+ ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL);
+ if (ts == NULL) {
+ E("%s: allocate himax_ts_data failed\n", __func__);
+ err = -ENOMEM;
+ goto err_alloc_data_failed;
+ }
+
+ i2c_set_clientdata(client, ts);
+ ts->client = client;
+ ts->dev = &client->dev;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL) { /*Allocate Platform data space*/
+ err = -ENOMEM;
+ goto err_dt_platform_data_fail;
+ }
+
+ ic_data = kzalloc(sizeof(*ic_data), GFP_KERNEL);
+ if (ic_data == NULL) { /*Allocate IC data space*/
+ err = -ENOMEM;
+ goto err_dt_ic_data_fail;
+ }
+
+#ifdef CONFIG_OF
+ if (client->dev.of_node) { /*DeviceTree Init Platform_data*/
+ err = himax_parse_dt(ts, pdata);
+ if (err < 0) {
+ I(" pdata is NULL for DT\n");
+ goto err_alloc_dt_pdata_failed;
+ }
+ }
+#endif
+
+#ifdef HX_RST_PIN_FUNC
+ ts->rst_gpio = pdata->gpio_reset;
+#endif
+
+himax_gpio_power_config(ts->client, pdata);
+
+ err = himax_ts_pinctrl_init(ts);
+ if (err || ts->ts_pinctrl == NULL) {
+ E(" Pinctrl init failed\n");
+ }
+
+#ifndef CONFIG_OF
+ if (pdata->power) {
+ err = pdata->power(1);
+ if (err < 0) {
+ E("%s: power on failed\n", __func__);
+ goto err_power_failed;
+ }
+ }
+#endif
+ ts->pdata = pdata;
+ private_ts = ts;
+
+ mutex_init(&ts->fb_mutex);
+ /* ts initialization is deferred till FB_UNBLACK event;
+ * probe is considered pending till then.*/
+ ts->probe_done = false;
+#ifdef CONFIG_FB
+ err = himax_fb_register(ts);
+ if (err) {
+ E("Falied to register fb notifier\n");
+ err = -ENOMEM;
+ goto err_fb_notif_wq_create;
+ }
+#endif
+
+ return 0;
+
+#ifdef CONFIG_FB
+err_fb_notif_wq_create:
+#endif
+#ifdef CONFIG_OF
+err_alloc_dt_pdata_failed:
+#else
+err_power_failed:
+err_get_platform_data_fail:
+#endif
+ if (ts->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) {
+ devm_pinctrl_put(ts->ts_pinctrl);
+ ts->ts_pinctrl = NULL;
+ } else {
+ err = pinctrl_select_state(ts->ts_pinctrl,
+ ts->pinctrl_state_release);
+ if (err)
+ E("failed to select relase pinctrl state %d\n",
+ err);
+ }
+ }
+ kfree(ic_data);
+
+err_dt_ic_data_fail:
+ kfree(pdata);
+
+err_dt_platform_data_fail:
+ kfree(ts);
+
+err_alloc_data_failed:
+
+err_check_functionality_failed:
+ probe_fail_flag = 1;
+ return err;
+
+}
+
+int himax_chip_common_remove(struct i2c_client *client)
+{
+ struct himax_ts_data *ts = i2c_get_clientdata(client);
+ int ret;
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+ himax_touch_proc_deinit();
+#endif
+#ifdef CONFIG_FB
+ if (fb_unregister_client(&ts->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#endif
+
+ if (!ts->use_irq)
+ hrtimer_cancel(&ts->timer);
+
+ destroy_workqueue(ts->himax_wq);
+
+ if (ts->protocol_type == PROTOCOL_TYPE_B)
+ input_mt_destroy_slots(ts->input_dev);
+
+ input_unregister_device(ts->input_dev);
+
+ if (ts->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) {
+ devm_pinctrl_put(ts->ts_pinctrl);
+ ts->ts_pinctrl = NULL;
+ } else {
+ ret = pinctrl_select_state(ts->ts_pinctrl,
+ ts->pinctrl_state_release);
+ if (ret)
+ E("failed to select relase pinctrl state %d\n",
+ ret);
+ }
+ }
+#ifdef HX_SMART_WAKEUP
+ wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+#endif
+ kfree(ts);
+
+ return 0;
+
+}
+
+int himax_chip_common_suspend(struct himax_ts_data *ts)
+{
+ int ret;
+
+ if(ts->suspended)
+ {
+ I("%s: Already suspended. Skipped. \n", __func__);
+ return 0;
+ }
+ else
+ {
+ ts->suspended = true;
+ I("%s: enter \n", __func__);
+ }
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+ if (getFlashDumpGoing())
+ {
+ I("[himax] %s: Flash dump is going, reject suspend\n",__func__);
+ return 0;
+ }
+#endif
+#ifdef HX_TP_PROC_HITOUCH
+ if(hitouch_is_connect)
+ {
+ I("[himax] %s: Hitouch connect, reject suspend\n",__func__);
+ return 0;
+ }
+#endif
+#ifdef HX_SMART_WAKEUP
+ if(ts->SMWP_enable)
+ {
+ atomic_set(&ts->suspend_mode, 1);
+ ts->pre_finger_mask = 0;
+ FAKE_POWER_KEY_SEND=false;
+ I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",__func__);
+ return 0;
+ }
+#endif
+#ifdef HX_ESD_WORKAROUND
+ ESD_00_counter = 0;
+ ESD_00_Flag = 0;
+#endif
+ if (!ts->use_irq) {
+ ret = cancel_work_sync(&ts->work);
+ if (ret)
+ himax_int_enable(ts->client->irq,1);
+ }
+
+ //ts->first_pressed = 0;
+ atomic_set(&ts->suspend_mode, 1);
+ ts->pre_finger_mask = 0;
+
+ if (ts->ts_pinctrl) {
+ ret = pinctrl_select_state(ts->ts_pinctrl,
+ ts->pinctrl_state_suspend);
+ if (ret < 0) {
+ E("Failed to get idle pinctrl state %d\n", ret);
+ }
+ }
+
+ if (ts->pdata->powerOff3V3 && ts->pdata->power)
+ ts->pdata->power(0);
+
+ return 0;
+}
+
+int himax_chip_common_resume(struct himax_ts_data *ts)
+{
+ int retval;
+
+ I("%s: enter \n", __func__);
+
+ if (ts->pdata->powerOff3V3 && ts->pdata->power)
+ ts->pdata->power(1);
+
+
+ /*************************************/
+ if (ts->protocol_type == PROTOCOL_TYPE_A)
+ input_mt_sync(ts->input_dev);
+ input_report_key(ts->input_dev, BTN_TOUCH, 0);
+ input_sync(ts->input_dev);
+ /*************************************/
+
+
+ if (ts->ts_pinctrl) {
+ retval = pinctrl_select_state(ts->ts_pinctrl,
+ ts->pinctrl_state_active);
+ if (retval < 0) {
+ E("Cannot get default pinctrl state %d\n", retval);
+ goto err_pinctrl_select_resume;
+ }
+ }
+
+ atomic_set(&ts->suspend_mode, 0);
+
+ himax_int_enable(ts->client->irq,1);
+
+ ts->suspended = false;
+#if defined(HX_USB_DETECT2)
+ ts->usb_connected = 0x00;
+ himax_cable_detect_func();
+#endif
+#ifdef HX_SMART_WAKEUP
+ queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(1000));
+#endif
+#ifdef HX_HIGH_SENSE
+ queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(1000));
+#endif
+ return 0;
+err_pinctrl_select_resume:
+ if (ts->pdata->powerOff3V3 && ts->pdata->power)
+ ts->pdata->power(0);
+ return retval;
+}
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h
new file mode 100644
index 000000000000..27ce9aafd959
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_common.h
@@ -0,0 +1,395 @@
+/* Himax Android Driver Sample Code for Himax chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 HIMAX_COMMON_H
+#define HIMAX_COMMON_H
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/async.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/input/mt.h>
+#include <linux/firmware.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include "himax_platform.h"
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#define HIMAX_DRIVER_VER "0.2.4.0"
+
+#define FLASH_DUMP_FILE "/data/user/Flash_Dump.bin"
+#define DIAG_COORDINATE_FILE "/sdcard/Coordinate_Dump.csv"
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+
+#define HX_TP_PROC_DIAG
+#define HX_TP_PROC_REGISTER
+#define HX_TP_PROC_DEBUG
+#define HX_TP_PROC_FLASH_DUMP
+#define HX_TP_PROC_SELF_TEST
+#define HX_TP_PROC_RESET
+#define HX_TP_PROC_SENSE_ON_OFF
+//#define HX_TP_PROC_2T2R
+
+int himax_touch_proc_init(void);
+void himax_touch_proc_deinit(void);
+#endif
+
+//===========Himax Option function=============
+//#define HX_RST_PIN_FUNC
+//#define HX_AUTO_UPDATE_FW
+//#define HX_HIGH_SENSE
+//#define HX_SMART_WAKEUP
+//#define HX_USB_DETECT
+//#define HX_ESD_WORKAROUND
+//#define HX_USB_DETECT2
+
+//#define HX_EN_SEL_BUTTON // Support Self Virtual key ,default is close
+#define HX_EN_MUT_BUTTON // Support Mutual Virtual Key ,default is close
+
+#define HX_KEY_MAX_COUNT 4
+#define DEFAULT_RETRY_CNT 3
+
+#define HX_VKEY_0 KEY_BACK
+#define HX_VKEY_1 KEY_HOME
+#define HX_VKEY_2 KEY_RESERVED
+#define HX_VKEY_3 KEY_RESERVED
+#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3}
+
+#define SHIFTBITS 5
+//#define FLASH_SIZE 131072
+#define FW_SIZE_60k 61440
+#define FW_SIZE_64k 65536
+#define FW_SIZE_124k 126976
+#define FW_SIZE_128k 131072
+
+struct himax_ic_data {
+ int vendor_fw_ver;
+ int vendor_config_ver;
+ int vendor_sensor_id;
+ int HX_RX_NUM;
+ int HX_TX_NUM;
+ int HX_BT_NUM;
+ int HX_X_RES;
+ int HX_Y_RES;
+ int HX_MAX_PT;
+ bool HX_XY_REVERSE;
+ bool HX_INT_IS_EDGE;
+#ifdef HX_TP_PROC_2T2R
+ int HX_RX_NUM_2;
+ int HX_TX_NUM_2;
+#endif
+};
+
+struct himax_virtual_key {
+ int index;
+ int keycode;
+ int x_range_min;
+ int x_range_max;
+ int y_range_min;
+ int y_range_max;
+};
+
+struct himax_config {
+ uint8_t default_cfg;
+ uint8_t sensor_id;
+ uint8_t fw_ver;
+ uint16_t length;
+ uint32_t tw_x_min;
+ uint32_t tw_x_max;
+ uint32_t tw_y_min;
+ uint32_t tw_y_max;
+ uint32_t pl_x_min;
+ uint32_t pl_x_max;
+ uint32_t pl_y_min;
+ uint32_t pl_y_max;
+ uint8_t c1[11];
+ uint8_t c2[11];
+ uint8_t c3[11];
+ uint8_t c4[11];
+ uint8_t c5[11];
+ uint8_t c6[11];
+ uint8_t c7[11];
+ uint8_t c8[11];
+ uint8_t c9[11];
+ uint8_t c10[11];
+ uint8_t c11[11];
+ uint8_t c12[11];
+ uint8_t c13[11];
+ uint8_t c14[11];
+ uint8_t c15[11];
+ uint8_t c16[11];
+ uint8_t c17[11];
+ uint8_t c18[17];
+ uint8_t c19[15];
+ uint8_t c20[5];
+ uint8_t c21[11];
+ uint8_t c22[4];
+ uint8_t c23[3];
+ uint8_t c24[3];
+ uint8_t c25[4];
+ uint8_t c26[2];
+ uint8_t c27[2];
+ uint8_t c28[2];
+ uint8_t c29[2];
+ uint8_t c30[2];
+ uint8_t c31[2];
+ uint8_t c32[2];
+ uint8_t c33[2];
+ uint8_t c34[2];
+ uint8_t c35[3];
+ uint8_t c36[5];
+ uint8_t c37[5];
+ uint8_t c38[9];
+ uint8_t c39[14];
+ uint8_t c40[159];
+ uint8_t c41[99];
+};
+
+struct himax_ts_data {
+ bool suspended;
+ bool probe_done;
+ struct mutex fb_mutex;
+ atomic_t suspend_mode;
+ uint8_t x_channel;
+ uint8_t y_channel;
+ uint8_t useScreenRes;
+ uint8_t diag_command;
+
+ uint8_t protocol_type;
+ uint8_t first_pressed;
+ uint8_t coord_data_size;
+ uint8_t area_data_size;
+ uint8_t raw_data_frame_size;
+ uint8_t raw_data_nframes;
+ uint8_t nFinger_support;
+ uint8_t irq_enabled;
+ uint8_t diag_self[50];
+
+ uint16_t finger_pressed;
+ uint16_t last_slot;
+ uint16_t pre_finger_mask;
+
+ uint32_t debug_log_level;
+ uint32_t widthFactor;
+ uint32_t heightFactor;
+ uint32_t tw_x_min;
+ uint32_t tw_x_max;
+ uint32_t tw_y_min;
+ uint32_t tw_y_max;
+ uint32_t pl_x_min;
+ uint32_t pl_x_max;
+ uint32_t pl_y_min;
+ uint32_t pl_y_max;
+
+ int use_irq;
+ int (*power)(int on);
+ int pre_finger_data[10][2];
+
+ struct device *dev;
+ struct workqueue_struct *himax_wq;
+ struct work_struct work;
+ struct input_dev *input_dev;
+ struct hrtimer timer;
+ struct i2c_client *client;
+ struct himax_i2c_platform_data *pdata;
+ struct himax_virtual_key *button;
+
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+ struct workqueue_struct *flash_wq;
+ struct work_struct flash_work;
+#endif
+
+#ifdef HX_RST_PIN_FUNC
+ int rst_gpio;
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ struct workqueue_struct *himax_diag_wq;
+ struct delayed_work himax_diag_delay_wrok;
+#endif
+#ifdef HX_SMART_WAKEUP
+ uint8_t SMWP_enable;
+ uint8_t gesture_cust_en[16];
+ struct wake_lock ts_SMWP_wake_lock;
+ struct workqueue_struct *himax_smwp_wq;
+ struct delayed_work smwp_work;
+#endif
+
+#ifdef HX_HIGH_SENSE
+ uint8_t HSEN_enable;
+ struct workqueue_struct *himax_hsen_wq;
+ struct delayed_work hsen_work;
+#endif
+
+#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+ uint8_t usb_connected;
+ uint8_t *cable_config;
+#endif
+
+ /* pinctrl data */
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+};
+
+#define HX_CMD_NOP 0x00
+#define HX_CMD_SETMICROOFF 0x35
+#define HX_CMD_SETROMRDY 0x36
+#define HX_CMD_TSSLPIN 0x80
+#define HX_CMD_TSSLPOUT 0x81
+#define HX_CMD_TSSOFF 0x82
+#define HX_CMD_TSSON 0x83
+#define HX_CMD_ROE 0x85
+#define HX_CMD_RAE 0x86
+#define HX_CMD_RLE 0x87
+#define HX_CMD_CLRES 0x88
+#define HX_CMD_TSSWRESET 0x9E
+#define HX_CMD_SETDEEPSTB 0xD7
+#define HX_CMD_SET_CACHE_FUN 0xDD
+#define HX_CMD_SETIDLE 0xF2
+#define HX_CMD_SETIDLEDELAY 0xF3
+#define HX_CMD_SELFTEST_BUFFER 0x8D
+#define HX_CMD_MANUALMODE 0x42
+#define HX_CMD_FLASH_ENABLE 0x43
+#define HX_CMD_FLASH_SET_ADDRESS 0x44
+#define HX_CMD_FLASH_WRITE_REGISTER 0x45
+#define HX_CMD_FLASH_SET_COMMAND 0x47
+#define HX_CMD_FLASH_WRITE_BUFFER 0x48
+#define HX_CMD_FLASH_PAGE_ERASE 0x4D
+#define HX_CMD_FLASH_SECTOR_ERASE 0x4E
+#define HX_CMD_CB 0xCB
+#define HX_CMD_EA 0xEA
+#define HX_CMD_4A 0x4A
+#define HX_CMD_4F 0x4F
+#define HX_CMD_B9 0xB9
+#define HX_CMD_76 0x76
+
+enum input_protocol_type {
+ PROTOCOL_TYPE_A = 0x00,
+ PROTOCOL_TYPE_B = 0x01,
+};
+
+#ifdef HX_HIGH_SENSE
+void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable);
+#endif
+
+#ifdef HX_SMART_WAKEUP
+#define GEST_PTLG_ID_LEN (4)
+#define GEST_PTLG_HDR_LEN (4)
+#define GEST_PTLG_HDR_ID1 (0xCC)
+#define GEST_PTLG_HDR_ID2 (0x44)
+#define GEST_PT_MAX_NUM (128)
+
+#ifdef HX_GESTURE_TRACK
+static int gest_pt_cnt;
+static int gest_pt_x[GEST_PT_MAX_NUM];
+static int gest_pt_y[GEST_PT_MAX_NUM];
+static int gest_start_x,gest_start_y,gest_end_x,gest_end_y;
+static int gest_width,gest_height,gest_mid_x,gest_mid_y;
+static int gn_gesture_coor[16];
+#endif
+
+void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable);
+extern bool FAKE_POWER_KEY_SEND;
+
+ enum gesture_event_type {
+ EV_GESTURE_01 = 0x01,
+ EV_GESTURE_02,
+ EV_GESTURE_03,
+ EV_GESTURE_04,
+ EV_GESTURE_05,
+ EV_GESTURE_06,
+ EV_GESTURE_07,
+ EV_GESTURE_08,
+ EV_GESTURE_09,
+ EV_GESTURE_10,
+ EV_GESTURE_11,
+ EV_GESTURE_12,
+ EV_GESTURE_13,
+ EV_GESTURE_14,
+ EV_GESTURE_15,
+ EV_GESTURE_PWR = 0x80,
+ };
+
+#define KEY_CUST_01 251
+#define KEY_CUST_02 252
+#define KEY_CUST_03 253
+#define KEY_CUST_04 254
+#define KEY_CUST_05 255
+#define KEY_CUST_06 256
+#define KEY_CUST_07 257
+#define KEY_CUST_08 258
+#define KEY_CUST_09 259
+#define KEY_CUST_10 260
+#define KEY_CUST_11 261
+#define KEY_CUST_12 262
+#define KEY_CUST_13 263
+#define KEY_CUST_14 264
+#define KEY_CUST_15 265
+#endif
+
+#ifdef HX_ESD_WORKAROUND
+ extern u8 HX_ESD_RESET_ACTIVATE;
+#endif
+
+extern int irq_enable_count;
+
+#ifdef QCT
+irqreturn_t himax_ts_thread(int irq, void *ptr);
+int himax_input_register(struct himax_ts_data *ts);
+#endif
+
+extern int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id);
+extern int himax_chip_common_remove(struct i2c_client *client);
+extern int himax_chip_common_suspend(struct himax_ts_data *ts);
+extern int himax_chip_common_resume(struct himax_ts_data *ts);
+int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata);
+
+#ifdef HX_USB_DETECT2
+//extern kal_bool upmu_is_chr_det(void);
+void himax_cable_detect_func(void);
+#endif
+
+#endif
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c
new file mode 100644
index 000000000000..f8bee11b4351
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.c
@@ -0,0 +1,2329 @@
+/* Himax Android Driver Sample Code for Himax chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_debug.h"
+#include "himax_ic.h"
+
+//struct himax_debug_data* debug_data;
+
+extern struct himax_ic_data* ic_data;
+extern struct himax_ts_data *private_ts;
+extern unsigned char IC_TYPE;
+extern unsigned char IC_CHECKSUM;
+extern int himax_input_register(struct himax_ts_data *ts);
+#ifdef QCT
+extern irqreturn_t himax_ts_thread(int irq, void *ptr);
+#endif
+#ifdef MTK
+#ifdef CONFIG_OF_TOUCH
+extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc);
+#else
+extern void tpd_eint_interrupt_handler(void);
+#endif
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+#ifdef HX_TP_PROC_2T2R
+int HX_RX_NUM_2 = 0;
+int HX_TX_NUM_2 = 0;
+#endif
+int touch_monitor_stop_flag = 0;
+int touch_monitor_stop_limit = 5;
+uint8_t g_diag_arr_num = 0;
+#endif
+
+#ifdef HX_ESD_WORKAROUND
+u8 HX_ESD_RESET_ACTIVATE;
+#endif
+
+#ifdef HX_SMART_WAKEUP
+bool FAKE_POWER_KEY_SEND;
+#endif
+
+//=============================================================================================================
+//
+// Segment : Himax PROC Debug Function
+//
+//=============================================================================================================
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+
+static ssize_t himax_vendor_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ ssize_t ret = 0;
+ char *temp_buf;
+
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+
+ ret += snprintf(temp_buf, len, "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", HIMAX_common_NAME,
+ ic_data->vendor_fw_ver, ic_data->vendor_config_ver, ic_data->vendor_sensor_id);
+ HX_PROC_SEND_FLAG=1;
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+
+ return ret;
+}
+
+static const struct file_operations himax_proc_vendor_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_vendor_read,
+};
+
+static ssize_t himax_attn_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ ssize_t ret = 0;
+ struct himax_ts_data *ts_data;
+ char *temp_buf;
+
+ ts_data = private_ts;
+
+ if (!HX_PROC_SEND_FLAG) {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ ret += snprintf(temp_buf, len, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq));
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+
+ return ret;
+}
+
+
+static const struct file_operations himax_proc_attn_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_attn_read,
+};
+
+static ssize_t himax_int_en_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ size_t ret = 0;
+ char *temp_buf;
+
+ if (!HX_PROC_SEND_FLAG) {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ ret += snprintf(temp_buf, len, "%d ", ts->irq_enabled);
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+}
+
+static ssize_t himax_int_en_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ char buf_tmp[12]= {0};
+ int value, ret=0;
+
+ if (len >= 12)
+ {
+ I("%s: no command exceeds 12 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf_tmp, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ if (buf_tmp[0] == '0')
+ value = false;
+ else if (buf_tmp[0] == '1')
+ value = true;
+ else
+ return -EINVAL;
+
+ if (value) {
+ if(ic_data->HX_INT_IS_EDGE)
+ {
+#ifdef MTK
+#ifdef CONFIG_OF_TOUCH
+ himax_int_enable(ts->client->irq,1);
+#else
+ //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
+ //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
+ mt_eint_registration(ts->client->irq, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);
+#endif
+#endif
+#ifdef QCT
+ ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->client->name, ts);
+#endif
+ }
+ else
+ {
+#ifdef MTK
+#ifdef CONFIG_OF_TOUCH
+ himax_int_enable(ts->client->irq,1);
+#else
+ //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
+ //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
+ mt_eint_registration(ts->client->irq, EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1);
+#endif
+#endif
+#ifdef QCT
+ ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts);
+#endif
+ }
+ if (ret == 0) {
+ ts->irq_enabled = 1;
+ irq_enable_count = 1;
+ }
+ } else {
+ himax_int_enable(ts->client->irq,0);
+ free_irq(ts->client->irq, ts);
+ ts->irq_enabled = 0;
+ }
+
+ return len;
+}
+
+static const struct file_operations himax_proc_int_en_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_int_en_read,
+ .write = himax_int_en_write,
+};
+
+static ssize_t himax_layout_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ size_t ret = 0;
+ char *temp_buf;
+
+ if (!HX_PROC_SEND_FLAG) {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min);
+ ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_x_max);
+ ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_min);
+ ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_max);
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+
+ return ret;
+}
+
+static ssize_t himax_layout_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ char buf_tmp[5];
+ int i = 0, j = 0, k = 0, ret;
+ unsigned long value;
+ int layout[4] = {0};
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ for (i = 0; i < 20; i++) {
+ if (buf[i] == ',' || buf[i] == '\n') {
+ memset(buf_tmp, 0x0, sizeof(buf_tmp));
+ if (i - j <= 5)
+ memcpy(buf_tmp, buf + j, i - j);
+ else {
+ I("buffer size is over 5 char\n");
+ return len;
+ }
+ j = i + 1;
+ if (k < 4) {
+ ret = kstrtoul(buf_tmp, 10, &value);
+ layout[k++] = value;
+ }
+ }
+ }
+ if (k == 4) {
+ ts->pdata->abs_x_min=layout[0];
+ ts->pdata->abs_x_max=layout[1];
+ ts->pdata->abs_y_min=layout[2];
+ ts->pdata->abs_y_max=layout[3];
+ I("%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+ input_unregister_device(ts->input_dev);
+ himax_input_register(ts);
+ } else
+ I("ERR@%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+ return len;
+}
+
+static const struct file_operations himax_proc_layout_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_layout_read,
+ .write = himax_layout_write,
+};
+
+static ssize_t himax_debug_level_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts_data;
+ size_t ret = 0;
+ char *temp_buf;
+ ts_data = private_ts;
+
+ if (!HX_PROC_SEND_FLAG) {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ ret += snprintf(temp_buf, len, "%d\n", ts_data->debug_log_level);
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+
+ return ret;
+}
+
+static ssize_t himax_debug_level_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts;
+ char buf_tmp[11];
+ int i;
+ ts = private_ts;
+
+ if (len >= 12)
+ {
+ I("%s: no command exceeds 12 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf_tmp, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ ts->debug_log_level = 0;
+ for(i=0; i<len-1; i++)
+ {
+ if( buf_tmp[i]>='0' && buf_tmp[i]<='9' )
+ ts->debug_log_level |= (buf_tmp[i]-'0');
+ else if( buf_tmp[i]>='A' && buf_tmp[i]<='F' )
+ ts->debug_log_level |= (buf_tmp[i]-'A'+10);
+ else if( buf_tmp[i]>='a' && buf_tmp[i]<='f' )
+ ts->debug_log_level |= (buf_tmp[i]-'a'+10);
+
+ if(i!=len-2)
+ ts->debug_log_level <<= 4;
+ }
+
+ if (ts->debug_log_level & BIT(3)) {
+ if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 &&
+ (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 &&
+ (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) {
+ ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS)/(ts->pdata->abs_x_max - ts->pdata->abs_x_min);
+ ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS)/(ts->pdata->abs_y_max - ts->pdata->abs_y_min);
+ if (ts->widthFactor > 0 && ts->heightFactor > 0)
+ ts->useScreenRes = 1;
+ else {
+ ts->heightFactor = 0;
+ ts->widthFactor = 0;
+ ts->useScreenRes = 0;
+ }
+ } else
+ I("Enable finger debug with raw position mode!\n");
+ } else {
+ ts->useScreenRes = 0;
+ ts->widthFactor = 0;
+ ts->heightFactor = 0;
+ }
+
+ return len;
+}
+
+static const struct file_operations himax_proc_debug_level_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_debug_level_read,
+ .write = himax_debug_level_write,
+};
+
+#ifdef HX_TP_PROC_REGISTER
+static ssize_t himax_proc_register_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ int ret = 0;
+ uint16_t loop_i;
+ uint8_t data[128];
+ char *temp_buf;
+
+ memset(data, 0x00, sizeof(data));
+
+ I("himax_register_show: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ himax_register_read(private_ts->client, register_command, 1, data);
+
+ ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+
+ for (loop_i = 0; loop_i < 128; loop_i++) {
+ ret += snprintf(temp_buf+ret, len-ret, "0x%2.2X ", data[loop_i]);
+ if ((loop_i % 16) == 15)
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+ }
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+ HX_PROC_SEND_FLAG=1;
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+}
+
+static ssize_t himax_proc_register_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ char buf_tmp[16], length = 0;
+ unsigned long result = 0;
+ uint8_t loop_i = 0;
+ uint16_t base = 5;
+ uint8_t write_da[128];
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ memset(buf_tmp, 0x0, sizeof(buf_tmp));
+ memset(write_da, 0x0, sizeof(write_da));
+
+ I("himax %s \n",buf);
+
+ if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':') {
+
+ if (buf[2] == 'x') {
+ memcpy(buf_tmp, buf + 3, 8);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ register_command[0] = (uint8_t)result;
+ register_command[1] = (uint8_t)(result >> 8);
+ register_command[2] = (uint8_t)(result >> 16);
+ register_command[3] = (uint8_t)(result >> 24);
+ }
+ base = 11;
+ I("CMD: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+
+ for (loop_i = 0; loop_i < 128 && (base+10)<80; loop_i++) {
+ if (buf[base] == '\n') {
+ if (buf[0] == 'w') {
+ himax_register_write(private_ts->client, register_command, 1, write_da);
+ I("CMD: %x, %x, %x, %x, len=%d\n", write_da[0], write_da[1],write_da[2],write_da[3],length);
+ }
+ I("\n");
+ return len;
+ }
+ if (buf[base + 1] == 'x') {
+ buf_tmp[10] = '\n';
+ buf_tmp[11] = '\0';
+ memcpy(buf_tmp, buf + base + 2, 8);
+ if (!kstrtoul(buf_tmp, 16, &result)) {
+ write_da[loop_i] = (uint8_t)result;
+ write_da[loop_i+1] = (uint8_t)(result >> 8);
+ write_da[loop_i+2] = (uint8_t)(result >> 16);
+ write_da[loop_i+3] = (uint8_t)(result >> 24);
+ }
+ length+=4;
+ }
+ base += 10;
+ }
+ }
+ }
+ return len;
+}
+
+static const struct file_operations himax_proc_register_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_proc_register_read,
+ .write = himax_proc_register_write,
+};
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+int16_t *getMutualBuffer(void)
+{
+ return diag_mutual;
+}
+int16_t *getMutualNewBuffer(void)
+{
+ return diag_mutual_new;
+}
+int16_t *getMutualOldBuffer(void)
+{
+ return diag_mutual_old;
+}
+int16_t *getSelfBuffer(void)
+{
+ return &diag_self[0];
+}
+uint8_t getXChannel(void)
+{
+ return x_channel;
+}
+uint8_t getYChannel(void)
+{
+ return y_channel;
+}
+uint8_t getDiagCommand(void)
+{
+ return diag_command;
+}
+void setXChannel(uint8_t x)
+{
+ x_channel = x;
+}
+void setYChannel(uint8_t y)
+{
+ y_channel = y;
+}
+void setMutualBuffer(void)
+{
+ diag_mutual = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+}
+void setMutualNewBuffer(void)
+{
+ diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+}
+void setMutualOldBuffer(void)
+{
+ diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+}
+
+#ifdef HX_TP_PROC_2T2R
+int16_t *getMutualBuffer_2(void)
+{
+ return diag_mutual_2;
+}
+uint8_t getXChannel_2(void)
+{
+ return x_channel_2;
+}
+uint8_t getYChannel_2(void)
+{
+ return y_channel_2;
+}
+void setXChannel_2(uint8_t x)
+{
+ x_channel_2 = x;
+}
+void setYChannel_2(uint8_t y)
+{
+ y_channel_2 = y;
+}
+void setMutualBuffer_2(void)
+{
+ diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL);
+}
+#endif
+
+static ssize_t himax_diag_arrange_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ //struct himax_ts_data *ts = private_ts;
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ g_diag_arr_num = buf[0] - '0';
+ I("%s: g_diag_arr_num = %d \n", __func__,g_diag_arr_num);
+
+ return len;
+}
+
+static const struct file_operations himax_proc_diag_arrange_ops =
+{
+ .owner = THIS_MODULE,
+ .write = himax_diag_arrange_write,
+};
+
+static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose)
+{
+ if(transpose)
+ seq_printf(s, "%6d", diag_mutual[ j + i*x_channel]);
+ else
+ seq_printf(s, "%6d", diag_mutual[ i + j*x_channel]);
+}
+
+static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,bool transpose, int j)
+{
+ int i;
+ int in_max = 0;
+
+ if(transpose)
+ in_max = y_channel;
+ else
+ in_max = x_channel;
+
+ if (in_init > 0)
+ {
+ for(i = in_init-1;i >= 0;i--)
+ {
+ himax_diag_arrange_print(s, i, j, transpose);
+ }
+ }
+ else
+ {
+ for (i = 0; i < in_max; i++)
+ {
+ himax_diag_arrange_print(s, i, j, transpose);
+ }
+ }
+}
+
+static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init)
+{
+ int j;
+ int out_max = 0;
+
+ if(transpose)
+ out_max = x_channel;
+ else
+ out_max = y_channel;
+
+ if(out_init > 0)
+ {
+ for(j = out_init-1;j >= 0;j--)
+ {
+ himax_diag_arrange_inloop(s, in_init, transpose, j);
+ seq_printf(s, " %5d\n", diag_self[j]);
+ }
+ }
+ else
+ {
+ for(j = 0;j < out_max;j++)
+ {
+ himax_diag_arrange_inloop(s, in_init, transpose, j);
+ seq_printf(s, " %5d\n", diag_self[j]);
+ }
+ }
+}
+
+static void himax_diag_arrange(struct seq_file *s)
+{
+ int bit2,bit1,bit0;
+ int i;
+
+ bit2 = g_diag_arr_num >> 2;
+ bit1 = g_diag_arr_num >> 1 & 0x1;
+ bit0 = g_diag_arr_num & 0x1;
+
+ if (g_diag_arr_num < 4)
+ {
+ himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel);
+ for (i = y_channel; i < x_channel + y_channel; i++) {
+ seq_printf(s, "%6d", diag_self[i]);
+ }
+ }
+ else
+ {
+ himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel);
+ for (i = x_channel; i < x_channel + y_channel; i++) {
+ seq_printf(s, "%6d", diag_self[i]);
+ }
+ }
+}
+
+static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos)
+{
+ if (*pos>=1) return NULL;
+ return (void *)((unsigned long) *pos+1);
+}
+
+static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ return NULL;
+}
+static void himax_diag_seq_stop(struct seq_file *s, void *v)
+{
+}
+static int himax_diag_seq_read(struct seq_file *s, void *v)
+{
+ size_t count = 0;
+ int32_t loop_i;//,loop_j
+ uint16_t mutual_num, self_num, width;
+
+#ifdef HX_TP_PROC_2T2R
+ if(Is_2T2R && diag_command == 4)
+ {
+ mutual_num = x_channel_2 * y_channel_2;
+ self_num = x_channel_2 + y_channel_2; //don't add KEY_COUNT
+ width = x_channel_2;
+ seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2);
+ }
+ else
+#endif
+ {
+ mutual_num = x_channel * y_channel;
+ self_num = x_channel + y_channel; //don't add KEY_COUNT
+ width = x_channel;
+ seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel);
+ }
+
+ // start to show out the raw data in adb shell
+ if (diag_command >= 1 && diag_command <= 6) {
+ if (diag_command <= 3) {
+ himax_diag_arrange(s);
+ seq_printf(s, "\n\n");
+#ifdef HX_EN_SEL_BUTTON
+ seq_printf(s, "\n");
+ for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
+ seq_printf(s, "%6d", diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]);
+#endif
+#ifdef HX_TP_PROC_2T2R
+ }else if(Is_2T2R && diag_command == 4 ) {
+ for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+ seq_printf(s, "%4d", diag_mutual_2[loop_i]);
+ if ((loop_i % width) == (width - 1))
+ seq_printf(s, " %6d\n", diag_self[width + loop_i/width]);
+ }
+ seq_printf(s, "\n");
+ for (loop_i = 0; loop_i < width; loop_i++) {
+ seq_printf(s, "%6d", diag_self[loop_i]);
+ if (((loop_i) % width) == (width - 1))
+ seq_printf(s, "\n");
+ }
+#ifdef HX_EN_SEL_BUTTON
+ seq_printf(s, "\n");
+ for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
+ seq_printf(s, "%4d", diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]);
+#endif
+#endif
+ } else if (diag_command > 4) {
+ for (loop_i = 0; loop_i < self_num; loop_i++) {
+ seq_printf(s, "%4d", diag_self[loop_i]);
+ if (((loop_i - mutual_num) % width) == (width - 1))
+ seq_printf(s, "\n");
+ }
+ } else {
+ for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+ seq_printf(s, "%4d", diag_mutual[loop_i]);
+ if ((loop_i % width) == (width - 1))
+ seq_printf(s, "\n");
+ }
+ }
+ seq_printf(s, "ChannelEnd");
+ seq_printf(s, "\n");
+ } else if (diag_command == 7) {
+ for (loop_i = 0; loop_i < 128 ;loop_i++) {
+ if ((loop_i % 16) == 0)
+ seq_printf(s, "LineStart:");
+ seq_printf(s, "%4d", diag_coor[loop_i]);
+ if ((loop_i % 16) == 15)
+ seq_printf(s, "\n");
+ }
+ } else if (diag_command == 9 || diag_command == 91 || diag_command == 92){
+ himax_diag_arrange(s);
+ seq_printf(s, "\n");
+ }
+
+ return count;
+}
+static const struct seq_operations himax_diag_seq_ops =
+{
+ .start = himax_diag_seq_start,
+ .next = himax_diag_seq_next,
+ .stop = himax_diag_seq_stop,
+ .show = himax_diag_seq_read,
+};
+static int himax_diag_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &himax_diag_seq_ops);
+};
+bool DSRAM_Flag;
+
+//DSRAM thread
+void himax_ts_diag_func(void)
+{
+ int i=0, j=0;
+ unsigned int index = 0;
+ int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
+ uint8_t info_data[total_size];
+ int16_t *mutual_data = NULL;
+ int16_t *mutual_data_new = NULL;
+ int16_t *mutual_data_old = NULL;
+ int16_t new_data;
+
+ himax_burst_enable(private_ts->client, 1);
+ if(diag_command == 9 || diag_command == 91)
+ {
+ mutual_data = getMutualBuffer();
+ }else if(diag_command == 92){
+ mutual_data = getMutualBuffer();
+ mutual_data_new = getMutualNewBuffer();
+ mutual_data_old = getMutualOldBuffer();
+ }
+ himax_get_DSRAM_data(private_ts->client, info_data);
+
+ index = 0;
+ for (i = 0; i < ic_data->HX_TX_NUM; i++)
+ {
+ for (j = 0; j < ic_data->HX_RX_NUM; j++)
+ {
+ new_data = (short)(info_data[index + 1] << 8 | info_data[index]);
+ if(diag_command == 9){
+ mutual_data[i*ic_data->HX_RX_NUM+j] = new_data;
+ }else if(diag_command == 91){ //Keep max data for 100 frame
+ if(mutual_data[i * ic_data->HX_RX_NUM + j] < new_data)
+ mutual_data[i * ic_data->HX_RX_NUM + j] = new_data;
+ }else if(diag_command == 92){ //Cal data for [N]-[N-1] frame
+ mutual_data_new[i * ic_data->HX_RX_NUM + j] = new_data;
+ mutual_data[i * ic_data->HX_RX_NUM + j] = mutual_data_new[i * ic_data->HX_RX_NUM + j] - mutual_data_old[i * ic_data->HX_RX_NUM + j];
+ }
+ index += 2;
+ }
+ }
+ if(diag_command == 92){
+ memcpy(mutual_data_old,mutual_data_new,x_channel * y_channel * sizeof(int16_t)); //copy N data to N-1 array
+ }
+ diag_max_cnt++;
+ if(diag_command == 9 || diag_command == 92){
+ queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
+ }else if(diag_command == 91){
+ if(diag_max_cnt > 100) //count for 100 frame
+ {
+ //Clear DSRAM flag
+ DSRAM_Flag = false;
+
+ //Enable ISR
+ himax_int_enable(private_ts->client->irq,1);
+
+ //=====================================
+ // test result command : 0x8002_0324 ==> 0x00
+ //=====================================
+ himax_diag_register_set(private_ts->client, 0x00);
+ }else{
+ queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
+ }
+ }
+}
+
+static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
+{
+ char messages[80] = {0};
+
+ uint8_t command[2] = {0x00, 0x00};
+ uint8_t receive[1];
+
+ memset(receive, 0x00, sizeof(receive));
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(messages, buff, len))
+ {
+ return -EFAULT;
+ }
+ if (messages[1] == 0x0A){
+ diag_command =messages[0] - '0';
+ }else{
+ diag_command =(messages[0] - '0')*10 + (messages[1] - '0');
+ }
+
+ I("[Himax]diag_command=0x%x\n",diag_command);
+ if (diag_command < 0x04){
+ if(DSRAM_Flag)
+ {
+ //1. Clear DSRAM flag
+ DSRAM_Flag = false;
+
+ //2. Stop DSRAM thread
+ cancel_delayed_work_sync(&private_ts->himax_diag_delay_wrok);
+
+ //3. Enable ISR
+ himax_int_enable(private_ts->client->irq,1);
+ }
+ command[0] = diag_command;
+ himax_diag_register_set(private_ts->client, command[0]);
+ }
+ //coordinate dump start
+ else if (diag_command == 0x08) {
+ E("%s: coordinate_dump_file_create error\n", __func__);
+ }
+ else if (diag_command == 0x09 || diag_command == 91 || diag_command == 92){
+ diag_max_cnt = 0;
+ memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int16_t)); //Set data 0 everytime
+
+ //1. Disable ISR
+ himax_int_enable(private_ts->client->irq,0);
+
+ //2. Start DSRAM thread
+ //himax_diag_register_set(private_ts->client, 0x0A);
+
+ queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2*HZ/100);
+
+ I("%s: Start get raw data in DSRAM\n", __func__);
+
+ //3. Set DSRAM flag
+ DSRAM_Flag = true;
+ }else{
+ command[0] = 0x00;
+ himax_diag_register_set(private_ts->client, command[0]);
+ E("[Himax]Diag command error!diag_command=0x%x\n",diag_command);
+ }
+ return len;
+}
+
+static const struct file_operations himax_proc_diag_ops =
+{
+ .owner = THIS_MODULE,
+ .open = himax_diag_proc_open,
+ .read = seq_read,
+ .write = himax_diag_write,
+};
+#endif
+
+#ifdef HX_TP_PROC_RESET
+static ssize_t himax_reset_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ char buf_tmp[12];
+
+ if (len >= 12)
+ {
+ I("%s: no command exceeds 12 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf_tmp, buff, len))
+ {
+ return -EFAULT;
+ }
+ //if (buf_tmp[0] == '1')
+ // ESD_HW_REST();
+
+ return len;
+}
+
+static const struct file_operations himax_proc_reset_ops =
+{
+ .owner = THIS_MODULE,
+ .write = himax_reset_write,
+};
+#endif
+
+#ifdef HX_TP_PROC_DEBUG
+static ssize_t himax_debug_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ size_t count = 0;
+ char *temp_buf;
+
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf){
+ HX_PROC_SEND_FLAG=0;
+ return count;
+ }
+
+ if (debug_level_cmd == 't')
+ {
+ if (fw_update_complete)
+ count += snprintf(temp_buf+count, len-count, "FW Update Complete ");
+ else
+ {
+ count += snprintf(temp_buf+count, len-count, "FW Update Fail ");
+ }
+ }
+ else if (debug_level_cmd == 'h')
+ {
+ if (handshaking_result == 0)
+ {
+ count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Running)\n", handshaking_result);
+ }
+ else if (handshaking_result == 1)
+ {
+ count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Stop)\n", handshaking_result);
+ }
+ else if (handshaking_result == 2)
+ {
+ count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (I2C Error)\n", handshaking_result);
+ }
+ else
+ {
+ count += snprintf(temp_buf+count, len-count, "Handshaking Result = error\n");
+ }
+ }
+ else if (debug_level_cmd == 'v')
+ {
+ count += snprintf(temp_buf+count, len-count, "FW_VER = ");
+ count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_fw_ver);
+ count += snprintf(temp_buf+count, len-count, "CONFIG_VER = ");
+ count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_config_ver);
+ count += snprintf(temp_buf+count, len-count, "\n");
+ }
+ else if (debug_level_cmd == 'd')
+ {
+ count += snprintf(temp_buf+count, len-count, "Himax Touch IC Information :\n");
+ if (IC_TYPE == HX_85XX_D_SERIES_PWON)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Type : D\n");
+ }
+ else if (IC_TYPE == HX_85XX_E_SERIES_PWON)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Type : E\n");
+ }
+ else if (IC_TYPE == HX_85XX_ES_SERIES_PWON)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Type : ES\n");
+ }
+ else if (IC_TYPE == HX_85XX_F_SERIES_PWON)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Type : F\n");
+ }
+ else
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Type error.\n");
+ }
+
+ if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Checksum : SW\n");
+ }
+ else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Checksum : HW\n");
+ }
+ else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC)
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Checksum : CRC\n");
+ }
+ else
+ {
+ count += snprintf(temp_buf+count, len-count, "IC Checksum error.\n");
+ }
+
+ if (ic_data->HX_INT_IS_EDGE)
+ {
+ count += snprintf(temp_buf+count, len-count, "Interrupt : EDGE TIRGGER\n");
+ }
+ else
+ {
+ count += snprintf(temp_buf+count, len-count, "Interrupt : LEVEL TRIGGER\n");
+ }
+
+ count += snprintf(temp_buf+count, len-count, "RX Num : %d\n", ic_data->HX_RX_NUM);
+ count += snprintf(temp_buf+count, len-count, "TX Num : %d\n", ic_data->HX_TX_NUM);
+ count += snprintf(temp_buf+count, len-count, "BT Num : %d\n", ic_data->HX_BT_NUM);
+ count += snprintf(temp_buf+count, len-count, "X Resolution : %d\n", ic_data->HX_X_RES);
+ count += snprintf(temp_buf+count, len-count, "Y Resolution : %d\n", ic_data->HX_Y_RES);
+ count += snprintf(temp_buf+count, len-count, "Max Point : %d\n", ic_data->HX_MAX_PT);
+ count += snprintf(temp_buf+count, len-count, "XY reverse : %d\n", ic_data->HX_XY_REVERSE);
+ #ifdef HX_TP_PROC_2T2R
+ if(Is_2T2R)
+ {
+ count += snprintf(temp_buf+count, len-count, "2T2R panel\n");
+ count += snprintf(temp_buf+count, len-count, "RX Num_2 : %d\n", HX_RX_NUM_2);
+ count += snprintf(temp_buf+count, len-count, "TX Num_2 : %d\n", HX_TX_NUM_2);
+ }
+ #endif
+ }
+ else if (debug_level_cmd == 'i')
+ {
+ count += snprintf(temp_buf+count, len-count, "Himax Touch Driver Version:\n");
+ count += snprintf(temp_buf+count, len-count, "%s\n", HIMAX_DRIVER_VER);
+ }
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG=1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return count;
+}
+
+static ssize_t himax_debug_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ const struct firmware *fw = NULL;
+ unsigned char *fw_data = NULL;
+ char fileName[128];
+ char buf[80] = {0};
+ int result;
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ if ( buf[0] == 'h') //handshaking
+ {
+ debug_level_cmd = buf[0];
+
+ himax_int_enable(private_ts->client->irq,0);
+
+ handshaking_result = himax_hand_shaking(private_ts->client); //0:Running, 1:Stop, 2:I2C Fail
+
+ himax_int_enable(private_ts->client->irq,1);
+
+ return len;
+ }
+
+ else if ( buf[0] == 'v') //firmware version
+ {
+ debug_level_cmd = buf[0];
+ himax_int_enable(private_ts->client->irq,0);
+#ifdef HX_RST_PIN_FUNC
+ himax_HW_reset(false,false);
+#endif
+ himax_read_FW_ver(private_ts->client);
+ //himax_check_chip_version();
+#ifdef HX_RST_PIN_FUNC
+ himax_HW_reset(true,false);
+#endif
+ himax_int_enable(private_ts->client->irq,1);
+ return len;
+ }
+
+ else if ( buf[0] == 'd') //ic information
+ {
+ debug_level_cmd = buf[0];
+ return len;
+ }
+
+ else if ( buf[0] == 'i') //driver version
+ {
+ debug_level_cmd = buf[0];
+ return len;
+ }
+
+ else if (buf[0] == 't')
+ {
+
+ himax_int_enable(private_ts->client->irq,0);
+
+ debug_level_cmd = buf[0];
+ fw_update_complete = false;
+
+ memset(fileName, 0, 128);
+ // parse the file name
+ snprintf(fileName, len-4, "%s", &buf[4]);
+ I("%s: upgrade from file(%s) start!\n", __func__, fileName);
+ // open file
+ result = request_firmware(&fw, fileName, private_ts->dev);
+ if (result) {
+ E("%s: open firmware file failed\n", __func__);
+ goto firmware_upgrade_done;
+ //return len;
+ }
+
+ I("%s: FW len %d\n", __func__, fw->size);
+ fw_data = (unsigned char *)fw->data;
+
+ I("%s: FW image,len %d: %02X, %02X, %02X, %02X\n", __func__, result, upgrade_fw[0], upgrade_fw[1], upgrade_fw[2], upgrade_fw[3]);
+
+ if (fw_data != NULL)
+ {
+ // start to upgrade
+ himax_int_enable(private_ts->client->irq,0);
+
+ if ((buf[1] == '6') && (buf[2] == '0'))
+ {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,upgrade_fw, result, false) == 0)
+ {
+ E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ fw_update_complete = false;
+ }
+ else
+ {
+ I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ fw_update_complete = true;
+ }
+ }
+ else if ((buf[1] == '6') && (buf[2] == '4'))
+ {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,upgrade_fw, result, false) == 0)
+ {
+ E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ fw_update_complete = false;
+ }
+ else
+ {
+ I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ fw_update_complete = true;
+ }
+ }
+ else if ((buf[1] == '2') && (buf[2] == '4'))
+ {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,upgrade_fw, result, false) == 0)
+ {
+ E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ fw_update_complete = false;
+ }
+ else
+ {
+ I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ fw_update_complete = true;
+ }
+ }
+ else if ((buf[1] == '2') && (buf[2] == '8'))
+ {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,upgrade_fw, result, false) == 0)
+ {
+ E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ fw_update_complete = false;
+ }
+ else
+ {
+ I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ fw_update_complete = true;
+ }
+ }
+ else
+ {
+ E("%s: Flash command fail: %d\n", __func__, __LINE__);
+ fw_update_complete = false;
+ }
+ release_firmware(fw);
+ goto firmware_upgrade_done;
+ //return count;
+ }
+ }
+
+ firmware_upgrade_done:
+
+#ifdef HX_RST_PIN_FUNC
+ himax_HW_reset(true,false);
+#endif
+
+ himax_sense_on(private_ts->client, 0x01);
+ msleep(120);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+ himax_int_enable(private_ts->client->irq,1);
+
+ //todo himax_chip->tp_firmware_upgrade_proceed = 0;
+ //todo himax_chip->suspend_state = 0;
+ //todo enable_irq(himax_chip->irq);
+ return len;
+}
+
+static const struct file_operations himax_proc_debug_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_debug_read,
+ .write = himax_debug_write,
+};
+
+#endif
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+
+static uint8_t getFlashCommand(void)
+{
+ return flash_command;
+}
+
+static uint8_t getFlashDumpProgress(void)
+{
+ return flash_progress;
+}
+
+static uint8_t getFlashDumpComplete(void)
+{
+ return flash_dump_complete;
+}
+
+static uint8_t getFlashDumpFail(void)
+{
+ return flash_dump_fail;
+}
+
+uint8_t getSysOperation(void)
+{
+ return sys_operation;
+}
+
+static uint8_t getFlashReadStep(void)
+{
+ return flash_read_step;
+}
+/*
+static uint8_t getFlashDumpSector(void)
+{
+ return flash_dump_sector;
+}
+
+static uint8_t getFlashDumpPage(void)
+{
+ return flash_dump_page;
+}
+*/
+bool getFlashDumpGoing(void)
+{
+ return flash_dump_going;
+}
+
+void setFlashBuffer(void)
+{
+ flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL);
+ if (flash_buffer)
+ memset(flash_buffer,0x00,Flash_Size);
+}
+
+void setSysOperation(uint8_t operation)
+{
+ sys_operation = operation;
+}
+
+static void setFlashDumpProgress(uint8_t progress)
+{
+ flash_progress = progress;
+ //I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress);
+}
+
+static void setFlashDumpComplete(uint8_t status)
+{
+ flash_dump_complete = status;
+}
+
+static void setFlashDumpFail(uint8_t fail)
+{
+ flash_dump_fail = fail;
+}
+
+static void setFlashCommand(uint8_t command)
+{
+ flash_command = command;
+}
+
+static void setFlashReadStep(uint8_t step)
+{
+ flash_read_step = step;
+}
+
+static void setFlashDumpSector(uint8_t sector)
+{
+ flash_dump_sector = sector;
+}
+
+static void setFlashDumpPage(uint8_t page)
+{
+ flash_dump_page = page;
+}
+
+static void setFlashDumpGoing(bool going)
+{
+ flash_dump_going = going;
+}
+
+static ssize_t himax_proc_flash_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ int ret = 0;
+ int loop_i;
+ uint8_t local_flash_read_step=0;
+ uint8_t local_flash_complete = 0;
+ uint8_t local_flash_progress = 0;
+ uint8_t local_flash_command = 0;
+ uint8_t local_flash_fail = 0;
+ char *temp_buf;
+ local_flash_complete = getFlashDumpComplete();
+ local_flash_progress = getFlashDumpProgress();
+ local_flash_command = getFlashCommand();
+ local_flash_fail = getFlashDumpFail();
+
+ I("flash_progress = %d \n",local_flash_progress);
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+
+ if (local_flash_fail)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Fail \n");
+ ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ return ret;
+ }
+
+ if (!local_flash_complete)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Ongoing:0x%2.2x \n",flash_progress);
+ ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ return ret;
+ }
+
+ if (local_flash_command == 1 && local_flash_complete)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Complete \n");
+ ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ return ret;
+ }
+
+ if (local_flash_command == 3 && local_flash_complete)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "FlashStart: \n");
+ for(loop_i = 0; loop_i < 128; loop_i++)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "x%2.2x", flash_buffer[loop_i]);
+ if ((loop_i % 16) == 15)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+ }
+ }
+ ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ return ret;
+ }
+
+ //flash command == 0 , report the data
+ local_flash_read_step = getFlashReadStep();
+
+ ret += snprintf(temp_buf+ret, len-ret, "FlashStart:%2.2x \n",local_flash_read_step);
+
+ for (loop_i = 0; loop_i < 1024; loop_i++)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "x%2.2X", flash_buffer[local_flash_read_step*1024 + loop_i]);
+
+ if ((loop_i % 16) == 15)
+ {
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+ }
+ }
+
+ ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
+ ret += snprintf(temp_buf+ret, len-ret, "\n");
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+}
+
+static ssize_t himax_proc_flash_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ char buf_tmp[6];
+ unsigned long result = 0;
+ uint8_t loop_i = 0;
+ int base = 0;
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+ memset(buf_tmp, 0x0, sizeof(buf_tmp));
+
+ I("%s: buf[0] = %s\n", __func__, buf);
+
+ if (getSysOperation() == 1)
+ {
+ E("%s: PROC is busy , return!\n", __func__);
+ return len;
+ }
+
+ if (buf[0] == '0')
+ {
+ setFlashCommand(0);
+ if (buf[1] == ':' && buf[2] == 'x')
+ {
+ memcpy(buf_tmp, buf + 3, 2);
+ I("%s: read_Step = %s\n", __func__, buf_tmp);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ I("%s: read_Step = %lu \n", __func__, result);
+ setFlashReadStep(result);
+ }
+ }
+ }
+ else if (buf[0] == '1')// 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k
+ {
+ setSysOperation(1);
+ setFlashCommand(1);
+ setFlashDumpProgress(0);
+ setFlashDumpComplete(0);
+ setFlashDumpFail(0);
+ if ((buf[1] == '_' ) && (buf[2] == '6' )){
+ if (buf[3] == '0'){
+ Flash_Size = FW_SIZE_60k;
+ }else if (buf[3] == '4'){
+ Flash_Size = FW_SIZE_64k;
+ }
+ }else if ((buf[1] == '_' ) && (buf[2] == '2' )){
+ if (buf[3] == '4'){
+ Flash_Size = FW_SIZE_124k;
+ }else if (buf[3] == '8'){
+ Flash_Size = FW_SIZE_128k;
+ }
+ }
+ queue_work(private_ts->flash_wq, &private_ts->flash_work);
+ }
+ else if (buf[0] == '2') // 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k
+ {
+ setSysOperation(1);
+ setFlashCommand(2);
+ setFlashDumpProgress(0);
+ setFlashDumpComplete(0);
+ setFlashDumpFail(0);
+ if ((buf[1] == '_' ) && (buf[2] == '6' )){
+ if (buf[3] == '0'){
+ Flash_Size = FW_SIZE_60k;
+ }else if (buf[3] == '4'){
+ Flash_Size = FW_SIZE_64k;
+ }
+ }else if ((buf[1] == '_' ) && (buf[2] == '2' )){
+ if (buf[3] == '4'){
+ Flash_Size = FW_SIZE_124k;
+ }else if (buf[3] == '8'){
+ Flash_Size = FW_SIZE_128k;
+ }
+ }
+ queue_work(private_ts->flash_wq, &private_ts->flash_work);
+ }
+ else if (buf[0] == '3')
+ {
+ setSysOperation(1);
+ setFlashCommand(3);
+ setFlashDumpProgress(0);
+ setFlashDumpComplete(0);
+ setFlashDumpFail(0);
+
+ memcpy(buf_tmp, buf + 3, 2);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ setFlashDumpSector(result);
+ }
+
+ memcpy(buf_tmp, buf + 7, 2);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ setFlashDumpPage(result);
+ }
+
+ queue_work(private_ts->flash_wq, &private_ts->flash_work);
+ }
+ else if (buf[0] == '4')
+ {
+ I("%s: command 4 enter.\n", __func__);
+ setSysOperation(1);
+ setFlashCommand(4);
+ setFlashDumpProgress(0);
+ setFlashDumpComplete(0);
+ setFlashDumpFail(0);
+
+ memcpy(buf_tmp, buf + 3, 2);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ setFlashDumpSector(result);
+ }
+ else
+ {
+ E("%s: command 4 , sector error.\n", __func__);
+ return len;
+ }
+
+ memcpy(buf_tmp, buf + 7, 2);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ setFlashDumpPage(result);
+ }
+ else
+ {
+ E("%s: command 4 , page error.\n", __func__);
+ return len;
+ }
+
+ base = 11;
+
+ I("=========Himax flash page buffer start=========\n");
+ for(loop_i=0;loop_i<128 && base<80;loop_i++)
+ {
+ memcpy(buf_tmp, buf + base, 2);
+ if (!kstrtoul(buf_tmp, 16, &result))
+ {
+ flash_buffer[loop_i] = result;
+ I("%d ",flash_buffer[loop_i]);
+ if (loop_i % 16 == 15)
+ {
+ I("\n");
+ }
+ }
+ base += 3;
+ }
+ I("=========Himax flash page buffer end=========\n");
+
+ queue_work(private_ts->flash_wq, &private_ts->flash_work);
+ }
+ return len;
+}
+
+static const struct file_operations himax_proc_flash_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_proc_flash_read,
+ .write = himax_proc_flash_write,
+};
+
+void himax_ts_flash_func(void)
+{
+ uint8_t local_flash_command = 0;
+
+ himax_int_enable(private_ts->client->irq,0);
+ setFlashDumpGoing(true);
+
+ //sector = getFlashDumpSector();
+ //page = getFlashDumpPage();
+
+ local_flash_command = getFlashCommand();
+
+ msleep(100);
+
+ I("%s: local_flash_command = %d enter.\n", __func__,local_flash_command);
+
+ if ((local_flash_command == 1 || local_flash_command == 2)|| (local_flash_command==0x0F))
+ {
+ himax_flash_dump_func(private_ts->client, local_flash_command,Flash_Size, flash_buffer);
+ }
+
+ I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n");
+
+ if (local_flash_command == 2)
+ {
+ E("Flash dump failed\n");
+ }
+
+ himax_int_enable(private_ts->client->irq,1);
+ setFlashDumpGoing(false);
+
+ setFlashDumpComplete(1);
+ setSysOperation(0);
+ return;
+
+/* Flash_Dump_i2c_transfer_error:
+
+ himax_int_enable(private_ts->client->irq,1);
+ setFlashDumpGoing(false);
+ setFlashDumpComplete(0);
+ setFlashDumpFail(1);
+ setSysOperation(0);
+ return;
+*/
+}
+
+#endif
+
+#ifdef HX_TP_PROC_SELF_TEST
+static ssize_t himax_self_test_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ int val=0x00;
+ int ret = 0;
+ char *temp_buf;
+
+ I("%s: enter, %d \n", __func__, __LINE__);
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ himax_int_enable(private_ts->client->irq,0);//disable irq
+ val = himax_chip_self_test(private_ts->client);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+ himax_int_enable(private_ts->client->irq,1);//enable irq
+
+ if (val == 0x01) {
+ ret += snprintf(temp_buf+ret, len-ret, "Self_Test Pass\n");
+ } else {
+ ret += snprintf(temp_buf+ret, len-ret, "Self_Test Fail\n");
+ }
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+}
+
+/*
+static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
+{
+ char buf_tmp[2];
+ unsigned long result = 0;
+
+ memset(buf_tmp, 0x0, sizeof(buf_tmp));
+ memcpy(buf_tmp, buf, 2);
+ if(!kstrtoul(buf_tmp, 16, &result))
+ {
+ sel_type = (uint8_t)result;
+ }
+ I("sel_type = %x \r\n", sel_type);
+ return count;
+}
+*/
+
+static const struct file_operations himax_proc_self_test_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_self_test_read,
+};
+#endif
+
+#ifdef HX_TP_PROC_SENSE_ON_OFF
+static ssize_t himax_sense_on_off_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ if(buf[0] == '0')
+ {
+ himax_sense_off(private_ts->client);
+ I("Sense off \n");
+ }
+ else if(buf[0] == '1')
+ {
+ if(buf[1] == '1'){
+ himax_sense_on(private_ts->client, 0x01);
+ I("Sense on re-map off, run flash \n");
+ }else if(buf[1] == '0'){
+ himax_sense_on(private_ts->client, 0x00);
+ I("Sense on re-map on, run sram \n");
+ }else{
+ I("Do nothing \n");
+ }
+ }
+ else
+ {
+ I("Do nothing \n");
+ }
+ return len;
+}
+
+static const struct file_operations himax_proc_sense_on_off_ops =
+{
+ .owner = THIS_MODULE,
+ .write = himax_sense_on_off_write,
+};
+#endif
+
+#ifdef HX_HIGH_SENSE
+static ssize_t himax_HSEN_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ size_t count = 0;
+ char *temp_buf;
+
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return count;
+ }
+ count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable);
+ HX_PROC_SEND_FLAG=1;
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+ return count;
+}
+
+static ssize_t himax_HSEN_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ char buf[80] = {0};
+
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ if (buf[0] == '0'){
+ ts->HSEN_enable = 0;
+ }
+ else if (buf[0] == '1'){
+ ts->HSEN_enable = 1;
+ }
+ else
+ return -EINVAL;
+
+ himax_set_HSEN_func(ts->client, ts->HSEN_enable);
+
+ I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable);
+
+ return len;
+}
+
+static const struct file_operations himax_proc_HSEN_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_HSEN_read,
+ .write = himax_HSEN_write,
+};
+#endif
+
+#ifdef HX_SMART_WAKEUP
+static ssize_t himax_SMWP_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ size_t count = 0;
+ struct himax_ts_data *ts = private_ts;
+ char *temp_buf;
+
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return count;
+ }
+ count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable);
+
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG=1;
+ }
+ else
+ HX_PROC_SEND_FLAG=0;
+
+ return count;
+}
+
+static ssize_t himax_SMWP_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+
+ if (buf[0] == '0')
+ {
+ ts->SMWP_enable = 0;
+ }
+ else if (buf[0] == '1')
+ {
+ ts->SMWP_enable = 1;
+ }
+ else
+ return -EINVAL;
+
+ himax_set_SMWP_func(ts->client, ts->SMWP_enable);
+ HX_SMWP_EN = ts->SMWP_enable;
+ I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN);
+
+ return len;
+}
+
+static const struct file_operations himax_proc_SMWP_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_SMWP_read,
+ .write = himax_SMWP_write,
+};
+
+static ssize_t himax_GESTURE_read(struct file *file, char *buf,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ int i =0;
+ int ret = 0;
+ char *temp_buf;
+
+ if(!HX_PROC_SEND_FLAG)
+ {
+ temp_buf = kzalloc(len, GFP_KERNEL);
+ if (!temp_buf) {
+ HX_PROC_SEND_FLAG=0;
+ return ret;
+ }
+ for(i=0;i<16;i++)
+ ret += snprintf(temp_buf+ret, len-ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]);
+ HX_PROC_SEND_FLAG = 1;
+ if (copy_to_user(buf, temp_buf, len))
+ {
+ I("%s,here:%d\n", __func__, __LINE__);
+ }
+
+ kfree(temp_buf);
+ HX_PROC_SEND_FLAG = 1;
+ }
+ else
+ {
+ HX_PROC_SEND_FLAG = 0;
+ ret = 0;
+ }
+ return ret;
+}
+
+static ssize_t himax_GESTURE_write(struct file *file, const char *buff,
+ size_t len, loff_t *pos)
+{
+ struct himax_ts_data *ts = private_ts;
+ int i =0;
+ char buf[80] = {0};
+
+ if (len >= 80)
+ {
+ I("%s: no command exceeds 80 chars.\n", __func__);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buff, len))
+ {
+ return -EFAULT;
+ }
+
+ I("himax_GESTURE_store= %s \n",buf);
+ for (i=0;i<16;i++)
+ {
+ if (buf[i] == '0')
+ ts->gesture_cust_en[i]= 0;
+ else if (buf[i] == '1')
+ ts->gesture_cust_en[i]= 1;
+ else
+ ts->gesture_cust_en[i]= 0;
+ I("gesture en[%d]=%d \n", i, ts->gesture_cust_en[i]);
+ }
+ return len;
+}
+
+static const struct file_operations himax_proc_Gesture_ops =
+{
+ .owner = THIS_MODULE,
+ .read = himax_GESTURE_read,
+ .write = himax_GESTURE_write,
+};
+#endif
+
+int himax_touch_proc_init(void)
+{
+ himax_touch_proc_dir = proc_mkdir( HIMAX_PROC_TOUCH_FOLDER, NULL);
+ if (himax_touch_proc_dir == NULL)
+ {
+ E(" %s: himax_touch_proc_dir file create failed!\n", __func__);
+ return -ENOMEM;
+ }
+
+ himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops);
+ if (himax_proc_debug_level_file == NULL)
+ {
+ E(" %s: proc debug_level file create failed!\n", __func__);
+ goto fail_1;
+ }
+
+ himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_vendor_ops);
+ if(himax_proc_vendor_file == NULL)
+ {
+ E(" %s: proc vendor file create failed!\n", __func__);
+ goto fail_2;
+ }
+
+ himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_attn_ops);
+ if(himax_proc_attn_file == NULL)
+ {
+ E(" %s: proc attn file create failed!\n", __func__);
+ goto fail_3;
+ }
+
+ himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops);
+ if(himax_proc_int_en_file == NULL)
+ {
+ E(" %s: proc int en file create failed!\n", __func__);
+ goto fail_4;
+ }
+
+ himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops);
+ if(himax_proc_layout_file == NULL)
+ {
+ E(" %s: proc layout file create failed!\n", __func__);
+ goto fail_5;
+ }
+
+#ifdef HX_TP_PROC_RESET
+ himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops);
+ if(himax_proc_reset_file == NULL)
+ {
+ E(" %s: proc reset file create failed!\n", __func__);
+ goto fail_6;
+ }
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops);
+ if(himax_proc_diag_file == NULL)
+ {
+ E(" %s: proc diag file create failed!\n", __func__);
+ goto fail_7;
+ }
+ himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
+ if(himax_proc_diag_arrange_file == NULL)
+ {
+ E(" %s: proc diag file create failed!\n", __func__);
+ goto fail_7_1;
+ }
+#endif
+
+#ifdef HX_TP_PROC_REGISTER
+ himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops);
+ if(himax_proc_register_file == NULL)
+ {
+ E(" %s: proc register file create failed!\n", __func__);
+ goto fail_8;
+ }
+#endif
+
+#ifdef HX_TP_PROC_DEBUG
+ himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops);
+ if(himax_proc_debug_file == NULL)
+ {
+ E(" %s: proc debug file create failed!\n", __func__);
+ goto fail_9;
+ }
+#endif
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+ himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops);
+ if(himax_proc_flash_dump_file == NULL)
+ {
+ E(" %s: proc flash dump file create failed!\n", __func__);
+ goto fail_10;
+ }
+#endif
+
+#ifdef HX_TP_PROC_SELF_TEST
+ himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops);
+ if(himax_proc_self_test_file == NULL)
+ {
+ E(" %s: proc self_test file create failed!\n", __func__);
+ goto fail_11;
+ }
+#endif
+
+#ifdef HX_HIGH_SENSE
+ himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_HSEN_ops);
+ if(himax_proc_HSEN_file == NULL)
+ {
+ E(" %s: proc HSEN file create failed!\n", __func__);
+ goto fail_12;
+ }
+#endif
+
+#ifdef HX_SMART_WAKEUP
+ himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_SMWP_ops);
+ if(himax_proc_SMWP_file == NULL)
+ {
+ E(" %s: proc SMWP file create failed!\n", __func__);
+ goto fail_13;
+ }
+ himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_Gesture_ops);
+ if(himax_proc_GESTURE_file == NULL)
+ {
+ E(" %s: proc GESTURE file create failed!\n", __func__);
+ goto fail_14;
+ }
+#endif
+
+#ifdef HX_TP_PROC_SENSE_ON_OFF
+ himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
+ if(himax_proc_SENSE_ON_OFF_file == NULL)
+ {
+ E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__);
+ goto fail_15;
+ }
+#endif
+
+ return 0 ;
+
+#ifdef HX_TP_PROC_SENSE_ON_OFF
+ fail_15:
+#endif
+#ifdef HX_SMART_WAKEUP
+ remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
+ fail_14:
+ remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
+ fail_13:
+#endif
+#ifdef HX_HIGH_SENSE
+ remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
+ fail_12:
+#endif
+#ifdef HX_TP_PROC_SELF_TEST
+ remove_proc_entry( HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir );
+ fail_11:
+#endif
+#ifdef HX_TP_PROC_FLASH_DUMP
+ remove_proc_entry( HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir );
+ fail_10:
+#endif
+#ifdef HX_TP_PROC_DEBUG
+ remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
+ fail_9:
+#endif
+#ifdef HX_TP_PROC_REGISTER
+ remove_proc_entry( HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir );
+ fail_8:
+#endif
+#ifdef HX_TP_PROC_DIAG
+ remove_proc_entry( HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir );
+ fail_7:
+ remove_proc_entry( HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir );
+ fail_7_1:
+#endif
+#ifdef HX_TP_PROC_RESET
+ remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
+ fail_6:
+#endif
+ remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
+ fail_5: remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
+ fail_4: remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
+ fail_3: remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
+ fail_2: remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
+ fail_1: remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+ return -ENOMEM;
+}
+
+void himax_touch_proc_deinit(void)
+{
+#ifdef HX_TP_PROC_SENSE_ON_OFF
+ remove_proc_entry( HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir );
+#endif
+#ifdef HX_SMART_WAKEUP
+ remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
+#endif
+#ifdef HX_DOT_VIEW
+ remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
+#endif
+#ifdef HX_TP_PROC_SELF_TEST
+ remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
+#endif
+#ifdef HX_TP_PROC_FLASH_DUMP
+ remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
+#endif
+#ifdef HX_TP_PROC_DEBUG
+ remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
+#endif
+#ifdef HX_TP_PROC_REGISTER
+ remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
+#endif
+#ifdef HX_TP_PROC_DIAG
+ remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
+#endif
+#ifdef HX_TP_PROC_RESET
+ remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
+#endif
+ remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
+ remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+}
+#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h
new file mode 100644
index 000000000000..91a7ae2eb7ab
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.h
@@ -0,0 +1,181 @@
+/* Himax Android Driver Sample Code for Himax chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_platform.h"
+#include "himax_common.h"
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+ #define HIMAX_PROC_TOUCH_FOLDER "android_touch"
+ #define HIMAX_PROC_DEBUG_LEVEL_FILE "debug_level"
+ #define HIMAX_PROC_VENDOR_FILE "vendor"
+ #define HIMAX_PROC_ATTN_FILE "attn"
+ #define HIMAX_PROC_INT_EN_FILE "int_en"
+ #define HIMAX_PROC_LAYOUT_FILE "layout"
+
+ static struct proc_dir_entry *himax_touch_proc_dir;
+ static struct proc_dir_entry *himax_proc_debug_level_file;
+ static struct proc_dir_entry *himax_proc_vendor_file;
+ static struct proc_dir_entry *himax_proc_attn_file;
+ static struct proc_dir_entry *himax_proc_int_en_file;
+ static struct proc_dir_entry *himax_proc_layout_file;
+
+ uint8_t HX_PROC_SEND_FLAG;
+
+extern int himax_touch_proc_init(void);
+extern void himax_touch_proc_deinit(void);
+bool getFlashDumpGoing(void);
+
+#ifdef HX_TP_PROC_REGISTER
+ #define HIMAX_PROC_REGISTER_FILE "register"
+ struct proc_dir_entry *himax_proc_register_file;
+ uint8_t register_command[4];
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ #define HIMAX_PROC_DIAG_FILE "diag"
+ struct proc_dir_entry *himax_proc_diag_file;
+ #define HIMAX_PROC_DIAG_ARR_FILE "diag_arr"
+ struct proc_dir_entry *himax_proc_diag_arrange_file;
+
+#ifdef HX_TP_PROC_2T2R
+ static bool Is_2T2R;
+ static uint8_t x_channel_2;
+ static uint8_t y_channel_2;
+ static uint8_t *diag_mutual_2;
+
+ int16_t *getMutualBuffer_2(void);
+ uint8_t getXChannel_2(void);
+ uint8_t getYChannel_2(void);
+
+ void setMutualBuffer_2(void);
+ void setXChannel_2(uint8_t x);
+ void setYChannel_2(uint8_t y);
+#endif
+ uint8_t x_channel;
+ uint8_t y_channel;
+ int16_t *diag_mutual;
+ int16_t *diag_mutual_new;
+ int16_t *diag_mutual_old;
+ uint8_t diag_max_cnt;
+
+ int diag_command;
+ uint8_t diag_coor[128];// = {0xFF};
+ int16_t diag_self[100] = {0};
+
+ int16_t *getMutualBuffer(void);
+ int16_t *getMutualNewBuffer(void);
+ int16_t *getMutualOldBuffer(void);
+ int16_t *getSelfBuffer(void);
+ uint8_t getDiagCommand(void);
+ uint8_t getXChannel(void);
+ uint8_t getYChannel(void);
+
+ void setMutualBuffer(void);
+ void setMutualNewBuffer(void);
+ void setMutualOldBuffer(void);
+ void setXChannel(uint8_t x);
+ void setYChannel(uint8_t y);
+ uint8_t coordinate_dump_enable = 0;
+ struct file *coordinate_fn;
+#endif
+
+#ifdef HX_TP_PROC_DEBUG
+ #define HIMAX_PROC_DEBUG_FILE "debug"
+ struct proc_dir_entry *himax_proc_debug_file = NULL;
+
+ bool fw_update_complete = false;
+ int handshaking_result = 0;
+ unsigned char debug_level_cmd = 0;
+ unsigned char upgrade_fw[128*1024];
+#endif
+
+#ifdef HX_TP_PROC_FLASH_DUMP
+ #define HIMAX_PROC_FLASH_DUMP_FILE "flash_dump"
+ struct proc_dir_entry *himax_proc_flash_dump_file = NULL;
+
+ static int Flash_Size = 131072;
+ static uint8_t *flash_buffer = NULL;
+ static uint8_t flash_command = 0;
+ static uint8_t flash_read_step = 0;
+ static uint8_t flash_progress = 0;
+ static uint8_t flash_dump_complete = 0;
+ static uint8_t flash_dump_fail = 0;
+ static uint8_t sys_operation = 0;
+ static uint8_t flash_dump_sector = 0;
+ static uint8_t flash_dump_page = 0;
+ static bool flash_dump_going = false;
+
+ static uint8_t getFlashCommand(void);
+ static uint8_t getFlashDumpComplete(void);
+ static uint8_t getFlashDumpFail(void);
+ static uint8_t getFlashDumpProgress(void);
+ static uint8_t getFlashReadStep(void);
+ //static uint8_t getFlashDumpSector(void);
+ //static uint8_t getFlashDumpPage(void);
+
+ void setFlashBuffer(void);
+ uint8_t getSysOperation(void);
+
+ static void setFlashCommand(uint8_t command);
+ static void setFlashReadStep(uint8_t step);
+ static void setFlashDumpComplete(uint8_t complete);
+ static void setFlashDumpFail(uint8_t fail);
+ static void setFlashDumpProgress(uint8_t progress);
+ void setSysOperation(uint8_t operation);
+ static void setFlashDumpSector(uint8_t sector);
+ static void setFlashDumpPage(uint8_t page);
+ static void setFlashDumpGoing(bool going);
+
+#endif
+
+#ifdef HX_TP_PROC_SELF_TEST
+ #define HIMAX_PROC_SELF_TEST_FILE "self_test"
+ struct proc_dir_entry *himax_proc_self_test_file = NULL;
+ uint32_t **raw_data_array;
+ uint8_t X_NUM = 0, Y_NUM = 0;
+ uint8_t sel_type = 0x0D;
+#endif
+
+#ifdef HX_TP_PROC_RESET
+#define HIMAX_PROC_RESET_FILE "reset"
+extern void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
+struct proc_dir_entry *himax_proc_reset_file = NULL;
+#endif
+
+#ifdef HX_HIGH_SENSE
+ #define HIMAX_PROC_HSEN_FILE "HSEN"
+ struct proc_dir_entry *himax_proc_HSEN_file = NULL;
+#endif
+
+#ifdef HX_TP_PROC_SENSE_ON_OFF
+ #define HIMAX_PROC_SENSE_ON_OFF_FILE "SenseOnOff"
+ struct proc_dir_entry *himax_proc_SENSE_ON_OFF_file = NULL;
+#endif
+
+#ifdef HX_RST_PIN_FUNC
+ void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
+#endif
+
+#ifdef HX_SMART_WAKEUP
+#define HIMAX_PROC_SMWP_FILE "SMWP"
+struct proc_dir_entry *himax_proc_SMWP_file = NULL;
+#define HIMAX_PROC_GESTURE_FILE "GESTURE"
+struct proc_dir_entry *himax_proc_GESTURE_file = NULL;
+uint8_t HX_SMWP_EN = 0;
+//extern bool FAKE_POWER_KEY_SEND;
+#endif
+
+#endif
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c
new file mode 100644
index 000000000000..6ad8dc03149b
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.c
@@ -0,0 +1,2118 @@
+/* Himax Android Driver Sample Code for HMX83100 chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_ic.h"
+
+static unsigned char i_TP_CRC_FW_128K[]=
+{
+ #include "HX_CRC_128.i"
+};
+static unsigned char i_TP_CRC_FW_64K[]=
+{
+ #include "HX_CRC_64.i"
+};
+static unsigned char i_TP_CRC_FW_124K[]=
+{
+ #include "HX_CRC_124.i"
+};
+static unsigned char i_TP_CRC_FW_60K[]=
+{
+ #include "HX_CRC_60.i"
+};
+
+
+unsigned long FW_VER_MAJ_FLASH_ADDR;
+unsigned long FW_VER_MAJ_FLASH_LENG;
+unsigned long FW_VER_MIN_FLASH_ADDR;
+unsigned long FW_VER_MIN_FLASH_LENG;
+unsigned long CFG_VER_MAJ_FLASH_ADDR;
+unsigned long CFG_VER_MAJ_FLASH_LENG;
+unsigned long CFG_VER_MIN_FLASH_ADDR;
+unsigned long CFG_VER_MIN_FLASH_LENG;
+
+unsigned char IC_TYPE = 0;
+unsigned char IC_CHECKSUM = 0;
+
+extern struct himax_ic_data* ic_data;
+
+int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C Fail
+{
+ int ret, result;
+ uint8_t hw_reset_check[1];
+ uint8_t hw_reset_check_2[1];
+ uint8_t buf0[2];
+ uint8_t IC_STATUS_CHECK = 0xAA;
+
+ memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
+ memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));
+
+ buf0[0] = 0xF2;
+ if (IC_STATUS_CHECK == 0xAA) {
+ buf0[1] = 0xAA;
+ IC_STATUS_CHECK = 0x55;
+ } else {
+ buf0[1] = 0x55;
+ IC_STATUS_CHECK = 0xAA;
+ }
+
+ ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+ if (ret < 0) {
+ E("[Himax]:write 0xF2 failed line: %d \n",__LINE__);
+ goto work_func_send_i2c_msg_fail;
+ }
+ msleep(50);
+
+ buf0[0] = 0xF2;
+ buf0[1] = 0x00;
+ ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+ if (ret < 0) {
+ E("[Himax]:write 0x92 failed line: %d \n",__LINE__);
+ goto work_func_send_i2c_msg_fail;
+ }
+ usleep_range(2000, 4000);
+
+ ret = i2c_himax_read(client, 0xD1, hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
+ if (ret < 0) {
+ E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+ goto work_func_send_i2c_msg_fail;
+ }
+
+ if ((IC_STATUS_CHECK != hw_reset_check[0])) {
+ usleep_range(2000, 4000);
+ ret = i2c_himax_read(client, 0xD1, hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
+ if (ret < 0) {
+ E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+ goto work_func_send_i2c_msg_fail;
+ }
+
+ if (hw_reset_check[0] == hw_reset_check_2[0]) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ } else {
+ result = 0;
+ }
+
+ return result;
+
+work_func_send_i2c_msg_fail:
+ return 2;
+}
+
+void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+
+ if(diag_command != 0)
+ diag_command = diag_command + 5;
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = diag_command;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+
+void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
+{
+ //struct himax_ts_data *ts = container_of(work, struct himax_ts_data, flash_work);
+
+// uint8_t sector = 0;
+// uint8_t page = 0;
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ uint8_t out_buffer[20];
+ uint8_t in_buffer[260] = {0};
+ int page_prog_start = 0;
+ int i = 0;
+
+ himax_sense_off(client);
+ himax_burst_enable(client, 0);
+ /*=============Dump Flash Start=============*/
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 256)
+ {
+ //=================================
+ // SPI Transfer Control
+ // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+ // Set read start address : 0x8000_0028 ==> 0x0000_0000
+ // Set command : 0x8000_0024 ==> 0x0000_003B
+ //=================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //==================================
+ // AHB_I2C Burst Read
+ // Set SPI data register : 0x8000_002C ==> 0x00
+ //==================================
+ out_buffer[0] = 0x2C;
+ out_buffer[1] = 0x00;
+ out_buffer[2] = 0x00;
+ out_buffer[3] = 0x80;
+ i2c_himax_write(client, 0x00 ,out_buffer, 4, 3);
+
+ //==================================
+ // Read access : 0x0C ==> 0x00
+ //==================================
+ out_buffer[0] = 0x00;
+ i2c_himax_write(client, 0x0C ,out_buffer, 1, 3);
+
+ //==================================
+ // Read 128 bytes two times
+ //==================================
+ i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
+ for (i = 0; i < 128; i++)
+ flash_buffer[i + page_prog_start] = in_buffer[i];
+
+ i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
+ for (i = 0; i < 128; i++)
+ flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+
+ I("%s:Verify Progress: %x\n", __func__, page_prog_start);
+ }
+
+/*=============Dump Flash End=============*/
+ //msleep(100);
+ /*
+ for( i=0 ; i<8 ;i++)
+ {
+ for(j=0 ; j<64 ; j++)
+ {
+ setFlashDumpProgress(i*32 + j);
+ }
+ }
+ */
+ himax_sense_on(client, 0x01);
+
+ return;
+
+}
+
+int himax_chip_self_test(struct i2c_client *client)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[128];
+ int pf_value=0x00;
+ uint8_t test_result_id = 0;
+ int j;
+
+ memset(tmp_addr, 0x00, sizeof(tmp_addr));
+ memset(tmp_data, 0x00, sizeof(tmp_data));
+
+ himax_interface_on(client);
+ himax_sense_off(client);
+
+ //Set criteria
+ himax_burst_enable(client, 1);
+
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
+ tmp_data[3] = 0x14; tmp_data[2] = 0xC8; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_data[7] = 0x13; tmp_data[6] = 0x60; tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
+
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8);
+
+ //start selftest
+ // 0x9008_805C ==> 0x0000_0001
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ himax_sense_on(client, 1);
+
+ msleep(2000);
+
+ himax_sense_off(client);
+ msleep(20);
+
+ //=====================================
+ // Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
+ //=====================================
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+
+ test_result_id = tmp_data[0];
+
+ I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__
+ ,test_result_id,tmp_data[0]);
+
+ if (test_result_id==0xF) {
+ I("[Himax]: self-test pass\n");
+ pf_value = 0x1;
+ } else {
+ E("[Himax]: self-test fail\n");
+ pf_value = 0x0;
+ }
+ himax_burst_enable(client, 1);
+
+ for (j = 0;j < 10; j++){
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+ I("[Himax]: 9006000C = %d\n", tmp_data[0]);
+ if (tmp_data[0] != 0){
+ tmp_data[3] = 0x90; tmp_data[2] = 0x06; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+ tmp_data[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+ i2c_himax_read(client, 0x08, tmp_data, 124,HIMAX_I2C_RETRY_TIMES);
+ }else{
+ break;
+ }
+ }
+
+ himax_sense_on(client, 1);
+ msleep(120);
+
+ return pf_value;
+}
+
+void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+
+ himax_burst_enable(client, 0);
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data)
+{
+ uint8_t tmp_addr[4];
+
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+}
+
+void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+
+void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data)
+{
+ uint8_t tmp_addr[4];
+
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+}
+
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
+{
+ uint8_t tmp_data[4];
+
+ tmp_data[0] = 0x31;
+ if ( i2c_himax_write(client, 0x13 ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return -EBUSY;
+ }
+
+ tmp_data[0] = (0x10 | auto_add_4_byte);
+ if ( i2c_himax_write(client, 0x0D ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return -EBUSY;
+ }
+ return 0;
+
+}
+
+void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data)
+{
+ uint8_t tmp_data[4];
+ int i = 0;
+ int address = 0;
+
+ if(read_length>256)
+ {
+ E("%s: read len over 256!\n", __func__);
+ return;
+ }
+ if (read_length > 1)
+ himax_burst_enable(client, 1);
+ else
+ himax_burst_enable(client, 0);
+ address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0];
+ i = address;
+ tmp_data[0] = (uint8_t)i;
+ tmp_data[1] = (uint8_t)(i >> 8);
+ tmp_data[2] = (uint8_t)(i >> 16);
+ tmp_data[3] = (uint8_t)(i >> 24);
+ if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ tmp_data[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x08 ,read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ if (read_length > 1)
+ himax_burst_enable(client, 0);
+}
+
+void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data)
+{
+ uint8_t tmpbyte[2];
+
+ if ( i2c_himax_write(client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ tmpbyte[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x08 ,&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x09 ,&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x0A ,&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x0B ,&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_read(client, 0x18 ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }// No bus request
+
+ if ( i2c_himax_read(client, 0x0F ,&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }// idle state
+
+}
+
+void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data)
+{
+ uint8_t data_byte[8];
+ int i = 0, j = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ data_byte[i] = reg_byte[i];
+ }
+ for (j = 4; j < 8; j++)
+ {
+ data_byte[j] = write_data[j-4];
+ }
+
+ if ( i2c_himax_write(client, 0x00 ,data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+}
+
+int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length)
+{
+ uint8_t data_byte[256];
+ int i = 0, j = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ data_byte[i] = reg_byte[i];
+ }
+ for (j = 4; j < length + 4; j++)
+ {
+ data_byte[j] = write_data[j - 4];
+ }
+
+ if ( i2c_himax_write(client, 0x00 ,data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data)
+{
+ int i =0, address = 0;
+ int ret = 0;
+
+ address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0];
+
+ for (i = address; i < address + write_length * 4; i = i + 4)
+ {
+ if (write_length > 1)
+ {
+ ret = himax_burst_enable(client, 1);
+ if(ret)
+ return ret;
+ }
+ else
+ {
+ ret = himax_burst_enable(client, 0);
+ if(ret)
+ return ret;
+ }
+ ret = himax_flash_write_burst_lenth(client, write_addr, write_data, write_length * 4);
+ if(ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+void himax_sense_off(struct i2c_client *client)
+{
+ uint8_t wdt_off = 0x00;
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[5];
+
+ himax_burst_enable(client, 0);
+
+ while(wdt_off == 0x00)
+ {
+ // 0x9000_800C ==> 0x0000_AC53
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Read Watch Dog disable password : 0x9000_800C ==> 0x0000_AC53
+ //=====================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+
+ //Check WDT
+ if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
+ wdt_off = 0x01;
+ else
+ wdt_off = 0x00;
+ }
+
+ // VCOM //0x9008_806C ==> 0x0000_0001
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ msleep(20);
+
+ // 0x9000_0010 ==> 0x0000_00DA
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
+ //=====================================
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+ I("%s: CPU clock off password data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
+ ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+
+}
+
+void himax_interface_on(struct i2c_client *client)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[5];
+
+ //===========================================
+ // Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
+ //===========================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ himax_flash_read(client, tmp_addr, tmp_data); //avoid RD/WR fail
+}
+
+bool wait_wip(struct i2c_client *client, int Timing)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ uint8_t in_buffer[10];
+ //uint8_t out_buffer[20];
+ int retry_cnt = 0;
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ in_buffer[0] = 0x01;
+
+ do
+ {
+ //=====================================
+ // SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x42; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x03;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // SPI Command : 0x8000_0024 ==> 0x0000_0005
+ // read 0x8000_002C for 0x01, means wait success
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x05;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ himax_register_read(client, tmp_addr, 1, in_buffer);
+
+ if ((in_buffer[0] & 0x01) == 0x00)
+ return true;
+
+ retry_cnt++;
+
+ if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00)
+ I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__,
+ retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]);
+
+ if (retry_cnt > 100)
+ {
+ E("%s: Wait wip error!\n", __func__);
+ return false;
+ }
+ msleep(Timing);
+ }while ((in_buffer[0] & 0x01) == 0x01);
+ return true;
+}
+
+void himax_sense_on(struct i2c_client *client, uint8_t FlashMode)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[128];
+
+ himax_interface_on(client);
+ himax_burst_enable(client, 0);
+ //CPU reset
+ // 0x9000_0014 ==> 0x0000_00CA
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
+ //=====================================
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+
+ I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
+ ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+
+ // 0x9000_0014 ==> 0x0000_0000
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
+ //=====================================
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+
+ I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
+ ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+
+ //=====================================
+ // Reset TCON
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+ usleep_range(10000, 20000);
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ if (FlashMode == 0x00) //SRAM
+ {
+ //=====================================
+ // Re-map
+ //=====================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ I("%s:83100_Chip_Re-map ON\n", __func__);
+ }
+ else
+ {
+ //=====================================
+ // Re-map off
+ //=====================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ I("%s:83100_Chip_Re-map OFF\n", __func__);
+ }
+ //=====================================
+ // CPU clock on
+ //=====================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+
+}
+
+void himax_chip_erase(struct i2c_client *client)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+
+ himax_burst_enable(client, 0);
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Chip Erase
+ // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
+ // 2. 0x8000_0024 ==> 0x0000_0006
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Chip Erase
+ // Erase Command : 0x8000_0024 ==> 0x0000_00C7
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ msleep(2000);
+
+ if (!wait_wip(client, 100))
+ E("%s:83100_Chip_Erase Fail\n", __func__);
+
+}
+
+bool himax_block_erase(struct i2c_client *client)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+
+ himax_burst_enable(client, 0);
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Chip Erase
+ // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
+ // 2. 0x8000_0024 ==> 0x0000_0006
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Block Erase
+ // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
+ // 0x8000_0020 ==> 0x6700_0000 //control
+ // 0x8000_0024 ==> 0x0000_0052 //BE
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x52;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ msleep(1000);
+
+ if (!wait_wip(client, 100))
+ {
+ E("%s:83100_Erase Fail\n", __func__);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+
+}
+
+bool himax_sector_erase(struct i2c_client *client, int start_addr)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ int page_prog_start = 0;
+
+ himax_burst_enable(client, 0);
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+ for (page_prog_start = start_addr; page_prog_start < start_addr + 0x0F000; page_prog_start = page_prog_start + 0x1000)
+ {
+ //=====================================
+ // Chip Erase
+ // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
+ // 2. 0x8000_0024 ==> 0x0000_0006
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=====================================
+ // Sector Erase
+ // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
+ // 0x8000_0020 ==> 0x6700_0000 //control
+ // 0x8000_0024 ==> 0x0000_0020 //SE
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100)
+ {
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
+ {
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
+ {
+ tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x20;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ msleep(200);
+
+ if (!wait_wip(client, 100))
+ {
+ E("%s:83100_Erase Fail\n", __func__);
+ return false;
+ }
+ }
+ return true;
+}
+
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
+{
+ int i = 0;
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[128];
+ int FW_length = 0x4000; // 0x4000 = 16K bin file
+
+ //himax_sense_off(client);
+
+ for (i = 0; i < FW_length; i = i + 128)
+ {
+ himax_burst_enable(client, 1);
+
+ if (i < 0x100)
+ {
+ tmp_addr[3] = 0x08;
+ tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00;
+ tmp_addr[0] = i;
+ }
+ else if (i >= 0x100 && i < 0x10000)
+ {
+ tmp_addr[3] = 0x08;
+ tmp_addr[2] = 0x00;
+ tmp_addr[1] = (i >> 8);
+ tmp_addr[0] = i;
+ }
+
+ memcpy(&tmp_data[0], &FW_content[i], 128);
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 128);
+
+ }
+
+ if (!wait_wip(client, 100))
+ E("%s:83100_Sram_Write Fail\n", __func__);
+}
+
+bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size)
+{
+ int i = 0;
+ uint8_t out_buffer[20];
+ uint8_t in_buffer[128];
+ uint8_t *get_fw_content;
+
+ get_fw_content = kzalloc(0x4000*sizeof(uint8_t), GFP_KERNEL);
+ if (!get_fw_content)
+ return false;
+
+ for (i = 0; i < 0x4000; i = i + 128)
+ {
+ himax_burst_enable(client, 1);
+
+ //==================================
+ // AHB_I2C Burst Read
+ //==================================
+ if (i < 0x100)
+ {
+ out_buffer[3] = 0x08;
+ out_buffer[2] = 0x00;
+ out_buffer[1] = 0x00;
+ out_buffer[0] = i;
+ }
+ else if (i >= 0x100 && i < 0x10000)
+ {
+ out_buffer[3] = 0x08;
+ out_buffer[2] = 0x00;
+ out_buffer[1] = (i >> 8);
+ out_buffer[0] = i;
+ }
+
+ if ( i2c_himax_write(client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return false;
+ }
+
+ out_buffer[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return false;
+ }
+
+ if ( i2c_himax_read(client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return false;
+ }
+ memcpy(&get_fw_content[i], &in_buffer[0], 128);
+ }
+
+ for (i = 0; i < FW_Size; i++)
+ {
+ if (FW_File[i] != get_fw_content[i])
+ {
+ E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", __func__,i,get_fw_content[i],FW_File[i]);
+ return false;
+ }
+ }
+
+ kfree(get_fw_content);
+
+ return true;
+}
+
+void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size)
+{
+ int page_prog_start = 0;
+ int program_length = 48;
+ int i = 0, j = 0, k = 0;
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ uint8_t buring_data[256]; // Read for flash data, 128K
+ // 4 bytes for 0x80002C padding
+
+ //himax_interface_on(client);
+ himax_burst_enable(client, 0);
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
+ {
+ //msleep(5);
+ //=====================================
+ // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
+ // 2. 0x8000_0024 ==> 0x0000_0006
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=================================
+ // SPI Transfer Control
+ // Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
+ // Set read start address : 0x8000_0028 ==> 0x0000_0000
+ //=================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x61; tmp_data[2] = 0x0F; tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
+ // data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000
+ // Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ //tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000
+
+ if (page_prog_start < 0x100)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+
+ //=================================
+ // Send 16 bytes data : 0x8000_002C ==> 16 bytes data
+ //=================================
+ buring_data[0] = 0x2C;
+ buring_data[1] = 0x00;
+ buring_data[2] = 0x00;
+ buring_data[3] = 0x80;
+
+ for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++) /// <------ bin file
+ {
+ buring_data[j + 4] = FW_content[i];
+ }
+
+
+ if ( i2c_himax_write(client, 0x00 ,buring_data, 20, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ //=================================
+ // Write command : 0x8000_0024 ==> 0x0000_0002
+ //=================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x02;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+ //=================================
+ // Send 240 bytes data : 0x8000_002C ==> 240 bytes data
+ //=================================
+
+ for (j = 0; j < 5; j++)
+ {
+ for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) /// <------ bin file
+ {
+ buring_data[k+4] = FW_content[i];//(byte)i;
+ }
+
+ if ( i2c_himax_write(client, 0x00 ,buring_data, program_length+4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ }
+
+ if (!wait_wip(client, 1))
+ E("%s:83100_Flash_Programming Fail\n", __func__);
+ }
+}
+
+bool himax_check_chip_version(struct i2c_client *client)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ uint8_t ret_data = 0x00;
+ int i = 0;
+ int ret = 0;
+ himax_sense_off(client);
+ for (i = 0; i < 5; i++)
+ {
+ // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ ret = himax_register_write(client, tmp_addr, 1, tmp_data);
+ if(ret)
+ return false;
+
+ // 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ ret = himax_register_write(client, tmp_addr, 1, tmp_data);
+ if(ret)
+ return false;
+
+ // 3. Read driver ID register RF4H 1 byte (0x8001_F401)
+ // Driver register RF4H 1 byte value = 0x84H, read back value will become 0x84848484
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+ ret_data = tmp_data[0];
+
+ I("%s:Read driver IC ID = %X\n", __func__, ret_data);
+ if (ret_data == 0x84)
+ {
+ IC_TYPE = HX_83100_SERIES_PWON;
+ //himax_sense_on(client, 0x01);
+ ret_data = true;
+ break;
+ }
+ else
+ {
+ ret_data = false;
+ E("%s:Read driver ID register Fail:\n", __func__);
+ }
+ }
+ // 4. After read finish, set DDREG_Req = 0 (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_register_write(client, tmp_addr, 1, tmp_data);
+ //himax_sense_on(client, 0x01);
+ return ret_data;
+}
+
+#if 1
+int himax_check_CRC(struct i2c_client *client, int mode)
+{
+ bool burnFW_success = false;
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ int tmp_value;
+ int CRC_value = 0;
+
+ memset(tmp_data, 0x00, sizeof(tmp_data));
+
+ if (1)
+ {
+ if(mode == fw_image_60k)
+ {
+ himax_sram_write(client, (i_TP_CRC_FW_60K));
+ burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_60K, 0x4000);
+ }
+ else if(mode == fw_image_64k)
+ {
+ himax_sram_write(client, (i_TP_CRC_FW_64K));
+ burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_64K, 0x4000);
+ }
+ else if(mode == fw_image_124k)
+ {
+ himax_sram_write(client, (i_TP_CRC_FW_124K));
+ burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_124K, 0x4000);
+ }
+ else if(mode == fw_image_128k)
+ {
+ himax_sram_write(client, (i_TP_CRC_FW_128K));
+ burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_128K, 0x4000);
+ }
+ if (burnFW_success)
+ {
+ I("%s: Start to do CRC FW mode=%d \n", __func__,mode);
+ himax_sense_on(client, 0x00); // run CRC firmware
+
+ while(true)
+ {
+ msleep(100);
+
+ tmp_addr[3] = 0x90;
+ tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80;
+ tmp_addr[0] = 0x94;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+
+ I("%s: CRC from firmware is %x, %x, %x, %x \n", __func__,tmp_data[3],
+ tmp_data[2],tmp_data[1],tmp_data[0]);
+
+ if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF)
+ {
+ }
+ else
+ break;
+ }
+
+ CRC_value = tmp_data[3];
+
+ tmp_value = tmp_data[2] << 8;
+ CRC_value += tmp_value;
+
+ tmp_value = tmp_data[1] << 16;
+ CRC_value += tmp_value;
+
+ tmp_value = tmp_data[0] << 24;
+ CRC_value += tmp_value;
+
+ I("%s: CRC Value is %x \n", __func__, CRC_value);
+
+ //Close Remapping
+ //=====================================
+ // Re-map close
+ //=====================================
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ return CRC_value;
+ }
+ else
+ {
+ E("%s: SRAM write fail\n", __func__);
+ return 0;
+ }
+ }
+ else
+ I("%s: NO CRC Check File \n", __func__);
+
+ return 0;
+}
+
+bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode)
+{
+ uint8_t tmp_data[4];
+ int i, j;
+ int fw_data;
+ int fw_data_2;
+ int CRC = 0xFFFFFFFF;
+ int PolyNomial = 0x82F63B78;
+ int length = 0;
+
+ if (mode == fw_image_128k)
+ length = 0x8000;
+ else if (mode == fw_image_124k)
+ length = 0x7C00;
+ else if (mode == fw_image_64k)
+ length = 0x4000;
+ else //if (mode == fw_image_60k)
+ length = 0x3C00;
+
+ for (i = 0; i < length; i++)
+ {
+ fw_data = FW_content[i * 4 ];
+
+ for (j = 1; j < 4; j++)
+ {
+ fw_data_2 = FW_content[i * 4 + j];
+ fw_data += (fw_data_2) << (8 * j);
+ }
+
+ CRC = fw_data ^ CRC;
+
+ for (j = 0; j < 32; j++)
+ {
+ if ((CRC % 2) != 0)
+ {
+ CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
+ }
+ else
+ {
+ CRC = (((CRC >> 1) ^ 0x7FFFFFFF)& 0x7FFFFFFF);
+ }
+ }
+ }
+
+ I("%s: CRC calculate from bin file is %x \n", __func__, CRC);
+
+ tmp_data[0] = (uint8_t)(CRC >> 24);
+ tmp_data[1] = (uint8_t)(CRC >> 16);
+ tmp_data[2] = (uint8_t)(CRC >> 8);
+ tmp_data[3] = (uint8_t) CRC;
+
+ CRC = tmp_data[0];
+ CRC += tmp_data[1] << 8;
+ CRC += tmp_data[2] << 16;
+ CRC += tmp_data[3] << 24;
+
+ I("%s: CRC calculate from bin file REVERSE %x \n", __func__, CRC);
+ I("%s: CRC calculate from FWis %x \n", __func__, CRC_from_FW);
+ if (CRC_from_FW == CRC)
+ return true;
+ else
+ return false;
+}
+#endif
+
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+{
+ int CRC_from_FW = 0;
+ int burnFW_success = 0;
+
+ if (len != 0x10000) //64k
+ {
+ E("%s: The file size is not 64K bytes\n", __func__);
+ return false;
+ }
+ himax_sense_off(client);
+ msleep(500);
+ himax_interface_on(client);
+ if (!himax_sector_erase(client, 0x00000))
+ {
+ E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
+ himax_flash_programming(client, fw, 0x0F000);
+
+ //burnFW_success = himax_83100_Verify(fw, len);
+ //if(burnFW_success==false)
+ // return burnFW_success;
+
+ CRC_from_FW = himax_check_CRC(client,fw_image_60k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_60k);
+ //himax_sense_on(client, 0x01);
+ return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+{
+ int CRC_from_FW = 0;
+ int burnFW_success = 0;
+
+ if (len != 0x10000) //64k
+ {
+ E("%s: The file size is not 64K bytes\n", __func__);
+ return false;
+ }
+ himax_sense_off(client);
+ msleep(500);
+ himax_interface_on(client);
+ himax_chip_erase(client);
+ himax_flash_programming(client, fw, len);
+
+ //burnFW_success = himax_83100_Verify(fw, len);
+ //if(burnFW_success==false)
+ // return burnFW_success;
+
+ CRC_from_FW = himax_check_CRC(client,fw_image_64k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_64k);
+ //himax_sense_on(client, 0x01);
+ return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+{
+ int CRC_from_FW = 0;
+ int burnFW_success = 0;
+
+ if (len != 0x20000) //128k
+ {
+ E("%s: The file size is not 128K bytes\n", __func__);
+ return false;
+ }
+ himax_sense_off(client);
+ msleep(500);
+ himax_interface_on(client);
+ if (!himax_block_erase(client))
+ {
+ E("%s:Block erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
+
+ if (!himax_sector_erase(client, 0x10000))
+ {
+ E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
+ himax_flash_programming(client, fw, 0x1F000);
+
+
+ //burnFW_success = himax_83100_Verify(fw, len);
+ //if(burnFW_success==false)
+ // return burnFW_success;
+
+ CRC_from_FW = himax_check_CRC(client,fw_image_124k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_124k);
+ //himax_sense_on(client, 0x01);
+ return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+{
+ int CRC_from_FW = 0;
+ int burnFW_success = 0;
+
+ if (len != 0x20000) //128k
+ {
+ E("%s: The file size is not 128K bytes\n", __func__);
+ return false;
+ }
+ himax_sense_off(client);
+ msleep(500);
+ himax_interface_on(client);
+ himax_chip_erase(client);
+
+ himax_flash_programming(client, fw, len);
+
+ //burnFW_success = himax_83100_Verify(fw, len);
+ //if(burnFW_success==false)
+ // return burnFW_success;
+
+ CRC_from_FW = himax_check_CRC(client,fw_image_128k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_128k);
+ //himax_sense_on(client, 0x01);
+ return burnFW_success;
+}
+
+void himax_touch_information(struct i2c_client *client)
+{
+ uint8_t cmd[4];
+ char data[12] = {0};
+
+ I("%s:IC_TYPE =%d\n", __func__,IC_TYPE);
+
+ if(IC_TYPE == HX_83100_SERIES_PWON)
+ {
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
+ himax_register_read(client, cmd, 1, data);
+
+ ic_data->HX_RX_NUM = data[1];
+ ic_data->HX_TX_NUM = data[2];
+ ic_data->HX_MAX_PT = data[3];
+
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
+ himax_register_read(client, cmd, 1, data);
+
+ if((data[1] & 0x04) == 0x04) {
+ ic_data->HX_XY_REVERSE = true;
+ } else {
+ ic_data->HX_XY_REVERSE = false;
+ }
+ ic_data->HX_Y_RES = data[3]*256;
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
+ himax_register_read(client, cmd, 1, data);
+ ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[0];
+ ic_data->HX_X_RES = data[1]*256 + data[2];
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
+ himax_register_read(client, cmd, 1, data);
+ if((data[0] & 0x01) == 1) {
+ ic_data->HX_INT_IS_EDGE = true;
+ } else {
+ ic_data->HX_INT_IS_EDGE = false;
+ }
+ if (ic_data->HX_RX_NUM > 40)
+ ic_data->HX_RX_NUM = 29;
+ if (ic_data->HX_TX_NUM > 20)
+ ic_data->HX_TX_NUM = 16;
+ if (ic_data->HX_MAX_PT > 10)
+ ic_data->HX_MAX_PT = 10;
+ if (ic_data->HX_Y_RES > 2000)
+ ic_data->HX_Y_RES = 1280;
+ if (ic_data->HX_X_RES > 2000)
+ ic_data->HX_X_RES = 720;
+#ifdef HX_EN_MUT_BUTTON
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
+ himax_register_read(client, cmd, 1, data);
+ ic_data->HX_BT_NUM = data[3];
+#endif
+ I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);
+ I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES);
+ I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE);
+ }
+ else
+ {
+ ic_data->HX_RX_NUM = 0;
+ ic_data->HX_TX_NUM = 0;
+ ic_data->HX_BT_NUM = 0;
+ ic_data->HX_X_RES = 0;
+ ic_data->HX_Y_RES = 0;
+ ic_data->HX_MAX_PT = 0;
+ ic_data->HX_XY_REVERSE = false;
+ ic_data->HX_INT_IS_EDGE = false;
+ }
+}
+
+void himax_read_FW_ver(struct i2c_client *client)
+{
+ uint8_t cmd[4];
+ uint8_t data[64] = {0};
+
+ //=====================================
+ // Read FW version : 0x0000_E303
+ //=====================================
+ cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
+ himax_register_read(client, cmd, 1, data);
+
+ ic_data->vendor_config_ver = data[3]<<8;
+
+ cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
+ himax_register_read(client, cmd, 1, data);
+
+ ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
+ I("CFG_VER : %X \n",ic_data->vendor_config_ver);
+
+ cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
+ himax_register_read(client, cmd, 1, data);
+
+ ic_data->vendor_fw_ver = data[0]<<8 | data[1];
+ I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+
+
+ return;
+}
+
+bool himax_ic_package_check(struct i2c_client *client)
+{
+#if 0
+ uint8_t cmd[3];
+ uint8_t data[3];
+
+ memset(cmd, 0x00, sizeof(cmd));
+ memset(data, 0x00, sizeof(data));
+
+ if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
+ return false ;
+
+ if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
+ return false;
+
+ if((data[0] == 0x85 && data[1] == 0x29))
+ {
+ IC_TYPE = HX_85XX_F_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 64901; //0xFD85
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 64902; //0xFD86
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 64928; //0xFDA0
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 64940; //0xFDAC
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x F\n");
+ }
+ if((data[0] == 0x85 && data[1] == 0x30) || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29))
+ {
+ IC_TYPE = HX_85XX_E_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 133; //0x0085
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; //0x0086
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x E\n");
+ }
+ else if((data[0] == 0x85 && data[1] == 0x31))
+ {
+ IC_TYPE = HX_85XX_ES_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 133; //0x0085
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; //0x0086
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x ES\n");
+ }
+ else if ((data[0] == 0x85 && data[1] == 0x28) || (cmd[0] == 0x04 && cmd[1] == 0x85 &&
+ (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28))) {
+ IC_TYPE = HX_85XX_D_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; // 0x0086
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; // 0x00A0
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; // 0x00AC
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x D\n");
+ } else if ((data[0] == 0x85 && data[1] == 0x23) || (cmd[0] == 0x03 && cmd[1] == 0x85 &&
+ (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28 || cmd[2] == 0x29))) {
+ IC_TYPE = HX_85XX_C_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; // 0x0086
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 135; // 0x0087
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 147; // 0x0093
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x C\n");
+ } else if ((data[0] == 0x85 && data[1] == 0x26) ||
+ (cmd[0] == 0x02 && cmd[1] == 0x85 &&
+ (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
+ IC_TYPE = HX_85XX_B_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 728; // 0x02D8
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 692; // 0x02B4
+ CFG_VER_MAJ_FLASH_LENG = 3;
+ CFG_VER_MIN_FLASH_ADDR = 704; // 0x02C0
+ CFG_VER_MIN_FLASH_LENG = 3;
+ I("Himax IC package 852x B\n");
+ } else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
+ cmd[1] == 0x85 && cmd[2] == 0x19)) {
+ IC_TYPE = HX_85XX_A_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+ I("Himax IC package 852x A\n");
+ } else {
+ E("Himax IC package incorrect!!\n");
+ }*/
+#else
+ IC_TYPE = HX_83100_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ //Himax: Set FW and CFG Flash Address
+ FW_VER_MAJ_FLASH_ADDR = 57384; //0xE028
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 57385; //0xE029
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 58115; //0xE303
+ CFG_VER_MAJ_FLASH_LENG = 1;
+ CFG_VER_MIN_FLASH_ADDR = 58116; //0xE304
+ CFG_VER_MIN_FLASH_LENG = 1;
+ I("Himax IC package 83100_in\n");
+
+#endif
+ return true;
+}
+
+void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length)
+{
+ uint8_t cmd[4];
+
+ cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
+ if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+
+ cmd[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+
+ i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
+}
+
+#if 0
+static void himax_83100_Flash_Write(uint8_t * reg_byte, uint8_t * write_data)
+{
+ uint8_t tmpbyte[2];
+
+ if ( i2c_himax_write(private_ts->client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if (isBusrtOn == false)
+ {
+ tmpbyte[0] = 0x01;
+ if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ }
+}
+#endif
+#if 0
+static void himax_83100_Flash_Burst_Write(uint8_t * reg_byte, uint8_t * write_data)
+{
+ //uint8_t tmpbyte[2];
+ int i = 0;
+
+ if ( i2c_himax_write(private_ts->client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ // Write 256 bytes with continue burst mode
+ for (i = 0; i < 256; i = i + 4)
+ {
+ if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ }
+
+ //if (isBusrtOn == false)
+ //{
+ // tmpbyte[0] = 0x01;
+ // if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, 3) < 0) {
+ // E("%s: i2c access fail!\n", __func__);
+ // return;
+ // }
+ //}
+
+}
+#endif
+
+#if 0
+static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
+{
+ uint8_t tmp_addr[4];
+ uint8_t tmp_data[4];
+ uint8_t out_buffer[20];
+ uint8_t in_buffer[260];
+
+ int fail_addr=0, fail_cnt=0;
+ int page_prog_start = 0;
+ int i = 0;
+
+ himax_interface_on(private_ts->client);
+ himax_burst_enable(private_ts->client, 0);
+
+ //=====================================
+ // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ //=====================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+ for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
+ {
+ //=================================
+ // SPI Transfer Control
+ // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+ // Set read start address : 0x8000_0028 ==> 0x0000_0000
+ // Set command : 0x8000_0024 ==> 0x0000_003B
+ //=================================
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+ himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
+ {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+ himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+ //==================================
+ // AHB_I2C Burst Read
+ // Set SPI data register : 0x8000_002C ==> 0x00
+ //==================================
+ out_buffer[0] = 0x2C;
+ out_buffer[1] = 0x00;
+ out_buffer[2] = 0x00;
+ out_buffer[3] = 0x80;
+ i2c_himax_write(private_ts->client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
+
+ //==================================
+ // Read access : 0x0C ==> 0x00
+ //==================================
+ out_buffer[0] = 0x00;
+ i2c_himax_write(private_ts->client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
+
+ //==================================
+ // Read 128 bytes two times
+ //==================================
+ i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+ for (i = 0; i < 128; i++)
+ flash_buffer[i + page_prog_start] = in_buffer[i];
+
+ i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+ for (i = 0; i < 128; i++)
+ flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+
+ //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ //himax_register_read(tmp_addr, 32, out in_buffer);
+ //for (int i = 0; i < 128; i++)
+ // flash_buffer[i + page_prog_start] = in_buffer[i];
+ //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ //himax_register_read(tmp_addr, 32, out in_buffer);
+ //for (int i = 0; i < 128; i++)
+ // flash_buffer[i + page_prog_start] = in_buffer[i];
+
+ I("%s:Verify Progress: %x\n", __func__, page_prog_start);
+ }
+
+ fail_cnt = 0;
+ for (i = 0; i < FW_Size; i++)
+ {
+ if (FW_File[i] != flash_buffer[i])
+ {
+ if (fail_cnt == 0)
+ fail_addr = i;
+
+ fail_cnt++;
+ //E("%s Fail Block:%x\n", __func__, i);
+ //return false;
+ }
+ }
+ if (fail_cnt > 0)
+ {
+ E("%s:Start Fail Block:%x and fail block count=%x\n" , __func__,fail_addr,fail_cnt);
+ return false;
+ }
+
+ I("%s:Byte read verify pass.\n", __func__);
+ return true;
+
+}
+#endif
+
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data)
+{
+ int i;
+ int cnt = 0;
+ unsigned char tmp_addr[4];
+ unsigned char tmp_data[4];
+ uint8_t max_i2c_size = 32;
+ int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
+ int total_size_4bytes = total_size / 4;
+ int total_read_times = 0;
+ unsigned long address = 0x08000468;
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+ do
+ {
+ cnt++;
+ himax_register_read(client, tmp_addr, 1, tmp_data);
+ usleep_range(10000, 20000);
+ } while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
+ if (total_size_4bytes % max_i2c_size == 0)
+ {
+ total_read_times = total_size_4bytes / max_i2c_size;
+ }
+ else
+ {
+ total_read_times = total_size_4bytes / max_i2c_size + 1;
+ }
+ for (i = 0; i < (total_read_times); i++)
+ {
+ if ( total_size_4bytes >= max_i2c_size)
+ {
+ himax_register_read(client, tmp_addr, max_i2c_size, &info_data[i*max_i2c_size*4]);
+ total_size_4bytes = total_size_4bytes - max_i2c_size;
+ }
+ else
+ {
+ himax_register_read(client, tmp_addr, total_size_4bytes % max_i2c_size, &info_data[i*max_i2c_size*4]);
+ }
+ address += max_i2c_size*4;
+ tmp_addr[1] = (uint8_t)((address>>8)&0x00FF);
+ tmp_addr[0] = (uint8_t)((address)&0x00FF);
+ }
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+ tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+//ts_work
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max){
+ int RawDataLen;
+ if (raw_cnt_rmd != 0x00) {
+ RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1;
+ }else{
+ RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1;
+ }
+ return RawDataLen;
+}
+
+bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length)
+{
+ uint8_t cmd[4];
+
+ if(length > 56)
+ length = 124;
+ //=====================
+ //AHB I2C Burst Read
+ //=====================
+ cmd[0] = 0x31;
+ if ( i2c_himax_write(client, 0x13 ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ goto err_workqueue_out;
+ }
+
+ cmd[0] = 0x10;
+ if ( i2c_himax_write(client, 0x0D ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ goto err_workqueue_out;
+ }
+ //=====================
+ //Read event stack
+ //=====================
+ cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
+ if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ goto err_workqueue_out;
+ }
+
+ cmd[0] = 0x00;
+ if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ goto err_workqueue_out;
+ }
+ i2c_himax_read(client, 0x08, buf, length,HIMAX_I2C_RETRY_TIMES);
+ return 1;
+
+ err_workqueue_out:
+ return 0;
+}
+
+bool post_read_event_stack(struct i2c_client *client)
+{
+ return 1;
+}
+bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf) //return checksum value
+{
+ uint16_t check_sum_cal = 0;
+ int i;
+
+ //Check 124th byte CRC
+ for (i = hx_touch_info_size, check_sum_cal = 0; i < 124; i=i+2)
+ {
+ check_sum_cal += (buf[i+1]*256 + buf[i]);
+ }
+ if (check_sum_cal % 0x10000 != 0)
+ {
+ I("%s: diag check sum fail! check_sum_cal=%X, hx_touch_info_size=%d, \n",__func__,check_sum_cal, hx_touch_info_size);
+ return 0;
+ }
+ return 1;
+}
+
+
+void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
+{
+ int RawDataLen_word;
+ int index = 0;
+ int temp1, temp2,i;
+
+ if (buf[hx_touch_info_size] == 0x3A && buf[hx_touch_info_size+1] == 0xA3 && buf[hx_touch_info_size+2] > 0 && buf[hx_touch_info_size+3] == diag_cmd+5 )
+ {
+ RawDataLen_word = RawDataLen/2;
+ index = (buf[hx_touch_info_size+2] - 1) * RawDataLen_word;
+ //I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
+ for (i = 0; i < RawDataLen_word; i++)
+ {
+ temp1 = index + i;
+
+ if (temp1 < mul_num)
+ { //mutual
+ mutual_data[index + i] = buf[i*2 + hx_touch_info_size+4+1]*256 + buf[i*2 + hx_touch_info_size+4]; //4: RawData Header, 1:HSB
+ }
+ else
+ {//self
+ temp1 = i + index;
+ temp2 = self_num + mul_num;
+
+ if (temp1 >= temp2)
+ {
+ break;
+ }
+
+ self_data[i+index-mul_num] = buf[i*2 + hx_touch_info_size+4]; //4: RawData Header
+ self_data[i+index-mul_num+1] = buf[i*2 + hx_touch_info_size+4+1];
+ }
+ }
+ }
+ else
+ {
+ I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
+ I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
+ }
+}
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h
new file mode 100644
index 000000000000..18cd12b8b36f
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.h
@@ -0,0 +1,82 @@
+/* Himax Android Driver Sample Code for HMX83100 chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_platform.h"
+#include "himax_common.h"
+
+#include <linux/slab.h>
+
+
+#define HX_85XX_A_SERIES_PWON 1
+#define HX_85XX_B_SERIES_PWON 2
+#define HX_85XX_C_SERIES_PWON 3
+#define HX_85XX_D_SERIES_PWON 4
+#define HX_85XX_E_SERIES_PWON 5
+#define HX_85XX_ES_SERIES_PWON 6
+#define HX_85XX_F_SERIES_PWON 7
+#define HX_83100_SERIES_PWON 8
+
+#define HX_TP_BIN_CHECKSUM_SW 1
+#define HX_TP_BIN_CHECKSUM_HW 2
+#define HX_TP_BIN_CHECKSUM_CRC 3
+
+enum fw_image_type {
+ fw_image_60k = 0x01,
+ fw_image_64k,
+ fw_image_124k,
+ fw_image_128k,
+};
+
+int himax_hand_shaking(struct i2c_client *client);
+void himax_set_SMWP_enable(struct i2c_client *client,uint8_t SMWP_enable);
+void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data);
+void himax_set_HSEN_enable(struct i2c_client *client,uint8_t HSEN_enable);
+void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data);
+void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command);
+void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+int himax_chip_self_test(struct i2c_client *client);
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); ////himax_83100_BURST_INC0_EN
+void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data); ////RegisterRead83100
+void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data); ////himax_83100_Flash_Read
+void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data); ////himax_83100_Flash_Write_Burst
+int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length); ////himax_83100_Flash_Write_Burst_lenth
+int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data); ////RegisterWrite83100
+void himax_sense_off(struct i2c_client *client); ////himax_83100_SenseOff
+void himax_interface_on(struct i2c_client *client); ////himax_83100_Interface_on
+bool wait_wip(struct i2c_client *client, int Timing);
+void himax_sense_on(struct i2c_client *client, uint8_t FlashMode); ////himax_83100_SenseOn
+void himax_chip_erase(struct i2c_client *client); ////himax_83100_Chip_Erase
+bool himax_block_erase(struct i2c_client *client); ////himax_83100_Block_Erase
+bool himax_sector_erase(struct i2c_client *client, int start_addr); ////himax_83100_Sector_Erase
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); ////himax_83100_Sram_Write
+bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size); ////himax_83100_Sram_Verify
+void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size); ////himax_83100_Flash_Programming
+bool himax_check_chip_version(struct i2c_client *client); ////himax_83100_CheckChipVersion
+int himax_check_CRC(struct i2c_client *client, int mode); ////himax_83100_Check_CRC
+bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode);
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+void himax_touch_information(struct i2c_client *client);
+void himax_read_FW_ver(struct i2c_client *client);
+bool himax_ic_package_check(struct i2c_client *client);
+void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length);
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max);
+bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length);
+bool post_read_event_stack(struct i2c_client *client);
+bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf_ts); //return checksum value
+void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf_ts, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data);
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data); \ No newline at end of file
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c
new file mode 100644
index 000000000000..7e8a1d6572c5
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.c
@@ -0,0 +1,796 @@
+/* Himax Android Driver Sample Code for HIMAX chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 "himax_platform.h"
+#include "himax_common.h"
+
+int irq_enable_count = 0;
+#ifdef HX_SMART_WAKEUP
+#define TS_WAKE_LOCK_TIMEOUT (2 * HZ)
+#endif
+
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
+
+extern struct himax_ic_data* ic_data;
+extern void himax_ts_work(struct himax_ts_data *ts);
+extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer);
+extern int himax_ts_init(struct himax_ts_data *ts);
+
+extern int tp_rst_gpio;
+
+#ifdef HX_TP_PROC_DIAG
+extern uint8_t getDiagCommand(void);
+#endif
+
+void himax_vk_parser(struct device_node *dt,
+ struct himax_i2c_platform_data *pdata)
+{
+ u32 data = 0;
+ uint8_t cnt = 0, i = 0;
+ uint32_t coords[4] = {0};
+ struct device_node *node, *pp = NULL;
+ struct himax_virtual_key *vk;
+
+ node = of_parse_phandle(dt, "virtualkey", 0);
+ if (node == NULL) {
+ I(" DT-No vk info in DT");
+ return;
+ } else {
+ while ((pp = of_get_next_child(node, pp)))
+ cnt++;
+ if (!cnt)
+ return;
+
+ vk = kzalloc(cnt * (sizeof *vk), GFP_KERNEL);
+ if (!vk)
+ return;
+ pp = NULL;
+ while ((pp = of_get_next_child(node, pp))) {
+ if (of_property_read_u32(pp, "idx", &data) == 0)
+ vk[i].index = data;
+ if (of_property_read_u32_array(pp, "range", coords, 4) == 0) {
+ vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1];
+ vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3];
+ } else
+ I(" range faile");
+ i++;
+ }
+ pdata->virtual_key = vk;
+ for (i = 0; i < cnt; i++)
+ I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,pdata->virtual_key[i].index,
+ pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max);
+ }
+}
+
+int himax_parse_dt(struct himax_ts_data *ts,
+ struct himax_i2c_platform_data *pdata)
+{
+ int rc, coords_size = 0;
+ uint32_t coords[4] = {0};
+ struct property *prop;
+ struct device_node *dt = ts->client->dev.of_node;
+ u32 data = 0;
+
+ prop = of_find_property(dt, "himax,panel-coords", NULL);
+ if (prop) {
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != 4)
+ D(" %s:Invalid panel coords size %d", __func__, coords_size);
+ }
+
+ if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) {
+ pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1];
+ pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3];
+ I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min,
+ pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max);
+ }
+
+ prop = of_find_property(dt, "himax,display-coords", NULL);
+ if (prop) {
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != 4)
+ D(" %s:Invalid display coords size %d", __func__, coords_size);
+ }
+ rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ D(" %s:Fail to read display-coords %d\n", __func__, rc);
+ return rc;
+ }
+ pdata->screenWidth = coords[1];
+ pdata->screenHeight = coords[3];
+ I(" DT-%s:display-coords = (%d, %d)", __func__, pdata->screenWidth,
+ pdata->screenHeight);
+
+ pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0);
+ if (!gpio_is_valid(pdata->gpio_irq)) {
+ I(" DT:gpio_irq value is not valid\n");
+ }
+
+ pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0);
+ if (!gpio_is_valid(pdata->gpio_reset)) {
+ I(" DT:gpio_rst value is not valid\n");
+ }
+ pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0);
+ if (!gpio_is_valid(pdata->gpio_3v3_en)) {
+ I(" DT:gpio_3v3_en value is not valid\n");
+ }
+ I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en);
+
+ if (of_property_read_u32(dt, "report_type", &data) == 0) {
+ pdata->protocol_type = data;
+ I(" DT:protocol_type=%d", pdata->protocol_type);
+ }
+
+ himax_vk_parser(dt, pdata);
+
+ return 0;
+}
+
+int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+{
+ int retry;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &command,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = data,
+ }
+ };
+
+ for (retry = 0; retry < toRetry; retry++) {
+ if (i2c_transfer(client->adapter, msg, 2) == 2)
+ break;
+ msleep(20);
+ }
+ if (retry == toRetry) {
+ E("%s: i2c_read_block retry over %d\n",
+ __func__, toRetry);
+ return -EIO;
+ }
+ return 0;
+
+}
+
+int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+{
+ int retry/*, loop_i*/;
+ uint8_t buf[length + 1];
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = length + 1,
+ .buf = buf,
+ }
+ };
+
+ buf[0] = command;
+ memcpy(buf+1, data, length);
+
+ for (retry = 0; retry < toRetry; retry++) {
+ if (i2c_transfer(client->adapter, msg, 1) == 1)
+ break;
+ msleep(20);
+ }
+
+ if (retry == toRetry) {
+ E("%s: i2c_write_block retry over %d\n",
+ __func__, toRetry);
+ return -EIO;
+ }
+ return 0;
+
+}
+
+int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry)
+{
+ int retry;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = data,
+ }
+ };
+
+ for (retry = 0; retry < toRetry; retry++) {
+ if (i2c_transfer(client->adapter, msg, 1) == 1)
+ break;
+ msleep(20);
+ }
+ if (retry == toRetry) {
+ E("%s: i2c_read_block retry over %d\n",
+ __func__, toRetry);
+ return -EIO;
+ }
+ return 0;
+}
+
+int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry)
+{
+ return i2c_himax_write(client, command, NULL, 0, toRetry);
+}
+
+int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry)
+{
+ int retry/*, loop_i*/;
+ uint8_t buf[length];
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = length,
+ .buf = buf,
+ }
+ };
+
+ memcpy(buf, data, length);
+
+ for (retry = 0; retry < toRetry; retry++) {
+ if (i2c_transfer(client->adapter, msg, 1) == 1)
+ break;
+ msleep(20);
+ }
+
+ if (retry == toRetry) {
+ E("%s: i2c_write_block retry over %d\n",
+ __func__, toRetry);
+ return -EIO;
+ }
+ return 0;
+}
+
+void himax_int_enable(int irqnum, int enable)
+{
+ if (enable == 1 && irq_enable_count == 0) {
+ enable_irq(irqnum);
+ irq_enable_count++;
+ } else if (enable == 0 && irq_enable_count == 1) {
+ disable_irq_nosync(irqnum);
+ irq_enable_count--;
+ }
+ I("irq_enable_count = %d", irq_enable_count);
+}
+
+void himax_rst_gpio_set(int pinnum, uint8_t value)
+{
+ gpio_direction_output(pinnum, value);
+}
+
+uint8_t himax_int_gpio_read(int pinnum)
+{
+ return gpio_get_value(pinnum);
+}
+
+#if defined(CONFIG_HMX_DB)
+static int himax_regulator_configure(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+{
+ int retval;
+ pdata->vcc_dig = regulator_get(&client->dev,
+ "vdd");
+ if (IS_ERR(pdata->vcc_dig))
+ {
+ E("%s: Failed to get regulator vdd\n",
+ __func__);
+ retval = PTR_ERR(pdata->vcc_dig);
+ return retval;
+ }
+ pdata->vcc_ana = regulator_get(&client->dev,
+ "avdd");
+ if (IS_ERR(pdata->vcc_ana))
+ {
+ E("%s: Failed to get regulator avdd\n",
+ __func__);
+ retval = PTR_ERR(pdata->vcc_ana);
+ regulator_put(pdata->vcc_ana);
+ return retval;
+ }
+
+ return 0;
+};
+
+static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on)
+{
+ int retval;
+
+ if (on)
+ {
+ retval = regulator_enable(pdata->vcc_dig);
+ if (retval)
+ {
+ E("%s: Failed to enable regulator vdd\n",
+ __func__);
+ return retval;
+ }
+ msleep(100);
+ retval = regulator_enable(pdata->vcc_ana);
+ if (retval)
+ {
+ E("%s: Failed to enable regulator avdd\n",
+ __func__);
+ regulator_disable(pdata->vcc_dig);
+ return retval;
+ }
+ }
+ else
+ {
+ regulator_disable(pdata->vcc_dig);
+ regulator_disable(pdata->vcc_ana);
+ }
+
+ return 0;
+}
+
+int himax_ts_pinctrl_init(struct himax_ts_data *ts)
+{
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ts->ts_pinctrl = devm_pinctrl_get(&(ts->client->dev));
+ if (IS_ERR_OR_NULL(ts->ts_pinctrl)) {
+ retval = PTR_ERR(ts->ts_pinctrl);
+ dev_dbg(&ts->client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ts->pinctrl_state_active
+ = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ts->pinctrl_state_active)) {
+ retval = PTR_ERR(ts->pinctrl_state_active);
+ dev_err(&ts->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts->pinctrl_state_suspend
+ = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ts->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ts->pinctrl_state_suspend);
+ dev_err(&ts->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts->pinctrl_state_release
+ = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) {
+ retval = PTR_ERR(ts->pinctrl_state_release);
+ dev_dbg(&ts->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ts->ts_pinctrl);
+err_pinctrl_get:
+ ts->ts_pinctrl = NULL;
+ return retval;
+}
+
+int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+{
+ int error;
+
+ error = himax_regulator_configure(client, pdata);
+ if (error)
+ {
+ E("Failed to intialize hardware\n");
+ goto err_regulator_not_on;
+ }
+
+#ifdef HX_RST_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_reset))
+ {
+ /* configure touchscreen reset out gpio */
+ error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio");
+ if (error)
+ {
+ E("unable to request gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_regulator_on;
+ }
+
+ error = gpio_direction_output(pdata->gpio_reset, 0);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_gpio_reset_req;
+ }
+ }
+#endif
+
+ error = himax_power_on(pdata, true);
+ if (error)
+ {
+ E("Failed to power on hardware\n");
+ goto err_gpio_reset_req;
+ }
+#ifdef HX_IRQ_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_irq))
+ {
+ /* configure touchscreen irq gpio */
+ error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq");
+ if (error)
+ {
+ E("unable to request gpio [%d]\n",
+ pdata->gpio_irq);
+ goto err_power_on;
+ }
+ error = gpio_direction_input(pdata->gpio_irq);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_irq);
+ goto err_gpio_irq_req;
+ }
+ client->irq = gpio_to_irq(pdata->gpio_irq);
+ }
+ else
+ {
+ E("irq gpio not provided\n");
+ goto err_power_on;
+ }
+#endif
+
+ msleep(20);
+
+#ifdef HX_RST_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_reset))
+ {
+ error = gpio_direction_output(pdata->gpio_reset, 1);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_gpio_irq_req;
+ }
+ }
+#endif
+ return 0;
+#ifdef HX_RST_PIN_FUNC
+ err_gpio_irq_req:
+#endif
+#ifdef HX_IRQ_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_irq))
+ gpio_free(pdata->gpio_irq);
+ err_power_on:
+#endif
+ himax_power_on(pdata, false);
+ err_gpio_reset_req:
+#ifdef HX_RST_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_reset))
+ gpio_free(pdata->gpio_reset);
+ err_regulator_on:
+#endif
+ err_regulator_not_on:
+
+ return error;
+}
+
+#else
+int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+{
+ int error=0;
+
+#ifdef HX_RST_PIN_FUNC
+ if (pdata->gpio_reset >= 0)
+ {
+ error = gpio_request(pdata->gpio_reset, "himax-reset");
+ if (error < 0)
+ {
+ E("%s: request reset pin failed\n", __func__);
+ return error;
+ }
+ error = gpio_direction_output(pdata->gpio_reset, 0);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ return error;
+ }
+ }
+#endif
+ if (pdata->gpio_3v3_en >= 0)
+ {
+ error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en");
+ if (error < 0)
+ {
+ E("%s: request 3v3_en pin failed\n", __func__);
+ return error;
+ }
+ gpio_direction_output(pdata->gpio_3v3_en, 1);
+ I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en));
+ }
+
+#ifdef HX_IRQ_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_irq))
+ {
+ /* configure touchscreen irq gpio */
+ error = gpio_request(pdata->gpio_irq, "himax_gpio_irq");
+ if (error)
+ {
+ E("unable to request gpio [%d]\n",pdata->gpio_irq);
+ return error;
+ }
+ error = gpio_direction_input(pdata->gpio_irq);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",pdata->gpio_irq);
+ return error;
+ }
+ client->irq = gpio_to_irq(pdata->gpio_irq);
+ }
+ else
+ {
+ E("irq gpio not provided\n");
+ return error;
+ }
+#endif
+
+ msleep(20);
+
+#ifdef HX_RST_PIN_FUNC
+ if (pdata->gpio_reset >= 0)
+ {
+ error = gpio_direction_output(pdata->gpio_reset, 1);
+ if (error)
+ {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ return error;
+ }
+ }
+ msleep(20);
+#endif
+
+ return error;
+ }
+#endif
+
+static void himax_ts_isr_func(struct himax_ts_data *ts)
+{
+ himax_ts_work(ts);
+}
+
+irqreturn_t himax_ts_thread(int irq, void *ptr)
+{
+ uint8_t diag_cmd;
+ struct himax_ts_data *ts = ptr;
+ struct timespec timeStart, timeEnd, timeDelta;
+
+ diag_cmd = getDiagCommand();
+
+ if (ts->debug_log_level & BIT(2)) {
+ getnstimeofday(&timeStart);
+ usleep_range(5000, 7000);
+ //I(" Irq start time = %ld.%06ld s\n",
+ // timeStart.tv_sec, timeStart.tv_nsec/1000);
+ }
+
+#ifdef HX_SMART_WAKEUP
+ if (atomic_read(&ts->suspend_mode)&&(!FAKE_POWER_KEY_SEND)&&(ts->SMWP_enable)&&(!diag_cmd)) {
+ wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
+ msleep(200);
+ himax_wake_check_func();
+ return IRQ_HANDLED;
+ }
+#endif
+ himax_ts_isr_func((struct himax_ts_data *)ptr);
+ if(ts->debug_log_level & BIT(2)) {
+ getnstimeofday(&timeEnd);
+ timeDelta.tv_nsec = (timeEnd.tv_sec*1000000000+timeEnd.tv_nsec)
+ -(timeStart.tv_sec*1000000000+timeStart.tv_nsec);
+ //I("Irq finish time = %ld.%06ld s\n",
+ // timeEnd.tv_sec, timeEnd.tv_nsec/1000);
+ //I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);
+ }
+ return IRQ_HANDLED;
+}
+
+static void himax_ts_work_func(struct work_struct *work)
+{
+ struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work);
+ himax_ts_work(ts);
+}
+
+int tp_irq = -1;
+
+int himax_ts_register_interrupt(struct i2c_client *client)
+{
+ struct himax_ts_data *ts = i2c_get_clientdata(client);
+ int ret = 0;
+
+ ts->irq_enabled = 0;
+ //Work functon
+ if (client->irq) {/*INT mode*/
+ ts->use_irq = 1;
+ if(ic_data->HX_INT_IS_EDGE)
+ {
+ I("%s edge triiger falling\n ",__func__);
+ ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts);
+ }
+ else
+ {
+ I("%s level trigger low\n ",__func__);
+ ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts);
+ }
+ if (ret == 0) {
+ ts->irq_enabled = 1;
+ irq_enable_count = 1;
+ tp_irq = client->irq;
+ I("%s: irq enabled at qpio: %d\n", __func__, client->irq);
+#ifdef HX_SMART_WAKEUP
+ irq_set_irq_wake(client->irq, 1);
+#endif
+ } else {
+ ts->use_irq = 0;
+ E("%s: request_irq failed\n", __func__);
+ }
+ } else {
+ I("%s: client->irq is empty, use polling mode.\n", __func__);
+ }
+
+ if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_WORKAROUND function*/
+ ts->himax_wq = create_singlethread_workqueue("himax_touch");
+
+ INIT_WORK(&ts->work, himax_ts_work_func);
+
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = himax_ts_timer_func;
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ I("%s: polling mode enabled\n", __func__);
+ }
+ return ret;
+}
+
+static int himax_common_suspend(struct device *dev)
+{
+ struct himax_ts_data *ts = dev_get_drvdata(dev);
+
+ I("%s: enter \n", __func__);
+
+ himax_chip_common_suspend(ts);
+ return 0;
+}
+
+static int himax_common_resume(struct device *dev)
+{
+ struct himax_ts_data *ts = dev_get_drvdata(dev);
+
+ I("%s: enter \n", __func__);
+
+ himax_chip_common_resume(ts);
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct himax_ts_data *ts=
+ container_of(self, struct himax_ts_data, fb_notif);
+
+ I(" %s\n", __func__);
+ if (evdata && evdata->data && event == FB_EVENT_BLANK && ts &&
+ ts->client) {
+ blank = evdata->data;
+
+ mutex_lock(&ts->fb_mutex);
+ switch (*blank) {
+ case FB_BLANK_UNBLANK:
+ if (!ts->probe_done) {
+ himax_ts_init(ts);
+ ts->probe_done = true;
+ } else {
+ himax_common_resume(&ts->client->dev);
+ }
+ break;
+
+ case FB_BLANK_POWERDOWN:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ himax_common_suspend(&ts->client->dev);
+ break;
+ }
+ mutex_unlock(&ts->fb_mutex);
+ }
+
+ return 0;
+}
+#endif
+
+static const struct i2c_device_id himax_common_ts_id[] = {
+ {HIMAX_common_NAME, 0 },
+ {}
+};
+
+static const struct dev_pm_ops himax_common_pm_ops = {
+#if (!defined(CONFIG_FB))
+ .suspend = himax_common_suspend,
+ .resume = himax_common_resume,
+#endif
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id himax_match_table[] = {
+ {.compatible = "himax,hxcommon" },
+ {},
+};
+#else
+#define himax_match_table NULL
+#endif
+
+static struct i2c_driver himax_common_driver = {
+ .id_table = himax_common_ts_id,
+ .probe = himax_chip_common_probe,
+ .remove = himax_chip_common_remove,
+ .driver = {
+ .name = HIMAX_common_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = himax_match_table,
+#ifdef CONFIG_PM
+ .pm = &himax_common_pm_ops,
+#endif
+ },
+};
+
+static void __init himax_common_init_async(void *unused, async_cookie_t cookie)
+{
+ I("%s:Enter \n", __func__);
+ i2c_add_driver(&himax_common_driver);
+}
+
+static int __init himax_common_init(void)
+{
+ I("Himax common touch panel driver init\n");
+ async_schedule(himax_common_init_async, NULL);
+ return 0;
+}
+
+static void __exit himax_common_exit(void)
+{
+ i2c_del_driver(&himax_common_driver);
+}
+
+module_init(himax_common_init);
+module_exit(himax_common_exit);
+
+MODULE_DESCRIPTION("Himax_common driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h
new file mode 100644
index 000000000000..1223685683aa
--- /dev/null
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.h
@@ -0,0 +1,135 @@
+/* Himax Android Driver Sample Code for Himax chipset
+*
+* Copyright (C) 2015 Himax Corporation.
+*
+* 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 HIMAX_PLATFORM_H
+#define HIMAX_PLATFORM_H
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#if defined(CONFIG_HMX_DB)
+#include <linux/regulator/consumer.h>
+#endif
+
+#define QCT
+
+#define HIMAX_I2C_RETRY_TIMES 10
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+#define D(x...) pr_debug("[HXTP] " x)
+#define I(x...) pr_info("[HXTP] " x)
+#define W(x...) pr_warning("[HXTP][WARNING] " x)
+#define E(x...) pr_err("[HXTP][ERROR] " x)
+#define DIF(x...) \
+do {\
+ if (debug_flag) \
+ pr_debug("[HXTP][DEBUG] " x) \
+} while(0)
+#else
+#define D(x...)
+#define I(x...)
+#define W(x...)
+#define E(x...)
+#define DIF(x...)
+#endif
+
+#if defined(CONFIG_HMX_DB)
+/* Analog voltage @2.7 V */
+#define HX_VTG_MIN_UV 2700000
+#define HX_VTG_MAX_UV 3300000
+#define HX_ACTIVE_LOAD_UA 15000
+#define HX_LPM_LOAD_UA 10
+/* Digital voltage @1.8 V */
+#define HX_VTG_DIG_MIN_UV 1800000
+#define HX_VTG_DIG_MAX_UV 1800000
+#define HX_ACTIVE_LOAD_DIG_UA 10000
+#define HX_LPM_LOAD_DIG_UA 10
+
+#define HX_I2C_VTG_MIN_UV 1800000
+#define HX_I2C_VTG_MAX_UV 1800000
+#define HX_I2C_LOAD_UA 10000
+#define HX_I2C_LPM_LOAD_UA 10
+#endif
+
+#define HIMAX_common_NAME "himax_tp"
+#define HIMAX_I2C_ADDR 0x48
+#define INPUT_DEV_NAME "himax-touchscreen"
+
+struct himax_i2c_platform_data {
+ int abs_x_min;
+ int abs_x_max;
+ int abs_x_fuzz;
+ int abs_y_min;
+ int abs_y_max;
+ int abs_y_fuzz;
+ int abs_pressure_min;
+ int abs_pressure_max;
+ int abs_pressure_fuzz;
+ int abs_width_min;
+ int abs_width_max;
+ int screenWidth;
+ int screenHeight;
+ uint8_t fw_version;
+ uint8_t tw_id;
+ uint8_t powerOff3V3;
+ uint8_t cable_config[2];
+ uint8_t protocol_type;
+ int gpio_irq;
+ int gpio_reset;
+ int gpio_3v3_en;
+ int (*power)(int on);
+ void (*reset)(void);
+ struct himax_virtual_key *virtual_key;
+ struct kobject *vk_obj;
+ struct kobj_attribute *vk2Use;
+
+ struct himax_config *hx_config;
+ int hx_config_size;
+#if defined(CONFIG_HMX_DB)
+ bool i2c_pull_up;
+ bool digital_pwr_regulator;
+ int reset_gpio;
+ u32 reset_gpio_flags;
+ int irq_gpio;
+ u32 irq_gpio_flags;
+
+ struct regulator *vcc_ana; //For Dragon Board
+ struct regulator *vcc_dig; //For Dragon Board
+ struct regulator *vcc_i2c; //For Dragon Board
+#endif
+};
+
+
+extern int irq_enable_count;
+extern int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
+extern int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
+extern int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry);
+extern int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry);
+extern int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry);
+extern void himax_int_enable(int irqnum, int enable);
+extern int himax_ts_register_interrupt(struct i2c_client *client);
+extern void himax_rst_gpio_set(int pinnum, uint8_t value);
+extern uint8_t himax_int_gpio_read(int pinnum);
+
+extern int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata);
+
+#if defined(CONFIG_FB)
+extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
+#endif
+
+#endif
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c
index 2c670eea1852..60f0983ad519 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c
@@ -918,9 +918,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_CFG_STREAM:
mutex_lock(&vfe_dev->core_mutex);
- mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_CFG_HW_STATE:
@@ -1021,9 +1019,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
mutex_lock(&vfe_dev->core_mutex);
- mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index aec7faa65bad..40c343014501 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -652,6 +652,8 @@ int vfe_hw_probe(struct platform_device *pdev)
spin_lock_init(&vfe_dev->shared_data_lock);
spin_lock_init(&vfe_dev->reg_update_lock);
spin_lock_init(&req_history_lock);
+ spin_lock_init(&vfe_dev->reset_completion_lock);
+ spin_lock_init(&vfe_dev->halt_completion_lock);
media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index d223401d8688..f1cf72e53b6d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -740,6 +740,8 @@ struct vfe_device {
struct mutex core_mutex;
spinlock_t shared_data_lock;
spinlock_t reg_update_lock;
+ spinlock_t reset_completion_lock;
+ spinlock_t halt_completion_lock;
spinlock_t tasklet_lock;
/* Tasklet info */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index c216defef880..d494328e82cc 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -358,15 +358,24 @@ static void msm_vfe40_clear_status_reg(struct vfe_device *vfe_dev)
static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1)
{
- if (irq_status0 & (1 << 31))
+ unsigned long flags;
+
+ if (irq_status0 & (1 << 31)) {
+ spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
complete(&vfe_dev->reset_complete);
+ spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
+ }
}
static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1)
{
+ unsigned long flags;
+
if (irq_status1 & (1 << 8)) {
+ spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
complete(&vfe_dev->halt_complete);
+ spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
}
}
@@ -756,7 +765,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev,
uint32_t first_start, uint32_t blocking_call)
{
long rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
init_completion(&vfe_dev->reset_complete);
+ spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
if (first_start) {
msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
@@ -1720,6 +1733,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
{
int rc = 0;
enum msm_vfe_input_src i;
+ unsigned long flags;
/* Keep only halt and restart mask */
msm_vfe40_set_halt_restart_mask(vfe_dev);
@@ -1754,7 +1768,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
}
if (blocking) {
+ spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
init_completion(&vfe_dev->halt_complete);
+ spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
/* Halt AXI Bus Bridge */
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
rc = wait_for_completion_interruptible_timeout(
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 14f95e15b45b..b008bbf10eed 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1635,12 +1635,38 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event)
struct msm_isp_event_data error_event;
struct msm_vfe_axi_halt_cmd halt_cmd;
uint32_t irq_status0, irq_status1;
+ struct vfe_device *vfe_dev_other = NULL;
+ uint32_t vfe_id_other = 0;
+ unsigned long flags;
if (atomic_read(&vfe_dev->error_info.overflow_state) !=
NO_OVERFLOW)
/* Recovery is already in Progress */
return;
+ /* if there are no active streams - do not start recovery */
+ if (vfe_dev->is_split) {
+ if (vfe_dev->pdev->id == ISP_VFE0)
+ vfe_id_other = ISP_VFE1;
+ else
+ vfe_id_other = ISP_VFE0;
+ spin_lock_irqsave(
+ &vfe_dev->common_data->common_dev_data_lock, flags);
+ vfe_dev_other = vfe_dev->common_data->dual_vfe_res->
+ vfe_dev[vfe_id_other];
+ if (!vfe_dev->axi_data.num_active_stream ||
+ !vfe_dev_other->axi_data.num_active_stream) {
+ spin_unlock_irqrestore(
+ &vfe_dev->common_data->common_dev_data_lock,
+ flags);
+ pr_err("%s:skip the recovery as no active streams\n",
+ __func__);
+ return;
+ }
+ spin_unlock_irqrestore(
+ &vfe_dev->common_data->common_dev_data_lock, flags);
+ } else if (!vfe_dev->axi_data.num_active_stream)
+ return;
if (ISP_EVENT_PING_PONG_MISMATCH == event &&
vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) {
vfe_dev->hw_info->vfe_ops.irq_ops.
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index c77944a0a047..0a4b80e5cbe2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -689,8 +689,10 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev,
vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask;
rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams(
stats_data->stream_info);
- if (rc < 0)
+ if (rc < 0) {
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return rc;
+ }
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c
index 7c12fb9af6c4..9d6c0a9da277 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -43,6 +43,8 @@
#define ISPIF_TIMEOUT_SLEEP_US 1000
#define ISPIF_TIMEOUT_ALL_US 1000000
+#define CSID_VERSION_V37 0x30070000
+
#undef CDBG
#ifdef CONFIG_MSMB_CAMERA_DEBUG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -123,6 +125,11 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif)
ispif->clk_idx = 0;
+ if (ispif->csid_version != CSID_VERSION_V37) {
+ pr_err("%s:%d error returning\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
rc = msm_cam_clk_enable(&ispif->pdev->dev,
ispif_8974_reset_clk_info, reset_clk,
ARRAY_SIZE(ispif_8974_reset_clk_info), 1);
@@ -1255,8 +1262,12 @@ static int msm_ispif_init(struct ispif_device *ispif,
goto error_ahb;
}
- msm_ispif_reset_hw(ispif);
-
+ rc = msm_ispif_reset_hw(ispif);
+ if (rc < 0) {
+ pr_err("%s:%d msm_ispif_reset_hw failed\n", __func__,
+ __LINE__);
+ goto error_ahb;
+ }
rc = msm_ispif_reset(ispif);
if (rc == 0) {
ispif->ispif_state = ISPIF_POWER_UP;
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 4e03a7eac022..994d9de0e643 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -74,9 +74,6 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev,
new_entry->session_id = buf_info->session_id;
new_entry->stream_id = buf_info->stream_id;
new_entry->index = new_entry->vb2_buf->v4l2_buf.index;
- spin_lock_irqsave(&dev->buf_q_spinlock, flags);
- list_add_tail(&new_entry->entry, &dev->buf_qhead);
- spin_unlock_irqrestore(&dev->buf_q_spinlock, flags);
buf_info->index = new_entry->vb2_buf->v4l2_buf.index;
if (buf_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) {
mutex_lock(&dev->cont_mutex);
@@ -89,6 +86,16 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev,
}
mutex_unlock(&dev->cont_mutex);
}
+ if (!rc) {
+ spin_lock_irqsave(&dev->buf_q_spinlock, flags);
+ list_add_tail(&new_entry->entry, &dev->buf_qhead);
+ spin_unlock_irqrestore(&dev->buf_q_spinlock, flags);
+ } else {
+ pr_err("List not empty or msm_buf_mngr_hdl_cont_get_buf failed %pK\n",
+ new_entry->vb2_buf);
+ kfree(new_entry);
+ }
+
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 30ef850da4a3..026b4e308123 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -3032,7 +3032,7 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
{
int rc = 0;
struct msm_smem *handle;
- struct internal_buf *binfo;
+ struct internal_buf *binfo = NULL;
u32 smem_flags = 0, buffer_size;
struct hal_buffer_requirements *output_buf, *extradata_buf;
int i;
@@ -3138,10 +3138,10 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
}
return rc;
fail_set_buffers:
- kfree(binfo);
-fail_kzalloc:
msm_comm_smem_free(inst, handle);
err_no_mem:
+ kfree(binfo);
+fail_kzalloc:
return rc;
}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 84a0a9bbd125..f2955be61899 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,6 +1,6 @@
/*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -109,6 +109,9 @@
#define DEFAULT_CE_INFO_UNIT 0
#define DEFAULT_NUM_CE_INFO_UNIT 1
+#define FDE_FLAG_POS 4
+#define ENABLE_KEY_WRAP_IN_KS (1 << FDE_FLAG_POS)
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -273,6 +276,7 @@ struct qseecom_control {
unsigned int ce_opp_freq_hz;
bool appsbl_qseecom_support;
uint32_t qsee_reentrancy_support;
+ bool enable_key_wrap_in_ks;
uint32_t app_block_ref_cnt;
wait_queue_head_t app_block_wq;
@@ -5779,6 +5783,9 @@ static int qseecom_create_key(struct qseecom_dev_handle *data,
else
flags |= QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE;
+ if (qseecom.enable_key_wrap_in_ks == true)
+ flags |= ENABLE_KEY_WRAP_IN_KS;
+
generate_key_ireq.flags = flags;
generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY;
memset((void *)generate_key_ireq.key_id,
@@ -8467,6 +8474,14 @@ static int qseecom_probe(struct platform_device *pdev)
qseecom.qsee_reentrancy_support);
}
+ qseecom.enable_key_wrap_in_ks =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,enable-key-wrap-in-ks");
+ if (qseecom.enable_key_wrap_in_ks) {
+ pr_warn("qseecom.enable_key_wrap_in_ks = %d\n",
+ qseecom.enable_key_wrap_in_ks);
+ }
+
/*
* The qseecom bus scaling flag can not be enabled when
* crypto clock is not handled by HLOS.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b4ad723b4e36..7cceec44d2d8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -3002,6 +3002,13 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
pm_wakeup_event(mmc_dev(host), 5000);
host->detect_change = 1;
+ /*
+ * Change in cd_gpio state, so make sure detection part is
+ * not overided because of manual resume.
+ */
+ if (cd_irq && mmc_bus_manual_resume(host))
+ host->ignore_bus_resume_flags = true;
+
mmc_schedule_delayed_work(&host->detect, delay);
}
@@ -3923,6 +3930,8 @@ void mmc_rescan(struct work_struct *work)
host->bus_ops->detect(host);
host->detect_change = 0;
+ if (host->ignore_bus_resume_flags)
+ host->ignore_bus_resume_flags = false;
/*
* Let mmc_bus_put() free the bus/bus_ops if we've found that
@@ -4184,7 +4193,8 @@ int mmc_pm_notify(struct notifier_block *notify_block,
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 0;
- if (mmc_bus_manual_resume(host)) {
+ if (mmc_bus_manual_resume(host) &&
+ !host->ignore_bus_resume_flags) {
spin_unlock_irqrestore(&host->lock, flags);
break;
}
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index 071adc101158..1b4e40c0aff6 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -79,6 +79,13 @@
#define SDIO_DEVICE_ID_QCA9377 0x701
#endif
+#ifndef SDIO_VENDOR_ID_QCA9379
+#define SDIO_VENDOR_ID_QCA9379 0x271
+#endif
+
+#ifndef SDIO_DEVICE_ID_QCA9379
+#define SDIO_DEVICE_ID_QCA9379 0x801
+#endif
/*
* This hook just adds a quirk for all sdio devices
@@ -131,6 +138,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = {
SDIO_FIXUP(SDIO_VENDOR_ID_QCA9377, SDIO_DEVICE_ID_QCA9377,
add_quirk, MMC_QUIRK_QCA9377_SETTINGS),
+
+ SDIO_FIXUP(SDIO_VENDOR_ID_QCA9379, SDIO_DEVICE_ID_QCA9379,
+ add_quirk, MMC_QUIRK_QCA9379_SETTINGS),
END_FIXUP
};
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index a29c4b2c8e97..b58bf6d1f505 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1234,7 +1234,10 @@ static int mmc_sd_suspend(struct mmc_host *host)
if (!err) {
pm_runtime_disable(&host->card->dev);
pm_runtime_set_suspended(&host->card->dev);
- }
+ /* if suspend fails, force mmc_detect_change during resume */
+ } else if (mmc_bus_manual_resume(host))
+ host->ignore_bus_resume_flags = true;
+
MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 5651cf63f8bd..65425a41a84f 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -228,7 +228,8 @@ static void sdio_enable_vendor_specific_settings(struct mmc_card *card)
u8 settings;
if (mmc_enable_qca6574_settings(card) ||
- mmc_enable_qca9377_settings(card)) {
+ mmc_enable_qca9377_settings(card) ||
+ mmc_enable_qca9379_settings(card)) {
ret = mmc_io_rw_direct(card, 1, 0, 0xF2, 0x0F, NULL);
if (ret) {
pr_crit("%s: failed to write to fn 0xf2 %d\n",
diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c
index 69a3159d34b1..253e341dbb58 100644
--- a/drivers/net/can/spi/qti-can.c
+++ b/drivers/net/can/spi/qti-can.c
@@ -445,8 +445,8 @@ static int qti_can_process_rx(struct qti_can *priv_data, char *rx_buf)
} else {
data = rx_buf + length_processed;
resp = (struct spi_miso *)data;
- if (resp->cmd == 0) {
- /* special case. ignore cmd==0 */
+ if (resp->cmd == 0x00 || resp->cmd == 0xFF) {
+ /* special case. ignore cmd==0x00, 0xFF */
length_processed += 1;
continue;
}
diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c
index fafab6910570..a2ca99f77aa3 100644
--- a/drivers/net/wireless/cnss/cnss_sdio.c
+++ b/drivers/net/wireless/cnss/cnss_sdio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -127,6 +127,7 @@ static struct cnss_sdio_data {
/* SDIO manufacturer ID and Codes */
#define MANUFACTURER_ID_AR6320_BASE 0x500
#define MANUFACTURER_ID_QCA9377_BASE 0x700
+#define MANUFACTURER_ID_QCA9379_BASE 0x800
#define MANUFACTURER_CODE 0x271
static const struct sdio_device_id ar6k_id_table[] = {
@@ -162,6 +163,22 @@ static const struct sdio_device_id ar6k_id_table[] = {
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))},
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))},
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x0))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x1))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x2))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x3))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x4))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x5))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x6))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x7))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x8))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x9))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xA))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xB))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xC))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xD))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xE))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xF))},
{},
};
MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
@@ -261,11 +278,6 @@ static int cnss_put_hw_resources(struct device *dev)
return ret;
}
- if (!cnss_pdata->regulator.wlan_vreg) {
- pr_debug("wlan_vreg regulator is invalid\n");
- return 0;
- }
-
ret = mmc_power_save_host(host);
if (ret) {
pr_err("Failed to Power Save Host err:%d\n",
@@ -273,7 +285,11 @@ static int cnss_put_hw_resources(struct device *dev)
return ret;
}
- regulator_disable(cnss_pdata->regulator.wlan_vreg);
+ if (cnss_pdata->regulator.wlan_vreg)
+ regulator_disable(cnss_pdata->regulator.wlan_vreg);
+ else
+ pr_debug("wlan_vreg regulator is invalid\n");
+
info->cnss_hw_state = CNSS_HW_SLEEP;
return ret;
@@ -307,22 +323,23 @@ static int cnss_get_hw_resources(struct device *dev)
return ret;
}
- if (!cnss_pdata->regulator.wlan_vreg) {
+ if (cnss_pdata->regulator.wlan_vreg) {
+ ret = regulator_enable(cnss_pdata->regulator.wlan_vreg);
+ if (ret) {
+ pr_err("Failed to enable wlan vreg\n");
+ return ret;
+ }
+ } else {
pr_debug("wlan_vreg regulator is invalid\n");
- return 0;
}
- ret = regulator_enable(cnss_pdata->regulator.wlan_vreg);
- if (ret) {
- pr_err("Failed to enable wlan vreg\n");
- return ret;
- }
ret = mmc_power_restore_host(host);
if (ret) {
pr_err("Failed to restore host power ret:%d\n",
ret);
- regulator_disable(cnss_pdata->regulator.wlan_vreg);
+ if (cnss_pdata->regulator.wlan_vreg)
+ regulator_disable(cnss_pdata->regulator.wlan_vreg);
return ret;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index 16bff82a116d..0261e857298a 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -432,6 +432,8 @@ static ssize_t ipa_read_hdr(struct file *file, char __user *ubuf, size_t count,
list_for_each_entry(entry, &ipa_ctx->hdr_tbl.head_hdr_entry_list,
link) {
+ if (entry->cookie != IPA_HDR_COOKIE)
+ continue;
nbytes = scnprintf(
dbg_buff,
IPA_MAX_MSG_LEN - 1,
@@ -597,6 +599,14 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
if (attrib->protocol_eq_present)
pr_err("protocol:%d ", attrib->protocol_eq);
+ if (attrib->num_ihl_offset_range_16 >
+ IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
+ IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
+ attrib->num_ihl_offset_range_16);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@@ -605,6 +615,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_range_16[i].range_high);
}
+ if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
+ IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_offset_meq_32; i++) {
pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@@ -626,6 +642,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_eq_16.value);
}
+ if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
+ IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, attrib->num_ihl_offset_meq_32);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@@ -634,6 +656,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_meq_32[i].value);
}
+ if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
+ IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[j];
@@ -803,11 +831,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
u32 rt_tbl_idx;
u32 bitmap;
bool eq;
+ int res = 0;
tbl = &ipa_ctx->glob_flt_tbl[ip];
mutex_lock(&ipa_ctx->lock);
i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
+ if (entry->cookie != IPA_FLT_COOKIE)
+ continue;
if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@@ -826,10 +857,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
i, entry->rule.action, rt_tbl_idx);
pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ",
bitmap, entry->rule.retain_hdr, eq);
- if (eq)
- ipa_attrib_dump_eq(
+ if (eq) {
+ res = ipa_attrib_dump_eq(
&entry->rule.eq_attrib);
- else
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
+ } else
ipa_attrib_dump(
&entry->rule.attrib, ip);
i++;
@@ -839,6 +874,8 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
tbl = &ipa_ctx->flt_tbl[j][ip];
i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
+ if (entry->cookie != IPA_FLT_COOKIE)
+ continue;
if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@@ -858,18 +895,23 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
pr_err("attrib_mask:%08x retain_hdr:%d ",
bitmap, entry->rule.retain_hdr);
pr_err("eq:%d ", eq);
- if (eq)
- ipa_attrib_dump_eq(
- &entry->rule.eq_attrib);
- else
+ if (eq) {
+ res = ipa_attrib_dump_eq(
+ &entry->rule.eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
+ } else
ipa_attrib_dump(
&entry->rule.attrib, ip);
i++;
}
}
+bail:
mutex_unlock(&ipa_ctx->lock);
- return 0;
+ return res;
}
static ssize_t ipa_read_stats(struct file *file, char __user *ubuf,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 33b0e2187bc2..be6b1a49ddcf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -531,6 +531,14 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
if (attrib->protocol_eq_present)
pr_err("protocol:%d ", attrib->protocol_eq);
+ if (attrib->num_ihl_offset_range_16 >
+ IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
+ IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
+ attrib->num_ihl_offset_range_16);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@@ -539,6 +547,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_range_16[i].range_high);
}
+ if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
+ IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_offset_meq_32; i++) {
pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@@ -560,6 +574,13 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_eq_16.value);
}
+ if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
+ IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS,
+ attrib->num_ihl_offset_meq_32);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@@ -568,6 +589,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_meq_32[i].value);
}
+ if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
+ IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n",
+ IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
+ return -EPERM;
+ }
+
for (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[j];
@@ -704,6 +731,7 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
struct ipa3_debugfs_rt_entry *entry;
enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data;
int num_tbls;
+ int res = 0;
if (ip == IPA_IP_v4)
num_tbls = IPA_MEM_PART(v4_rt_num_index);
@@ -736,7 +764,11 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
pr_err("rule_id:%u prio:%u retain_hdr:%u ",
entry[i].rule_id, entry[i].prio,
entry[i].retain_hdr);
- ipa3_attrib_dump_eq(&entry[i].eq_attrib);
+ res = ipa3_attrib_dump_eq(&entry[i].eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
}
pr_err("== HASHABLE TABLE tbl:%d ==\n", j);
@@ -758,14 +790,19 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
pr_err("rule_id:%u prio:%u retain_hdr:%u ",
entry[i].rule_id, entry[i].prio,
entry[i].retain_hdr);
- ipa3_attrib_dump_eq(&entry[i].eq_attrib);
+ res = ipa3_attrib_dump_eq(&entry[i].eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
}
}
+bail:
mutex_unlock(&ipa3_ctx->lock);
kfree(entry);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return 0;
+ return res;
}
static ssize_t ipa3_read_proc_ctx(struct file *file, char __user *ubuf,
@@ -830,6 +867,7 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
u32 rt_tbl_idx;
u32 bitmap;
bool eq;
+ int res = 0;
mutex_lock(&ipa3_ctx->lock);
@@ -860,18 +898,23 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
pr_err("hashable:%u rule_id:%u max_prio:%u prio:%u ",
entry->rule.hashable, entry->rule_id,
entry->rule.max_prio, entry->prio);
- if (eq)
- ipa3_attrib_dump_eq(
- &entry->rule.eq_attrib);
- else
+ if (eq) {
+ res = ipa3_attrib_dump_eq(
+ &entry->rule.eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
+ } else
ipa3_attrib_dump(
&entry->rule.attrib, ip);
i++;
}
}
+bail:
mutex_unlock(&ipa3_ctx->lock);
- return 0;
+ return res;
}
static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
@@ -884,6 +927,7 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data;
u32 rt_tbl_idx;
u32 bitmap;
+ int res = 0;
entry = kzalloc(sizeof(*entry) * IPA_DBG_MAX_RULE_IN_TBL, GFP_KERNEL);
if (!entry)
@@ -906,7 +950,11 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
bitmap, entry[i].rule.retain_hdr);
pr_err("rule_id:%u prio:%u ",
entry[i].rule_id, entry[i].prio);
- ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
+ res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
}
pr_err("== HASHABLE TABLE ep:%d ==\n", j);
@@ -922,14 +970,19 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
pr_err("rule_id:%u max_prio:%u prio:%u ",
entry[i].rule_id,
entry[i].rule.max_prio, entry[i].prio);
- ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
+ res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
+ if (res) {
+ IPAERR_RL("failed read attrib eq\n");
+ goto bail;
+ }
}
}
+bail:
mutex_unlock(&ipa3_ctx->lock);
kfree(entry);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return 0;
+ return res;
}
static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 0f6a0d255db6..48edff5a60f6 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -122,22 +122,18 @@ void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer)
host_addr_pa = transfer->host_pa | bit_40;
}
- if (mhi->use_ipa) {
- mhi_log(MHI_MSG_VERBOSE,
- "device 0x%x <<-- host 0x%llx, size %d\n",
- transfer->phy_addr, host_addr_pa,
- (int) transfer->size);
- rc = ipa_dma_async_memcpy((u64)transfer->phy_addr, host_addr_pa,
- (int)transfer->size,
- mhi_dev_ring_cache_completion_cb, &ring_req);
- if (rc)
- pr_err("error while reading from host:%d\n", rc);
+ mhi_log(MHI_MSG_VERBOSE,
+ "device 0x%x <<-- host 0x%llx, size %d\n",
+ transfer->phy_addr, host_addr_pa,
+ (int) transfer->size);
+ rc = ipa_dma_async_memcpy((u64)transfer->phy_addr, host_addr_pa,
+ (int)transfer->size,
+ mhi_dev_ring_cache_completion_cb, &ring_req);
+ if (rc)
+ pr_err("error while reading from host:%d\n", rc);
+
+ wait_for_completion(&done);
- wait_for_completion(&done);
- } else {
- memcpy(transfer->virt_addr, (void *) &transfer->device_va,
- (int) transfer->size);
- }
}
EXPORT_SYMBOL(mhi_dev_read_from_host);
@@ -160,42 +156,35 @@ void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *transfer,
host_addr_pa = transfer->host_pa | bit_40;
}
- if (mhi->use_ipa) {
- mhi_log(MHI_MSG_VERBOSE,
- "device 0x%llx --> host 0x%llx, size %d\n",
- (uint64_t) mhi->cache_dma_handle, host_addr_pa,
- (int) transfer->size);
- if (tr_type == MHI_DEV_DMA_ASYNC) {
- dma = dma_map_single(&mhi->pdev->dev,
- transfer->virt_addr, transfer->size,
- DMA_TO_DEVICE);
- if (ereq->event_type == SEND_EVENT_BUFFER) {
- ereq->dma = dma;
- ereq->dma_len = transfer->size;
- } else if (ereq->event_type == SEND_EVENT_RD_OFFSET) {
- ereq->event_rd_dma = dma;
- }
- rc = ipa_dma_async_memcpy(host_addr_pa, (uint64_t) dma,
- (int)transfer->size,
- ereq->client_cb, ereq);
- if (rc)
- pr_err("error while writing to host:%d\n", rc);
- } else if (tr_type == MHI_DEV_DMA_SYNC) {
- /* Copy the device content to a local device
- * physical address */
- memcpy(mhi->dma_cache, transfer->virt_addr,
- transfer->size);
- rc = ipa_dma_sync_memcpy(host_addr_pa,
- (u64) mhi->cache_dma_handle,
- (int) transfer->size);
- if (rc)
- pr_err("error while writing to host:%d\n", rc);
- }
- } else {
- memcpy((void *) &transfer->device_va, transfer->virt_addr,
+ mhi_log(MHI_MSG_VERBOSE,
+ "device 0x%llx --> host 0x%llx, size %d\n",
+ (uint64_t) mhi->cache_dma_handle, host_addr_pa,
+ (int) transfer->size);
+ if (tr_type == MHI_DEV_DMA_ASYNC) {
+ dma = dma_map_single(&mhi->pdev->dev,
+ transfer->virt_addr, transfer->size,
+ DMA_TO_DEVICE);
+ if (ereq->event_type == SEND_EVENT_BUFFER) {
+ ereq->dma = dma;
+ ereq->dma_len = transfer->size;
+ } else if (ereq->event_type == SEND_EVENT_RD_OFFSET) {
+ ereq->event_rd_dma = dma;
+ }
+ rc = ipa_dma_async_memcpy(host_addr_pa, (uint64_t) dma,
+ (int)transfer->size,
+ ereq->client_cb, ereq);
+ if (rc)
+ pr_err("error while writing to host:%d\n", rc);
+ } else if (tr_type == MHI_DEV_DMA_SYNC) {
+ /* Copy the device content to a local device
+ * physical address */
+ memcpy(mhi->dma_cache, transfer->virt_addr,
transfer->size);
- /* Update state before sending events */
- wmb();
+ rc = ipa_dma_sync_memcpy(host_addr_pa,
+ (u64) mhi->cache_dma_handle,
+ (int) transfer->size);
+ if (rc)
+ pr_err("error while writing to host:%d\n", rc);
}
}
EXPORT_SYMBOL(mhi_dev_write_to_host);
diff --git a/drivers/power/qcom/lpm-stats.c b/drivers/power/qcom/lpm-stats.c
index 7f1967d432b7..bfd897a4323b 100644
--- a/drivers/power/qcom/lpm-stats.c
+++ b/drivers/power/qcom/lpm-stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018 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
@@ -682,11 +682,14 @@ static void cleanup_stats(struct lpm_stats *stats)
{
struct list_head *centry = NULL;
struct lpm_stats *pos = NULL;
+ struct lpm_stats *n = NULL;
centry = &stats->child;
- list_for_each_entry_reverse(pos, centry, sibling) {
- if (!list_empty(&pos->child))
+ list_for_each_entry_safe_reverse(pos, n, centry, sibling) {
+ if (!list_empty(&pos->child)) {
cleanup_stats(pos);
+ continue;
+ }
list_del_init(&pos->child);
diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c
index 30b92657b6bc..f56cddfa7208 100644
--- a/drivers/soc/qcom/rpm_stats.c
+++ b/drivers/soc/qcom/rpm_stats.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2017-2018, 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
@@ -430,7 +431,7 @@ static ssize_t rpmstats_show(struct kobject *kobj,
prvdata);
}
- ret = snprintf(buf, prvdata->len, prvdata->buf);
+ ret = snprintf(buf, prvdata->len, "%s", prvdata->buf);
iounmap(prvdata->reg_base);
ioremap_fail:
kfree(prvdata);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index c18d9b2ba642..776ba2aa3f92 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -651,8 +651,11 @@ int mdp3_ctrl_get_source_format(u32 imgType)
case MDP_RGB_888:
format = MDP3_DMA_IBUF_FORMAT_RGB888;
break;
+ case MDP_XRGB_8888:
case MDP_ARGB_8888:
case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
format = MDP3_DMA_IBUF_FORMAT_XRGB8888;
break;
default:
diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h
index 276c79ff1591..5baddb80c66e 100644
--- a/include/linux/ipc_router_xprt.h
+++ b/include/linux/ipc_router_xprt.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2018, 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
@@ -100,6 +100,7 @@ struct rr_opt_hdr {
* @pkt_fragment_q: Queue of SKBs containing payload.
* @length: Length of data in the chain of SKBs
* @ref: Reference count for the packet.
+ * @ws_need: Flag to check wakeup soruce need
*/
struct rr_packet {
struct list_head list;
@@ -108,6 +109,7 @@ struct rr_packet {
struct sk_buff_head *pkt_fragment_q;
uint32_t length;
struct kref ref;
+ bool ws_need;
};
/**
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index f6cec9c43d98..9f7cbb375a37 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -393,6 +393,8 @@ struct mmc_card {
/* Make sure CMDQ is empty before queuing DCMD */
#define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 17)
+#define MMC_QUIRK_QCA9379_SETTINGS (1 << 18) /* QCA9379 card settings*/
+
unsigned int erase_size; /* erase size in sectors */
unsigned int erase_shift; /* if erase unit is power 2 */
unsigned int pref_erase; /* in sectors */
@@ -693,6 +695,11 @@ static inline bool mmc_enable_qca9377_settings(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_QCA9377_SETTINGS;
}
+static inline bool mmc_enable_qca9379_settings(const struct mmc_card *c)
+{
+ return c->quirks & MMC_QUIRK_QCA9379_SETTINGS;
+}
+
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) (dev_name(&(c)->dev))
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 3c354aeb69bc..7de48a57f68f 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -551,6 +551,7 @@ struct mmc_host {
unsigned int bus_resume_flags;
#define MMC_BUSRESUME_MANUAL_RESUME (1 << 0)
#define MMC_BUSRESUME_NEEDS_RESUME (1 << 1)
+ bool ignore_bus_resume_flags;
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index c7f1639f350e..b2a73fe82b7d 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -216,6 +216,25 @@ enum {
UP,
};
+/**
+ * is_sensor_port() - Check if the remote port is sensor service or not
+ * @rport: Pointer to the remote port.
+ *
+ * Return: true if the remote port is sensor service else false.
+ */
+static int is_sensor_port(struct msm_ipc_router_remote_port *rport)
+{
+ u32 svcid = 0;
+
+ if (rport && rport->server) {
+ svcid = rport->server->name.service;
+ if (svcid == 400 || (svcid >= 256 && svcid <= 320))
+ return true;
+ }
+
+ return false;
+}
+
static void init_routing_table(void)
{
int i;
@@ -1165,7 +1184,8 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr,
}
mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
- __pm_stay_awake(port_ptr->port_rx_ws);
+ if (pkt->ws_need)
+ __pm_stay_awake(port_ptr->port_rx_ws);
list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q);
wake_up(&port_ptr->port_rx_wait_q);
notify = port_ptr->notify;
@@ -2740,7 +2760,6 @@ static void do_read_data(struct work_struct *work)
struct rr_packet *pkt = NULL;
struct msm_ipc_port *port_ptr;
struct msm_ipc_router_remote_port *rport_ptr;
- int ret;
struct msm_ipc_router_xprt_info *xprt_info =
container_of(work,
@@ -2748,16 +2767,7 @@ static void do_read_data(struct work_struct *work)
read_data);
while ((pkt = rr_read(xprt_info)) != NULL) {
- if (pkt->length < calc_rx_header_size(xprt_info) ||
- pkt->length > MAX_IPC_PKT_SIZE) {
- IPC_RTR_ERR("%s: Invalid pkt length %d\n",
- __func__, pkt->length);
- goto read_next_pkt1;
- }
- ret = extract_header(pkt);
- if (ret < 0)
- goto read_next_pkt1;
hdr = &(pkt->hdr);
if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) &&
@@ -4199,6 +4209,7 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
{
struct msm_ipc_router_xprt_info *xprt_info = xprt->priv;
struct msm_ipc_router_xprt_work *xprt_work;
+ struct msm_ipc_router_remote_port *rport_ptr = NULL;
struct rr_packet *pkt;
int ret;
@@ -4251,9 +4262,34 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
if (!pkt)
return;
+ if (pkt->length < calc_rx_header_size(xprt_info) ||
+ pkt->length > MAX_IPC_PKT_SIZE) {
+ IPC_RTR_ERR("%s: Invalid pkt length %d\n",
+ __func__, pkt->length);
+ release_pkt(pkt);
+ return;
+ }
+
+ ret = extract_header(pkt);
+ if (ret < 0) {
+ release_pkt(pkt);
+ return;
+ }
+
+ pkt->ws_need = true;
+
+ if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA)
+ rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id,
+ pkt->hdr.src_port_id);
+
mutex_lock(&xprt_info->rx_lock_lhb2);
list_add_tail(&pkt->list, &xprt_info->pkt_list);
- __pm_stay_awake(&xprt_info->ws);
+ /* check every pkt is from SENSOR services or not*/
+ if (is_sensor_port(rport_ptr))
+ pkt->ws_need = false;
+ else
+ __pm_stay_awake(&xprt_info->ws);
+
mutex_unlock(&xprt_info->rx_lock_lhb2);
queue_work(xprt_info->workqueue, &xprt_info->read_data);
}
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 9b1452e8e868..72ebc3f300e5 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2759,7 +2759,7 @@ static struct genl_family ip_vs_genl_family = {
.hdrsize = 0,
.name = IPVS_GENL_NAME,
.version = IPVS_GENL_VERSION,
- .maxattr = IPVS_CMD_MAX,
+ .maxattr = IPVS_CMD_ATTR_MAX,
.netnsok = true, /* Make ipvsadm to work on netns */
};