summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt44
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt53
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt60
-rw-r--r--Documentation/devicetree/bindings/sound/wcd_codec.txt8
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi564
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi30
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi4
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig5
-rw-r--r--arch/arm64/configs/msmcortex_defconfig5
-rw-r--r--drivers/devfreq/arm-memlat-mon.c12
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ft5x06_ts.c777
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c1234
-rw-r--r--drivers/input/touchscreen/msg21xx_ts.c3272
-rw-r--r--drivers/media/platform/msm/vidc/hfi_packetization.c26
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c7
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c103
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c28
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_debug.c2
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c12
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi.h1
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_api.h10
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_helper.h12
-rw-r--r--drivers/mfd/wcd9xxx-utils.c10
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msmfalcon.c932
-rw-r--r--drivers/platform/msm/gsi/gsi_dbg.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c22
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c16
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c5
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c15
-rw-r--r--drivers/regulator/cpr3-mmss-regulator.c64
-rw-r--r--drivers/soc/qcom/Kconfig10
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/core_hang_detect.c11
-rw-r--r--drivers/soc/qcom/gladiator_hang_detect.c8
-rw-r--r--drivers/soc/qcom/glink.c60
-rw-r--r--drivers/soc/qcom/glink_core_if.h7
-rw-r--r--drivers/soc/qcom/glink_spi_xprt.c2192
-rw-r--r--drivers/soc/qcom/glink_xprt_if.h5
-rw-r--r--drivers/soc/qcom/irq-helper.c3
-rw-r--r--drivers/soc/qcom/peripheral-loader.c20
-rw-r--r--drivers/soc/qcom/peripheral-loader.h2
-rw-r--r--drivers/soc/qcom/pil-q6v5-mss.c1
-rw-r--r--drivers/usb/gadget/configfs.c3
-rw-r--r--drivers/usb/gadget/function/f_cdev.c5
-rw-r--r--drivers/usb/gadget/function/f_fs.c385
-rw-r--r--drivers/usb/gadget/function/f_gsi.c199
-rw-r--r--drivers/usb/phy/phy-msm-qusb-v2.c2
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c106
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h6
-rw-r--r--include/linux/input/ft5x06_ts.h24
-rwxr-xr-xinclude/linux/mfd/wcd9xxx/pdata.h1
-rw-r--r--include/linux/power_supply.h2
-rw-r--r--include/soc/qcom/irq-helper.h20
-rw-r--r--include/uapi/linux/v4l2-controls.h23
-rw-r--r--include/uapi/media/msm_vidc.h120
-rw-r--r--kernel/cpu.c15
-rw-r--r--net/wireless/db.txt62
-rw-r--r--sound/soc/codecs/wcd9335.c23
-rw-r--r--sound/soc/msm/msm-cpe-lsm.c9
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c1
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-slim.c4
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c2
-rw-r--r--sound/soc/msm/qdsp6v2/q6lsm.c3
77 files changed, 8086 insertions, 2666 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt b/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt
new file mode 100644
index 000000000000..0a78eb6b91fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt
@@ -0,0 +1,44 @@
+Qualcomm Technologies, Inc. G-link SPI Transport
+
+Required properties:
+-compatible : should be "qcom,glink-spi-xprt".
+-label : the name of the subsystem this link connects to.
+
+Optional properties:
+-qcom,remote-fifo-config: Reference to the FIFO configuratio in the remote
+ processor.
+-qcom,qos-config: Reference to the qos configuration elements.It depends on
+ ramp-time.
+-qcom,ramp-time: Worst case time in microseconds to transition to this power
+ state. Power states are numbered by array index position.
+
+Example:
+
+ glink_spi_xprt_wdsp: qcom,glink-spi-xprt-wdsp {
+ compatible = "qcom,glink-spi-xprt";
+ label = "wdsp";
+ qcom,remote-fifo-config = <&glink_fifo_wdsp>;
+ qcom,qos-config = <&glink_qos_wdsp>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_fifo_wdsp: qcom,glink-fifo-config-wdsp {
+ compatible = "qcom,glink-fifo-config";
+ qcom,out-read-idx-reg = <0x12000>;
+ qcom,out-write-idx-reg = <0x12004>;
+ qcom,in-read-idx-reg = <0x1200C>;
+ qcom,in-write-idx-reg = <0x12010>;
+ };
+
+ glink_qos_wdsp: qcom,glink-qos-config-wdsp {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
new file mode 100644
index 000000000000..1c7c2c5ea99f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -0,0 +1,53 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "focaltech,5x06".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - focaltech,family-id : family identification of the controller.
+ - focaltech,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - focaltech,reset-gpio : reset gpio to control the reset of chip.
+ - focaltech,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:
+
+ - focaltech,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.
+ - focaltech,i2c-pull-up : to specify pull up is required.
+ - focaltech,no-force-update : to specify force update is allowed.
+ - focaltech,button-map : button map of key codes. The number
+ of key codes depend on panel.
+
+Example:
+ i2c@f9924000 {
+ ft5x06_ts@38 {
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd-supply = <&pm8941_l22>;
+ vcc_i2c-supply = <&pm8941_s3>;
+ focaltech,reset-gpio = <&msmgpio 60 0x00>;
+ focaltech,irq-gpio = <&msmgpio 61 0x00>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,button-map= <158 102 139 217>;
+ focaltech,family-id = <0x0a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
new file mode 100644
index 000000000000..26f01ca8577f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
@@ -0,0 +1,60 @@
+Mstar touch controller
+
+The mstar controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "mstar,msg21xx".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - mstar,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - mstar,reset-gpio : reset gpio to control the reset of chip.
+ - mstar,display-coords : display coords in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+ - pinctrl-names : This should be defined if a target uses pinctrl framework.
+ See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
+ Specify the names of the configs that pinctrl can install in driver.
+ Following are the pinctrl configs that can be installed:
+ "pmx_ts_active" : Active configuration of pins, this should specify active
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_release" : Release configuration of pins, this should specify
+ release config defined in pin groups of interrupt and reset gpio.
+
+Optional properties:
+
+ - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes.
+ - mstar,panel-coords : panel coords for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+
+Example:
+ i2c@78b9000 { /* BLSP1 QUP5 */
+ mstar@26 {
+ compatible = "mstar,msg21xx";
+ reg = <0x26>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <13 0x2008>;
+ mstar,irq-gpio = <&msm_gpio 13 0x00000001>;
+ mstar,reset-gpio = <&msm_gpio 12 0x0>;
+ vdd-supply = <&pm8916_l17>;
+ vcc_i2c-supply = <&pm8916_l6>;
+ mstar,display-coords = <0 0 480 854>;
+ pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ mstar,button-map= <172 139 158>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt
index d585595f21c6..e37e7c2bea3c 100644
--- a/Documentation/devicetree/bindings/sound/wcd_codec.txt
+++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt
@@ -92,6 +92,14 @@ Optional properties:
involving DMIC will use the rate defined by
cdc-dmic-sample-rate.
+ - qcom,cdc-ecpp-dmic-rate: Specifies the sample rate of digital mic in HZ to be
+ used by ECPP (Echo Cancellation Ping Pong) block
+ on the codec. The valid set of values are same
+ as that of cdc-dmic-sample-rate, but this rate will
+ only be used by ECPP and all other audio use cases
+ involving DMIC will use the rate defined by
+ cdc-dmic-sample-rate.
+
- qcom,cdc-dmic-clk-drv-strength: Specifies the drive strength for digital microphone
clock in the codec. Accepted values are 2,4,8 and 16.
The clock drive strentgh is in uA. Codec driver will
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4097b7cd6454..aca2dd3e4ccb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -146,6 +146,7 @@ mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
msi Micro-Star International Co. Ltd.
+mstar MStar Semiconductor, Inc.
mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
mundoreader Mundo Reader S.L.
murata Murata Manufacturing Co., Ltd.
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
new file mode 100644
index 000000000000..feb74b5480f1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
@@ -0,0 +1,564 @@
+/* Copyright (c) 2016, 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.
+ */
+
+
+&kgsl_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6470 0x110011>,
+ <0x6478 0x0>,
+ <0x647c 0x1000100>,
+ <0x6480 0x81108110>,
+ <0x6484 0x81108110>,
+ <0x6488 0x3e003e0>,
+ <0x648c 0x3e003e0>,
+ <0x6490 0x80008010>,
+ <0x6494 0x8020>,
+ <0x649c 0x6>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x604>,
+ <0x6928 0x11000>,
+ <0x6930 0x800>,
+ <0x6b64 0x1a5551>,
+ <0x6b68 0x2aaa2f82>;
+};
+
+&lpass_q6_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0xe0>,
+ <0x6074 0xe0>,
+ <0x6078 0xe0>,
+ <0x607c 0xe0>,
+ <0x60f0 0xc0>,
+ <0x60f4 0xc8>,
+ <0x60f8 0xd0>,
+ <0x60fc 0xd8>,
+ <0x6170 0x0>,
+ <0x6174 0x30>,
+ <0x6178 0x60>,
+ <0x617c 0x90>,
+ <0x6270 0x0>,
+ <0x6274 0x2>,
+ <0x6278 0x4>,
+ <0x627c 0x6>,
+ <0x62f0 0x8>,
+ <0x62f4 0xe>,
+ <0x62f8 0x14>,
+ <0x62fc 0x1a>,
+ <0x6370 0x20>,
+ <0x6374 0x40>,
+ <0x6378 0x60>,
+ <0x637c 0x80>,
+ <0x67a0 0x0>,
+ <0x67a4 0x0>,
+ <0x67a8 0x20>,
+ <0x67b0 0x0>,
+ <0x67b4 0x8>,
+ <0x67b8 0xc8>,
+ <0x67d0 0x4>,
+ <0x67dc 0x8>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x202>,
+ <0x6928 0x10a00>,
+ <0x6930 0x500>,
+ <0x6b64 0x121151>,
+ <0x6b68 0x8a840080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x1>,
+ <0x6c14 0x1>,
+ <0x6c18 0x1>,
+ <0x6c1c 0x1>,
+ <0x6c20 0x2>,
+ <0x6c24 0x2>,
+ <0x6c28 0x2>,
+ <0x6c2c 0x2>,
+ <0x6c30 0x3>,
+ <0x6c34 0x3>,
+ <0x6c38 0x3>,
+ <0x6c3c 0x3>;
+};
+
+&mmss_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x204>,
+ <0x6928 0x11002>,
+ <0x6930 0x800>,
+ <0x6960 0xffffffff>,
+ <0x6964 0xffffffff>,
+ <0x6968 0xffffffff>,
+ <0x696c 0xffffffff>,
+ <0x6b48 0x330330>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x3333>,
+ <0x6b54 0x3333>,
+ <0x6b64 0x1a5555>,
+ <0x6b68 0x9aaa892a>,
+ <0x6b70 0x10100002>,
+ <0x6b74 0x10100002>,
+ <0x6b78 0x10100002>,
+ <0x6b80 0x20042004>,
+ <0x6b84 0x20042004>;
+};
+
+&anoc1_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x19>,
+ <0x6074 0x39>,
+ <0x6078 0x41>,
+ <0x607c 0x59>,
+ <0x6080 0x95>,
+ <0x6084 0x98>,
+ <0x6088 0xc0>,
+ <0x608c 0xc0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x2>,
+ <0x60f8 0x5>,
+ <0x60fc 0x8>,
+ <0x6100 0x16>,
+ <0x6104 0x17>,
+ <0x6108 0x19>,
+ <0x610c 0x19>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0xd>,
+ <0x6278 0xe>,
+ <0x627c 0x12>,
+ <0x6280 0x16>,
+ <0x6284 0x16>,
+ <0x6288 0x18>,
+ <0x628c 0x18>,
+ <0x62f0 0x18>,
+ <0x62f4 0x1b>,
+ <0x62f8 0x1c>,
+ <0x62fc 0x24>,
+ <0x6300 0x28>,
+ <0x6304 0x2b>,
+ <0x6308 0x31>,
+ <0x630c 0x31>,
+ <0x6370 0x31>,
+ <0x6374 0x34>,
+ <0x6378 0x35>,
+ <0x637c 0x47>,
+ <0x6380 0x4f>,
+ <0x6384 0x54>,
+ <0x6388 0x60>,
+ <0x638c 0x60>,
+ <0x67a0 0x0>,
+ <0x67a4 0xa7>,
+ <0x67a8 0xc0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x18>,
+ <0x67b8 0x7c>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b64 0x121151>,
+ <0x6b68 0xbb804080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x0>,
+ <0x6c14 0x0>,
+ <0x6c18 0x0>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x0>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x1>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x4>,
+ <0x6c94 0x3>,
+ <0x6c98 0x2>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x5>,
+ <0x6ca4 0x5>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x0>,
+ <0x6d04 0x0>,
+ <0x6d08 0x0>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x0>,
+ <0x6d14 0x0>,
+ <0x6d18 0x0>,
+ <0x6d1c 0x0>,
+ <0x6d20 0x0>,
+ <0x6d24 0x0>,
+ <0x6d28 0x0>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x0>,
+ <0x6d34 0x0>,
+ <0x6d38 0x0>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x0>,
+ <0x6d48 0x0>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x0>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
+
+&anoc2_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x12>,
+ <0x6074 0x26>,
+ <0x6078 0x3a>,
+ <0x607c 0x3c>,
+ <0x6080 0x3f>,
+ <0x6084 0x67>,
+ <0x6088 0x6c>,
+ <0x608c 0x74>,
+ <0x6090 0x7c>,
+ <0x6094 0x80>,
+ <0x6098 0xa0>,
+ <0x609c 0xa0>,
+ <0x60a0 0xa0>,
+ <0x60a4 0xa0>,
+ <0x60a8 0xa0>,
+ <0x60ac 0xa0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x1>,
+ <0x60f8 0x3>,
+ <0x60fc 0x4>,
+ <0x6100 0x5>,
+ <0x6104 0x7>,
+ <0x6108 0x8>,
+ <0x610c 0x10>,
+ <0x6110 0x10>,
+ <0x6114 0x10>,
+ <0x6118 0x12>,
+ <0x611c 0x12>,
+ <0x6120 0x12>,
+ <0x6124 0x12>,
+ <0x6128 0x12>,
+ <0x612c 0x12>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6190 0x0>,
+ <0x6194 0x0>,
+ <0x6198 0x0>,
+ <0x619c 0x0>,
+ <0x61a0 0x0>,
+ <0x61a4 0x0>,
+ <0x61a8 0x0>,
+ <0x61ac 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0x1>,
+ <0x6278 0x2>,
+ <0x627c 0x4>,
+ <0x6280 0x4>,
+ <0x6284 0x6>,
+ <0x6288 0x6>,
+ <0x628c 0x18>,
+ <0x6290 0x1a>,
+ <0x6294 0x1a>,
+ <0x6298 0x1e>,
+ <0x629c 0x1e>,
+ <0x62a0 0x1e>,
+ <0x62a4 0x1e>,
+ <0x62a8 0x1e>,
+ <0x62ac 0x1e>,
+ <0x62f0 0x1e>,
+ <0x62f4 0x24>,
+ <0x62f8 0x2a>,
+ <0x62fc 0x2c>,
+ <0x6300 0x2d>,
+ <0x6304 0x33>,
+ <0x6308 0x34>,
+ <0x630c 0x3a>,
+ <0x6310 0x3c>,
+ <0x6314 0x44>,
+ <0x6318 0x48>,
+ <0x631c 0x48>,
+ <0x6320 0x48>,
+ <0x6324 0x48>,
+ <0x6328 0x48>,
+ <0x632c 0x48>,
+ <0x6370 0x48>,
+ <0x6374 0x4d>,
+ <0x6378 0x52>,
+ <0x637c 0x56>,
+ <0x6380 0x59>,
+ <0x6384 0x63>,
+ <0x6388 0x68>,
+ <0x638c 0x70>,
+ <0x6390 0x78>,
+ <0x6394 0x88>,
+ <0x6398 0x90>,
+ <0x639c 0x90>,
+ <0x63a0 0x90>,
+ <0x63a4 0x90>,
+ <0x63a8 0x90>,
+ <0x63ac 0x90>,
+ <0x67a0 0x0>,
+ <0x67a4 0x8e>,
+ <0x67a8 0xa0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x1e>,
+ <0x67b8 0xc6>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b48 0x330331>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x1313>,
+ <0x6b64 0x121155>,
+ <0x6b68 0xea880920>,
+ <0x6b70 0x10100101>,
+ <0x6b74 0xc0c0000>,
+ <0x6b78 0xc0c0000>,
+ <0x6b80 0x20012001>,
+ <0x6b84 0x20012001>,
+ <0x6c00 0x5>,
+ <0x6c04 0x0>,
+ <0x6c08 0x5>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x5>,
+ <0x6c14 0x0>,
+ <0x6c18 0x5>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x5>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x0>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x0>,
+ <0x6c94 0x0>,
+ <0x6c98 0x0>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x0>,
+ <0x6ca4 0x0>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x8>,
+ <0x6d04 0x0>,
+ <0x6d08 0x8>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x7>,
+ <0x6d14 0x0>,
+ <0x6d18 0x3>,
+ <0x6d1c 0x2>,
+ <0x6d20 0x4>,
+ <0x6d24 0x0>,
+ <0x6d28 0x4>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x6>,
+ <0x6d34 0x0>,
+ <0x6d38 0x9>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x1>,
+ <0x6d48 0x4>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x4>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
index 6ab19b298aa7..d273d757dba5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
@@ -79,6 +79,8 @@
qcom,snapshot-size = <1048576>; //bytes
+ qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
+
clocks = <&clock_gfx clk_gpucc_gfx3d_clk>,
<&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gpu clk_gpucc_rbbmtimer_clk>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
index 5833b30d1fd1..9f8ecea15568 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
@@ -944,20 +944,20 @@
qcom,cpr-voltage-ceiling =
<896000 896000 896000 896000 896000
1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>;
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>;
qcom,cpr-voltage-floor =
<896000 896000 896000 896000 896000
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index c9a2abf0d5b5..4e98a844d059 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -1309,6 +1309,35 @@
qcom,rx-ring-size = <0x800>;
};
+ glink_spi_xprt_wdsp: qcom,glink-spi-xprt-wdsp {
+ compatible = "qcom,glink-spi-xprt";
+ label = "wdsp";
+ qcom,remote-fifo-config = <&glink_fifo_wdsp>;
+ qcom,qos-config = <&glink_qos_wdsp>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_fifo_wdsp: qcom,glink-fifo-config-wdsp {
+ compatible = "qcom,glink-fifo-config";
+ qcom,out-read-idx-reg = <0x12000>;
+ qcom,out-write-idx-reg = <0x12004>;
+ qcom,in-read-idx-reg = <0x1200C>;
+ qcom,in-write-idx-reg = <0x12010>;
+ };
+
+ glink_qos_wdsp: qcom,glink-qos-config-wdsp {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
+
qcom,glink_pkt {
compatible = "qcom,glinkpkt";
@@ -2918,6 +2947,7 @@
#include "msmcobalt-pm.dtsi"
#include "msm-arm-smmu-cobalt.dtsi"
+#include "msm-arm-smmu-impl-defs-cobalt.dtsi"
#include "msmcobalt-ion.dtsi"
#include "msmcobalt-camera.dtsi"
#include "msmcobalt-vidc.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
index a397310d4a61..6a000e4d4fd0 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
@@ -11,9 +11,9 @@
*/
&soc {
- tlmm: pinctrl@03400000 {
+ tlmm: pinctrl@03000000 {
compatible = "qcom,msmfalcon-pinctrl";
- reg = <0x03400000 0xc00000>;
+ reg = <0x03000000 0xc00000>;
interrupts = <0 208 0>;
gpio-controller;
#gpio-cells = <2>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index f9d9a882db1f..3a9fcfc95d00 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -419,6 +419,7 @@ CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_MTP=y
@@ -481,6 +482,7 @@ CONFIG_MSM_GLINK=y
CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
@@ -495,6 +497,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_MSM_RUN_QUEUE_STATS=y
@@ -517,7 +520,9 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index bdfcbb4d1621..a3bad54c0b5b 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -421,6 +421,7 @@ CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_MTP=y
@@ -494,6 +495,7 @@ CONFIG_MSM_GLINK=y
CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
@@ -510,6 +512,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_MSM_GLADIATOR_ERP_V2=y
@@ -538,7 +541,9 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c
index 370d7d95042b..4fb0a5ffda50 100644
--- a/drivers/devfreq/arm-memlat-mon.c
+++ b/drivers/devfreq/arm-memlat-mon.c
@@ -311,19 +311,19 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0);
if (!hw->of_node) {
dev_err(dev, "Couldn't find a target device\n");
- goto err_out;
+ return -ENODEV;
}
if (get_mask_from_dev_handle(pdev, &cpu_grp->cpus)) {
dev_err(dev, "CPU list is empty\n");
- goto err_out;
+ return -ENODEV;
}
hw->num_cores = cpumask_weight(&cpu_grp->cpus);
hw->core_stats = devm_kzalloc(dev, hw->num_cores *
sizeof(*(hw->core_stats)), GFP_KERNEL);
if (!hw->core_stats)
- goto err_out;
+ return -ENOMEM;
for_each_cpu(cpu, &cpu_grp->cpus)
hw->core_stats[cpu - cpumask_first(&cpu_grp->cpus)].id = cpu;
@@ -335,14 +335,10 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
ret = register_memlat(dev, hw);
if (ret) {
pr_err("Mem Latency Gov registration failed\n");
- goto err_out;
+ return ret;
}
return 0;
-
-err_out:
- kfree(cpu_grp);
- return -EINVAL;
}
static struct of_device_id match_table[] = {
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 529edb16565a..69028bd45fdd 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1110,6 +1110,17 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
+config TOUCHSCREEN_MSTAR21XX
+ tristate "Mstar touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a mstar touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called msg21xx_ts.
+
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index e04e787cea6e..e1777f11d77b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -97,3 +97,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index d619c1d06e9e..45ce036b1693 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -24,13 +24,19 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
#include <linux/input/ft5x06_ts.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
/* Early-suspend level */
-#define FT5X06_SUSPEND_LEVEL 1
+#define FT_SUSPEND_LEVEL 1
#endif
#define CFG_MAX_TOUCH_POINTS 5
@@ -50,33 +56,136 @@
#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
-/*register address*/
-#define FT5X06_REG_PMODE 0xA5
-#define FT5X06_REG_FW_VER 0xA6
-#define FT5X06_REG_POINT_RATE 0x88
-#define FT5X06_REG_THGROUP 0x80
-
-/* power register bits*/
-#define FT5X06_PMODE_ACTIVE 0x00
-#define FT5X06_PMODE_MONITOR 0x01
-#define FT5X06_PMODE_STANDBY 0x02
-#define FT5X06_PMODE_HIBERNATE 0x03
-
-#define FT5X06_VTG_MIN_UV 2600000
-#define FT5X06_VTG_MAX_UV 3300000
-#define FT5X06_I2C_VTG_MIN_UV 1800000
-#define FT5X06_I2C_VTG_MAX_UV 1800000
+/* register address*/
+#define FT_REG_DEV_MODE 0x00
+#define FT_DEV_MODE_REG_CAL 0x02
+#define FT_REG_ID 0xA3
+#define FT_REG_PMODE 0xA5
+#define FT_REG_FW_VER 0xA6
+#define FT_REG_POINT_RATE 0x88
+#define FT_REG_THGROUP 0x80
+#define FT_REG_ECC 0xCC
+#define FT_REG_RESET_FW 0x07
+
+/* power register bits */
+#define FT_PMODE_ACTIVE 0x00
+#define FT_PMODE_MONITOR 0x01
+#define FT_PMODE_STANDBY 0x02
+#define FT_PMODE_HIBERNATE 0x03
+#define FT_FACTORYMODE_VALUE 0x40
+#define FT_WORKMODE_VALUE 0x00
+#define FT_RST_CMD_REG 0xFC
+#define FT_READ_ID_REG 0x90
+#define FT_ERASE_APP_REG 0x61
+#define FT_ERASE_PANEL_REG 0x63
+#define FT_FW_START_REG 0xBF
+
+
+#define FT_VTG_MIN_UV 2600000
+#define FT_VTG_MAX_UV 3300000
+#define FT_I2C_VTG_MIN_UV 1800000
+#define FT_I2C_VTG_MAX_UV 1800000
+
+#define FT_COORDS_ARR_SIZE 4
+#define MAX_BUTTONS 4
+
+#define FT_8BIT_SHIFT 8
+#define FT_4BIT_SHIFT 4
+#define FT_FW_NAME_MAX_LEN 50
+
+#define FT5316_ID 0x0A
+#define FT5306I_ID 0x55
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+/* upgrade config of FT5606 */
+#define FT5606_UPGRADE_AA_DELAY 50
+#define FT5606_UPGRADE_55_DELAY 10
+#define FT5606_UPGRADE_ID_1 0x79
+#define FT5606_UPGRADE_ID_2 0x06
+#define FT5606_UPGRADE_READID_DELAY 100
+#define FT5606_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT5316 */
+#define FT5316_UPGRADE_AA_DELAY 50
+#define FT5316_UPGRADE_55_DELAY 30
+#define FT5316_UPGRADE_ID_1 0x79
+#define FT5316_UPGRADE_ID_2 0x07
+#define FT5316_UPGRADE_READID_DELAY 1
+#define FT5316_UPGRADE_EARSE_DELAY 1500
+
+/* upgrade config of FT5x06(x=2,3,4) */
+#define FT5X06_UPGRADE_AA_DELAY 50
+#define FT5X06_UPGRADE_55_DELAY 30
+#define FT5X06_UPGRADE_ID_1 0x79
+#define FT5X06_UPGRADE_ID_2 0x03
+#define FT5X06_UPGRADE_READID_DELAY 1
+#define FT5X06_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT6208 */
+#define FT6208_UPGRADE_AA_DELAY 60
+#define FT6208_UPGRADE_55_DELAY 10
+#define FT6208_UPGRADE_ID_1 0x79
+#define FT6208_UPGRADE_ID_2 0x05
+#define FT6208_UPGRADE_READID_DELAY 10
+#define FT6208_UPGRADE_EARSE_DELAY 2000
+
+#define FT_UPGRADE_INFO(x, y) do { \
+ x->delay_55 = y##_UPGRADE_55_DELAY; \
+ x->delay_aa = y##_UPGRADE_AA_DELAY; \
+ x->upgrade_id_1 = y##_UPGRADE_ID_1; \
+ x->upgrade_id_2 = y##_UPGRADE_ID_2; \
+ x->delay_readid = y##_UPGRADE_READID_DELAY; \
+ x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
+ } while (0)
+
+#define FT_FW_MIN_SIZE 8
+#define FT_FW_MAX_SIZE 32768
+#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
+#define FT_FW_CHECK(x) \
+ (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
+ && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
+ && (((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)))
+
+#define FT_MAX_TRIES 5
+#define FT_RETRY_DLY 20
+
+#define FT_MAX_WR_BUF 10
+#define FT_MAX_RD_BUF 2
+#define FT_FW_PKT_LEN 128
+#define FT_FW_PKT_META_LEN 6
+#define FT_FW_PKT_DLY_MS 20
+#define FT_FW_LAST_PKT 0x6ffa
+#define FT_EARSE_DLY_MS 100
+
+#define FT_UPGRADE_LOOP 3
+#define FT_CAL_START 0x04
+#define FT_CAL_FIN 0x00
+#define FT_CAL_STORE 0x05
+#define FT_CAL_RETRY 100
+#define FT_REG_CAL 0x00
+#define FT_CAL_MASK 0x70
struct ts_event {
- u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
- u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ u16 x[CFG_MAX_TOUCH_POINTS]; /* x coordinate */
+ u16 y[CFG_MAX_TOUCH_POINTS]; /* y coordinate */
/* touch event: 0 -- down; 1-- contact; 2 -- contact */
u8 touch_event[CFG_MAX_TOUCH_POINTS];
- u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u8 finger_id[CFG_MAX_TOUCH_POINTS]; /* touch ID */
u16 pressure;
u8 touch_point;
};
+struct upgrade_info {
+ u16 delay_aa; /* delay of write FT_UPGRADE_AA */
+ u16 delay_55; /* delay of write FT_UPGRADE_55 */
+ u8 upgrade_id_1; /* upgrade id 1 */
+ u8 upgrade_id_2; /* upgrade id 2 */
+ u16 delay_readid; /* delay of read id */
+ u16 delay_earse_flash; /* delay of earse flash */
+};
+
struct ft5x06_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -84,7 +193,12 @@ struct ft5x06_ts_data {
const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *vcc_i2c;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ char fw_name[FT_FW_NAME_MAX_LEN];
+ bool loading_fw;
+ u8 family_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
@@ -149,6 +263,21 @@ static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
return ret;
}
+static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
+{
+ u8 buf[2] = {0};
+
+ buf[0] = addr;
+ buf[1] = val;
+
+ return ft5x06_i2c_write(client, buf, sizeof(buf));
+}
+
+static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+ return ft5x06_i2c_read(client, &addr, 1, val, 1);
+}
+
static void ft5x06_report_value(struct ft5x06_ts_data *data)
{
struct ts_event *event = &data->event;
@@ -289,8 +418,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vdd) > 0) {
- rc = regulator_set_voltage(data->vdd, FT5X06_VTG_MIN_UV,
- FT5X06_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
+ FT_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vdd rc=%d\n", rc);
@@ -307,8 +436,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vcc_i2c) > 0) {
- rc = regulator_set_voltage(data->vcc_i2c, FT5X06_I2C_VTG_MIN_UV,
- FT5X06_I2C_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
+ FT_I2C_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
@@ -322,19 +451,19 @@ reg_vcc_i2c_put:
regulator_put(data->vcc_i2c);
reg_vdd_set_vtg:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
reg_vdd_put:
regulator_put(data->vdd);
return rc;
pwr_deinit:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
regulator_put(data->vdd);
if (regulator_count_voltages(data->vcc_i2c) > 0)
- regulator_set_voltage(data->vcc_i2c, 0, FT5X06_I2C_VTG_MAX_UV);
+ regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
regulator_put(data->vcc_i2c);
return 0;
@@ -349,8 +478,8 @@ static int ft5x06_ts_suspend(struct device *dev)
disable_irq(data->client->irq);
if (gpio_is_valid(data->pdata->reset_gpio)) {
- txbuf[0] = FT5X06_REG_PMODE;
- txbuf[1] = FT5X06_PMODE_HIBERNATE;
+ txbuf[0] = FT_REG_PMODE;
+ txbuf[1] = FT_PMODE_HIBERNATE;
ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
}
@@ -371,7 +500,27 @@ static int ft5x06_ts_resume(struct device *dev)
return 0;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct ft5x06_ts_data *ft5x06_data =
+ container_of(self, struct ft5x06_ts_data, fb_notif);
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+ ft5x06_data && ft5x06_data->client) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ ft5x06_ts_resume(&ft5x06_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ ft5x06_ts_suspend(&ft5x06_data->client->dev);
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
static void ft5x06_ts_early_suspend(struct early_suspend *handler)
{
struct ft5x06_ts_data *data = container_of(handler,
@@ -392,23 +541,478 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler)
#endif
static const struct dev_pm_ops ft5x06_ts_pm_ops = {
-#ifndef CONFIG_HAS_EARLYSUSPEND
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
.suspend = ft5x06_ts_suspend,
.resume = ft5x06_ts_resume,
#endif
};
#endif
+static int ft5x06_auto_cal(struct i2c_client *client)
+{
+ u8 temp = 0, i;
+
+ /* set to factory mode */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* start calibration */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
+ msleep(2 * FT_STARTUP_DLY);
+ for (i = 0; i < FT_CAL_RETRY; i++) {
+ ft5x0x_read_reg(client, FT_REG_CAL, &temp);
+ /* return to normal mode, calibration finish */
+ if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
+ break;
+ }
+
+ /* calibration OK */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* store calibration data */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ /* set to normal mode */
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
+{
+ switch (family_id) {
+ case FT5306I_ID:
+ FT_UPGRADE_INFO(info, FT5X06);
+ break;
+ case FT5316_ID:
+ FT_UPGRADE_INFO(info, FT5316);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade_start(struct i2c_client *client,
+ const u8 *data, u32 data_len)
+{
+ struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
+ struct upgrade_info info;
+ u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
+ u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
+ int rc, i, j, temp;
+ u32 pkt_num, pkt_len;
+ u8 fw_ecc;
+
+ rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
+ if (rc < 0) {
+ dev_err(&client->dev, "Cannot get upgrade information!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < FT_UPGRADE_LOOP; i++) {
+ /* reset - write 0xaa and 0x55 to register 0xfc */
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_AA);
+ msleep(info.delay_aa);
+
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_55);
+ msleep(info.delay_55);
+
+ /* Enter upgrade mode */
+ w_buf[0] = FT_UPGRADE_55;
+ w_buf[1] = FT_UPGRADE_AA;
+ do {
+ i++;
+ rc = ft5x06_i2c_write(client, w_buf, 2);
+ msleep(FT_RETRY_DLY);
+ } while (rc <= 0 && i < FT_MAX_TRIES);
+
+ /* check READ_ID */
+ msleep(info.delay_readid);
+ w_buf[0] = FT_READ_ID_REG;
+ w_buf[1] = 0x00;
+ w_buf[2] = 0x00;
+ w_buf[3] = 0x00;
+
+ ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
+
+ if (r_buf[0] != info.upgrade_id_1
+ || r_buf[1] != info.upgrade_id_2) {
+ dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
+ } else
+ break;
+ }
+
+ if (i >= FT_UPGRADE_LOOP) {
+ dev_err(&client->dev, "Abort upgrade\n");
+ return -EIO;
+ }
+
+ /* erase app and panel paramenter area */
+ w_buf[0] = FT_ERASE_APP_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(info.delay_earse_flash);
+
+ w_buf[0] = FT_ERASE_PANEL_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_EARSE_DLY_MS);
+
+ /* program firmware */
+ data_len = data_len - 8;
+ pkt_num = (data_len) / FT_FW_PKT_LEN;
+ pkt_len = FT_FW_PKT_LEN;
+ pkt_buf[0] = FT_FW_START_REG;
+ pkt_buf[1] = 0x00;
+ fw_ecc = 0;
+
+ for (i = 0; i < pkt_num; i++) {
+ temp = i * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) pkt_len;
+
+ for (j = 0; j < FT_FW_PKT_LEN; j++) {
+ pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
+ fw_ecc ^= pkt_buf[6 + j];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf,
+ FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send remaining bytes */
+ if ((data_len) % FT_FW_PKT_LEN > 0) {
+ temp = pkt_num * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ temp = (data_len) % FT_FW_PKT_LEN;
+ pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
+ fw_ecc ^= pkt_buf[6 + i];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send the finishing packet */
+ for (i = 0; i < 6; i++) {
+ temp = FT_FW_LAST_PKT + i;
+ pkt_buf[2] = (u8) (temp >> 8);
+ pkt_buf[3] = (u8) temp;
+ temp = 1;
+ pkt_buf[4] = (u8) (temp >> 8);
+ pkt_buf[5] = (u8) temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* verify checksum */
+ w_buf[0] = FT_REG_ECC;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+ if (r_buf[0] != fw_ecc) {
+ dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
+ r_buf[0], fw_ecc);
+ return -EIO;
+ }
+
+ /* reset */
+ w_buf[0] = FT_REG_RESET_FW;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade(struct device *dev, bool force)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ const struct firmware *fw = NULL;
+ int rc;
+ u8 val = 0;
+
+ rc = request_firmware(&fw, data->fw_name, dev);
+ if (rc < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ data->fw_name, rc);
+ return rc;
+ }
+
+ if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
+ dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
+ rc = -EIO;
+ goto rel_fw;
+ }
+
+ /* check firmware version */
+ rc = ft5x0x_read_reg(data->client, FT_REG_FW_VER, &val);
+ if (rc < 0) {
+ dev_err(dev, "Get firmware version failed\n");
+ goto rel_fw;
+ }
+
+ if (val == FT_FW_FILE_VER(fw) && !force) {
+ dev_err(dev, "No need to update (0x%x)\n", val);
+ rc = -EFAULT;
+ goto rel_fw;
+ }
+
+ dev_info(dev, "upgrade to fw ver 0x%x from 0x%x\n",
+ FT_FW_FILE_VER(fw), val);
+
+ /* start firmware upgrade */
+ if (FT_FW_CHECK(fw)) {
+ rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
+ if (rc < 0)
+ dev_err(dev, "update failed (%d)\n", rc);
+ else
+ ft5x06_auto_cal(data->client);
+ } else {
+ dev_err(dev, "FW format error\n");
+ rc = -EIO;
+ }
+
+rel_fw:
+ release_firmware(fw);
+ return rc;
+}
+
+static ssize_t ft5x06_update_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 2, "%d\n", data->loading_fw);
+}
+
+static ssize_t ft5x06_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, false);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_update_fw_store);
+
+static ssize_t ft5x06_force_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, true);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_force_update_fw_store);
+
+static ssize_t ft5x06_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t ft5x06_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ if (size > FT_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->fw_name, buf, size);
+ if (data->fw_name[size-1] == '\n')
+ data->fw_name[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
+
+#ifdef CONFIG_OF
+static int ft5x06_get_dt_coords(struct device *dev, char *name,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val, num_buttons;
+ u32 button_map[MAX_BUTTONS];
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ pdata->i2c_pull_up = of_property_read_bool(np,
+ "focaltech,i2c-pull-up");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "focaltech,no-force-update");
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+ rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
+ if (!rc)
+ pdata->family_id = temp_val;
+ else
+ return rc;
+
+ prop = of_find_property(np, "focaltech,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "focaltech,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+#else
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ return -ENODEV;
+}
+#endif
+
static int ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data;
+ struct ft5x06_ts_platform_data *pdata;
struct ft5x06_ts_data *data;
struct input_dev *input_dev;
u8 reg_value;
u8 reg_addr;
int err;
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ err = ft5x06_parse_dt(&client->dev, pdata);
+ if (err)
+ return err;
+ } else
+ pdata = client->dev.platform_data;
+
if (!pdata) {
dev_err(&client->dev, "Invalid pdata\n");
return -EINVAL;
@@ -446,9 +1050,9 @@ static int ft5x06_ts_probe(struct i2c_client *client,
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
CFG_MAX_TOUCH_POINTS, 0, 0);
@@ -523,25 +1127,44 @@ static int ft5x06_ts_probe(struct i2c_client *client,
/* make sure CTP already finish startup process */
msleep(FT_STARTUP_DLY);
- /*get some register information */
- reg_addr = FT5X06_REG_FW_VER;
+ /* check the controller id */
+ reg_addr = FT_REG_ID;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0) {
dev_err(&client->dev, "version read failed");
+ return err;
+ }
+
+ dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
- dev_info(&client->dev, "[FTS] Firmware version = 0x%x\n", reg_value);
+ if (pdata->family_id != reg_value) {
+ dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
+ goto free_reset_gpio;
+ }
+
+ data->family_id = reg_value;
+
+ /* get some register information */
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "version read failed");
- reg_addr = FT5X06_REG_POINT_RATE;
+ dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+ reg_addr = FT_REG_POINT_RATE;
ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "report rate read failed");
- dev_info(&client->dev, "[FTS] report rate is %dHz.\n", reg_value * 10);
- reg_addr = FT5X06_REG_THGROUP;
+ dev_dbg(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "threshold read failed");
- dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n", reg_value * 4);
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
@@ -551,9 +1174,36 @@ static int ft5x06_ts_probe(struct i2c_client *client,
goto free_reset_gpio;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ err = device_create_file(&client->dev, &dev_attr_fw_name);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto irq_free;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_fw_name_sys;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_force_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_update_fw_sys;
+ }
+
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+
+ err = fb_register_client(&data->fb_notif);
+
+ if (err)
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
- FT5X06_SUSPEND_LEVEL;
+ FT_SUSPEND_LEVEL;
data->early_suspend.suspend = ft5x06_ts_early_suspend;
data->early_suspend.resume = ft5x06_ts_late_resume;
register_early_suspend(&data->early_suspend);
@@ -561,12 +1211,18 @@ static int ft5x06_ts_probe(struct i2c_client *client,
return 0;
+free_update_fw_sys:
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+free_fw_name_sys:
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+irq_free:
+ free_irq(client->irq, data);
free_reset_gpio:
if (gpio_is_valid(pdata->reset_gpio))
gpio_free(pdata->reset_gpio);
free_irq_gpio:
if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->reset_gpio);
+ gpio_free(pdata->irq_gpio);
pwr_off:
if (pdata->power_on)
pdata->power_on(false);
@@ -591,7 +1247,14 @@ static int ft5x06_ts_remove(struct i2c_client *client)
{
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&data->early_suspend);
#endif
free_irq(client->irq, data);
@@ -600,7 +1263,7 @@ static int ft5x06_ts_remove(struct i2c_client *client)
gpio_free(data->pdata->reset_gpio);
if (gpio_is_valid(data->pdata->irq_gpio))
- gpio_free(data->pdata->reset_gpio);
+ gpio_free(data->pdata->irq_gpio);
if (data->pdata->power_on)
data->pdata->power_on(false);
@@ -625,12 +1288,22 @@ static const struct i2c_device_id ft5x06_ts_id[] = {
MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+#ifdef CONFIG_OF
+static const struct of_device_id ft5x06_match_table[] = {
+ { .compatible = "focaltech,5x06",},
+ { },
+};
+#else
+#define ft5x06_match_table NULL
+#endif
+
static struct i2c_driver ft5x06_ts_driver = {
.probe = ft5x06_ts_probe,
.remove = __devexit_p(ft5x06_ts_remove),
.driver = {
.name = "ft5x06_ts",
.owner = THIS_MODULE,
+ .of_match_table = ft5x06_match_table,
#ifdef CONFIG_PM
.pm = &ft5x06_ts_pm_ops,
#endif
diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c
index c60a2b5a94b0..9080a13069a8 100644
--- a/drivers/input/touchscreen/it7258_ts_i2c.c
+++ b/drivers/input/touchscreen/it7258_ts_i2c.c
@@ -1,7 +1,7 @@
/* drivers/input/touchscreen/it7258_ts_i2c.c
*
* Copyright (C) 2014 ITE Tech. Inc.
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -30,7 +30,7 @@
#include <linux/string.h>
#define MAX_BUFFER_SIZE 144
-#define DEVICE_NAME "IT7260"
+#define DEVICE_NAME "it7260"
#define SCREEN_X_RESOLUTION 320
#define SCREEN_Y_RESOLUTION 320
#define DEBUGFS_DIR_NAME "ts_debug"
@@ -99,18 +99,20 @@
#define FW_WRITE_CHUNK_SIZE 128
#define FW_WRITE_RETRY_COUNT 4
#define CHIP_FLASH_SIZE 0x8000
-#define DEVICE_READY_MAX_WAIT 10
+#define DEVICE_READY_COUNT_MAX 500
+#define DEVICE_READY_COUNT_20 20
+#define IT_I2C_WAIT_10MS 10
+#define IT_I2C_READ_RET 2
+#define IT_I2C_WRITE_RET 1
/* result of reading with BUF_QUERY bits */
#define CMD_STATUS_BITS 0x07
#define CMD_STATUS_DONE 0x00
#define CMD_STATUS_BUSY 0x01
#define CMD_STATUS_ERROR 0x02
+#define CMD_STATUS_NO_CONN 0x07
#define PT_INFO_BITS 0xF8
-#define BT_INFO_NONE 0x00
#define PT_INFO_YES 0x80
-/* no new data but finder(s) still down */
-#define BT_INFO_NONE_BUT_DOWN 0x08
#define PD_FLAGS_DATA_TYPE_BITS 0xF0
/* other types (like chip-detected gestures) exist but we do not care */
@@ -133,22 +135,21 @@
#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define IT_I2C_WAIT 1000
-struct FingerData {
+struct finger_data {
uint8_t xLo;
uint8_t hi;
uint8_t yLo;
uint8_t pressure;
} __packed;
-struct PointData {
+struct point_data {
uint8_t flags;
uint8_t palm;
- struct FingerData fd[3];
+ struct finger_data fd[3];
} __packed;
-struct IT7260_ts_platform_data {
+struct it7260_ts_platform_data {
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
@@ -172,10 +173,10 @@ struct IT7260_ts_platform_data {
bool low_reset;
};
-struct IT7260_ts_data {
+struct it7260_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- const struct IT7260_ts_platform_data *pdata;
+ const struct it7260_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *avdd;
bool device_needs_wakeup;
@@ -204,44 +205,49 @@ struct IT7260_ts_data {
/* Function declarations */
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data);
-static int IT7260_ts_resume(struct device *dev);
-static int IT7260_ts_suspend(struct device *dev);
+static int it7260_ts_resume(struct device *dev);
+static int it7260_ts_suspend(struct device *dev);
-static struct IT7260_ts_data *gl_ts;
-
-static int IT7260_debug_suspend_set(void *_data, u64 val)
+static int it7260_debug_suspend_set(void *_data, u64 val)
{
+ struct it7260_ts_data *ts_data = _data;
+
if (val)
- IT7260_ts_suspend(&gl_ts->client->dev);
+ it7260_ts_suspend(&ts_data->client->dev);
else
- IT7260_ts_resume(&gl_ts->client->dev);
+ it7260_ts_resume(&ts_data->client->dev);
return 0;
}
-static int IT7260_debug_suspend_get(void *_data, u64 *val)
+static int it7260_debug_suspend_get(void *_data, u64 *val)
{
- *val = gl_ts->suspended;
+ struct it7260_ts_data *ts_data = _data;
+
+ mutex_lock(&ts_data->input_dev->mutex);
+ *val = ts_data->suspended;
+ mutex_lock(&ts_data->input_dev->mutex);
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, IT7260_debug_suspend_get,
- IT7260_debug_suspend_set, "%lld\n");
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, it7260_debug_suspend_get,
+ it7260_debug_suspend_set, "%lld\n");
/* internal use func - does not make sure chip is ready before read */
-static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, uint8_t *buffer, uint16_t buf_len)
{
+ int ret;
struct i2c_msg msgs[2] = {
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_NOSTART,
.len = 1,
.buf = &buf_index
},
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_RD,
.len = buf_len,
.buf = buffer
@@ -250,15 +256,20 @@ static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
memset(buffer, 0xFF, buf_len);
- return i2c_transfer(gl_ts->client->adapter, msgs, 2);
+ ret = i2c_transfer(ts_data->client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c read failed %d\n", ret);
+
+ return ret;
}
-static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
- const uint8_t *buffer, uint16_t buf_len)
+static int it7260_i2c_write_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, const uint8_t *buffer, uint16_t buf_len)
{
uint8_t txbuf[257];
+ int ret;
struct i2c_msg msg = {
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = 0,
.len = buf_len + 1,
.buf = txbuf
@@ -266,110 +277,178 @@ static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
/* just to be careful */
if (buf_len > sizeof(txbuf) - 1) {
- dev_err(&gl_ts->client->dev, "buf length is out of limit\n");
+ dev_err(&ts_data->client->dev, "buf length is out of limit\n");
return false;
}
txbuf[0] = buf_index;
memcpy(txbuf + 1, buffer, buf_len);
- return i2c_transfer(gl_ts->client->adapter, &msg, 1);
+ ret = i2c_transfer(ts_data->client->adapter, &msg, 1);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c write failed %d\n", ret);
+
+ return ret;
}
/*
- * Device is apparently always ready for i2c but not for actual
- * register reads/writes. This function ascertains it is ready
- * for that too. the results of this call often were ignored.
+ * Device is apparently always ready for I2C communication but not for
+ * actual register reads/writes. This function checks if it is ready
+ * for that too. The results of this call often were ignored.
+ * If forever is set to TRUE, then check the device's status until it
+ * becomes ready with 500 retries at max. Otherwise retry 25 times only.
+ * If slowly is set to TRUE, then add sleep of 50 ms in each retry,
+ * otherwise don't sleep.
*/
-static bool IT7260_waitDeviceReady(bool forever, bool slowly)
+static int it7260_wait_device_ready(struct it7260_ts_data *ts_data,
+ bool forever, bool slowly)
{
uint8_t query;
- uint32_t count = DEVICE_READY_MAX_WAIT;
+ uint32_t count = DEVICE_READY_COUNT_20;
+ int ret;
+
+ if (ts_data->fw_cfg_uploading || forever)
+ count = DEVICE_READY_COUNT_MAX;
do {
- if (!IT7260_i2cReadNoReadyCheck(BUF_QUERY, &query,
- sizeof(query)))
- query = CMD_STATUS_BUSY;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &query,
+ sizeof(query));
+ if (ret < 0 && ((query & CMD_STATUS_BITS)
+ == CMD_STATUS_NO_CONN))
+ continue;
- if (slowly)
- msleep(IT_I2C_WAIT);
- if (!forever)
- count--;
+ if ((query & CMD_STATUS_BITS) == CMD_STATUS_DONE)
+ break;
- } while ((query & CMD_STATUS_BUSY) && count);
+ query = CMD_STATUS_BUSY;
+ if (slowly)
+ msleep(IT_I2C_WAIT_10MS);
+ } while (--count);
- return !query;
+ return ((!(query & CMD_STATUS_BITS)) ? 0 : -ENODEV);
}
-static bool IT7260_i2cRead(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cReadNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_read_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_i2cWrite(uint8_t buf_index, const uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_write(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ const uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cWriteNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_write_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_firmware_reinitialize(u8 command)
+static int it7260_firmware_reinitialize(struct it7260_ts_data *ts_data,
+ u8 command)
{
uint8_t cmd[] = {command};
uint8_t rsp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw reinit command %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, rsp, sizeof(rsp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !rsp[0] && !rsp[1];
+ if (rsp[0] == 0 && rsp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_enter_exit_fw_ugrade_mode(bool enter)
+static int it7260_enter_exit_fw_ugrade_mode(struct it7260_ts_data *ts_data,
+ bool enter)
{
uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2',
'6', '0', 0x55, 0xAA};
uint8_t resp[2];
+ int ret;
cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE :
SUB_CMD_EXIT_FW_UPGRADE_MODE;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_FIRMWARE_UPGRADE %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_chipSetStartOffset(uint16_t offset)
+static int it7260_set_start_offset(struct it7260_ts_data *ts_data,
+ uint16_t offset)
{
uint8_t cmd[] = {CMD_SET_START_OFFSET, 0, ((uint8_t)(offset)),
((uint8_t)((offset) >> 8))};
uint8_t resp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, 4))
- return false;
-
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, 4);
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_SET_START_OFFSET %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
/* write fw_length bytes from fw_data at chip offset wr_start_offset */
-static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
- const uint8_t *fw_data, uint16_t wr_start_offset)
+static int it7260_fw_flash_write_verify(struct it7260_ts_data *ts_data,
+ unsigned int fw_length, const uint8_t *fw_data,
+ uint16_t wr_start_offset)
{
uint32_t cur_data_off;
@@ -399,17 +478,18 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
retries++) {
/* set write offset and write the data */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_write,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_write,
cur_wr_size + 2);
/* set offset and read the data back */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_read,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read,
sizeof(cmd_read));
- IT7260_i2cRead(BUF_RESPONSE, buf_read, cur_wr_size);
+ it7260_i2c_read(ts_data, BUF_RESPONSE, buf_read,
+ cur_wr_size);
/* verify. If success break out of retry loop */
i = 0;
@@ -421,68 +501,96 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
}
/* if we've failed after all the retries, tell the caller */
if (retries == FW_WRITE_RETRY_COUNT) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"write of data offset %u failed on try %u at byte %u/%u\n",
cur_data_off, retries, i, cur_wr_size);
- return false;
+ return -EIO;
}
}
- return true;
+ return 0;
}
/*
* this code to get versions from the chip via i2c transactions, and save
* them in driver data structure.
*/
-static void IT7260_get_chip_versions(struct device *dev)
+static void it7260_get_chip_versions(struct it7260_ts_data *ts_data)
{
static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_FIRMWARE_VERSION};
static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_CONFIG_VERSION};
u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH];
- bool ret = true;
+ int ret;
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_fw_ver,
sizeof(cmd_read_fw_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH);
- if (ret)
- memcpy(gl_ts->fw_ver, ver_fw + (5 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_fw, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->fw_ver, ver_fw + (5 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read fw-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read fw version from chip\n");
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_cfg_ver,
sizeof(cmd_read_cfg_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH)
- && ret;
- if (ret)
- memcpy(gl_ts->cfg_ver, ver_cfg + (1 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_cfg, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->cfg_ver, ver_cfg + (1 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read cfg-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write cfg-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read cfg version from chip\n");
- dev_info(dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ dev_info(&ts_data->client->dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1], ts_data->fw_ver[2],
+ ts_data->fw_ver[3], ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
-static int IT7260_cfg_upload(struct device *dev, bool force)
+static int it7260_cfg_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *cfg = NULL;
int ret;
- bool success, cfg_upgrade = false;
+ bool cfg_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&cfg, gl_ts->cfg_name, dev);
+ ret = request_firmware(&cfg, ts_data->cfg_name, dev);
if (ret) {
dev_err(dev, "failed to get config data %s for it7260 %d\n",
- gl_ts->cfg_name, ret);
+ ts_data->cfg_name, ret);
return ret;
}
@@ -493,43 +601,59 @@ static int IT7260_cfg_upload(struct device *dev, bool force)
*/
if (force)
cfg_upgrade = true;
- else if (IT_CFG_CHECK(gl_ts->cfg_ver, cfg))
+ else if (IT_CFG_CHECK(ts_data->cfg_ver, cfg))
cfg_upgrade = true;
if (!cfg_upgrade) {
- dev_err(dev, "CFG upgrade no required ...\n");
+ dev_err(dev, "CFG upgrade not required ...\n");
+ dev_info(dev,
+ "Chip CFG : %X.%X.%X.%X Binary CFG : %X.%X.%X.%X\n",
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3],
+ cfg->data[cfg->size - 8], cfg->data[cfg->size - 7],
+ cfg->data[cfg->size - 6], cfg->data[cfg->size - 5]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Config upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter cfg upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter cfg upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter cfg upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash config data if requested */
- success = IT7260_fw_flash_write_verify(cfg->size, cfg->data,
- CHIP_FLASH_SIZE - cfg->size);
- if (!success) {
- dev_err(dev, "failed to upgrade touch cfg data\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, cfg->size,
+ cfg->data, CHIP_FLASH_SIZE - cfg->size);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch cfg data %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit cfg upgrade mode%d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit cfg %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->cfg_ver, cfg->data +
+ memcpy(ts_data->cfg_ver, cfg->data +
(cfg->size - 8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n",
- gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -538,16 +662,17 @@ out:
return ret;
}
-static int IT7260_fw_upload(struct device *dev, bool force)
+static int it7260_fw_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *fw = NULL;
int ret;
- bool success, fw_upgrade = false;
+ bool fw_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&fw, gl_ts->fw_name, dev);
+ ret = request_firmware(&fw, ts_data->fw_name, dev);
if (ret) {
dev_err(dev, "failed to get firmware %s for it7260 %d\n",
- gl_ts->fw_name, ret);
+ ts_data->fw_name, ret);
return ret;
}
@@ -558,40 +683,55 @@ static int IT7260_fw_upload(struct device *dev, bool force)
*/
if (force)
fw_upgrade = true;
- else if (IT_FW_CHECK(gl_ts->fw_ver, fw))
+ else if (IT_FW_CHECK(ts_data->fw_ver, fw))
fw_upgrade = true;
if (!fw_upgrade) {
dev_err(dev, "FW upgrade not required ...\n");
+ dev_info(dev, "Chip FW : %X.%X.%X.%X Binary FW : %X.%X.%X.%X\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ fw->data[8], fw->data[9], fw->data[10], fw->data[11]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Firmware upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter fw upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter fw upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter fw upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash the firmware if requested */
- success = IT7260_fw_flash_write_verify(fw->size, fw->data, 0);
- if (!success) {
- dev_err(dev, "failed to upgrade touch firmware\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, fw->size,
+ fw->data, 0);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch firmware %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit fw upgrade mode %d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit firmware %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->fw_ver, fw->data + (8 * sizeof(u8)),
+ memcpy(ts_data->fw_ver, fw->data + (8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1],
- gl_ts->fw_ver[2], gl_ts->fw_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -600,16 +740,18 @@ out:
return ret;
}
-static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
+static int it7260_ts_chip_low_power_mode(struct it7260_ts_data *ts_data,
+ const u8 sleep_type)
{
const uint8_t cmd_sleep[] = {CMD_PWR_CTL, 0x00, sleep_type};
uint8_t dummy;
if (sleep_type)
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_sleep,
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_sleep,
sizeof(cmd_sleep));
else
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dummy,
+ sizeof(dummy));
msleep(WAIT_CHANGE_MODE);
return 0;
@@ -618,32 +760,33 @@ static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
static ssize_t sysfs_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -651,32 +794,33 @@ static ssize_t sysfs_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -684,46 +828,51 @@ static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->fw_upgrade_result);
+ ts_data->fw_upgrade_result);
}
static ssize_t sysfs_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->cfg_upgrade_result);
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -731,32 +880,33 @@ static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -764,51 +914,65 @@ static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_force_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d", ts_data->fw_upgrade_result);
}
static ssize_t sysfs_force_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->cfg_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d",
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_calibration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->calibration_success);
+ ts_data->calibration_success);
}
-static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on)
+static int it7260_ts_send_calibration_cmd(struct it7260_ts_data *ts_data,
+ bool auto_tune_on)
{
uint8_t cmd_calibrate[] = {CMD_CALIBRATE, 0,
auto_tune_on ? 1 : 0, 0, 0};
- return IT7260_i2cWrite(BUF_COMMAND, cmd_calibrate,
+
+ return it7260_i2c_write(ts_data, BUF_COMMAND, cmd_calibrate,
sizeof(cmd_calibrate));
}
static ssize_t sysfs_calibration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
uint8_t resp;
+ int ret;
- if (!IT7260_chipSendCalibrationCmd(false)) {
+ ret = it7260_ts_send_calibration_cmd(ts_data, false);
+ if (ret < 0) {
dev_err(dev, "failed to send calibration command\n");
} else {
- gl_ts->calibration_success =
- IT7260_i2cRead(BUF_RESPONSE, &resp, sizeof(resp));
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, &resp,
+ sizeof(resp));
+ if (ret == IT_I2C_READ_RET)
+ ts_data->calibration_success = true;
/*
* previous logic that was here never called
- * IT7260_firmware_reinitialize() due to checking a
+ * it7260_firmware_reinitialize() due to checking a
* guaranteed-not-null value against null. We now
* call it. Hopefully this is OK
*/
if (!resp)
- dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n",
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F)
- ? "success" : "fail");
+ dev_dbg(dev, "it7260_firmware_reinitialize-> %s\n",
+ it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F) ? "success" : "fail");
}
return count;
@@ -817,21 +981,22 @@ static ssize_t sysfs_calibration_store(struct device *dev,
static ssize_t sysfs_point_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- uint8_t point_data[sizeof(struct PointData)];
- bool readSuccess;
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ uint8_t pt_data[sizeof(struct point_data)];
+ int readSuccess;
ssize_t ret;
- readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data,
- sizeof(point_data));
+ readSuccess = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ pt_data, sizeof(pt_data));
- if (readSuccess) {
+ if (readSuccess == IT_I2C_READ_RET) {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n",
- readSuccess, point_data[0], point_data[1],
- point_data[2], point_data[3], point_data[4],
- point_data[5], point_data[6], point_data[7],
- point_data[8], point_data[9], point_data[10],
- point_data[11], point_data[12], point_data[13]);
+ readSuccess, pt_data[0], pt_data[1],
+ pt_data[2], pt_data[3], pt_data[4],
+ pt_data[5], pt_data[6], pt_data[7],
+ pt_data[8], pt_data[9], pt_data[10],
+ pt_data[11], pt_data[12], pt_data[13]);
} else {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"failed to read point data\n");
@@ -844,51 +1009,57 @@ static ssize_t sysfs_point_show(struct device *dev,
static ssize_t sysfs_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE,
"fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
static ssize_t sysfs_sleep_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
/*
* The usefulness of this was questionable at best - we were at least
* leaking a byte of kernel data (by claiming to return a byte but not
* writing to buf. To fix this now we actually return the sleep status
*/
- *buf = gl_ts->suspended ? '1' : '0';
+ *buf = ts_data->suspended ? '1' : '0';
+
return 1;
}
static ssize_t sysfs_sleep_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int go_to_sleep, ret;
ret = kstrtoint(buf, 10, &go_to_sleep);
- /* (gl_ts->suspended == true && goToSleepVal > 0) means
+ /* (ts_data->suspended == true && goToSleepVal > 0) means
* device is already suspended and you want it to be in sleep,
- * (gl_ts->suspended == false && goToSleepVal == 0) means
+ * (ts_data->suspended == false && goToSleepVal == 0) means
* device is already active and you also want it to be active.
*/
- if ((gl_ts->suspended && go_to_sleep > 0) ||
- (!gl_ts->suspended && go_to_sleep == 0))
+ if ((ts_data->suspended && go_to_sleep > 0) ||
+ (!ts_data->suspended && go_to_sleep == 0))
dev_err(dev, "duplicate request to %s chip\n",
go_to_sleep ? "sleep" : "wake");
else if (go_to_sleep) {
- disable_irq(gl_ts->client->irq);
- IT7260_ts_chipLowPowerMode(PWR_CTL_SLEEP_MODE);
+ disable_irq(ts_data->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_SLEEP_MODE);
dev_dbg(dev, "touch is going to sleep...\n");
} else {
- IT7260_ts_chipLowPowerMode(PWR_CTL_ACTIVE_MODE);
- enable_irq(gl_ts->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_ACTIVE_MODE);
+ enable_irq(ts_data->client->irq);
dev_dbg(dev, "touch is going to wake!\n");
}
- gl_ts->suspended = go_to_sleep;
+ ts_data->suspended = go_to_sleep;
return count;
}
@@ -896,6 +1067,7 @@ static ssize_t sysfs_sleep_store(struct device *dev,
static ssize_t sysfs_cfg_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -909,7 +1081,7 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->cfg_name, buf, count);
+ strlcpy(ts_data->cfg_name, buf, count);
return count;
}
@@ -917,9 +1089,11 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
static ssize_t sysfs_cfg_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->cfg_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->cfg_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->cfg_name);
+ ts_data->cfg_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No config file name given\n");
@@ -928,6 +1102,7 @@ static ssize_t sysfs_cfg_name_show(struct device *dev,
static ssize_t sysfs_fw_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -941,16 +1116,18 @@ static ssize_t sysfs_fw_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->fw_name, buf, count);
+ strlcpy(ts_data->fw_name, buf, count);
return count;
}
static ssize_t sysfs_fw_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->fw_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->fw_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->fw_name);
+ ts_data->fw_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No firmware file name given\n");
@@ -997,59 +1174,47 @@ static const struct attribute_group it7260_attr_group = {
.attrs = it7260_attributes,
};
-static void IT7260_chipExternalCalibration(bool autoTuneEnabled)
-{
- uint8_t resp[2];
-
- dev_dbg(&gl_ts->client->dev, "sent calibration command -> %d\n",
- IT7260_chipSendCalibrationCmd(autoTuneEnabled));
- IT7260_waitDeviceReady(true, true);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp));
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C);
-}
-
-void IT7260_sendCalibrationCmd(void)
-{
- IT7260_chipExternalCalibration(false);
-}
-EXPORT_SYMBOL(IT7260_sendCalibrationCmd);
-
-static void IT7260_ts_release_all(void)
+static void it7260_ts_release_all(struct it7260_ts_data *ts_data)
{
int finger;
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- input_mt_slot(gl_ts->input_dev, finger);
- input_mt_report_slot_state(gl_ts->input_dev,
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ input_mt_slot(ts_data->input_dev, finger);
+ input_mt_report_slot_state(ts_data->input_dev,
MT_TOOL_FINGER, 0);
}
- input_report_key(gl_ts->input_dev, BTN_TOUCH, 0);
- input_sync(gl_ts->input_dev);
+ input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
+ input_sync(ts_data->input_dev);
}
-static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
+static irqreturn_t it7260_ts_threaded_handler(int irq, void *devid)
{
- struct PointData point_data;
- struct input_dev *input_dev = gl_ts->input_dev;
+ struct point_data pt_data;
+ struct it7260_ts_data *ts_data = devid;
+ struct input_dev *input_dev = ts_data->input_dev;
u8 dev_status, finger, touch_count = 0, finger_status;
u8 pressure = FD_PRESSURE_NONE;
u16 x, y;
bool palm_detected;
+ int ret;
/* verify there is point data to read & it is readable and valid */
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dev_status, sizeof(dev_status));
- if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
- return IRQ_HANDLED;
- if (!IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, (void *)&point_data,
- sizeof(point_data))) {
- dev_err(&gl_ts->client->dev,
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dev_status,
+ sizeof(dev_status));
+ if (ret == IT_I2C_READ_RET)
+ if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
+ return IRQ_HANDLED;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ (void *)&pt_data, sizeof(pt_data));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
"failed to read point data buffer\n");
return IRQ_HANDLED;
}
/* Check if controller moves from idle to active state */
- if ((point_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
+ if ((pt_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
PD_FLAGS_DATA_TYPE_TOUCH) {
/*
* This code adds the touch-to-wake functionality to the ITE
@@ -1061,40 +1226,40 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
* schedule a work that tells the pm core to relax once the CPU
* cores are up.
*/
- if (gl_ts->device_needs_wakeup) {
- pm_stay_awake(&gl_ts->client->dev);
+ if (ts_data->device_needs_wakeup) {
+ pm_stay_awake(&ts_data->client->dev);
input_report_key(input_dev, KEY_WAKEUP, 1);
input_sync(input_dev);
input_report_key(input_dev, KEY_WAKEUP, 0);
input_sync(input_dev);
- schedule_work(&gl_ts->work_pm_relax);
+ schedule_work(&ts_data->work_pm_relax);
return IRQ_HANDLED;
}
}
- palm_detected = point_data.palm & PD_PALM_FLAG_BIT;
- if (palm_detected && gl_ts->pdata->palm_detect_en) {
+ palm_detected = pt_data.palm & PD_PALM_FLAG_BIT;
+ if (palm_detected && ts_data->pdata->palm_detect_en) {
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 1);
+ ts_data->pdata->palm_detect_keycode, 1);
input_sync(input_dev);
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 0);
+ ts_data->pdata->palm_detect_keycode, 0);
input_sync(input_dev);
}
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- finger_status = point_data.flags & (0x01 << finger);
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ finger_status = pt_data.flags & (0x01 << finger);
input_mt_slot(input_dev, finger);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
finger_status != 0);
- x = point_data.fd[finger].xLo +
- (((u16)(point_data.fd[finger].hi & 0x0F)) << 8);
- y = point_data.fd[finger].yLo +
- (((u16)(point_data.fd[finger].hi & 0xF0)) << 4);
+ x = pt_data.fd[finger].xLo +
+ (((u16)(pt_data.fd[finger].hi & 0x0F)) << 8);
+ y = pt_data.fd[finger].yLo +
+ (((u16)(pt_data.fd[finger].hi & 0xF0)) << 4);
- pressure = point_data.fd[finger].pressure & FD_PRESSURE_BITS;
+ pressure = pt_data.fd[finger].pressure & FD_PRESSURE_BITS;
if (finger_status) {
if (pressure >= FD_PRESSURE_LIGHT) {
@@ -1114,35 +1279,66 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
return IRQ_HANDLED;
}
-static void IT7260_ts_work_func(struct work_struct *work)
+static void it7260_ts_work_func(struct work_struct *work)
{
- pm_relax(&gl_ts->client->dev);
+ struct it7260_ts_data *ts_data = container_of(work,
+ struct it7260_ts_data, work_pm_relax);
+
+ pm_relax(&ts_data->client->dev);
}
-static int IT7260_chipIdentify(void)
+static int it7260_ts_chip_identify(struct it7260_ts_data *ts_data)
{
static const uint8_t cmd_ident[] = {CMD_IDENT_CHIP};
static const uint8_t expected_id[] = {0x0A, 'I', 'T', 'E', '7',
'2', '6', '0'};
uint8_t chip_id[10] = {0,};
+ int ret;
- IT7260_waitDeviceReady(false, false);
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * FALSE means to retry 20 times at max to read the chip status.
+ * TRUE means to add delay in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, false, true);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_ident,
- sizeof(cmd_ident))) {
- dev_err(&gl_ts->client->dev, "failed to write CMD_IDENT_CHIP\n");
- return -ENODEV;
+ ret = it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_ident,
+ sizeof(cmd_ident));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_IDENT_CHIP %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * TRUE means to retry 500 times at max to read the chip status.
+ * FALSE means to avoid unnecessary delays in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
}
- IT7260_waitDeviceReady(false, false);
- if (!IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, chip_id,
- sizeof(chip_id))) {
- dev_err(&gl_ts->client->dev, "failed to read chip-id\n");
- return -ENODEV;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, chip_id,
+ sizeof(chip_id));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip-id %d\n", ret);
+ return ret;
}
- dev_info(&gl_ts->client->dev,
- "IT7260_chipIdentify read id: %02X %c%c%c%c%c%c%c %c%c\n",
+ dev_info(&ts_data->client->dev,
+ "it7260_ts_chip_identify read id: %02X %c%c%c%c%c%c%c %c%c\n",
chip_id[0], chip_id[1], chip_id[2], chip_id[3], chip_id[4],
chip_id[5], chip_id[6], chip_id[7], chip_id[8], chip_id[9]);
@@ -1150,11 +1346,11 @@ static int IT7260_chipIdentify(void)
return -EINVAL;
if (chip_id[8] == '5' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX3 found\n");
+ dev_info(&ts_data->client->dev, "rev BX3 found\n");
else if (chip_id[8] == '6' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX4 found\n");
+ dev_info(&ts_data->client->dev, "rev BX4 found\n");
else
- dev_info(&gl_ts->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
+ dev_info(&ts_data->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
chip_id[8], chip_id[9]);
return 0;
@@ -1166,44 +1362,44 @@ static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
regulator_set_optimum_mode(reg, load_uA) : 0;
}
-static int IT7260_regulator_configure(bool on)
+static int it7260_regulator_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto hw_shutdown;
- gl_ts->vdd = devm_regulator_get(&gl_ts->client->dev, "vdd");
- if (IS_ERR(gl_ts->vdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->vdd = devm_regulator_get(&ts_data->client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get vdd regulator\n", __func__);
- return PTR_ERR(gl_ts->vdd);
+ return PTR_ERR(ts_data->vdd);
}
- if (regulator_count_voltages(gl_ts->vdd) > 0) {
- retval = regulator_set_voltage(gl_ts->vdd,
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ retval = regulator_set_voltage(ts_data->vdd,
IT_VTG_MIN_UV, IT_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"regulator set_vtg failed retval =%d\n",
retval);
goto err_set_vtg_vdd;
}
}
- gl_ts->avdd = devm_regulator_get(&gl_ts->client->dev, "avdd");
- if (IS_ERR(gl_ts->avdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->avdd = devm_regulator_get(&ts_data->client->dev, "avdd");
+ if (IS_ERR(ts_data->avdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get i2c regulator\n", __func__);
- retval = PTR_ERR(gl_ts->avdd);
+ retval = PTR_ERR(ts_data->avdd);
goto err_get_vtg_i2c;
}
- if (regulator_count_voltages(gl_ts->avdd) > 0) {
- retval = regulator_set_voltage(gl_ts->avdd,
+ if (regulator_count_voltages(ts_data->avdd) > 0) {
+ retval = regulator_set_voltage(ts_data->avdd,
IT_I2C_VTG_MIN_UV, IT_I2C_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reg set i2c vtg failed retval =%d\n",
retval);
goto err_set_vtg_i2c;
@@ -1214,55 +1410,55 @@ static int IT7260_regulator_configure(bool on)
err_set_vtg_i2c:
err_get_vtg_i2c:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
err_set_vtg_vdd:
return retval;
hw_shutdown:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
- if (regulator_count_voltages(gl_ts->avdd) > 0)
- regulator_set_voltage(gl_ts->avdd, 0, IT_I2C_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->avdd) > 0)
+ regulator_set_voltage(ts_data->avdd, 0, IT_I2C_VTG_MAX_UV);
return 0;
};
-static int IT7260_power_on(bool on)
+static int it7260_power_on(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto power_off;
- retval = reg_set_optimum_mode_check(gl_ts->vdd,
+ retval = reg_set_optimum_mode_check(ts_data->vdd,
IT_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd set_opt failed rc=%d\n",
retval);
return retval;
}
- retval = regulator_enable(gl_ts->vdd);
+ retval = regulator_enable(ts_data->vdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd enable failed rc=%d\n",
retval);
goto error_reg_en_vdd;
}
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ retval = reg_set_optimum_mode_check(ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd set_opt failed rc=%d\n",
retval);
goto error_reg_opt_i2c;
}
- retval = regulator_enable(gl_ts->avdd);
+ retval = regulator_enable(ts_data->avdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd enable failed rc=%d\n",
retval);
goto error_reg_en_avdd;
@@ -1271,118 +1467,119 @@ static int IT7260_power_on(bool on)
return 0;
error_reg_en_avdd:
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
error_reg_opt_i2c:
- regulator_disable(gl_ts->vdd);
+ regulator_disable(ts_data->vdd);
error_reg_en_vdd:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
return retval;
power_off:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
- regulator_disable(gl_ts->vdd);
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
- regulator_disable(gl_ts->avdd);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
+ regulator_disable(ts_data->vdd);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
+ regulator_disable(ts_data->avdd);
return 0;
}
-static int IT7260_gpio_configure(bool on)
+static int it7260_gpio_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval = 0;
if (on) {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
/* configure touchscreen irq gpio */
- retval = gpio_request(gl_ts->pdata->irq_gpio,
+ retval = gpio_request(ts_data->pdata->irq_gpio,
"ite_irq_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request irq gpio [%d]\n",
retval);
goto err_irq_gpio_req;
}
- retval = gpio_direction_input(gl_ts->pdata->irq_gpio);
+ retval = gpio_direction_input(ts_data->pdata->irq_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for irq gpio [%d]\n",
retval);
goto err_irq_gpio_dir;
}
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"irq gpio not provided\n");
goto err_irq_gpio_req;
}
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/* configure touchscreen reset out gpio */
- retval = gpio_request(gl_ts->pdata->reset_gpio,
+ retval = gpio_request(ts_data->pdata->reset_gpio,
"ite_reset_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request reset gpio [%d]\n",
retval);
goto err_reset_gpio_req;
}
retval = gpio_direction_output(
- gl_ts->pdata->reset_gpio, 1);
+ ts_data->pdata->reset_gpio, 1);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for reset gpio [%d]\n",
retval);
goto err_reset_gpio_dir;
}
- if (gl_ts->pdata->low_reset)
- gpio_set_value(gl_ts->pdata->reset_gpio, 0);
+ if (ts_data->pdata->low_reset)
+ gpio_set_value(ts_data->pdata->reset_gpio, 0);
else
- gpio_set_value(gl_ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts_data->pdata->reset_gpio, 1);
- msleep(gl_ts->pdata->reset_delay);
+ msleep(ts_data->pdata->reset_delay);
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reset gpio not provided\n");
goto err_reset_gpio_req;
}
} else {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/*
* This is intended to save leakage current
* only. Even if the call(gpio_direction_input)
* fails, only leakage current will be more but
* functionality will not be affected.
*/
- retval = gpio_direction_input(gl_ts->pdata->reset_gpio);
+ retval = gpio_direction_input(
+ ts_data->pdata->reset_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for gpio reset [%d]\n",
retval);
}
- gpio_free(gl_ts->pdata->reset_gpio);
+ gpio_free(ts_data->pdata->reset_gpio);
}
}
return 0;
err_reset_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
err_reset_gpio_req:
err_irq_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
err_irq_gpio_req:
return retval;
}
#if CONFIG_OF
-static int IT7260_get_dt_coords(struct device *dev, char *name,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_get_dt_coords(struct device *dev, char *name,
+ struct it7260_ts_platform_data *pdata)
{
u32 coords[IT7260_COORDS_ARR_SIZE];
struct property *prop;
@@ -1435,9 +1632,10 @@ static int IT7260_get_dt_coords(struct device *dev, char *name,
return 0;
}
-static int IT7260_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
struct device_node *np = dev->of_node;
u32 temp_val;
int rc;
@@ -1481,9 +1679,9 @@ static int IT7260_parse_dt(struct device *dev,
return rc;
}
- snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->fw_name, MAX_BUFFER_SIZE, "%s",
(pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME);
- snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->cfg_name, MAX_BUFFER_SIZE, "%s",
(pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME);
rc = of_property_read_u32(np, "ite,reset-delay", &temp_val);
@@ -1504,25 +1702,25 @@ static int IT7260_parse_dt(struct device *dev,
pdata->low_reset = of_property_read_bool(np, "ite,low-reset");
- rc = IT7260_get_dt_coords(dev, "ite,display-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,display-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
- rc = IT7260_get_dt_coords(dev, "ite,panel-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,panel-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
return 0;
}
#else
-static inline int IT7260_ts_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static inline int it7260_ts_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
return 0;
}
#endif
-static int IT7260_ts_pinctrl_init(struct IT7260_ts_data *ts_data)
+static int it7260_ts_pinctrl_init(struct it7260_ts_data *ts_data)
{
int retval;
@@ -1576,11 +1774,12 @@ err_pinctrl_get:
return retval;
}
-static int IT7260_ts_probe(struct i2c_client *client,
+static int it7260_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const uint8_t cmd_start[] = {CMD_UNKNOWN_7};
- struct IT7260_ts_platform_data *pdata;
+ struct it7260_ts_data *ts_data;
+ struct it7260_ts_platform_data *pdata;
uint8_t rsp[2];
int ret = -1, err;
struct dentry *temp;
@@ -1590,40 +1789,39 @@ static int IT7260_ts_probe(struct i2c_client *client,
return -ENODEV;
}
- gl_ts = devm_kzalloc(&client->dev, sizeof(*gl_ts), GFP_KERNEL);
- if (!gl_ts)
+ ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL);
+ if (!ts_data)
return -ENOMEM;
- gl_ts->client = client;
- i2c_set_clientdata(client, gl_ts);
-
- if (client->dev.platform_data == NULL)
- return -ENODEV;
+ ts_data->client = client;
+ i2c_set_clientdata(client, ts_data);
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- ret = IT7260_parse_dt(&client->dev, pdata);
+ ret = it7260_parse_dt(&client->dev, pdata);
if (ret)
return ret;
} else {
pdata = client->dev.platform_data;
}
- if (!pdata)
+ if (!pdata) {
+ dev_err(&client->dev, "No platform data found\n");
return -ENOMEM;
+ }
- gl_ts->pdata = pdata;
+ ts_data->pdata = pdata;
- ret = IT7260_regulator_configure(true);
+ ret = it7260_regulator_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure regulators\n");
goto err_reg_configure;
}
- ret = IT7260_power_on(true);
+ ret = it7260_power_on(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to power on\n");
goto err_power_device;
@@ -1635,81 +1833,82 @@ static int IT7260_ts_probe(struct i2c_client *client,
*/
msleep(DELAY_VTG_REG_EN);
- ret = IT7260_ts_pinctrl_init(gl_ts);
- if (!ret && gl_ts->ts_pinctrl) {
+ ret = it7260_ts_pinctrl_init(ts_data);
+ if (!ret && ts_data->ts_pinctrl) {
/*
* Pinctrl handle is optional. If pinctrl handle is found
* let pins to be configured in active state. If not
* found continue further without error.
*/
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (ret < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select pin to active state %d",
ret);
}
} else {
- ret = IT7260_gpio_configure(true);
+ ret = it7260_gpio_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure gpios\n");
goto err_gpio_config;
}
}
- ret = IT7260_chipIdentify();
+ ret = it7260_ts_chip_identify(ts_data);
if (ret) {
dev_err(&client->dev, "Failed to identify chip %d!!!", ret);
goto err_identification_fail;
}
- IT7260_get_chip_versions(&client->dev);
+ it7260_get_chip_versions(ts_data);
- gl_ts->input_dev = input_allocate_device();
- if (!gl_ts->input_dev) {
+ ts_data->input_dev = input_allocate_device();
+ if (!ts_data->input_dev) {
dev_err(&client->dev, "failed to allocate input device\n");
ret = -ENOMEM;
goto err_input_alloc;
}
/* Initialize mutex for fw and cfg upgrade */
- mutex_init(&gl_ts->fw_cfg_mutex);
-
- gl_ts->input_dev->name = DEVICE_NAME;
- gl_ts->input_dev->phys = "I2C";
- gl_ts->input_dev->id.bustype = BUS_I2C;
- gl_ts->input_dev->id.vendor = 0x0001;
- gl_ts->input_dev->id.product = 0x7260;
- set_bit(EV_SYN, gl_ts->input_dev->evbit);
- set_bit(EV_KEY, gl_ts->input_dev->evbit);
- set_bit(EV_ABS, gl_ts->input_dev->evbit);
- set_bit(INPUT_PROP_DIRECT, gl_ts->input_dev->propbit);
- set_bit(BTN_TOUCH, gl_ts->input_dev->keybit);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_X,
- gl_ts->pdata->disp_minx, gl_ts->pdata->disp_maxx, 0, 0);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y,
- gl_ts->pdata->disp_miny, gl_ts->pdata->disp_maxy, 0, 0);
- input_mt_init_slots(gl_ts->input_dev, gl_ts->pdata->num_of_fingers, 0);
-
- input_set_drvdata(gl_ts->input_dev, gl_ts);
+ mutex_init(&ts_data->fw_cfg_mutex);
+
+ ts_data->input_dev->name = DEVICE_NAME;
+ ts_data->input_dev->phys = "I2C";
+ ts_data->input_dev->id.bustype = BUS_I2C;
+ ts_data->input_dev->id.vendor = 0x0001;
+ ts_data->input_dev->id.product = 0x7260;
+ set_bit(EV_SYN, ts_data->input_dev->evbit);
+ set_bit(EV_KEY, ts_data->input_dev->evbit);
+ set_bit(EV_ABS, ts_data->input_dev->evbit);
+ set_bit(INPUT_PROP_DIRECT, ts_data->input_dev->propbit);
+ set_bit(BTN_TOUCH, ts_data->input_dev->keybit);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_X,
+ ts_data->pdata->disp_minx, ts_data->pdata->disp_maxx, 0, 0);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_Y,
+ ts_data->pdata->disp_miny, ts_data->pdata->disp_maxy, 0, 0);
+ input_mt_init_slots(ts_data->input_dev,
+ ts_data->pdata->num_of_fingers, 0);
+
+ input_set_drvdata(ts_data->input_dev, ts_data);
if (pdata->wakeup) {
- set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit);
- INIT_WORK(&gl_ts->work_pm_relax, IT7260_ts_work_func);
+ set_bit(KEY_WAKEUP, ts_data->input_dev->keybit);
+ INIT_WORK(&ts_data->work_pm_relax, it7260_ts_work_func);
device_init_wakeup(&client->dev, pdata->wakeup);
}
if (pdata->palm_detect_en)
- set_bit(gl_ts->pdata->palm_detect_keycode,
- gl_ts->input_dev->keybit);
+ set_bit(ts_data->pdata->palm_detect_keycode,
+ ts_data->input_dev->keybit);
- if (input_register_device(gl_ts->input_dev)) {
+ if (input_register_device(ts_data->input_dev)) {
dev_err(&client->dev, "failed to register input device\n");
goto err_input_register;
}
- if (request_threaded_irq(client->irq, NULL, IT7260_ts_threaded_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, gl_ts)) {
+ if (request_threaded_irq(client->irq, NULL, it7260_ts_threaded_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts_data)) {
dev_err(&client->dev, "request_irq failed\n");
goto err_irq_reg;
}
@@ -1720,30 +1919,31 @@ static int IT7260_ts_probe(struct i2c_client *client,
}
#if defined(CONFIG_FB)
- gl_ts->fb_notif.notifier_call = fb_notifier_callback;
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&gl_ts->fb_notif);
+ ret = fb_register_client(&ts_data->fb_notif);
if (ret)
dev_err(&client->dev, "Unable to register fb_notifier %d\n",
ret);
#endif
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_start, sizeof(cmd_start));
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_start,
+ sizeof(cmd_start));
msleep(pdata->reset_delay);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, rsp, sizeof(rsp));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
msleep(pdata->reset_delay);
- gl_ts->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
- if (gl_ts->dir == NULL || IS_ERR(gl_ts->dir)) {
+ ts_data->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (ts_data->dir == NULL || IS_ERR(ts_data->dir)) {
dev_err(&client->dev,
"%s: Failed to create debugfs directory, ret = %ld\n",
- __func__, PTR_ERR(gl_ts->dir));
- ret = PTR_ERR(gl_ts->dir);
+ __func__, PTR_ERR(ts_data->dir));
+ ret = PTR_ERR(ts_data->dir);
goto err_create_debugfs_dir;
}
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, gl_ts->dir,
- gl_ts, &debug_suspend_fops);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, ts_data->dir,
+ ts_data, &debug_suspend_fops);
if (temp == NULL || IS_ERR(temp)) {
dev_err(&client->dev,
"%s: Failed to create suspend debugfs file, ret = %ld\n",
@@ -1755,40 +1955,40 @@ static int IT7260_ts_probe(struct i2c_client *client,
return 0;
err_create_debugfs_file:
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
err_create_debugfs_dir:
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
err_sysfs_grp_create:
- free_irq(client->irq, gl_ts);
+ free_irq(client->irq, ts_data);
err_irq_reg:
- input_unregister_device(gl_ts->input_dev);
+ input_unregister_device(ts_data->input_dev);
err_input_register:
if (pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
err_input_alloc:
err_identification_fail:
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- err = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ err = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (err)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
err);
}
@@ -1800,54 +2000,55 @@ err_identification_fail:
}
err_gpio_config:
- IT7260_power_on(false);
+ it7260_power_on(ts_data, false);
err_power_device:
- IT7260_regulator_configure(false);
+ it7260_regulator_configure(ts_data, false);
err_reg_configure:
return ret;
}
-static int IT7260_ts_remove(struct i2c_client *client)
+static int it7260_ts_remove(struct i2c_client *client)
{
+ struct it7260_ts_data *ts_data = i2c_get_clientdata(client);
int ret;
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
- free_irq(client->irq, gl_ts);
- input_unregister_device(gl_ts->input_dev);
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
- if (gl_ts->pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ free_irq(client->irq, ts_data);
+ input_unregister_device(ts_data->input_dev);
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
+ if (ts_data->pdata->wakeup) {
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (ret)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
ret);
}
} else {
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
}
- IT7260_power_on(false);
- IT7260_regulator_configure(false);
+ it7260_power_on(ts_data, false);
+ it7260_regulator_configure(ts_data, false);
return 0;
}
@@ -1856,17 +2057,19 @@ static int IT7260_ts_remove(struct i2c_client *client)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
+ struct it7260_ts_data *ts_data = container_of(self,
+ struct it7260_ts_data, fb_notif);
struct fb_event *evdata = data;
int *blank;
- if (evdata && evdata->data && gl_ts && gl_ts->client) {
+ if (evdata && evdata->data && ts_data && ts_data->client) {
if (event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK)
- IT7260_ts_resume(&(gl_ts->client->dev));
+ it7260_ts_resume(&(ts_data->client->dev));
else if (*blank == FB_BLANK_POWERDOWN ||
*blank == FB_BLANK_VSYNC_SUSPEND)
- IT7260_ts_suspend(&(gl_ts->client->dev));
+ it7260_ts_suspend(&(ts_data->client->dev));
}
}
@@ -1875,30 +2078,32 @@ static int fb_notifier_callback(struct notifier_block *self,
#endif
#ifdef CONFIG_PM
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
if (device_may_wakeup(dev)) {
- if (gl_ts->device_needs_wakeup) {
+ if (ts_data->device_needs_wakeup) {
/* Set active current for the avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at resume rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = false;
- disable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = false;
+ disable_irq_wake(ts_data->client->irq);
}
return 0;
}
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (retval < 0) {
dev_err(dev, "Cannot get default pinctrl state %d\n",
retval);
@@ -1906,50 +2111,53 @@ static int IT7260_ts_resume(struct device *dev)
}
}
- enable_irq(gl_ts->client->irq);
- gl_ts->suspended = false;
+ enable_irq(ts_data->client->irq);
+ ts_data->suspended = false;
return 0;
err_pinctrl_select_suspend:
return retval;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
- if (gl_ts->fw_cfg_uploading) {
+ if (ts_data->fw_cfg_uploading) {
dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n");
return -EBUSY;
}
if (device_may_wakeup(dev)) {
- if (!gl_ts->device_needs_wakeup) {
+ if (!ts_data->device_needs_wakeup) {
/* put the device in low power idle mode */
- IT7260_ts_chipLowPowerMode(PWR_CTL_LOW_POWER_MODE);
+ it7260_ts_chip_low_power_mode(ts_data,
+ PWR_CTL_LOW_POWER_MODE);
/* Set lpm current for avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
- gl_ts->pdata->avdd_lpm_cur);
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
+ ts_data->pdata->avdd_lpm_cur);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at suspend rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = true;
- enable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = true;
+ enable_irq_wake(ts_data->client->irq);
}
return 0;
}
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
- IT7260_ts_release_all();
+ it7260_ts_release_all(ts_data);
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_suspend);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
if (retval < 0) {
dev_err(dev, "Cannot get idle pinctrl state %d\n",
retval);
@@ -1957,7 +2165,7 @@ static int IT7260_ts_suspend(struct device *dev)
}
}
- gl_ts->suspended = true;
+ ts_data->suspended = true;
return 0;
@@ -1965,49 +2173,49 @@ err_pinctrl_select_suspend:
return retval;
}
-static const struct dev_pm_ops IT7260_ts_dev_pm_ops = {
- .suspend = IT7260_ts_suspend,
- .resume = IT7260_ts_resume,
+static const struct dev_pm_ops it7260_ts_dev_pm_ops = {
+ .suspend = it7260_ts_suspend,
+ .resume = it7260_ts_resume,
};
#else
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
return 0;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
return 0;
}
#endif
-static const struct i2c_device_id IT7260_ts_id[] = {
+static const struct i2c_device_id it7260_ts_id[] = {
{ DEVICE_NAME, 0},
{}
};
-MODULE_DEVICE_TABLE(i2c, IT7260_ts_id);
+MODULE_DEVICE_TABLE(i2c, it7260_ts_id);
-static const struct of_device_id IT7260_match_table[] = {
+static const struct of_device_id it7260_match_table[] = {
{ .compatible = "ite,it7260_ts",},
{},
};
-static struct i2c_driver IT7260_ts_driver = {
+static struct i2c_driver it7260_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DEVICE_NAME,
- .of_match_table = IT7260_match_table,
+ .of_match_table = it7260_match_table,
#ifdef CONFIG_PM
- .pm = &IT7260_ts_dev_pm_ops,
+ .pm = &it7260_ts_dev_pm_ops,
#endif
},
- .probe = IT7260_ts_probe,
- .remove = IT7260_ts_remove,
- .id_table = IT7260_ts_id,
+ .probe = it7260_ts_probe,
+ .remove = it7260_ts_remove,
+ .id_table = it7260_ts_id,
};
-module_i2c_driver(IT7260_ts_driver);
+module_i2c_driver(it7260_ts_driver);
-MODULE_DESCRIPTION("IT7260 Touchscreen Driver");
+MODULE_DESCRIPTION("it7260 Touchscreen Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
index 4eb7fd4b1cc9..8f2c4da578fc 100644
--- a/drivers/input/touchscreen/msg21xx_ts.c
+++ b/drivers/input/touchscreen/msg21xx_ts.c
@@ -5,6 +5,8 @@
*
* Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com>
*
+ * Copyright (c) 2014-2016, 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 as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -17,72 +19,55 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/timer.h>
#include <linux/gpio.h>
-
+#include <linux/of_gpio.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
-#include <mach/gpio.h>
-#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/slab.h>
-
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fcntl.h>
+#include <linux/firmware.h>
#include <linux/string.h>
-#include <asm/unistd.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif
-#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/regulator/consumer.h>
+
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
#include <linux/input/vir_ps.h>
#endif
-/*=============================================================*/
-// Macro Definition
-/*=============================================================*/
+/* Macro Definition */
#define TOUCH_DRIVER_DEBUG 0
#if (TOUCH_DRIVER_DEBUG == 1)
-#define DBG(fmt, arg...) pr_err(fmt, ##arg) //pr_info(fmt, ##arg)
+#define DBG(fmt, arg...) pr_info(fmt, ##arg)
#else
#define DBG(fmt, arg...)
#endif
-/*=============================================================*/
-// Constant Value & Variable Definition
-/*=============================================================*/
+/* Constant Value & Variable Definition */
-#define U8 unsigned char
-#define U16 unsigned short
-#define U32 unsigned int
-#define S8 signed char
-#define S16 signed short
-#define S32 signed int
+#define MSTAR_VTG_MIN_UV 2800000
+#define MSTAR_VTG_MAX_UV 3300000
+#define MSTAR_I2C_VTG_MIN_UV 1800000
+#define MSTAR_I2C_VTG_MAX_UV 1800000
+
+#define MAX_BUTTONS 4
+#define FT_COORDS_ARR_SIZE 4
+#define MSTAR_FW_NAME_MAX_LEN 50
+
+#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E
+#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC
+#define MSTAR_INIT_SW_ID 0x7FF
-#define TOUCH_SCREEN_X_MIN (0)
-#define TOUCH_SCREEN_Y_MIN (0)
-/*
- * Note.
- * Please change the below touch screen resolution according to the touch panel that you are using.
- */
-#define TOUCH_SCREEN_X_MAX (480)
-#define TOUCH_SCREEN_Y_MAX (800)
/*
* Note.
* Please do not change the below setting.
@@ -90,62 +75,29 @@
#define TPD_WIDTH (2048)
#define TPD_HEIGHT (2048)
-/*
- * Note.
- * Please change the below GPIO pin setting to follow the platform that you are using
- */
-static int int_gpio = 1;
-static int reset_gpio = 0;
-#define MS_TS_MSG21XX_GPIO_RST reset_gpio
-#define MS_TS_MSG21XX_GPIO_INT int_gpio
-//---------------------------------------------------------------------//
-
-//#define SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-
-#ifdef SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-#define SYSFS_AUTHORITY (0644)
-#else
-#define SYSFS_AUTHORITY (0777)
-#endif
-
-#define FIRMWARE_AUTOUPDATE
#ifdef FIRMWARE_AUTOUPDATE
-typedef enum {
- SWID_START = 1,
- SWID_TRULY = SWID_START,
- SWID_NULL,
-} SWID_ENUM;
+enum {
+ SWID_START = 1,
+ SWID_TRULY = SWID_START,
+ SWID_NULL,
+};
-unsigned char MSG_FIRMWARE[1][33*1024] =
-{
- {
- #include "msg21xx_truly_update_bin.h"
- }
+static unsigned char MSG_FIRMWARE[1][33*1024] = { {
+ #include "msg21xx_truly_update_bin.h"
+ }
};
#endif
#define CONFIG_TP_HAVE_KEY
-/*
- * Note.
- * If the below virtual key value definition are not consistent with those that defined in key layout file of platform,
- * please change the below virtual key value to follow the platform that you are using.
- */
-#ifdef CONFIG_TP_HAVE_KEY
-#define TOUCH_KEY_MENU (139) //229
-#define TOUCH_KEY_HOME (172) //102
-#define TOUCH_KEY_BACK (158)
-#define TOUCH_KEY_SEARCH (217)
-
-const U16 tp_key_array[] = {TOUCH_KEY_MENU, TOUCH_KEY_HOME, TOUCH_KEY_BACK, TOUCH_KEY_SEARCH};
-#define MAX_KEY_NUM (sizeof(tp_key_array)/sizeof(tp_key_array[0]))
-#endif
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define SLAVE_I2C_ID_DWI2C (0x4C>>1)
+#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define DEMO_MODE_PACKET_LENGTH (8)
-#define MAX_TOUCH_NUM (2) //5
+#define DEMO_MODE_PACKET_LENGTH (8)
+#define MAX_TOUCH_NUM (2)
#define TP_PRINT
#ifdef TP_PRINT
@@ -153,1605 +105,2089 @@ static int tp_print_proc_read(void);
static void tp_print_create_entry(void);
#endif
-static char *fw_version = NULL; // customer firmware version
-static U16 fw_version_major = 0;
-static U16 fw_version_minor = 0;
-static U8 temp[94][1024];
-static U32 crc32_table[256];
-static int FwDataCnt = 0;
-static U8 bFwUpdating = 0;
-static struct class *firmware_class = NULL;
-static struct device *firmware_cmd_dev = NULL;
+static char *fw_version; /* customer firmware version */
+static unsigned short fw_version_major;
+static unsigned short fw_version_minor;
+static unsigned char temp[94][1024];
+static unsigned int crc32_table[256];
+static int FwDataCnt;
+static unsigned char bFwUpdating;
+static struct class *firmware_class;
+static struct device *firmware_cmd_dev;
+
+static struct i2c_client *i2c_client;
+
+static u32 button_map[MAX_BUTTONS];
+static u32 num_buttons;
+
+static unsigned short update_bin_major, update_bin_minor;
+static unsigned short main_sw_id = MSTAR_INIT_SW_ID;
+static unsigned short info_sw_id = MSTAR_INIT_SW_ID;
+static unsigned int bin_conf_crc32;
+
+struct msg21xx_ts_platform_data {
+ const char *name;
+ char fw_name[MSTAR_FW_NAME_MAX_LEN];
+ char *fw_version;
+ unsigned short fw_version_major;
+ unsigned short fw_version_minor;
+ u32 irqflags;
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ u32 num_max_touches;
+ bool no_force_update;
+ bool i2c_pull_up;
+ bool ignore_id_check;
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+};
-static struct i2c_client *i2c_client = NULL;
+static struct msg21xx_ts_platform_data *pdata;
+
+struct msg21xx_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct msg21xx_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ bool loading_fw;
+ u8 family_id;
+ struct dentry *dir;
+ u16 addr;
+ bool suspended;
+ char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#endif
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+ struct mutex ts_mutex;
+};
+
+static struct msg21xx_ts_data *ts_data;
#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
-static struct notifier_block msg21xx_fb_notif;
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
-static struct early_suspend mstar_ts_early_suspend;
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
#endif
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static U8 bEnableTpProximity = 0;
-static U8 bFaceClosingTp = 0;
+static unsigned char bEnableTpProximity;
+static unsigned char bFaceClosingTp;
#endif
-static U8 bTpInSuspend = 0;
-static int irq_msg21xx = -1;
-static struct work_struct msg21xx_wk;
static struct mutex msg21xx_mutex;
-static struct input_dev *input_dev = NULL;
+static struct input_dev *input_dev;
-/*=============================================================*/
-// Data Type Definition
-/*=============================================================*/
-typedef struct
-{
- U16 x;
- U16 y;
-} touchPoint_t;
+/* Data Type Definition */
-/// max 80+1+1 = 82 bytes
-typedef struct
-{
- touchPoint_t point[MAX_TOUCH_NUM];
- U8 count;
- U8 keycode;
-} touchInfo_t;
+struct touchPoint_t {
+ unsigned short x;
+ unsigned short y;
+};
-enum i2c_speed
-{
- I2C_SLOW = 0,
- I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */
- I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */
+struct touchInfo_t {
+ struct touchPoint_t point[MAX_TOUCH_NUM];
+ unsigned char count;
+ unsigned char keycode;
};
-typedef enum
-{
- EMEM_ALL = 0,
- EMEM_MAIN,
- EMEM_INFO,
-} EMEM_TYPE_t;
-/*=============================================================*/
-// Function Definition
-/*=============================================================*/
+enum EMEM_TYPE_t {
+ EMEM_ALL = 0,
+ EMEM_MAIN,
+ EMEM_INFO,
+};
+
+/* Function Definition */
-/// CRC
-static U32 _CRC_doReflect(U32 ref, S8 ch)
+static unsigned int _CRC_doReflect(unsigned int ref, signed char ch)
{
- U32 value = 0;
- U32 i = 0;
-
- for (i = 1; i < (ch + 1); i ++)
- {
- if (ref & 1)
- {
- value |= 1 << (ch - i);
- }
- ref >>= 1;
- }
-
- return value;
+ unsigned int value = 0;
+ unsigned int i = 0;
+
+ for (i = 1; i < (ch + 1); i++) {
+ if (ref & 1)
+ value |= 1 << (ch - i);
+ ref >>= 1;
+ }
+
+ return value;
}
-U32 _CRC_getValue(U32 text, U32 prevCRC)
+static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC)
{
- U32 ulCRC = prevCRC;
+ unsigned int ulCRC = prevCRC;
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
+ ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
- return ulCRC;
+ return ulCRC;
}
static void _CRC_initTable(void)
{
- U32 magic_number = 0x04c11db7;
- U32 i, j;
-
- for (i = 0; i <= 0xFF; i ++)
- {
- crc32_table[i] = _CRC_doReflect (i, 8) << 24;
- for (j = 0; j < 8; j ++)
- {
- crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (0x80000000L) ? magic_number : 0);
- }
- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
- }
+ unsigned int magic_number = 0x04c11db7;
+ unsigned int i, j;
+
+ for (i = 0; i <= 0xFF; i++) {
+ crc32_table[i] = _CRC_doReflect(i, 8) << 24;
+ for (j = 0; j < 8; j++)
+ crc32_table[i] = (crc32_table[i] << 1) ^
+ (crc32_table[i] & (0x80000000L) ?
+ magic_number : 0);
+ crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
+ }
}
static void reset_hw(void)
{
- DBG("reset_hw()\n");
-
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(100); /* Note that the RST must be in LOW 10ms at least */
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100); /* Enable the interrupt service thread/routine for INT after 50ms */
+ DBG("reset_hw()\n");
+
+ gpio_direction_output(pdata->reset_gpio, 1);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(100); /* Note that the RST must be in LOW 10ms at least */
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ /* Enable the interrupt service thread/routine for INT after 50ms */
+ msleep(100);
}
-static int read_i2c_seq(U8 addr, U8* buf, U16 size)
+static int read_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = I2C_M_RD, // read flag
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if (rc < 0)
- {
- DBG("read_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ .flags = I2C_M_RD, /* read flag*/
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("read_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static int write_i2c_seq(U8 addr, U8* buf, U16 size)
+static int write_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = 0, // if read flag is undefined, then it means write flag.
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if ( rc < 0 )
- {
- DBG("write_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ /* if read flag is undefined,
+ * then it means write flag.
+ */
+ .flags = 0,
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("write_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static U16 read_reg(U8 bank, U8 addr)
+static unsigned short read_reg(unsigned char bank, unsigned char addr)
{
- U8 tx_data[3] = {0x10, bank, addr};
- U8 rx_data[2] = {0};
+ unsigned char tx_data[3] = {0x10, bank, addr};
+ unsigned char rx_data[2] = {0};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
+ read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
- return (rx_data[1] << 8 | rx_data[0]);
+ return rx_data[1] << 8 | rx_data[0];
}
-static void write_reg(U8 bank, U8 addr, U16 data)
+static void write_reg(unsigned char bank, unsigned char addr,
+ unsigned short data)
{
- U8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
-}
+ unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
-static void write_reg_8bit(U8 bank, U8 addr, U8 data)
-{
- U8 tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
}
-void dbbusDWIICEnterSerialDebugMode(void)
+static void write_reg_8bit(unsigned char bank, unsigned char addr,
+ unsigned char data)
{
- U8 data[5];
-
- // Enter the Serial Debug Mode
- data[0] = 0x53;
- data[1] = 0x45;
- data[2] = 0x52;
- data[3] = 0x44;
- data[4] = 0x42;
+ unsigned char tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
}
-void dbbusDWIICStopMCU(void)
+static void dbbusDWIICEnterSerialDebugMode(void)
{
- U8 data[1];
+ unsigned char data[5];
- // Stop the MCU
- data[0] = 0x37;
+ /* Enter the Serial Debug Mode */
+ data[0] = 0x53;
+ data[1] = 0x45;
+ data[2] = 0x52;
+ data[3] = 0x44;
+ data[4] = 0x42;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
}
-void dbbusDWIICIICUseBus(void)
+static void dbbusDWIICStopMCU(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Use Bus
- data[0] = 0x35;
+ /* Stop the MCU */
+ data[0] = 0x37;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICReshape(void)
+static void dbbusDWIICIICUseBus(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Re-shape
- data[0] = 0x71;
+ /* IIC Use Bus */
+ data[0] = 0x35;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICNotUseBus(void)
+static void dbbusDWIICIICReshape(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Not Use Bus
- data[0] = 0x34;
+ /* IIC Re-shape */
+ data[0] = 0x71;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICNotStopMCU(void)
+static unsigned char get_ic_type(void)
{
- U8 data[1];
-
- // Not Stop the MCU
- data[0] = 0x36;
+ unsigned char ic_type = 0;
+ unsigned char bank;
+ unsigned char addr;
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* stop mcu */
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+ /* disable watch dog */
+ write_reg(0x3C, 0x60, 0xAA55);
+ /* get ic type */
+ bank = MSTAR_CHIPTOP_REGISTER_BANK;
+ addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
+ ic_type = (0xff)&(read_reg(bank, addr));
+
+ if (ic_type != 1 /* msg2133 */
+ && ic_type != 2 /* msg21xxA */
+ && ic_type != 3) /* msg26xxM */ {
+ ic_type = 0;
+ }
+
+ reset_hw();
+
+ return ic_type;
+}
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+static int msg21xx_read_firmware_id(void)
+{
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ int ret = 0;
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x2A;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ pdata->fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ pdata->fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ dev_dbg(&i2c_client->dev, "major num = %d, minor num = %d\n",
+ pdata->fw_version_major, pdata->fw_version_minor);
+
+ if (pdata->fw_version == NULL)
+ pdata->fw_version = kzalloc(sizeof(char), GFP_KERNEL);
+
+ snprintf(pdata->fw_version, sizeof(char) * 7, "%03d%03d",
+ pdata->fw_version_major,
+ pdata->fw_version_minor);
+
+ return ret;
}
-void dbbusDWIICExitSerialDebugMode(void)
+static int firmware_erase_c33(enum EMEM_TYPE_t emem_type)
{
- U8 data[1];
+ /* stop mcu */
+ write_reg(0x0F, 0xE6, 0x0001);
- // Exit the Serial Debug Mode
- data[0] = 0x45;
+ /* disable watch dog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ /* set PROGRAM password */
+ write_reg_8bit(0x16, 0x1A, 0xBA);
+ write_reg_8bit(0x16, 0x1B, 0xAB);
- // Delay some interval to guard the next transaction
- //udelay ( 200 ); // delay about 0.2ms
-}
+ write_reg_8bit(0x16, 0x18, 0x80);
-//---------------------------------------------------------------------//
+ if (emem_type == EMEM_ALL)
+ write_reg_8bit(0x16, 0x08, 0x10);
-static U8 get_ic_type(void)
-{
- U8 ic_type = 0;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- // stop mcu
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
- // disable watch dog
- write_reg ( 0x3C, 0x60, 0xAA55 );
- // get ic type
- ic_type = (0xff)&(read_reg(0x1E, 0xCC));
-
- if (ic_type != 1 //msg2133
- && ic_type != 2 //msg21xxA
- && ic_type != 3) //msg26xxM
- {
- ic_type = 0;
- }
-
- reset_hw();
-
- return ic_type;
-}
+ write_reg_8bit(0x16, 0x18, 0x40);
+ msleep(20);
-static int get_customer_firmware_version(void)
-{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[4] = {0};
- int ret = 0;
+ /* clear pce */
+ write_reg_8bit(0x16, 0x18, 0x80);
- DBG("get_customer_firmware_version()\n");
+ /* erase trigger */
+ if (emem_type == EMEM_MAIN)
+ write_reg_8bit(0x16, 0x0E, 0x04); /* erase main */
+ else
+ write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x2A;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+ return 1;
+}
- DBG("*** major = %d ***\n", fw_version_major);
- DBG("*** minor = %d ***\n", fw_version_minor);
+static void _ReadBinConfig(void);
+static unsigned int _CalMainCRC32(void);
- if (fw_version == NULL)
- {
- fw_version = kzalloc(sizeof(char), GFP_KERNEL);
- }
+static int check_fw_update(void)
+{
+ int ret = 0;
+
+ msg21xx_read_firmware_id();
+ _ReadBinConfig();
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ /*check upgrading*/
+ if ((update_bin_major == pdata->fw_version_major) &&
+ (update_bin_minor > pdata->fw_version_minor)) {
+ ret = 1;
+ }
+ }
+ }
+ return ret;
- sprintf(fw_version, "%03d%03d", fw_version_major, fw_version_minor);
+}
- return ret;
+static ssize_t firmware_update_c33(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size,
+ enum EMEM_TYPE_t emem_type,
+ bool isForce) {
+ unsigned int i, j;
+ unsigned int crc_main, crc_main_tp;
+ unsigned int crc_info, crc_info_tp;
+ unsigned short reg_data = 0;
+ int update_pass = 1;
+
+ crc_main = 0xffffffff;
+ crc_info = 0xffffffff;
+
+ reset_hw();
+
+ if (!check_fw_update() && !isForce) {
+ DBG("****no need to update\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
+ }
+ reset_hw();
+ msleep(300);
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* erase main */
+ firmware_erase_c33(EMEM_MAIN);
+ msleep(1000);
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* polling 0x3CE4 is 0x1C70 */
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x1C70);
+ }
+
+ switch (emem_type) {
+ case EMEM_ALL:
+ write_reg(0x3C, 0xE4, 0xE38F); /* for all-blocks */
+ break;
+ case EMEM_MAIN:
+ write_reg(0x3C, 0xE4, 0x7731); /* for main block */
+ break;
+ case EMEM_INFO:
+ write_reg(0x3C, 0xE4, 0x7731); /* for info block */
+
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+
+ write_reg_8bit(0x3C, 0xE4, 0xC5);
+ write_reg_8bit(0x3C, 0xE5, 0x78);
+
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x9F);
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x05, 0x82);
+
+ write_reg_8bit(0x0F, 0xE6, 0x00);
+ msleep(100);
+ break;
+ }
+
+ /* polling 0x3CE4 is 0x2F43 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x2F43);
+
+ /* calculate CRC 32 */
+ _CRC_initTable();
+
+ /* total 32 KB : 2 byte per R/W */
+ for (i = 0; i < 32; i++) {
+ if (i == 31) {
+ fw_bin_data[i][1014] = 0x5A;
+ fw_bin_data[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ } else {
+ for (j = 0; j < 1024; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ }
+
+ for (j = 0; j < 8; j++)
+ write_i2c_seq(ts_data->client->addr,
+ &fw_bin_data[i][j * 128], 128);
+ msleep(100);
+
+ /* polling 0x3CE4 is 0xD0BC */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0xD0BC);
+
+ write_reg(0x3C, 0xE4, 0x2F43);
+ }
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* write file done and check crc */
+ write_reg(0x3C, 0xE4, 0x1380);
+ }
+ msleep(20);
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* polling 0x3CE4 is 0x9432 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
+ }
+
+ crc_main = crc_main ^ 0xffffffff;
+ crc_info = crc_info ^ 0xffffffff;
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* CRC Main from TP */
+ crc_main_tp = read_reg(0x3C, 0x80);
+ crc_main_tp = (crc_main_tp << 16) | read_reg(0x3C, 0x82);
+
+ /* CRC Info from TP */
+ crc_info_tp = read_reg(0x3C, 0xA0);
+ crc_info_tp = (crc_info_tp << 16) | read_reg(0x3C, 0xA2);
+ }
+
+ update_pass = 1;
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ if (crc_main_tp != crc_main)
+ update_pass = 0;
+ }
+
+ if (!update_pass) {
+ DBG("update_C33 failed\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return 0;
+ }
+
+ DBG("update_C33 OK\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
}
-static int firmware_erase_c33 ( EMEM_TYPE_t emem_type )
+static unsigned int _CalMainCRC32(void)
{
- // stop mcu
- write_reg ( 0x0F, 0xE6, 0x0001 );
+ unsigned int ret = 0;
+ unsigned short reg_data = 0;
+
+ reset_hw();
- //disable watch dog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
- // set PROGRAM password
- write_reg_8bit ( 0x16, 0x1A, 0xBA );
- write_reg_8bit ( 0x16, 0x1B, 0xAB );
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- if ( emem_type == EMEM_ALL )
- {
- write_reg_8bit ( 0x16, 0x08, 0x10 ); //mark
- }
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xDF4C);
+ write_reg(0x1E, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
- write_reg_8bit ( 0x16, 0x18, 0x40 );
- mdelay ( 10 );
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
- // clear pce
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
- // erase trigger
- if ( emem_type == EMEM_MAIN )
- {
- write_reg_8bit ( 0x16, 0x0E, 0x04 ); //erase main
- }
- else
- {
- write_reg_8bit ( 0x16, 0x0E, 0x08 ); //erase all block
- }
+ /* Cal CRC Main from TP */
+ ret = read_reg(0x3C, 0x80);
+ ret = (ret << 16) | read_reg(0x3C, 0x82);
- return ( 1 );
+ DBG("[21xxA]:Current main crc32=0x%x\n", ret);
+ return ret;
}
-static ssize_t firmware_update_c33 ( struct device *dev, struct device_attribute *attr,
- const char *buf, size_t size, EMEM_TYPE_t emem_type )
+static void _ReadBinConfig(void)
{
- U32 i, j;
- U32 crc_main, crc_main_tp;
- U32 crc_info, crc_info_tp;
- U16 reg_data = 0;
- int update_pass = 1;
-
- crc_main = 0xffffffff;
- crc_info = 0xffffffff;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- //erase main
- firmware_erase_c33 ( EMEM_MAIN );
- mdelay ( 1000 );
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- /////////////////////////
- // Program
- /////////////////////////
-
- //polling 0x3CE4 is 0x1C70
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x1C70 );
- }
-
- switch ( emem_type )
- {
- case EMEM_ALL:
- write_reg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks
- break;
- case EMEM_MAIN:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for main block
- break;
- case EMEM_INFO:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for info block
-
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
-
- write_reg_8bit ( 0x3C, 0xE4, 0xC5 );
- write_reg_8bit ( 0x3C, 0xE5, 0x78 );
-
- write_reg_8bit ( 0x1E, 0x04, 0x9F );
- write_reg_8bit ( 0x1E, 0x05, 0x82 );
-
- write_reg_8bit ( 0x0F, 0xE6, 0x00 );
- mdelay ( 100 );
- break;
- }
-
- // polling 0x3CE4 is 0x2F43
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x2F43 );
-
- // calculate CRC 32
- _CRC_initTable ();
-
- for ( i = 0; i < 32; i++ ) // total 32 KB : 2 byte per R/W
- {
- if ( i == 31 )
- {
- temp[i][1014] = 0x5A;
- temp[i][1015] = 0xA5;
-
- for ( j = 0; j < 1016; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
- else
- {
- for ( j = 0; j < 1024; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
-
- //write_i2c_seq(SLAVE_I2C_ID_DWI2C, temp[i], 1024);
- for (j = 0; j < 8; j++)
- {
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &temp[i][j*128], 128 );
- }
- msleep (100);
-
- // polling 0x3CE4 is 0xD0BC
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0xD0BC );
-
- write_reg ( 0x3C, 0xE4, 0x2F43 );
- }
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // write file done and check crc
- write_reg ( 0x3C, 0xE4, 0x1380 );
- }
- mdelay ( 10 );
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // polling 0x3CE4 is 0x9432
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
- }
-
- crc_main = crc_main ^ 0xffffffff;
- crc_info = crc_info ^ 0xffffffff;
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // CRC Main from TP
- crc_main_tp = read_reg ( 0x3C, 0x80 );
- crc_main_tp = ( crc_main_tp << 16 ) | read_reg ( 0x3C, 0x82 );
-
- // CRC Info from TP
- crc_info_tp = read_reg ( 0x3C, 0xA0 );
- crc_info_tp = ( crc_info_tp << 16 ) | read_reg ( 0x3C, 0xA2 );
- }
-
- update_pass = 1;
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- if ( crc_main_tp != crc_main )
- update_pass = 0;
-
- /*
- if ( crc_info_tp != crc_info )
- update_pass = 0;
- */
- }
-
- if ( !update_pass )
- {
- DBG( "update_C33 failed\n" );
- reset_hw();
- FwDataCnt = 0;
- return 0;
- }
-
- DBG( "update_C33 OK\n" );
- reset_hw();
- FwDataCnt = 0;
- return size;
+ unsigned char dbbus_tx_data[5] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ unsigned short reg_data = 0;
+
+ reset_hw();
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
+
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
+
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
+
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xA4AB);
+ write_reg(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
+ /* TP SW reset*/
+
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
+
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x5B58);
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0x55;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0xFC;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ bin_conf_crc32 = dbbus_rx_data[0];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x83;
+ dbbus_tx_data[2] = 0x00;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n",
+ main_sw_id, info_sw_id, bin_conf_crc32);
}
-#ifdef FIRMWARE_AUTOUPDATE
-unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF;
-U32 bin_conf_crc32 = 0;
-
-static U32 _CalMainCRC32(void)
+static ssize_t firmware_update_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- U32 ret=0;
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
+ DBG("*** firmware_update_show() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xDF4C );
- write_reg ( 0x1E, 0x04, 0x7d60 );
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
+ return snprintf(buf, sizeof(char) - 1, "%s\n", pdata->fw_version);
+}
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
+static ssize_t firmware_update_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
- // Cal CRC Main from TP
- ret = read_reg ( 0x3C, 0x80 );
- ret = ( ret << 16 ) | read_reg ( 0x3C, 0x82 );
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
- DBG("[21xxA]:Current main crc32=0x%x\n",ret);
- return (ret);
+ return size;
}
-static void _ReadBinConfig ( void )
-{
- U8 dbbus_tx_data[5]={0};
- U8 dbbus_rx_data[4]={0};
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
-
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xA4AB );
- write_reg ( 0x1E, 0x04, 0x7d60 );
-
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
-
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
-
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x5B58 );
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0x55;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- main_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0xFC;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- bin_conf_crc32 = dbbus_rx_data[0];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x83;
- dbbus_tx_data[2] = 0x00;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- info_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", main_sw_id, info_sw_id, bin_conf_crc32);
-}
+static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_store);
-static int fwAutoUpdate(void *unused)
+static int prepare_fw_data(struct device *dev)
{
- int time = 0;
- ssize_t ret = 0;
-
- for (time = 0; time < 5; time++)
- {
- DBG("fwAutoUpdate time = %d\n",time);
- ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN);
- if (ret == 1)
- {
- DBG("AUTO_UPDATE OK!!!");
- break;
- }
- }
- if (time == 5)
- {
- DBG("AUTO_UPDATE failed!!!");
- }
- enable_irq(irq_msg21xx);
- return 0;
+ int count;
+ int i;
+ int ret;
+ const struct firmware *fw = NULL;
+
+ ret = request_firmware(&fw, pdata->fw_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ pdata->fw_name, ret);
+ return ret;
+ }
+ DBG("*** prepare_fw_data() ret = %d, size = %d***\n", ret, fw->size);
+
+ count = fw->size / 1024;
+
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], fw->data + (i * 1024), 1024);
+ FwDataCnt++;
+ }
+ update_bin_major = (fw->data[0x7f4f] << 8) + fw->data[0x7f4e];
+ update_bin_minor = (fw->data[0x7f51] << 8) + fw->data[0x7f50];
+ DBG("*** prepare_fw_data bin major = %d ***\n", update_bin_major);
+ DBG("*** prepare_fw_data bin minor = %d ***\n", update_bin_minor);
+
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+
+ return fw->size;
}
-#endif
-//------------------------------------------------------------------------------//
-static ssize_t firmware_update_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t firmware_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version);
+ int ret;
- return sprintf(buf, "%s\n", fw_version);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
+
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 ret = %d ***\n", ret);
+
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static ssize_t firmware_update_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+static ssize_t firmware_force_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- bFwUpdating = 1;
- disable_irq(irq_msg21xx);
+ int ret;
- DBG("*** update fw size = %d ***\n", FwDataCnt);
- size = firmware_update_c33 (dev, attr, buf, size, EMEM_MAIN);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- enable_irq(irq_msg21xx);
- bFwUpdating = 0;
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 et = %d ***\n", ret);
- return size;
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static DEVICE_ATTR(update, SYSFS_AUTHORITY, firmware_update_show, firmware_update_store);
+static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_smart_store);
+
+static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_force_update_smart_store);
static ssize_t firmware_version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_version_show() fw_version = %s ***\n", fw_version);
-
- return sprintf(buf, "%s\n", fw_version);
+ msg21xx_read_firmware_id();
+ return snprintf(buf, 8, "%s\n", pdata->fw_version);
}
static ssize_t firmware_version_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- get_customer_firmware_version();
+ msg21xx_read_firmware_id();
+ DBG("*** firmware_version_store() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
+
+ return size;
+}
- DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version);
+static DEVICE_ATTR(version, (S_IRUGO | S_IWUSR),
+ firmware_version_show,
+ firmware_version_store);
- return size;
+
+static ssize_t msg21xx_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, "%s\n", pdata->fw_name);
}
-static DEVICE_ATTR(version, SYSFS_AUTHORITY, firmware_version_show, firmware_version_store);
+static ssize_t msg21xx_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+
+ if (size > MSTAR_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(pdata->fw_name, buf, size);
+ if (pdata->fw_name[size - 1] == '\n')
+ pdata->fw_name[size - 1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR),
+ msg21xx_fw_name_show, msg21xx_fw_name_store);
static ssize_t firmware_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
- return FwDataCnt;
+ return FwDataCnt;
}
static ssize_t firmware_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- int count = size / 1024;
- int i;
+ int count = size / 1024;
+ int i;
- for (i = 0; i < count; i ++)
- {
- memcpy(temp[FwDataCnt], buf+(i*1024), 1024);
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], buf + (i * 1024), 1024);
- FwDataCnt ++;
- }
+ FwDataCnt++;
+ }
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
- if (buf != NULL)
- {
- DBG("*** buf[0] = %c ***\n", buf[0]);
- }
+ if (buf != NULL)
+ DBG("*** buf[0] = %c ***\n", buf[0]);
- return size;
+ return size;
}
-static DEVICE_ATTR(data, SYSFS_AUTHORITY, firmware_data_show, firmware_data_store);
+static DEVICE_ATTR(data, (S_IRUGO | S_IWUSR),
+ firmware_data_show, firmware_data_store);
#ifdef TP_PRINT
static ssize_t tp_print_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- tp_print_proc_read();
+ tp_print_proc_read();
- return sprintf(buf, "%d\n", bTpInSuspend);
+ return snprintf(buf, sizeof(char) - 1, "%d\n", ts_data->suspended);
}
static ssize_t tp_print_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** tp_print_store() ***\n");
+ DBG("*** tp_print_store() ***\n");
- return size;
+ return size;
}
-static DEVICE_ATTR(tpp, SYSFS_AUTHORITY, tp_print_show, tp_print_store);
+static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR),
+ tp_print_show, tp_print_store);
#endif
-//------------------------------------------------------------------------------//
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
static void _msg_enable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_enable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa0;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 1;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_enable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa0;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 1;
}
static void _msg_disable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_disable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa1;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 0;
- bFaceClosingTp = 0;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_disable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa1;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 0;
+ bFaceClosingTp = 0;
}
-void tsps_msg21xx_enable(int en)
+static void tsps_msg21xx_enable(int en)
{
- if (en)
- {
- _msg_enable_proximity();
- }
- else
- {
- _msg_disable_proximity();
- }
+ if (en)
+ _msg_enable_proximity();
+ else
+ _msg_disable_proximity();
}
-int tsps_msg21xx_data(void)
+static int tsps_msg21xx_data(void)
{
- return bFaceClosingTp;
+ return bFaceClosingTp;
}
#endif
-static U8 calculate_checksum(U8 *msg, S32 length)
+static int msg21xx_pinctrl_init(void)
{
- S32 Checksum = 0;
- S32 i;
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ts_data->ts_pinctrl = devm_pinctrl_get(&(i2c_client->dev));
+ if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
+ retval = PTR_ERR(ts_data->ts_pinctrl);
+ dev_dbg(&i2c_client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ts_data->pinctrl_state_active = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_active);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_suspend = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_suspend);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_release = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_release);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+err_pinctrl_get:
+ ts_data->ts_pinctrl = NULL;
+ return retval;
+}
- for (i = 0; i < length; i ++)
- {
- Checksum += msg[i];
- }
+static unsigned char calculate_checksum(unsigned char *msg, int length)
+{
+ int checksum = 0, i;
- return (U8)((-Checksum) & 0xFF);
+ for (i = 0; i < length; i++)
+ checksum += msg[i];
+
+ return (unsigned char)((-checksum) & 0xFF);
}
-static S32 parse_info(touchInfo_t *info)
+static int parse_info(struct touchInfo_t *info)
{
- U8 data[DEMO_MODE_PACKET_LENGTH] = {0};
- U8 checksum = 0;
- U32 x = 0, y = 0;
- U32 x2 = 0, y2 = 0;
- U32 delta_x = 0, delta_y = 0;
-
- mutex_lock(&msg21xx_mutex);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &data[0], DEMO_MODE_PACKET_LENGTH);
- mutex_unlock(&msg21xx_mutex);
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
- DBG("check sum: [%x] == [%x]? \n", data[DEMO_MODE_PACKET_LENGTH-1], checksum);
-
- if(data[DEMO_MODE_PACKET_LENGTH-1] != checksum)
- {
- DBG("WRONG CHECKSUM\n");
- return -1;
- }
-
- if(data[0] != 0x52)
- {
- DBG("WRONG HEADER\n");
- return -1;
- }
-
- info->keycode = 0xFF;
- if ((data[1] == 0xFF) && (data[2] == 0xFF) && (data[3] == 0xFF) && (data[4] == 0xFF) && (data[6] == 0xFF))
- {
- if ((data[5] == 0xFF) || (data[5] == 0))
- {
- info->keycode = 0xFF;
- }
- else if ((data[5] == 1) || (data[5] == 2) || (data[5] == 4) || (data[5] == 8))
- {
- if (data[5] == 1)
- {
- info->keycode = 0;
- }
- else if (data[5] == 2)
- {
- info->keycode = 1;
- }
- else if (data[5] == 4)
- {
- info->keycode = 2;
- }
- else if (data[5] == 8)
- {
- info->keycode = 3;
- }
- }
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- else if (bEnableTpProximity &&((data[5] == 0x80) || (data[5] == 0x40)))
- {
- if (data[5] == 0x80)
- {
- bFaceClosingTp = 1;
- }
- else if (data[5] == 0x40)
- {
- bFaceClosingTp = 0;
- }
- DBG("bEnableTpProximity=%d; bFaceClosingTp=%d; data[5]=%x;\n", bEnableTpProximity, bFaceClosingTp, data[5]);
- return -1;
- }
- #endif
- else
- {
- DBG("WRONG KEY\n");
- return -1;
- }
- }
- else
- {
- x = (((data[1] & 0xF0 ) << 4) | data[2]);
- y = ((( data[1] & 0x0F) << 8) | data[3]);
- delta_x = (((data[4] & 0xF0) << 4 ) | data[5]);
- delta_y = (((data[4] & 0x0F) << 8 ) | data[6]);
-
- if ((delta_x == 0) && (delta_y == 0))
- {
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 1;
- }
- else
- {
- if (delta_x > 2048)
- {
- delta_x -= 4096;
- }
- if (delta_y > 2048)
- {
- delta_y -= 4096;
- }
- x2 = (U32)((S16)x + (S16)delta_x);
- y2 = (U32)((S16)y + (S16)delta_y);
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->point[1].x = x2 * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[1].y = y2 * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 2;
- }
- }
-
- return 0;
+ unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0};
+ unsigned char checksum = 0;
+ unsigned int x = 0, y = 0;
+ unsigned int x2 = 0, y2 = 0;
+ unsigned int delta_x = 0, delta_y = 0;
+
+ mutex_lock(&msg21xx_mutex);
+ read_i2c_seq(ts_data->client->addr, &data[0], DEMO_MODE_PACKET_LENGTH);
+ mutex_unlock(&msg21xx_mutex);
+ checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
+ DBG("check sum: [%x] == [%x]?\n",
+ data[DEMO_MODE_PACKET_LENGTH-1], checksum);
+
+ if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
+ DBG("WRONG CHECKSUM\n");
+ return -EINVAL;
+ }
+
+ if (data[0] != 0x52) {
+ DBG("WRONG HEADER\n");
+ return -EINVAL;
+ }
+
+ info->keycode = 0xFF;
+ if ((data[1] == 0xFF) && (data[2] == 0xFF) &&
+ (data[3] == 0xFF) && (data[4] == 0xFF) &&
+ (data[6] == 0xFF)) {
+ if ((data[5] == 0xFF) || (data[5] == 0)) {
+ info->keycode = 0xFF;
+ } else if ((data[5] == 1) || (data[5] == 2) ||
+ (data[5] == 4) || (data[5] == 8)) {
+ info->keycode = data[5] >> 1;
+
+ DBG("info->keycode index %d\n", info->keycode);
+ }
+ #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ else if (bEnableTpProximity && ((data[5] == 0x80) ||
+ (data[5] == 0x40))) {
+ if (data[5] == 0x80)
+ bFaceClosingTp = 1;
+ else if (data[5] == 0x40)
+ bFaceClosingTp = 0;
+
+ return -EINVAL;
+ }
+ #endif
+ else {
+ DBG("WRONG KEY\n");
+ return -EINVAL;
+ }
+ } else {
+ x = (((data[1] & 0xF0) << 4) | data[2]);
+ y = (((data[1] & 0x0F) << 8) | data[3]);
+ delta_x = (((data[4] & 0xF0) << 4) | data[5]);
+ delta_y = (((data[4] & 0x0F) << 8) | data[6]);
+
+ if ((delta_x == 0) && (delta_y == 0)) {
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->count = 1;
+ } else {
+ if (delta_x > 2048)
+ delta_x -= 4096;
+
+ if (delta_y > 2048)
+ delta_y -= 4096;
+
+ x2 = (unsigned int)((signed short)x +
+ (signed short)delta_x);
+ y2 = (unsigned int)((signed short)y +
+ (signed short)delta_y);
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->point[1].x = x2 * pdata->x_max / TPD_WIDTH;
+ info->point[1].y = y2 * pdata->y_max / TPD_HEIGHT;
+ info->count = 2;
+ }
+ }
+
+ return 0;
}
-static void touch_driver_touch_pressed(int x, int y)
+static void touch_driver_touch_released(void)
{
- DBG("point touch pressed");
+ int i;
+
+ DBG("point touch released\n");
+
+ for (i = 0; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_mt_sync(input_dev);
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, 0);
+ input_sync(input_dev);
}
-static void touch_driver_touch_released(void)
+/* read data through I2C then report data to input
+ *sub-system when interrupt occurred
+ */
+static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id)
{
- DBG("point touch released");
+ struct touchInfo_t info;
+ int i = 0;
+ static int last_keycode = 0xFF;
+ static int last_count;
+
+ DBG("touch_driver_do_work()\n");
+
+ memset(&info, 0x0, sizeof(info));
+ if (parse_info(&info) == 0) {
+ #ifdef CONFIG_TP_HAVE_KEY
+ if (info.keycode != 0xFF) { /* key touch pressed */
+ if (info.keycode < num_buttons) {
+ if (info.keycode != last_keycode) {
+ DBG("key touch pressed");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(input_dev,
+ button_map[info.keycode], 1);
+
+ last_keycode = info.keycode;
+ } else {
+ /* pass duplicate key-pressing */
+ DBG("REPEATED KEY\n");
+ }
+ } else {
+ DBG("WRONG KEY\n");
+ }
+ } else { /* key touch released */
+ if (last_keycode != 0xFF) {
+ DBG("key touch released");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(input_dev,
+ button_map[last_keycode],
+ 0);
+
+ last_keycode = 0xFF;
+ }
+ }
+ #endif /* CONFIG_TP_HAVE_KEY */
+
+ if (info.count > 0) { /* point touch pressed */
+ for (i = 0; i < info.count; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 1);
+ input_report_abs(input_dev,
+ ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X,
+ info.point[i].x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y,
+ info.point[i].y);
+ }
+ }
+
+ if (last_count > info.count) {
+ for (i = info.count; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+ }
+ last_count = info.count;
+
+ input_report_key(input_dev, BTN_TOUCH, info.count > 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, info.count > 0);
+
+ input_sync(input_dev);
+ }
+
+ return IRQ_HANDLED;
+}
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_mt_sync(input_dev);
+
+static int msg21xx_ts_power_init(void)
+{
+ int rc;
+
+ ts_data->vdd = regulator_get(&i2c_client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ rc = PTR_ERR(ts_data->vdd);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ rc = regulator_set_voltage(ts_data->vdd, MSTAR_VTG_MIN_UV,
+ MSTAR_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ ts_data->vcc_i2c = regulator_get(&i2c_client->dev, "vcc_i2c");
+ if (IS_ERR(ts_data->vcc_i2c)) {
+ rc = PTR_ERR(ts_data->vcc_i2c);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(ts_data->vcc_i2c,
+ MSTAR_I2C_VTG_MIN_UV,
+ MSTAR_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(ts_data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(ts_data->vdd);
+ return rc;
}
-/* read data through I2C then report data to input sub-system when interrupt occurred */
-void touch_driver_do_work(struct work_struct *work)
+
+static int msg21xx_ts_power_deinit(void)
{
- touchInfo_t info;
- int i = 0;
- static int last_keycode = 0xFF;
- static int last_count = 0;
-
- DBG("touch_driver_do_work()\n");
-
- memset(&info, 0x0, sizeof(info));
- if (0 == parse_info(&info))
- {
- #ifdef CONFIG_TP_HAVE_KEY
- if (info.keycode != 0xFF) //key touch pressed
- {
- DBG("touch_driver_do_work() info.keycode=%x, last_keycode=%x, tp_key_array[%d]=%d\n", info.keycode, last_keycode, info.keycode, tp_key_array[info.keycode]);
- if (info.keycode < MAX_KEY_NUM)
- {
- if (info.keycode != last_keycode)
- {
- DBG("key touch pressed");
-
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_key(input_dev, tp_key_array[info.keycode], 1);
-
- last_keycode = info.keycode;
- }
- else
- {
- /// pass duplicate key-pressing
- DBG("REPEATED KEY\n");
- }
- }
- else
- {
- DBG("WRONG KEY\n");
- }
- }
- else //key touch released
- {
- if (last_keycode != 0xFF)
- {
- DBG("key touch released");
-
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_report_key(input_dev, tp_key_array[last_keycode], 0);
-
- last_keycode = 0xFF;
- }
- }
- #endif //CONFIG_TP_HAVE_KEY
-
- if (info.count > 0) //point touch pressed
- {
- for (i = 0; i < info.count; i ++)
- {
- touch_driver_touch_pressed(info.point[i].x, info.point[i].y);
- }
- last_count = info.count;
- }
- else if (last_count > 0) //point touch released
- {
- touch_driver_touch_released();
- last_count = 0;
- }
-
- input_sync(input_dev);
- }
-
- enable_irq(irq_msg21xx);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+
+ regulator_put(ts_data->vdd);
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
+ regulator_set_voltage(ts_data->vcc_i2c, 0,
+ MSTAR_I2C_VTG_MAX_UV);
+
+ regulator_put(ts_data->vcc_i2c);
+ return 0;
}
-/* The interrupt service routine will be triggered when interrupt occurred */
-irqreturn_t touch_driver_isr(int irq, void *dev_id)
+static int msg21xx_ts_power_on(void)
{
- DBG("touch_driver_isr()\n");
+ int rc;
+
+ rc = regulator_enable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ regulator_disable(ts_data->vdd);
+ }
+
+ return rc;
+}
- disable_irq_nosync(irq_msg21xx);
- schedule_work(&msg21xx_wk);
+static int msg21xx_ts_power_off(void)
+{
+ int rc;
+
+ DBG("*** %s ***\n", __func__);
+ rc = regulator_disable(vdd);
+ rc = regulator_disable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c disable failed rc=%d\n", rc);
+ rc = regulator_enable(ts_data->vdd);
+ }
+
+ return rc;
+}
- return IRQ_HANDLED;
+static int msg21xx_ts_gpio_configure(bool on)
+{
+ int ret = 0;
+
+ if (on) {
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ ret = gpio_request(pdata->irq_gpio, "msg21xx_irq_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_req;
+ }
+ ret = gpio_direction_input(pdata->irq_gpio);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for gpio[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_dir;
+ }
+ gpio_set_value_cansleep(pdata->irq_gpio, 1);
+ } else {
+ dev_err(&i2c_client->dev, "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ ret = gpio_request(pdata->reset_gpio,
+ "msg21xx_reset_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_req;
+ }
+
+ /* power on TP */
+ ret = gpio_direction_output(pdata->reset_gpio, 1);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_dir;
+ }
+ msleep(100);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ msleep(200);
+ } else {
+ dev_err(&i2c_client->dev, "reset gpio not provided\n");
+ goto err_reset_gpio_req;
+ }
+
+ } else {
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ ret = gpio_direction_input(pdata->reset_gpio);
+ if (ret)
+ dev_err(&i2c_client->dev,
+ "Unable to set direction for gpio [%d]\n",
+ pdata->reset_gpio);
+ gpio_free(pdata->reset_gpio);
+ }
+ }
+ return 0;
+err_reset_gpio_dir:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->irq_gpio);
+err_reset_gpio_req:
+err_irq_gpio_dir:
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+err_irq_gpio_req:
+ return ret;
}
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
+#ifdef CONFIG_PM
+static int msg21xx_ts_resume(struct device *dev)
{
- struct fb_event *evdata = data;
- int *blank;
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK )
- {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- {
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
- }
- else if (*blank == FB_BLANK_POWERDOWN)
- {
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return 0;
- }
-
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return 0;
- }
- #endif
-
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
- }
- }
-
- return 0;
+ int retval;
+
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended) {
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get active pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(true);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in active state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ enable_irq(ts_data->client->irq);
+
+ retval = msg21xx_ts_power_on();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power on failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 0;
+ } else {
+ dev_info(dev, "msg21xx_ts already in resume\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+ return 0;
}
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void touch_driver_early_suspend(struct early_suspend *p)
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_suspend()\n");
+ int retval;
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return;
- }
+ if (bFwUpdating) {
+ DBG("suspend bFwUpdating=%d\n", bFwUpdating);
+ return 0;
+ }
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return;
- }
+ if (bEnableTpProximity) {
+ DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
+ return 0;
+ }
#endif
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended == 0) {
+ disable_irq(ts_data->client->irq);
+
+ touch_driver_touch_released();
+
+ retval = msg21xx_ts_power_off();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power off failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(&i2c_client->dev, "Cannot get idle pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(false);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in idle state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 1;
+ } else {
+ dev_err(dev, "msg21xx_ts already in suspend\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+
+ return 0;
}
-
-void touch_driver_early_resume(struct early_suspend *p)
+#else
+static int msg21xx_ts_resume(struct device *dev)
+{
+ return 0;
+}
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend);
-
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
+ return 0;
}
#endif
-/* probe function is used for matching and initializing input device */
-static int touch_driver_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
{
-#ifdef FIRMWARE_AUTOUPDATE
- unsigned short update_bin_major = 0, update_bin_minor = 0;
- int i, update_flag = 0;
+ struct fb_event *evdata = data;
+ int *blank;
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ msg21xx_ts_resume(&i2c_client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ msg21xx_ts_suspend(&i2c_client->dev);
+ }
+
+ return 0;
+}
#endif
- int ret = 0;
-
- if (input_dev != NULL)
- {
- DBG("input device has found\n");
- return -1;
- }
-
- DBG("*** %s ***\n", __FUNCTION__);
-
- i2c_client = client;
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_RST, "reset");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_RST, ret);
- goto err0;
- }
-
- // power on TP
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
- if (0 == get_ic_type())
- {
- pr_err("the currnet ic is not Mstar\n");
- ret = -1;
- goto err0;
- }
-
- mutex_init(&msg21xx_mutex);
-
- /* allocate an input device */
- input_dev = input_allocate_device();
- if (!input_dev)
- {
- ret = -ENOMEM;
- pr_err("*** input device allocation failed ***\n");
- goto err1;
- }
-
- input_dev->name = client->name;
- input_dev->phys = "I2C";
- input_dev->dev.parent = &client->dev;
- input_dev->id.bustype = BUS_I2C;
-
- /* set the supported event type for input device */
- set_bit(EV_ABS, input_dev->evbit);
- set_bit(EV_SYN, input_dev->evbit);
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(BTN_TOUCH, input_dev->keybit);
- set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+static int msg21xx_get_dt_coords(struct device *dev, char *name,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "mstar,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "mstar,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msg21xx_parse_dt(struct device *dev,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+
+ prop = of_find_property(np, "mstar,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "mstar,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/* probe function is used for matching and initializing input device */
+static int msg21xx_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id) {
+
+ int ret = 0;
+
+ if (input_dev != NULL) {
+ DBG("input device has found\n");
+ return -EINVAL;
+ }
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = msg21xx_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "DT parsing failed\n");
+ return ret;
+ }
+ } else
+ pdata = client->dev.platform_data;
+
+ ts_data = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_data), GFP_KERNEL);
+ if (!ts_data)
+ return -ENOMEM;
+
+ DBG("*** %s ***\n", __func__);
+
+ i2c_client = client;
+
+ ret = msg21xx_ts_power_init();
+ if (ret)
+ dev_err(&client->dev, "Mstar power init failed\n");
+
+ ret = msg21xx_ts_power_on();
+ if (ret) {
+ dev_err(&client->dev, "Mstar power on failed\n");
+ goto exit_deinit_power;
+ }
+
+ ret = msg21xx_pinctrl_init();
+ if (!ret && ts_data->ts_pinctrl) {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (ret < 0)
+ goto exit_pinctrl_select;
+ } else {
+ goto exit_pinctrl_init;
+ }
+
+ ret = msg21xx_ts_gpio_configure(true);
+ if (ret) {
+ dev_err(&client->dev, "Failed to configure gpio %d\n", ret);
+ goto exit_gpio_config;
+ }
+
+ if (get_ic_type() == 0) {
+ pr_err("the currnet ic is not Mstar\n");
+ ret = -1;
+ goto err_wrong_ic_type;
+ }
+
+ mutex_init(&msg21xx_mutex);
+ mutex_init(&ts_data->ts_mutex);
+
+ /* allocate an input device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ ret = -ENOMEM;
+ pr_err("*** input device allocation failed ***\n");
+ goto err_input_allocate_dev;
+ }
+
+ input_dev->name = client->name;
+ input_dev->phys = "I2C";
+ input_dev->dev.parent = &client->dev;
+ input_dev->id.bustype = BUS_I2C;
+
+ /* set the supported event type for input device */
+ set_bit(EV_ABS, input_dev->evbit);
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ ts_data->input_dev = input_dev;
+ ts_data->client = client;
+ ts_data->pdata = pdata;
+
+ input_set_drvdata(input_dev, ts_data);
+ i2c_set_clientdata(client, ts_data);
#ifdef CONFIG_TP_HAVE_KEY
- {
- int i;
- for (i = 0; i < MAX_KEY_NUM; i ++)
- {
- input_set_capability(input_dev, EV_KEY, tp_key_array[i]);
- }
- }
+ {
+ int i;
+
+ for (i = 0; i < num_buttons; i++)
+ input_set_capability(input_dev, EV_KEY, button_map[i]);
+ }
#endif
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, TOUCH_SCREEN_X_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, TOUCH_SCREEN_Y_MAX, 0, 0);
-
- /* register the input device to input sub-system */
- ret = input_register_device(input_dev);
- if (ret < 0)
- {
- pr_err("*** Unable to register ms-touchscreen input device ***\n");
- goto err1;
- }
-
- /* set sysfs for firmware */
- firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); //client->name
- if (IS_ERR(firmware_class))
- pr_err("Failed to create class(firmware)!\n");
-
- firmware_cmd_dev = device_create(firmware_class, NULL, 0, NULL, "device");
- if (IS_ERR(firmware_cmd_dev))
- pr_err("Failed to create device(firmware_cmd_dev)!\n");
-
- // version
- if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name);
- // update
- if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name);
- // data
- if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, 2, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, pdata->y_max, 0, 0);
+ ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM, 0);
+ if (ret) {
+ pr_err("Error %d initialising slots\n", ret);
+ goto err_free_mem;
+ }
+
+ /* register the input device to input sub-system */
+ ret = input_register_device(input_dev);
+ if (ret < 0) {
+ pr_err("*** Unable to register ms-touchscreen input device ***\n");
+ goto err_input_reg_dev;
+ }
+
+ /* set sysfs for firmware */
+ firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg21xx");
+ if (IS_ERR(firmware_class))
+ pr_err("Failed to create class(firmware)!\n");
+
+ firmware_cmd_dev = device_create(firmware_class, NULL, 0,
+ NULL, "device");
+ if (IS_ERR(firmware_cmd_dev))
+ pr_err("Failed to create device(firmware_cmd_dev)!\n");
+
+ /* version */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_version.attr.name);
+ /* update */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update.attr.name);
+ /* data */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_data.attr.name);
+ /* fw name*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_fw_name) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_fw_name.attr.name);
+ /* smart fw update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update_fw.attr.name);
+ /* smart fw force update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_force_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_force_update_fw.attr.name);
#ifdef TP_PRINT
- tp_print_create_entry();
+ tp_print_create_entry();
#endif
- dev_set_drvdata(firmware_cmd_dev, NULL);
-
- /* initialize the work queue */
- INIT_WORK(&msg21xx_wk, touch_driver_do_work);
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_INT, "interrupt");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err2;
- }
- gpio_direction_input(MS_TS_MSG21XX_GPIO_INT);
- gpio_set_value(MS_TS_MSG21XX_GPIO_INT, 1);
+ dev_set_drvdata(firmware_cmd_dev, NULL);
- irq_msg21xx = gpio_to_irq(MS_TS_MSG21XX_GPIO_INT);
+ ret = request_threaded_irq(client->irq, NULL,
+ msg21xx_ts_interrupt,
+ pdata->irq_gpio_flags | IRQF_ONESHOT,
+ "msg21xx", ts_data);
+ if (ret)
+ goto err_req_irq;
- /* request an irq and register the isr */
- ret = request_irq(irq_msg21xx, touch_driver_isr, IRQF_TRIGGER_RISING, "msg21xx", NULL);
- if (ret != 0)
- {
- pr_err("*** Unable to claim irq %d; error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err3;
- }
-
- disable_irq(irq_msg21xx);
+ disable_irq(ts_data->client->irq);
#if defined(CONFIG_FB)
- msg21xx_fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&msg21xx_fb_notif);
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
- mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- mstar_ts_early_suspend.suspend = touch_driver_early_suspend;
- mstar_ts_early_suspend.resume = touch_driver_early_resume;
- register_early_suspend(&mstar_ts_early_suspend);
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
+ ret = fb_register_client(&ts_data->fb_notif);
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, &tsps_msg21xx_data);
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable,
+ &tsps_msg21xx_data);
#endif
#ifdef FIRMWARE_AUTOUPDATE
- get_customer_firmware_version();
- _ReadBinConfig();
-
- if (main_sw_id == info_sw_id)
- {
- if (_CalMainCRC32() == bin_conf_crc32)
- {
- if ((main_sw_id >= SWID_START) && (main_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f50];
-
- //check upgrading
- if ((update_bin_major == fw_version_major) && (update_bin_minor > fw_version_minor))
- {
- update_flag = 1;
- }
- }
- DBG("MAIN sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",main_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO1 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO2 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
-
- if (update_flag == 1)
- {
- DBG("MSG21XX_fw_auto_update begin....\n");
- //transfer data
- for (i = 0; i < 33; i++)
- {
- firmware_data_store(NULL, NULL, &(MSG_FIRMWARE[info_sw_id-SWID_START][i*1024]), 1024);
- }
-
- kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
- DBG("*** mstar touch screen registered ***\n");
- return 0;
- }
-
- reset_hw();
+ get_customer_firmware_version();
+ _ReadBinConfig();
+
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ if ((main_sw_id >= SWID_START) &&
+ (main_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f50];
+
+ /* check upgrading */
+ if ((update_bin_major == fw_version_major) &&
+ (update_bin_minor > fw_version_minor)) {
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) &&
+ (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+
+ if (update_flag == 1) {
+ DBG("MSG21XX_fw_auto_update begin....\n");
+ /* transfer data */
+ for (i = 0; i < 33; i++) {
+ firmware_data_store(NULL, NULL,
+ &(MSG_FIRMWARE[info_sw_id - SWID_START][i * 1024]),
+ 1024);
+ }
+
+ kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
+ DBG("*** mstar touch screen registered ***\n");
+ return 0;
+ }
+
+ reset_hw();
#endif
- DBG("*** mstar touch screen registered ***\n");
- enable_irq(irq_msg21xx);
- return 0;
-
-err3:
- free_irq(irq_msg21xx, input_dev);
-
-err2:
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
-
-err1:
- mutex_destroy(&msg21xx_mutex);
- input_unregister_device(input_dev);
- input_free_device(input_dev);
- input_dev = NULL;
-
-err0:
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
-
- return ret;
+ DBG("*** mstar touch screen registered ***\n");
+ enable_irq(ts_data->client->irq);
+ return 0;
+
+err_req_irq:
+ free_irq(ts_data->client->irq, ts_data);
+
+err_input_reg_dev:
+err_input_allocate_dev:
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+ input_unregister_device(input_dev);
+ input_free_device(input_dev);
+ input_dev = NULL;
+
+err_wrong_ic_type:
+ msg21xx_ts_gpio_configure(false);
+exit_gpio_config:
+exit_pinctrl_select:
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (ret < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+exit_pinctrl_init:
+ msg21xx_ts_power_off();
+exit_deinit_power:
+ msg21xx_ts_power_deinit();
+err_free_mem:
+ input_free_device(input_dev);
+
+ return ret;
}
-/* remove function is triggered when the input device is removed from input sub-system */
+/* remove function is triggered when the input device is removed
+ *from input sub-system
+ */
static int touch_driver_remove(struct i2c_client *client)
{
- DBG("touch_driver_remove()\n");
-
- free_irq(irq_msg21xx, input_dev);
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
- input_unregister_device(input_dev);
- mutex_destroy(&msg21xx_mutex);
-
- return 0;
+ int retval = 0;
+
+ DBG("touch_driver_remove()\n");
+
+ free_irq(ts_data->client->irq, ts_data);
+ gpio_free(pdata->irq_gpio);
+ gpio_free(pdata->reset_gpio);
+
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (retval < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+
+ input_unregister_device(input_dev);
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+
+ return retval;
}
-/* The I2C device list is used for matching I2C device and I2C device driver. */
-static const struct i2c_device_id touch_device_id[] =
-{
- {"msg21xx", 0},
- {}, /* should not omitted */
+/* The I2C device list is used for matching I2C device
+ *and I2C device driver.
+ */
+static const struct i2c_device_id touch_device_id[] = {
+ {"msg21xx", 0},
+ {}, /* should not omitted */
};
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
-
-static struct i2c_driver touch_device_driver =
-{
- .driver = {
- .name = "msg21xx",
- .owner = THIS_MODULE,
- },
- .probe = touch_driver_probe,
- .remove = touch_driver_remove,
- .id_table = touch_device_id,
+static const struct of_device_id msg21xx_match_table[] = {
+ { .compatible = "mstar,msg21xx", },
+ { },
};
-static int __init touch_driver_init(void)
-{
- int ret;
-
- /* register driver */
- ret = i2c_add_driver(&touch_device_driver);
- if (ret < 0)
- {
- DBG("add touch_device_driver i2c driver failed.\n");
- return -ENODEV;
- }
- DBG("add touch_device_driver i2c driver.\n");
-
- return ret;
-}
+MODULE_DEVICE_TABLE(i2c, touch_device_id);
-static void __exit touch_driver_exit(void)
-{
- DBG("remove touch_device_driver i2c driver.\n");
+static struct i2c_driver touch_device_driver = {
+ .driver = {
+ .name = "ms-msg21xx",
+ .owner = THIS_MODULE,
+ .of_match_table = msg21xx_match_table,
+ },
+ .probe = msg21xx_ts_probe,
+ .remove = touch_driver_remove,
+ .id_table = touch_device_id,
+};
- i2c_del_driver(&touch_device_driver);
-}
+module_i2c_driver(touch_device_driver);
#ifdef TP_PRINT
#include <linux/proc_fs.h>
-static U16 InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
-static U8 row, units, cnt;
+static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
+static unsigned char row, units, cnt;
static int tp_print_proc_read(void)
{
- U16 i, j;
- U16 left, offset = 0;
- U8 dbbus_tx_data[3] = {0};
- U8 u8Data;
- S16 s16Data;
- S32 s32Data;
- char *buf = NULL;
-
- left = cnt*row*units;
- if ((bTpInSuspend == 0) && (InfoAddr != 0x0F) && (PoolAddr != 0x10) && (left > 0))
- {
- buf = kmalloc(left, GFP_KERNEL);
- if (buf != NULL)
- {
- printk("tpp: \n");
-
- while (left > 0)
- {
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) & 0xFF;
- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &buf[offset], left > TransLen ? TransLen : left);
- mutex_unlock(&msg21xx_mutex);
-
- if (left > TransLen)
- {
- left -= TransLen;
- offset += TransLen;
- }
- else
- {
- left = 0;
- }
- }
-
- for (i = 0; i < cnt; i++)
- {
- printk("tpp: ");
- for (j = 0; j < row; j++)
- {
- if (units == 1)
- {
- u8Data = buf[i*row*units + j*units];
- printk("%d\t", u8Data);
- }
- else if (units == 2)
- {
- s16Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8);
- printk("%d\t", s16Data);
- }
- else if (units == 4)
- {
- s32Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8) + (buf[i*row*units + j*units + 2] << 16) + (buf[i*row*units + j*units + 3] << 24);
- printk("%d\t", s32Data);
- }
- }
- printk("\n");
- }
-
- kfree(buf);
- }
- }
-
- return 0;
+ unsigned short i, j;
+ unsigned short left, offset = 0;
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char u8Data;
+ signed short s16Data;
+ int s32Data;
+ char *buf = NULL;
+
+ left = cnt*row*units;
+ if ((ts_data->suspended == 0) &&
+ (InfoAddr != 0x0F) &&
+ (PoolAddr != 0x10) &&
+ (left > 0)) {
+ buf = kmalloc(left, GFP_KERNEL);
+ if (buf != NULL) {
+
+ while (left > 0) {
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = ((PoolAddr + offset) >> 8)
+ & 0xFF;
+ dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr,
+ &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr,
+ &buf[offset],
+ left > TransLen ? TransLen : left);
+ mutex_unlock(&msg21xx_mutex);
+
+ if (left > TransLen) {
+ left -= TransLen;
+ offset += TransLen;
+ } else {
+ left = 0;
+ }
+ }
+
+ for (i = 0; i < cnt; i++) {
+ for (j = 0; j < row; j++) {
+ if (units == 1) {
+ u8Data = buf[i * row * units +
+ j * units];
+ } else if (units == 2) {
+ s16Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8);
+ } else if (units == 4) {
+ s32Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8) +
+ (buf[i * row * units +
+ j * units + 2] << 16) +
+ (buf[i * row * units +
+ j * units + 3] << 24);
+ }
+ }
+ }
+
+ kfree(buf);
+ }
+ }
+
+ return 0;
}
static void tp_print_create_entry(void)
{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[8] = {0};
-
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x58;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
- printk("InfoAddr=0x%X\n", InfoAddr);
- printk("PoolAddr=0x%X\n", PoolAddr);
-
- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10))
- {
- msleep(10);
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
- dbbus_tx_data[2] = InfoAddr & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 8);
- mutex_unlock(&msg21xx_mutex);
-
- units = dbbus_rx_data[0];
- row = dbbus_rx_data[1];
- cnt = dbbus_rx_data[2];
- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
- printk("tpp: row=%d, units=%d\n", row, units);
- printk("tpp: cnt=%d, TransLen=%d\n", cnt, TransLen);
-
- // tpp
- if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0)
- {
- pr_err("Failed to create device file(%s)!\n", dev_attr_tpp.attr.name);
- }
- }
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[8] = {0};
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x58;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) {
+ msleep(20);
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
+ dbbus_tx_data[2] = InfoAddr & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 8);
+ mutex_unlock(&msg21xx_mutex);
+
+ units = dbbus_rx_data[0];
+ row = dbbus_rx_data[1];
+ cnt = dbbus_rx_data[2];
+ TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
+
+ if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_tpp.attr.name);
+ }
+ }
}
#endif
-module_init(touch_driver_init);
-module_exit(touch_driver_exit);
MODULE_AUTHOR("MStar Semiconductor, Inc.");
MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index cbe77022404b..9b9b74436d88 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -675,6 +675,12 @@ static int get_hfi_extradata_index(enum hal_extradata_id index)
case HAL_EXTRADATA_PQ_INFO:
ret = HFI_PROPERTY_PARAM_VENC_OVERRIDE_QP_EXTRADATA;
break;
+ case HAL_EXTRADATA_VUI_DISPLAY_INFO:
+ ret = HFI_PROPERTY_PARAM_VUI_DISPLAY_INFO_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_VPX_COLORSPACE:
+ ret = HFI_PROPERTY_PARAM_VDEC_VPX_COLORSPACE_EXTRADATA;
+ break;
default:
dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
break;
@@ -2127,6 +2133,26 @@ int create_pkt_cmd_session_set_property(
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_VENC_VIDEO_SIGNAL_INFO:
+ {
+ struct hal_video_signal_info *hal = pdata;
+ struct hfi_video_signal_metadata *signal_info =
+ (struct hfi_video_signal_metadata *)
+ &pkt->rg_property_data[1];
+
+ signal_info->enable = true;
+ signal_info->video_format = MSM_VIDC_NTSC;
+ signal_info->video_full_range = hal->full_range;
+ signal_info->color_description = MSM_VIDC_COLOR_DESC_PRESENT;
+ signal_info->color_primaries = hal->color_space;
+ signal_info->transfer_characteristics = hal->transfer_chars;
+ signal_info->matrix_coeffs = hal->matrix_coeffs;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pkt->size += sizeof(u32) + sizeof(*signal_info);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 0c26cc7debaf..96fefea39241 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -247,7 +247,7 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
.name = "Extradata Type",
.type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
- .maximum = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI,
+ .maximum = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE,
.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
.menu_skip_mask = ~(
(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -273,7 +273,10 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
(1 << V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI) |
(1 << V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP) |
(1 << V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI) |
- (1 << V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI)
+ (1 <<
+ V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE)
),
.qmenu = mpeg_video_vidc_extradata,
},
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 55e54f7eb008..c08084a54e86 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1242,6 +1242,46 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.default_value = V4L2_MPEG_VIDC_VIDEO_H264_TRANSFORM_8x8_ENABLE,
.step = 1,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE,
+ .name = "Set Color space",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_BT709_5,
+ .maximum = MSM_VIDC_BT2020,
+ .default_value = MSM_VIDC_BT601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE,
+ .name = "Set Color space range",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE,
+ .maximum = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_ENABLE,
+ .default_value = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE,
+ .step = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS,
+ .name = "Set Color space transfer characterstics",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_TRANSFER_BT709_5,
+ .maximum = MSM_VIDC_TRANSFER_BT_2020_12,
+ .default_value = MSM_VIDC_TRANSFER_601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS,
+ .name = "Set Color space matrix coefficients",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_MATRIX_BT_709_5,
+ .maximum = MSM_VIDC_MATRIX_BT_2020_CONST,
+ .default_value = MSM_VIDC_MATRIX_601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -2105,6 +2145,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
int baselayerid = 0;
int frameqp = 0;
int pic_order_cnt = 0;
+ struct hal_video_signal_info signal_info = {0};
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -3093,6 +3134,64 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
pdata = &pic_order_cnt;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE:
+ {
+ signal_info.color_space = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE:
+ {
+ signal_info.full_range = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS:
+ {
+ signal_info.transfer_chars = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS:
+ {
+ signal_info.matrix_coeffs = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC:
if (ctrl->val == V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_ENABLE) {
rc = msm_venc_set_csc(inst);
@@ -3516,10 +3615,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
}
hdev = inst->core->device;
- if (msm_vidc_vpe_csc_601_to_709) {
- msm_venc_set_csc(inst);
- }
-
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats,
ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 8541e06d997a..1f071ba36ec1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -77,6 +77,8 @@ const char *const mpeg_video_vidc_extradata[] = {
"Extradata display colour SEI",
"Extradata light level SEI",
"Extradata PQ Info",
+ "Extradata display VUI",
+ "Extradata vpx color space",
};
struct getprop_buf {
@@ -210,7 +212,8 @@ int msm_comm_ctrl_init(struct msm_vidc_inst *inst,
}
if (!ctrl) {
- dprintk(VIDC_ERR, "%s - invalid ctrl\n", __func__);
+ dprintk(VIDC_ERR, "%s - invalid ctrl %s\n", __func__,
+ drv_ctrls[idx].name);
return -EINVAL;
}
@@ -1719,6 +1722,19 @@ static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq,
return vb;
}
+static void msm_vidc_try_suspend(struct msm_vidc_inst *inst)
+{
+ bool batch_mode;
+
+ batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
+ == V4L2_VIDC_QBUF_BATCHED;
+ if (batch_mode) {
+ dprintk(VIDC_DBG,
+ "Trying to suspend Venus after finishing Batch\n");
+ msm_comm_suspend(inst->core->id);
+ }
+}
+
static void handle_ebd(enum hal_command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
@@ -1790,6 +1806,8 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
}
+ msm_vidc_try_suspend(inst);
+
put_inst(inst);
}
@@ -2089,6 +2107,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
}
+ msm_vidc_try_suspend(inst);
err_handle_fbd:
put_inst(inst);
}
@@ -4692,6 +4711,13 @@ enum hal_extradata_id msm_comm_get_hal_extradata_index(
case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
ret = HAL_EXTRADATA_PQ_INFO;
break;
+
+ case V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY:
+ ret = HAL_EXTRADATA_VUI_DISPLAY_INFO;
+ break;
+ case V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE:
+ ret = HAL_EXTRADATA_VPX_COLORSPACE;
+ break;
default:
dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index fb79661dd2d7..7976d6e8a603 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -171,8 +171,6 @@ struct dentry *msm_vidc_debugfs_init_drv(void)
&msm_vidc_fw_low_power_mode) &&
__debugfs_create(u32, "debug_output", &msm_vidc_debug_out) &&
__debugfs_create(u32, "hw_rsp_timeout", &msm_vidc_hw_rsp_timeout) &&
- __debugfs_create(bool, "enable_vpe_csc_601_709",
- &msm_vidc_vpe_csc_601_to_709) &&
__debugfs_create(bool, "sys_idle_indicator",
&msm_vidc_sys_idle_indicator) &&
__debugfs_create(u32, "firmware_unload_delay",
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 20e217cc0445..50c0eb351d4f 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1297,17 +1297,9 @@ static int venus_hfi_suspend(void *dev)
return -ENOTSUPP;
}
- mutex_lock(&device->lock);
+ dprintk(VIDC_DBG, "Suspending Venus\n");
+ rc = flush_delayed_work(&venus_hfi_pm_work);
- if (device->power_enabled) {
- dprintk(VIDC_DBG, "Venus is busy\n");
- rc = -EBUSY;
- } else {
- dprintk(VIDC_DBG, "Venus is power suspended\n");
- rc = 0;
- }
-
- mutex_unlock(&device->lock);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 330710631211..4cbb59d12f92 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -85,6 +85,7 @@
#define HFI_EXTRADATA_STREAM_USERDATA 0x0000000E
#define HFI_EXTRADATA_FRAME_QP 0x0000000F
#define HFI_EXTRADATA_FRAME_BITS_INFO 0x00000010
+#define HFI_EXTRADATA_VPX_COLORSPACE 0x00000014
#define HFI_EXTRADATA_MULTISLICE_INFO 0x7F100000
#define HFI_EXTRADATA_NUM_CONCEALED_MB 0x7F100001
#define HFI_EXTRADATA_INDEX 0x7F100002
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 36df3a1d45a1..34ab36a4647b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -125,6 +125,8 @@ enum hal_extradata_id {
HAL_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI,
HAL_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI,
HAL_EXTRADATA_PQ_INFO,
+ HAL_EXTRADATA_VUI_DISPLAY_INFO,
+ HAL_EXTRADATA_VPX_COLORSPACE,
};
enum hal_property {
@@ -239,6 +241,7 @@ enum hal_property {
HAL_CONFIG_VENC_BLUR_RESOLUTION,
HAL_PARAM_VENC_SESSION_QP_RANGE_PACKED,
HAL_PARAM_VENC_H264_TRANSFORM_8x8,
+ HAL_PARAM_VENC_VIDEO_SIGNAL_INFO,
};
enum hal_domain {
@@ -992,6 +995,13 @@ struct hal_vpe_color_space_conversion {
u32 csc_limit[HAL_MAX_LIMIT_COEFFS];
};
+struct hal_video_signal_info {
+ u32 color_space;
+ u32 transfer_chars;
+ u32 matrix_coeffs;
+ bool full_range;
+};
+
enum vidc_resource_id {
VIDC_RESOURCE_NONE,
VIDC_RESOURCE_OCMEM,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index ff043e9a819b..23240746baf1 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -350,7 +350,7 @@ struct hfi_buffer_info {
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01B)
#define HFI_PROPERTY_PARAM_VENC_LTRMODE \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01C)
-#define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE \
+#define HFI_PROPERTY_PARAM_VENC_VIDEO_SIGNAL_INFO \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01D)
#define HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01E)
@@ -671,6 +671,16 @@ struct hfi_frame_size {
u32 height;
};
+struct hfi_video_signal_metadata {
+ u32 enable;
+ u32 video_format;
+ u32 video_full_range;
+ u32 color_description;
+ u32 color_primaries;
+ u32 transfer_characteristics;
+ u32 matrix_coeffs;
+};
+
struct hfi_h264_vui_timing_info {
u32 enable;
u32 fixed_frame_rate;
diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c
index 22d61d96a11d..38286831a02c 100644
--- a/drivers/mfd/wcd9xxx-utils.c
+++ b/drivers/mfd/wcd9xxx-utils.c
@@ -298,6 +298,7 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
struct wcd9xxx_pdata *pdata;
u32 dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
u32 mad_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+ u32 ecpp_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
u32 dmic_clk_drive = WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED;
u32 prop_val;
@@ -358,6 +359,15 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
pdata->mclk_rate,
"mad_dmic_rate");
+ if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-ecpp-dmic-rate",
+ &prop_val)))
+ ecpp_dmic_sample_rate = prop_val;
+
+ pdata->ecpp_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
+ ecpp_dmic_sample_rate,
+ pdata->mclk_rate,
+ "ecpp_dmic_rate");
+
if (!(of_property_read_u32(dev->of_node,
"qcom,cdc-dmic-clk-drv-strength",
&prop_val)))
diff --git a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
index 14abb75fffe0..45db409eb7c1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
+++ b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
@@ -25,9 +25,9 @@
.ngroups = ARRAY_SIZE(fname##_groups), \
}
-#define SOUTH 0x00500000
-#define WEST 0x00100000
-#define EAST 0x00900000
+#define NORTH 0x00900000
+#define CENTER 0x00500000
+#define SOUTH 0x00100000
#define REG_SIZE 0x1000
#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
@@ -204,9 +204,16 @@ static const struct pinctrl_pin_desc msmfalcon_pins[] = {
PINCTRL_PIN(108, "GPIO_108"),
PINCTRL_PIN(109, "GPIO_109"),
PINCTRL_PIN(110, "GPIO_110"),
- PINCTRL_PIN(111, "SDC2_CLK"),
- PINCTRL_PIN(112, "SDC2_CMD"),
- PINCTRL_PIN(113, "SDC2_DATA"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "SDC1_CLK"),
+ PINCTRL_PIN(115, "SDC1_CMD"),
+ PINCTRL_PIN(116, "SDC1_DATA"),
+ PINCTRL_PIN(117, "SDC2_CLK"),
+ PINCTRL_PIN(118, "SDC2_CMD"),
+ PINCTRL_PIN(119, "SDC2_DATA"),
+ PINCTRL_PIN(120, "SDC1_RCLK"),
};
#define DECLARE_MSM_GPIO_PINS(pin) \
@@ -322,88 +329,101 @@ DECLARE_MSM_GPIO_PINS(107);
DECLARE_MSM_GPIO_PINS(108);
DECLARE_MSM_GPIO_PINS(109);
DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
-static const unsigned int sdc2_clk_pins[] = { 111 };
-static const unsigned int sdc2_cmd_pins[] = { 112 };
-static const unsigned int sdc2_data_pins[] = { 113 };
+static const unsigned int sdc1_clk_pins[] = { 114 };
+static const unsigned int sdc1_cmd_pins[] = { 115 };
+static const unsigned int sdc1_data_pins[] = { 116 };
+static const unsigned int sdc2_clk_pins[] = { 117 };
+static const unsigned int sdc2_cmd_pins[] = { 118 };
+static const unsigned int sdc2_data_pins[] = { 119 };
+static const unsigned int sdc1_rclk_pins[] = { 120 };
enum msmfalcon_functions {
msm_mux_blsp_spi1,
msm_mux_gpio,
+ msm_mux_blsp_uim1,
msm_mux_tgu_ch0,
- msm_mux_tgu_ch1,
+ msm_mux_qdss_gpio4,
+ msm_mux_atest_gpsadc1,
msm_mux_blsp_uart1,
+ msm_mux_SMB_STAT,
+ msm_mux_phase_flag14,
+ msm_mux_blsp_i2c2,
+ msm_mux_phase_flag31,
msm_mux_blsp_spi3,
msm_mux_wlan1_adc1,
msm_mux_atest_usb13,
- msm_mux_bimc_dte1,
- msm_mux_wlan1_adc0,
- msm_mux_atest_usb12,
- msm_mux_bimc_dte0,
+ msm_mux_tgu_ch1,
+ msm_mux_qdss_gpio5,
+ msm_mux_atest_gpsadc0,
msm_mux_blsp_i2c1,
- msm_mux_blsp_uim1,
msm_mux_ddr_bist,
msm_mux_atest_tsens2,
msm_mux_atest_usb1,
msm_mux_blsp_spi2,
- msm_mux_phase_flag3,
- msm_mux_phase_flag14,
- msm_mux_blsp_i2c2,
msm_mux_blsp_uim2,
- msm_mux_phase_flag31,
+ msm_mux_phase_flag3,
+ msm_mux_bimc_dte1,
+ msm_mux_wlan1_adc0,
+ msm_mux_atest_usb12,
+ msm_mux_bimc_dte0,
msm_mux_blsp_i2c3,
- msm_mux_atest_gpsadc1,
msm_mux_wlan2_adc1,
msm_mux_atest_usb11,
msm_mux_dbg_out,
- msm_mux_atest_gpsadc0,
msm_mux_wlan2_adc0,
msm_mux_atest_usb10,
+ msm_mux_RCM_MARKER,
msm_mux_blsp_spi4,
msm_mux_pri_mi2s,
msm_mux_phase_flag26,
- msm_mux_qdss_gpio4,
+ msm_mux_qdss_cti,
+ msm_mux_DP_HOT,
msm_mux_pri_mi2s_ws,
msm_mux_phase_flag27,
- msm_mux_qdss_gpio5,
msm_mux_blsp_i2c4,
msm_mux_phase_flag28,
msm_mux_blsp_uart5,
msm_mux_blsp_spi5,
+ msm_mux_blsp_uim5,
msm_mux_phase_flag5,
msm_mux_blsp_i2c5,
- msm_mux_blsp_uim5,
msm_mux_blsp_spi6,
msm_mux_blsp_uart2,
- msm_mux_qdss_cti,
- msm_mux_sec_mi2s,
- msm_mux_sndwire_clk,
- msm_mux_phase_flag17,
- msm_mux_vsense_clkout,
- msm_mux_sndwire_data,
- msm_mux_phase_flag18,
- msm_mux_blsp_i2c7,
- msm_mux_wsa_en1,
- msm_mux_phase_flag19,
+ msm_mux_blsp_uim6,
msm_mux_phase_flag11,
msm_mux_vsense_data0,
msm_mux_blsp_i2c6,
- msm_mux_blsp_uim6,
msm_mux_phase_flag12,
msm_mux_vsense_data1,
msm_mux_phase_flag13,
msm_mux_vsense_mode,
msm_mux_blsp_spi7,
msm_mux_BLSP_UART,
+ msm_mux_sec_mi2s,
+ msm_mux_sndwire_clk,
+ msm_mux_phase_flag17,
+ msm_mux_vsense_clkout,
+ msm_mux_sndwire_data,
+ msm_mux_phase_flag18,
+ msm_mux_WSA_SPKR,
+ msm_mux_blsp_i2c7,
+ msm_mux_phase_flag19,
msm_mux_vfr_1,
- msm_mux_wsa_en2,
msm_mux_phase_flag20,
+ msm_mux_NFC_INT,
msm_mux_blsp_spi,
msm_mux_m_voc,
msm_mux_phase_flag21,
+ msm_mux_NFC_EN,
msm_mux_phase_flag22,
+ msm_mux_NFC_DWL,
msm_mux_BLSP_I2C,
msm_mux_phase_flag23,
+ msm_mux_NFC_ESE,
msm_mux_pwr_modem,
msm_mux_phase_flag24,
msm_mux_qdss_gpio,
@@ -419,88 +439,92 @@ enum msmfalcon_functions {
msm_mux_qspi_data2,
msm_mux_jitter_bist,
msm_mux_qdss_gpio3,
+ msm_mux_qdss_gpio7,
+ msm_mux_FL_R3LED,
+ msm_mux_CCI_TIMER0,
+ msm_mux_FL_STROBE,
+ msm_mux_CCI_TIMER1,
+ msm_mux_CAM_LDO1,
+ msm_mux_mdss_vsync0,
+ msm_mux_mdss_vsync1,
+ msm_mux_mdss_vsync2,
+ msm_mux_mdss_vsync3,
+ msm_mux_qdss_gpio9,
+ msm_mux_CAM_IRQ,
+ msm_mux_atest_usb2,
msm_mux_cci_i2c,
msm_mux_pll_bypassnl,
msm_mux_atest_tsens,
+ msm_mux_atest_usb21,
msm_mux_pll_reset,
- msm_mux_qdss_gpio9,
- msm_mux_CAM_IRQ,
+ msm_mux_atest_usb23,
+ msm_mux_qdss_gpio6,
msm_mux_CCI_TIMER3,
msm_mux_CCI_ASYNC,
msm_mux_qspi_cs,
msm_mux_qdss_gpio10,
- msm_mux_CAM4_STANDBY,
+ msm_mux_CAM3_STANDBY,
msm_mux_CCI_TIMER4,
msm_mux_qdss_gpio11,
- msm_mux_bt_reset,
+ msm_mux_CAM_LDO2,
msm_mux_cci_async,
msm_mux_qdss_gpio12,
- msm_mux_CAM1_RST,
- msm_mux_qdss_gpio6,
- msm_mux_qdss_gpio7,
- msm_mux_FL_FRONT,
- msm_mux_CCI_TIMER0,
- msm_mux_qdss_gpio8,
- msm_mux_FL_STROBE,
- msm_mux_CCI_TIMER1,
- msm_mux_LASER_CE,
- msm_mux_mdss_vsync0,
- msm_mux_mdss_vsync1,
- msm_mux_mdss_vsync2,
- msm_mux_mdss_vsync3,
+ msm_mux_CAM0_RST,
msm_mux_qdss_gpio13,
- msm_mux_CAM2_RST,
+ msm_mux_CAM1_RST,
msm_mux_qspi_clk,
msm_mux_phase_flag30,
msm_mux_qdss_gpio14,
- msm_mux_CAM3_RST,
msm_mux_qspi_resetn,
msm_mux_phase_flag1,
msm_mux_qdss_gpio15,
- msm_mux_CAM1_STANDBY,
+ msm_mux_CAM0_STANDBY,
msm_mux_phase_flag2,
- msm_mux_CAM2_STANDBY,
+ msm_mux_CAM1_STANDBY,
msm_mux_phase_flag9,
- msm_mux_CAM3_STANDBY,
+ msm_mux_CAM2_STANDBY,
msm_mux_qspi_data3,
msm_mux_phase_flag15,
- msm_mux_CAM4_RST,
+ msm_mux_qdss_gpio8,
+ msm_mux_CAM3_RST,
msm_mux_CCI_TIMER2,
msm_mux_phase_flag16,
+ msm_mux_LCD0_RESET,
msm_mux_phase_flag6,
- msm_mux_RCM_MARKER2,
+ msm_mux_SD_CARD,
msm_mux_phase_flag29,
- msm_mux_SS_SWITCH,
+ msm_mux_DP_EN,
msm_mux_phase_flag25,
+ msm_mux_USBC_ORIENTATION,
msm_mux_phase_flag10,
+ msm_mux_atest_usb20,
msm_mux_gcc_gp1,
msm_mux_phase_flag4,
- msm_mux_USB_DIR,
+ msm_mux_atest_usb22,
msm_mux_USB_PHY,
msm_mux_gcc_gp2,
msm_mux_atest_char,
msm_mux_mdp_vsync,
msm_mux_gcc_gp3,
msm_mux_atest_char3,
- msm_mux_Lcd_mode,
- msm_mux_EDP_HOT,
+ msm_mux_FORCE_TOUCH,
msm_mux_cri_trng0,
msm_mux_atest_char2,
msm_mux_cri_trng1,
msm_mux_atest_char1,
+ msm_mux_AUDIO_USBC,
msm_mux_audio_ref,
msm_mux_MDP_VSYNC,
msm_mux_cri_trng,
msm_mux_atest_char0,
msm_mux_US_EURO,
- msm_mux_KEY_FOCUS,
- msm_mux_NAV_PPS,
+ msm_mux_LCD_BACKLIGHT,
msm_mux_blsp_spi8,
msm_mux_sp_cmu,
- msm_mux_SLT_PWR,
+ msm_mux_NAV_PPS,
+ msm_mux_GPS_TX,
msm_mux_adsp_ext,
msm_mux_TS_RESET,
- msm_mux_TS_INT,
msm_mux_ssc_irq,
msm_mux_isense_dbg,
msm_mux_phase_flag0,
@@ -508,8 +532,10 @@ enum msmfalcon_functions {
msm_mux_phase_flag8,
msm_mux_tsense_pwm1,
msm_mux_tsense_pwm2,
+ msm_mux_SENSOR_RST,
+ msm_mux_WMSS_RESETN,
msm_mux_HAPTICS_PWM,
- msm_mux_wmss_reset,
+ msm_mux_GPS_eLNA,
msm_mux_mss_lte,
msm_mux_uim2_data,
msm_mux_uim2_clk,
@@ -521,12 +547,12 @@ enum msmfalcon_functions {
msm_mux_uim1_present,
msm_mux_uim_batt,
msm_mux_pa_indicator,
- msm_mux_ssbi_gnss,
msm_mux_ldo_en,
msm_mux_ldo_update,
msm_mux_qlink_request,
msm_mux_qlink_enable,
msm_mux_prng_rosc,
+ msm_mux_LCD_PWR,
msm_mux_NA,
};
@@ -534,27 +560,44 @@ static const char * const blsp_spi1_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3", "gpio46",
};
static const char * const gpio_groups[] = {
- "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
- "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
- "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
- "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
- "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
- "gpio36", "gpio37", "gpio38", "gpio39", "gpio53", "gpio57", "gpio59",
- "gpio61", "gpio62", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
- "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
- "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
- "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
- "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio6", "gpio7", "gpio8",
+ "gpio9", "gpio10", "gpio11", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", "gpio24",
+ "gpio25", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37",
+ "gpio38", "gpio39", "gpio57", "gpio58", "gpio59", "gpio61", "gpio65",
+ "gpio81", "gpio82", "gpio83", "gpio84", "gpio85", "gpio86", "gpio87",
+ "gpio88", "gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94",
+ "gpio95", "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio0", "gpio1",
};
static const char * const tgu_ch0_groups[] = {
"gpio0",
};
-static const char * const tgu_ch1_groups[] = {
- "gpio1",
+static const char * const qdss_gpio4_groups[] = {
+ "gpio0", "gpio36",
+};
+static const char * const atest_gpsadc1_groups[] = {
+ "gpio0",
};
static const char * const blsp_uart1_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
};
+static const char * const SMB_STAT_groups[] = {
+ "gpio5",
+};
+static const char * const phase_flag14_groups[] = {
+ "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const phase_flag31_groups[] = {
+ "gpio6",
+};
static const char * const blsp_spi3_groups[] = {
"gpio8", "gpio9", "gpio10", "gpio11", "gpio30", "gpio65",
};
@@ -564,24 +607,18 @@ static const char * const wlan1_adc1_groups[] = {
static const char * const atest_usb13_groups[] = {
"gpio8",
};
-static const char * const bimc_dte1_groups[] = {
- "gpio8", "gpio10",
-};
-static const char * const wlan1_adc0_groups[] = {
- "gpio9",
+static const char * const tgu_ch1_groups[] = {
+ "gpio1",
};
-static const char * const atest_usb12_groups[] = {
- "gpio9",
+static const char * const qdss_gpio5_groups[] = {
+ "gpio1", "gpio37",
};
-static const char * const bimc_dte0_groups[] = {
- "gpio9", "gpio11",
+static const char * const atest_gpsadc0_groups[] = {
+ "gpio1",
};
static const char * const blsp_i2c1_groups[] = {
"gpio2", "gpio3",
};
-static const char * const blsp_uim1_groups[] = {
- "gpio2", "gpio3",
-};
static const char * const ddr_bist_groups[] = {
"gpio3", "gpio8", "gpio9", "gpio10",
};
@@ -594,27 +631,27 @@ static const char * const atest_usb1_groups[] = {
static const char * const blsp_spi2_groups[] = {
"gpio4", "gpio5", "gpio6", "gpio7",
};
+static const char * const blsp_uim2_groups[] = {
+ "gpio4", "gpio5",
+};
static const char * const phase_flag3_groups[] = {
"gpio4",
};
-static const char * const phase_flag14_groups[] = {
- "gpio5",
+static const char * const bimc_dte1_groups[] = {
+ "gpio8", "gpio10",
};
-static const char * const blsp_i2c2_groups[] = {
- "gpio6", "gpio7",
+static const char * const wlan1_adc0_groups[] = {
+ "gpio9",
};
-static const char * const blsp_uim2_groups[] = {
- "gpio6", "gpio7",
+static const char * const atest_usb12_groups[] = {
+ "gpio9",
};
-static const char * const phase_flag31_groups[] = {
- "gpio6",
+static const char * const bimc_dte0_groups[] = {
+ "gpio9", "gpio11",
};
static const char * const blsp_i2c3_groups[] = {
"gpio10", "gpio11",
};
-static const char * const atest_gpsadc1_groups[] = {
- "gpio10",
-};
static const char * const wlan2_adc1_groups[] = {
"gpio10",
};
@@ -624,15 +661,15 @@ static const char * const atest_usb11_groups[] = {
static const char * const dbg_out_groups[] = {
"gpio11",
};
-static const char * const atest_gpsadc0_groups[] = {
- "gpio11",
-};
static const char * const wlan2_adc0_groups[] = {
"gpio11",
};
static const char * const atest_usb10_groups[] = {
"gpio11",
};
+static const char * const RCM_MARKER_groups[] = {
+ "gpio12", "gpio13",
+};
static const char * const blsp_spi4_groups[] = {
"gpio12", "gpio13", "gpio14", "gpio15",
};
@@ -642,8 +679,12 @@ static const char * const pri_mi2s_groups[] = {
static const char * const phase_flag26_groups[] = {
"gpio12",
};
-static const char * const qdss_gpio4_groups[] = {
- "gpio12", "gpio36",
+static const char * const qdss_cti_groups[] = {
+ "gpio12", "gpio13", "gpio21", "gpio49", "gpio50", "gpio53", "gpio55",
+ "gpio66",
+};
+static const char * const DP_HOT_groups[] = {
+ "gpio13",
};
static const char * const pri_mi2s_ws_groups[] = {
"gpio13",
@@ -651,9 +692,6 @@ static const char * const pri_mi2s_ws_groups[] = {
static const char * const phase_flag27_groups[] = {
"gpio13",
};
-static const char * const qdss_gpio5_groups[] = {
- "gpio13", "gpio37",
-};
static const char * const blsp_i2c4_groups[] = {
"gpio14", "gpio15",
};
@@ -666,51 +704,23 @@ static const char * const blsp_uart5_groups[] = {
static const char * const blsp_spi5_groups[] = {
"gpio16", "gpio17", "gpio18", "gpio19",
};
+static const char * const blsp_uim5_groups[] = {
+ "gpio16", "gpio17",
+};
static const char * const phase_flag5_groups[] = {
"gpio17",
};
static const char * const blsp_i2c5_groups[] = {
"gpio18", "gpio19",
};
-static const char * const blsp_uim5_groups[] = {
- "gpio18", "gpio19",
-};
static const char * const blsp_spi6_groups[] = {
"gpio20", "gpio21", "gpio22", "gpio23",
};
static const char * const blsp_uart2_groups[] = {
"gpio20", "gpio21", "gpio22", "gpio23",
};
-static const char * const qdss_cti_groups[] = {
- "gpio20", "gpio21", "gpio24", "gpio25", "gpio26", "gpio49", "gpio50",
- "gpio61",
-};
-static const char * const sec_mi2s_groups[] = {
- "gpio24", "gpio25", "gpio26", "gpio27", "gpio62",
-};
-static const char * const sndwire_clk_groups[] = {
- "gpio24",
-};
-static const char * const phase_flag17_groups[] = {
- "gpio24",
-};
-static const char * const vsense_clkout_groups[] = {
- "gpio24",
-};
-static const char * const sndwire_data_groups[] = {
- "gpio25",
-};
-static const char * const phase_flag18_groups[] = {
- "gpio25",
-};
-static const char * const blsp_i2c7_groups[] = {
- "gpio26", "gpio27",
-};
-static const char * const wsa_en1_groups[] = {
- "gpio26",
-};
-static const char * const phase_flag19_groups[] = {
- "gpio26",
+static const char * const blsp_uim6_groups[] = {
+ "gpio20", "gpio21",
};
static const char * const phase_flag11_groups[] = {
"gpio21",
@@ -721,9 +731,6 @@ static const char * const vsense_data0_groups[] = {
static const char * const blsp_i2c6_groups[] = {
"gpio22", "gpio23",
};
-static const char * const blsp_uim6_groups[] = {
- "gpio22", "gpio23",
-};
static const char * const phase_flag12_groups[] = {
"gpio22",
};
@@ -743,15 +750,42 @@ static const char * const BLSP_UART_groups[] = {
"gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30",
"gpio31",
};
-static const char * const vfr_1_groups[] = {
- "gpio27",
+static const char * const sec_mi2s_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio62",
+};
+static const char * const sndwire_clk_groups[] = {
+ "gpio24",
+};
+static const char * const phase_flag17_groups[] = {
+ "gpio24",
+};
+static const char * const vsense_clkout_groups[] = {
+ "gpio24",
+};
+static const char * const sndwire_data_groups[] = {
+ "gpio25",
+};
+static const char * const phase_flag18_groups[] = {
+ "gpio25",
+};
+static const char * const WSA_SPKR_groups[] = {
+ "gpio26", "gpio27",
};
-static const char * const wsa_en2_groups[] = {
+static const char * const blsp_i2c7_groups[] = {
+ "gpio26", "gpio27",
+};
+static const char * const phase_flag19_groups[] = {
+ "gpio26",
+};
+static const char * const vfr_1_groups[] = {
"gpio27",
};
static const char * const phase_flag20_groups[] = {
"gpio27",
};
+static const char * const NFC_INT_groups[] = {
+ "gpio28",
+};
static const char * const blsp_spi_groups[] = {
"gpio28", "gpio29", "gpio30", "gpio31", "gpio40", "gpio41", "gpio44",
"gpio52",
@@ -762,15 +796,24 @@ static const char * const m_voc_groups[] = {
static const char * const phase_flag21_groups[] = {
"gpio28",
};
+static const char * const NFC_EN_groups[] = {
+ "gpio29",
+};
static const char * const phase_flag22_groups[] = {
"gpio29",
};
+static const char * const NFC_DWL_groups[] = {
+ "gpio30",
+};
static const char * const BLSP_I2C_groups[] = {
"gpio30", "gpio31", "gpio44", "gpio52",
};
static const char * const phase_flag23_groups[] = {
"gpio30",
};
+static const char * const NFC_ESE_groups[] = {
+ "gpio31",
+};
static const char * const pwr_modem_groups[] = {
"gpio31",
};
@@ -778,7 +821,7 @@ static const char * const phase_flag24_groups[] = {
"gpio31",
};
static const char * const qdss_gpio_groups[] = {
- "gpio31", "gpio41", "gpio68", "gpio69",
+ "gpio31", "gpio52", "gpio68", "gpio69",
};
static const char * const cam_mclk_groups[] = {
"gpio32", "gpio33", "gpio34", "gpio35",
@@ -787,7 +830,7 @@ static const char * const pwr_nav_groups[] = {
"gpio32",
};
static const char * const qdss_gpio0_groups[] = {
- "gpio32", "gpio62",
+ "gpio32", "gpio67",
};
static const char * const qspi_data0_groups[] = {
"gpio33",
@@ -814,7 +857,46 @@ static const char * const jitter_bist_groups[] = {
"gpio35",
};
static const char * const qdss_gpio3_groups[] = {
- "gpio35", "gpio65",
+ "gpio35", "gpio56",
+};
+static const char * const qdss_gpio7_groups[] = {
+ "gpio39", "gpio71",
+};
+static const char * const FL_R3LED_groups[] = {
+ "gpio40",
+};
+static const char * const CCI_TIMER0_groups[] = {
+ "gpio40",
+};
+static const char * const FL_STROBE_groups[] = {
+ "gpio41",
+};
+static const char * const CCI_TIMER1_groups[] = {
+ "gpio41",
+};
+static const char * const CAM_LDO1_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync0_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync1_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync2_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync3_groups[] = {
+ "gpio42",
+};
+static const char * const qdss_gpio9_groups[] = {
+ "gpio42", "gpio76",
+};
+static const char * const CAM_IRQ_groups[] = {
+ "gpio43",
+};
+static const char * const atest_usb2_groups[] = {
+ "gpio35",
};
static const char * const cci_i2c_groups[] = {
"gpio36", "gpio37", "gpio38", "gpio39",
@@ -825,14 +907,17 @@ static const char * const pll_bypassnl_groups[] = {
static const char * const atest_tsens_groups[] = {
"gpio36",
};
+static const char * const atest_usb21_groups[] = {
+ "gpio36",
+};
static const char * const pll_reset_groups[] = {
"gpio37",
};
-static const char * const qdss_gpio9_groups[] = {
- "gpio42", "gpio76",
+static const char * const atest_usb23_groups[] = {
+ "gpio37",
};
-static const char * const CAM_IRQ_groups[] = {
- "gpio43",
+static const char * const qdss_gpio6_groups[] = {
+ "gpio38", "gpio70",
};
static const char * const CCI_TIMER3_groups[] = {
"gpio43",
@@ -846,7 +931,7 @@ static const char * const qspi_cs_groups[] = {
static const char * const qdss_gpio10_groups[] = {
"gpio43", "gpio77",
};
-static const char * const CAM4_STANDBY_groups[] = {
+static const char * const CAM3_STANDBY_groups[] = {
"gpio44",
};
static const char * const CCI_TIMER4_groups[] = {
@@ -855,7 +940,7 @@ static const char * const CCI_TIMER4_groups[] = {
static const char * const qdss_gpio11_groups[] = {
"gpio44", "gpio79",
};
-static const char * const bt_reset_groups[] = {
+static const char * const CAM_LDO2_groups[] = {
"gpio45",
};
static const char * const cci_async_groups[] = {
@@ -864,49 +949,13 @@ static const char * const cci_async_groups[] = {
static const char * const qdss_gpio12_groups[] = {
"gpio45", "gpio80",
};
-static const char * const CAM1_RST_groups[] = {
+static const char * const CAM0_RST_groups[] = {
"gpio46",
};
-static const char * const qdss_gpio6_groups[] = {
- "gpio38", "gpio70",
-};
-static const char * const qdss_gpio7_groups[] = {
- "gpio39", "gpio71",
-};
-static const char * const FL_FRONT_groups[] = {
- "gpio40",
-};
-static const char * const CCI_TIMER0_groups[] = {
- "gpio40",
-};
-static const char * const qdss_gpio8_groups[] = {
- "gpio40", "gpio75",
-};
-static const char * const FL_STROBE_groups[] = {
- "gpio41",
-};
-static const char * const CCI_TIMER1_groups[] = {
- "gpio41",
-};
-static const char * const LASER_CE_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync0_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync1_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync2_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync3_groups[] = {
- "gpio42",
-};
static const char * const qdss_gpio13_groups[] = {
"gpio46", "gpio78",
};
-static const char * const CAM2_RST_groups[] = {
+static const char * const CAM1_RST_groups[] = {
"gpio47",
};
static const char * const qspi_clk_groups[] = {
@@ -918,9 +967,6 @@ static const char * const phase_flag30_groups[] = {
static const char * const qdss_gpio14_groups[] = {
"gpio47", "gpio72",
};
-static const char * const CAM3_RST_groups[] = {
- "gpio48",
-};
static const char * const qspi_resetn_groups[] = {
"gpio48",
};
@@ -930,19 +976,19 @@ static const char * const phase_flag1_groups[] = {
static const char * const qdss_gpio15_groups[] = {
"gpio48", "gpio73",
};
-static const char * const CAM1_STANDBY_groups[] = {
+static const char * const CAM0_STANDBY_groups[] = {
"gpio49",
};
static const char * const phase_flag2_groups[] = {
"gpio49",
};
-static const char * const CAM2_STANDBY_groups[] = {
+static const char * const CAM1_STANDBY_groups[] = {
"gpio50",
};
static const char * const phase_flag9_groups[] = {
"gpio50",
};
-static const char * const CAM3_STANDBY_groups[] = {
+static const char * const CAM2_STANDBY_groups[] = {
"gpio51",
};
static const char * const qspi_data3_groups[] = {
@@ -951,7 +997,10 @@ static const char * const qspi_data3_groups[] = {
static const char * const phase_flag15_groups[] = {
"gpio51",
};
-static const char * const CAM4_RST_groups[] = {
+static const char * const qdss_gpio8_groups[] = {
+ "gpio51", "gpio75",
+};
+static const char * const CAM3_RST_groups[] = {
"gpio52",
};
static const char * const CCI_TIMER2_groups[] = {
@@ -960,32 +1009,41 @@ static const char * const CCI_TIMER2_groups[] = {
static const char * const phase_flag16_groups[] = {
"gpio52",
};
+static const char * const LCD0_RESET_groups[] = {
+ "gpio53",
+};
static const char * const phase_flag6_groups[] = {
"gpio53",
};
-static const char * const RCM_MARKER2_groups[] = {
+static const char * const SD_CARD_groups[] = {
"gpio54",
};
static const char * const phase_flag29_groups[] = {
"gpio54",
};
-static const char * const SS_SWITCH_groups[] = {
- "gpio55", "gpio56",
+static const char * const DP_EN_groups[] = {
+ "gpio55",
};
static const char * const phase_flag25_groups[] = {
"gpio55",
};
+static const char * const USBC_ORIENTATION_groups[] = {
+ "gpio56",
+};
static const char * const phase_flag10_groups[] = {
"gpio56",
};
+static const char * const atest_usb20_groups[] = {
+ "gpio56",
+};
static const char * const gcc_gp1_groups[] = {
"gpio57", "gpio78",
};
static const char * const phase_flag4_groups[] = {
"gpio57",
};
-static const char * const USB_DIR_groups[] = {
- "gpio58",
+static const char * const atest_usb22_groups[] = {
+ "gpio57",
};
static const char * const USB_PHY_groups[] = {
"gpio58",
@@ -1005,11 +1063,8 @@ static const char * const gcc_gp3_groups[] = {
static const char * const atest_char3_groups[] = {
"gpio59",
};
-static const char * const Lcd_mode_groups[] = {
- "gpio60",
-};
-static const char * const EDP_HOT_groups[] = {
- "gpio60",
+static const char * const FORCE_TOUCH_groups[] = {
+ "gpio60", "gpio73",
};
static const char * const cri_trng0_groups[] = {
"gpio60",
@@ -1023,6 +1078,9 @@ static const char * const cri_trng1_groups[] = {
static const char * const atest_char1_groups[] = {
"gpio61",
};
+static const char * const AUDIO_USBC_groups[] = {
+ "gpio62",
+};
static const char * const audio_ref_groups[] = {
"gpio62",
};
@@ -1038,20 +1096,20 @@ static const char * const atest_char0_groups[] = {
static const char * const US_EURO_groups[] = {
"gpio63",
};
-static const char * const KEY_FOCUS_groups[] = {
+static const char * const LCD_BACKLIGHT_groups[] = {
"gpio64",
};
-static const char * const NAV_PPS_groups[] = {
- "gpio64", "gpio65", "gpio98", "gpio98",
-};
static const char * const blsp_spi8_groups[] = {
"gpio64", "gpio76",
};
static const char * const sp_cmu_groups[] = {
"gpio64",
};
-static const char * const SLT_PWR_groups[] = {
- "gpio65",
+static const char * const NAV_PPS_groups[] = {
+ "gpio65", "gpio65", "gpio80", "gpio80", "gpio98", "gpio98",
+};
+static const char * const GPS_TX_groups[] = {
+ "gpio65", "gpio80", "gpio98",
};
static const char * const adsp_ext_groups[] = {
"gpio65",
@@ -1059,12 +1117,9 @@ static const char * const adsp_ext_groups[] = {
static const char * const TS_RESET_groups[] = {
"gpio66",
};
-static const char * const TS_INT_groups[] = {
- "gpio67",
-};
static const char * const ssc_irq_groups[] = {
- "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
- "gpio75", "gpio76", "gpio77",
+ "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio74",
+ "gpio75", "gpio76",
};
static const char * const isense_dbg_groups[] = {
"gpio68",
@@ -1084,12 +1139,18 @@ static const char * const tsense_pwm1_groups[] = {
static const char * const tsense_pwm2_groups[] = {
"gpio71",
};
-static const char * const HAPTICS_PWM_groups[] = {
+static const char * const SENSOR_RST_groups[] = {
+ "gpio77",
+};
+static const char * const WMSS_RESETN_groups[] = {
"gpio78",
};
-static const char * const wmss_reset_groups[] = {
+static const char * const HAPTICS_PWM_groups[] = {
"gpio79",
};
+static const char * const GPS_eLNA_groups[] = {
+ "gpio80",
+};
static const char * const mss_lte_groups[] = {
"gpio81", "gpio82",
};
@@ -1123,9 +1184,6 @@ static const char * const uim_batt_groups[] = {
static const char * const pa_indicator_groups[] = {
"gpio92",
};
-static const char * const ssbi_gnss_groups[] = {
- "gpio94",
-};
static const char * const ldo_en_groups[] = {
"gpio97",
};
@@ -1141,84 +1199,93 @@ static const char * const qlink_enable_groups[] = {
static const char * const prng_rosc_groups[] = {
"gpio102",
};
+static const char * const LCD_PWR_groups[] = {
+ "gpio113",
+};
static const struct msm_function msmfalcon_functions[] = {
FUNCTION(blsp_spi1),
FUNCTION(gpio),
+ FUNCTION(blsp_uim1),
FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
+ FUNCTION(qdss_gpio4),
+ FUNCTION(atest_gpsadc1),
FUNCTION(blsp_uart1),
+ FUNCTION(SMB_STAT),
+ FUNCTION(phase_flag14),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(phase_flag31),
FUNCTION(blsp_spi3),
FUNCTION(wlan1_adc1),
FUNCTION(atest_usb13),
- FUNCTION(bimc_dte1),
- FUNCTION(wlan1_adc0),
- FUNCTION(atest_usb12),
- FUNCTION(bimc_dte0),
+ FUNCTION(tgu_ch1),
+ FUNCTION(qdss_gpio5),
+ FUNCTION(atest_gpsadc0),
FUNCTION(blsp_i2c1),
- FUNCTION(blsp_uim1),
FUNCTION(ddr_bist),
FUNCTION(atest_tsens2),
FUNCTION(atest_usb1),
FUNCTION(blsp_spi2),
- FUNCTION(phase_flag3),
- FUNCTION(phase_flag14),
- FUNCTION(blsp_i2c2),
FUNCTION(blsp_uim2),
- FUNCTION(phase_flag31),
+ FUNCTION(phase_flag3),
+ FUNCTION(bimc_dte1),
+ FUNCTION(wlan1_adc0),
+ FUNCTION(atest_usb12),
+ FUNCTION(bimc_dte0),
FUNCTION(blsp_i2c3),
- FUNCTION(atest_gpsadc1),
FUNCTION(wlan2_adc1),
FUNCTION(atest_usb11),
FUNCTION(dbg_out),
- FUNCTION(atest_gpsadc0),
FUNCTION(wlan2_adc0),
FUNCTION(atest_usb10),
+ FUNCTION(RCM_MARKER),
FUNCTION(blsp_spi4),
FUNCTION(pri_mi2s),
FUNCTION(phase_flag26),
- FUNCTION(qdss_gpio4),
+ FUNCTION(qdss_cti),
+ FUNCTION(DP_HOT),
FUNCTION(pri_mi2s_ws),
FUNCTION(phase_flag27),
- FUNCTION(qdss_gpio5),
FUNCTION(blsp_i2c4),
FUNCTION(phase_flag28),
FUNCTION(blsp_uart5),
FUNCTION(blsp_spi5),
+ FUNCTION(blsp_uim5),
FUNCTION(phase_flag5),
FUNCTION(blsp_i2c5),
- FUNCTION(blsp_uim5),
FUNCTION(blsp_spi6),
FUNCTION(blsp_uart2),
- FUNCTION(qdss_cti),
- FUNCTION(sec_mi2s),
- FUNCTION(sndwire_clk),
- FUNCTION(phase_flag17),
- FUNCTION(vsense_clkout),
- FUNCTION(sndwire_data),
- FUNCTION(phase_flag18),
- FUNCTION(blsp_i2c7),
- FUNCTION(wsa_en1),
- FUNCTION(phase_flag19),
+ FUNCTION(blsp_uim6),
FUNCTION(phase_flag11),
FUNCTION(vsense_data0),
FUNCTION(blsp_i2c6),
- FUNCTION(blsp_uim6),
FUNCTION(phase_flag12),
FUNCTION(vsense_data1),
FUNCTION(phase_flag13),
FUNCTION(vsense_mode),
FUNCTION(blsp_spi7),
FUNCTION(BLSP_UART),
+ FUNCTION(sec_mi2s),
+ FUNCTION(sndwire_clk),
+ FUNCTION(phase_flag17),
+ FUNCTION(vsense_clkout),
+ FUNCTION(sndwire_data),
+ FUNCTION(phase_flag18),
+ FUNCTION(WSA_SPKR),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(phase_flag19),
FUNCTION(vfr_1),
- FUNCTION(wsa_en2),
FUNCTION(phase_flag20),
+ FUNCTION(NFC_INT),
FUNCTION(blsp_spi),
FUNCTION(m_voc),
FUNCTION(phase_flag21),
+ FUNCTION(NFC_EN),
FUNCTION(phase_flag22),
+ FUNCTION(NFC_DWL),
FUNCTION(BLSP_I2C),
FUNCTION(phase_flag23),
+ FUNCTION(NFC_ESE),
FUNCTION(pwr_modem),
FUNCTION(phase_flag24),
FUNCTION(qdss_gpio),
@@ -1234,88 +1301,92 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(qspi_data2),
FUNCTION(jitter_bist),
FUNCTION(qdss_gpio3),
+ FUNCTION(qdss_gpio7),
+ FUNCTION(FL_R3LED),
+ FUNCTION(CCI_TIMER0),
+ FUNCTION(FL_STROBE),
+ FUNCTION(CCI_TIMER1),
+ FUNCTION(CAM_LDO1),
+ FUNCTION(mdss_vsync0),
+ FUNCTION(mdss_vsync1),
+ FUNCTION(mdss_vsync2),
+ FUNCTION(mdss_vsync3),
+ FUNCTION(qdss_gpio9),
+ FUNCTION(CAM_IRQ),
+ FUNCTION(atest_usb2),
FUNCTION(cci_i2c),
FUNCTION(pll_bypassnl),
FUNCTION(atest_tsens),
+ FUNCTION(atest_usb21),
FUNCTION(pll_reset),
- FUNCTION(qdss_gpio9),
- FUNCTION(CAM_IRQ),
+ FUNCTION(atest_usb23),
+ FUNCTION(qdss_gpio6),
FUNCTION(CCI_TIMER3),
FUNCTION(CCI_ASYNC),
FUNCTION(qspi_cs),
FUNCTION(qdss_gpio10),
- FUNCTION(CAM4_STANDBY),
+ FUNCTION(CAM3_STANDBY),
FUNCTION(CCI_TIMER4),
FUNCTION(qdss_gpio11),
- FUNCTION(bt_reset),
+ FUNCTION(CAM_LDO2),
FUNCTION(cci_async),
FUNCTION(qdss_gpio12),
- FUNCTION(CAM1_RST),
- FUNCTION(qdss_gpio6),
- FUNCTION(qdss_gpio7),
- FUNCTION(FL_FRONT),
- FUNCTION(CCI_TIMER0),
- FUNCTION(qdss_gpio8),
- FUNCTION(FL_STROBE),
- FUNCTION(CCI_TIMER1),
- FUNCTION(LASER_CE),
- FUNCTION(mdss_vsync0),
- FUNCTION(mdss_vsync1),
- FUNCTION(mdss_vsync2),
- FUNCTION(mdss_vsync3),
+ FUNCTION(CAM0_RST),
FUNCTION(qdss_gpio13),
- FUNCTION(CAM2_RST),
+ FUNCTION(CAM1_RST),
FUNCTION(qspi_clk),
FUNCTION(phase_flag30),
FUNCTION(qdss_gpio14),
- FUNCTION(CAM3_RST),
FUNCTION(qspi_resetn),
FUNCTION(phase_flag1),
FUNCTION(qdss_gpio15),
- FUNCTION(CAM1_STANDBY),
+ FUNCTION(CAM0_STANDBY),
FUNCTION(phase_flag2),
- FUNCTION(CAM2_STANDBY),
+ FUNCTION(CAM1_STANDBY),
FUNCTION(phase_flag9),
- FUNCTION(CAM3_STANDBY),
+ FUNCTION(CAM2_STANDBY),
FUNCTION(qspi_data3),
FUNCTION(phase_flag15),
- FUNCTION(CAM4_RST),
+ FUNCTION(qdss_gpio8),
+ FUNCTION(CAM3_RST),
FUNCTION(CCI_TIMER2),
FUNCTION(phase_flag16),
+ FUNCTION(LCD0_RESET),
FUNCTION(phase_flag6),
- FUNCTION(RCM_MARKER2),
+ FUNCTION(SD_CARD),
FUNCTION(phase_flag29),
- FUNCTION(SS_SWITCH),
+ FUNCTION(DP_EN),
FUNCTION(phase_flag25),
+ FUNCTION(USBC_ORIENTATION),
FUNCTION(phase_flag10),
+ FUNCTION(atest_usb20),
FUNCTION(gcc_gp1),
FUNCTION(phase_flag4),
- FUNCTION(USB_DIR),
+ FUNCTION(atest_usb22),
FUNCTION(USB_PHY),
FUNCTION(gcc_gp2),
FUNCTION(atest_char),
FUNCTION(mdp_vsync),
FUNCTION(gcc_gp3),
FUNCTION(atest_char3),
- FUNCTION(Lcd_mode),
- FUNCTION(EDP_HOT),
+ FUNCTION(FORCE_TOUCH),
FUNCTION(cri_trng0),
FUNCTION(atest_char2),
FUNCTION(cri_trng1),
FUNCTION(atest_char1),
+ FUNCTION(AUDIO_USBC),
FUNCTION(audio_ref),
FUNCTION(MDP_VSYNC),
FUNCTION(cri_trng),
FUNCTION(atest_char0),
FUNCTION(US_EURO),
- FUNCTION(KEY_FOCUS),
- FUNCTION(NAV_PPS),
+ FUNCTION(LCD_BACKLIGHT),
FUNCTION(blsp_spi8),
FUNCTION(sp_cmu),
- FUNCTION(SLT_PWR),
+ FUNCTION(NAV_PPS),
+ FUNCTION(GPS_TX),
FUNCTION(adsp_ext),
FUNCTION(TS_RESET),
- FUNCTION(TS_INT),
FUNCTION(ssc_irq),
FUNCTION(isense_dbg),
FUNCTION(phase_flag0),
@@ -1323,8 +1394,10 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(phase_flag8),
FUNCTION(tsense_pwm1),
FUNCTION(tsense_pwm2),
+ FUNCTION(SENSOR_RST),
+ FUNCTION(WMSS_RESETN),
FUNCTION(HAPTICS_PWM),
- FUNCTION(wmss_reset),
+ FUNCTION(GPS_eLNA),
FUNCTION(mss_lte),
FUNCTION(uim2_data),
FUNCTION(uim2_clk),
@@ -1336,153 +1409,155 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(uim1_present),
FUNCTION(uim_batt),
FUNCTION(pa_indicator),
- FUNCTION(ssbi_gnss),
FUNCTION(ldo_en),
FUNCTION(ldo_update),
FUNCTION(qlink_request),
FUNCTION(qlink_enable),
FUNCTION(prng_rosc),
+ FUNCTION(LCD_PWR),
};
static const struct msm_pingroup msmfalcon_groups[] = {
- PINGROUP(0, SOUTH, blsp_spi1, blsp_uart1, tgu_ch0, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(1, SOUTH, blsp_spi1, blsp_uart1, tgu_ch1, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(2, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, blsp_uim1, NA, NA,
- NA, NA, NA),
- PINGROUP(3, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, blsp_uim1,
- ddr_bist, NA, atest_tsens2, atest_usb1, NA),
- PINGROUP(4, WEST, blsp_spi2, phase_flag3, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(5, WEST, blsp_spi2, phase_flag14, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(6, WEST, blsp_spi2, blsp_i2c2, blsp_uim2, phase_flag31, NA,
- NA, NA, NA, NA),
- PINGROUP(7, WEST, blsp_spi2, blsp_i2c2, blsp_uim2, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(8, WEST, blsp_spi3, ddr_bist, NA, NA, wlan1_adc1, atest_usb13,
- bimc_dte1, NA, NA),
- PINGROUP(9, WEST, blsp_spi3, ddr_bist, NA, NA, wlan1_adc0, atest_usb12,
- bimc_dte0, NA, NA),
- PINGROUP(10, WEST, blsp_spi3, blsp_i2c3, ddr_bist, NA, atest_gpsadc1,
- wlan2_adc1, atest_usb11, bimc_dte1, NA),
- PINGROUP(11, WEST, blsp_spi3, blsp_i2c3, dbg_out, atest_gpsadc0,
- wlan2_adc0, atest_usb10, bimc_dte0, NA, NA),
- PINGROUP(12, SOUTH, blsp_spi4, pri_mi2s, phase_flag26, qdss_gpio4, NA,
+ PINGROUP(0, SOUTH, blsp_spi1, blsp_uart1, blsp_uim1, tgu_ch0, NA, NA,
+ qdss_gpio4, atest_gpsadc1, NA),
+ PINGROUP(1, SOUTH, blsp_spi1, blsp_uart1, blsp_uim1, tgu_ch1, NA, NA,
+ qdss_gpio5, atest_gpsadc0, NA),
+ PINGROUP(2, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(3, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, ddr_bist, NA, NA,
+ atest_tsens2, atest_usb1, NA),
+ PINGROUP(4, NORTH, blsp_spi2, blsp_uim2, NA, phase_flag3, NA, NA, NA,
+ NA, NA),
+ PINGROUP(5, SOUTH, blsp_spi2, blsp_uim2, NA, phase_flag14, NA, NA, NA,
+ NA, NA),
+ PINGROUP(6, SOUTH, blsp_spi2, blsp_i2c2, NA, phase_flag31, NA, NA, NA,
+ NA, NA),
+ PINGROUP(7, SOUTH, blsp_spi2, blsp_i2c2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(8, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc1,
+ atest_usb13, bimc_dte1, NA),
+ PINGROUP(9, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc0,
+ atest_usb12, bimc_dte0, NA),
+ PINGROUP(10, NORTH, blsp_spi3, blsp_i2c3, ddr_bist, NA, NA, wlan2_adc1,
+ atest_usb11, bimc_dte1, NA),
+ PINGROUP(11, NORTH, blsp_spi3, blsp_i2c3, NA, dbg_out, wlan2_adc0,
+ atest_usb10, bimc_dte0, NA, NA),
+ PINGROUP(12, NORTH, blsp_spi4, pri_mi2s, NA, phase_flag26, qdss_cti,
NA, NA, NA, NA),
- PINGROUP(13, SOUTH, blsp_spi4, pri_mi2s_ws, NA, phase_flag27,
- qdss_gpio5, NA, NA, NA, NA),
- PINGROUP(14, SOUTH, blsp_spi4, blsp_i2c4, pri_mi2s, phase_flag28, NA,
+ PINGROUP(13, NORTH, blsp_spi4, DP_HOT, pri_mi2s_ws, NA, NA,
+ phase_flag27, qdss_cti, NA, NA),
+ PINGROUP(14, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, phase_flag28,
NA, NA, NA, NA),
- PINGROUP(15, SOUTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA,
+ PINGROUP(15, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA,
NA),
- PINGROUP(16, WEST, blsp_uart5, blsp_spi5, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(17, WEST, blsp_uart5, blsp_spi5, phase_flag5, NA, NA, NA, NA,
+ PINGROUP(16, CENTER, blsp_uart5, blsp_spi5, blsp_uim5, NA, NA, NA, NA,
NA, NA),
- PINGROUP(18, WEST, blsp_uart5, blsp_spi5, blsp_i2c5, blsp_uim5, NA, NA,
- NA, NA, NA),
- PINGROUP(19, WEST, blsp_uart5, blsp_spi5, blsp_i2c5, blsp_uim5, NA, NA,
- NA, NA, NA),
- PINGROUP(20, WEST, blsp_spi6, blsp_uart2, NA, qdss_cti, NA, NA, NA, NA,
- NA),
- PINGROUP(21, WEST, blsp_spi6, blsp_uart2, phase_flag11, qdss_cti,
- vsense_data0, NA, NA, NA, NA),
- PINGROUP(22, WEST, blsp_spi6, blsp_uart2, blsp_i2c6, blsp_uim6,
+ PINGROUP(17, CENTER, blsp_uart5, blsp_spi5, blsp_uim5, NA, phase_flag5,
+ NA, NA, NA, NA),
+ PINGROUP(18, CENTER, blsp_uart5, blsp_spi5, blsp_i2c5, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(19, CENTER, blsp_uart5, blsp_spi5, blsp_i2c5, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(20, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(21, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, phase_flag11,
+ qdss_cti, vsense_data0, NA, NA),
+ PINGROUP(22, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
phase_flag12, vsense_data1, NA, NA, NA),
- PINGROUP(23, WEST, blsp_spi6, blsp_uart2, blsp_i2c6, blsp_uim6,
+ PINGROUP(23, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
phase_flag13, vsense_mode, NA, NA, NA),
- PINGROUP(24, WEST, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA,
- phase_flag17, qdss_cti, vsense_clkout, NA),
- PINGROUP(25, WEST, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA,
- phase_flag18, qdss_cti, NA, NA),
- PINGROUP(26, WEST, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, wsa_en1,
- phase_flag19, qdss_cti, NA, NA),
- PINGROUP(27, WEST, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s,
- wsa_en2, phase_flag20, NA, NA),
- PINGROUP(28, SOUTH, blsp_spi, BLSP_UART, m_voc, phase_flag21, NA, NA,
+ PINGROUP(24, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA,
+ NA, phase_flag17, vsense_clkout, NA),
+ PINGROUP(25, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA,
+ NA, phase_flag18, NA, NA),
+ PINGROUP(26, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, NA,
+ phase_flag19, NA, NA, NA),
+ PINGROUP(27, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s,
+ NA, phase_flag20, NA, NA),
+ PINGROUP(28, CENTER, blsp_spi, BLSP_UART, m_voc, NA, phase_flag21, NA,
NA, NA, NA),
- PINGROUP(29, SOUTH, blsp_spi, BLSP_UART, NA, phase_flag22, NA, NA, NA,
+ PINGROUP(29, CENTER, blsp_spi, BLSP_UART, NA, NA, phase_flag22, NA, NA,
NA, NA),
- PINGROUP(30, SOUTH, blsp_spi, BLSP_UART, BLSP_I2C, blsp_spi3,
- phase_flag23, NA, NA, NA, NA),
- PINGROUP(31, SOUTH, blsp_spi, BLSP_UART, BLSP_I2C, pwr_modem,
- phase_flag24, qdss_gpio, NA, NA, NA),
- PINGROUP(32, SOUTH, cam_mclk, pwr_nav, NA, qdss_gpio0, NA, NA, NA, NA,
+ PINGROUP(30, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, blsp_spi3, NA,
+ phase_flag23, NA, NA, NA),
+ PINGROUP(31, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, pwr_modem, NA,
+ phase_flag24, qdss_gpio, NA, NA),
+ PINGROUP(32, SOUTH, cam_mclk, pwr_nav, NA, NA, qdss_gpio0, NA, NA, NA,
NA),
- PINGROUP(33, SOUTH, cam_mclk, qspi_data0, pwr_crypto, NA, qdss_gpio1,
- NA, NA, NA, NA),
- PINGROUP(34, SOUTH, cam_mclk, qspi_data1, agera_pll, NA, qdss_gpio2,
- NA, NA, NA, NA),
- PINGROUP(35, SOUTH, cam_mclk, qspi_data2, jitter_bist, NA, qdss_gpio3,
- NA, NA, NA, NA),
- PINGROUP(36, SOUTH, cci_i2c, pll_bypassnl, agera_pll, NA, qdss_gpio4,
- atest_tsens, NA, NA, NA),
- PINGROUP(37, SOUTH, cci_i2c, pll_reset, NA, qdss_gpio5, NA, NA, NA, NA,
- NA),
- PINGROUP(38, SOUTH, cci_i2c, NA, qdss_gpio6, NA, NA, NA, NA, NA, NA),
- PINGROUP(39, SOUTH, cci_i2c, NA, qdss_gpio7, NA, NA, NA, NA, NA, NA),
- PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi, NA, qdss_gpio8, NA, NA,
- NA, NA),
- PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi, NA, qdss_gpio, NA, NA,
- NA, NA),
+ PINGROUP(33, SOUTH, cam_mclk, qspi_data0, pwr_crypto, NA, NA,
+ qdss_gpio1, NA, NA, NA),
+ PINGROUP(34, SOUTH, cam_mclk, qspi_data1, agera_pll, NA, NA,
+ qdss_gpio2, NA, NA, NA),
+ PINGROUP(35, SOUTH, cam_mclk, qspi_data2, jitter_bist, NA, NA,
+ qdss_gpio3, NA, atest_usb2, NA),
+ PINGROUP(36, SOUTH, cci_i2c, pll_bypassnl, agera_pll, NA, NA,
+ qdss_gpio4, atest_tsens, atest_usb21, NA),
+ PINGROUP(37, SOUTH, cci_i2c, pll_reset, NA, NA, qdss_gpio5,
+ atest_usb23, NA, NA, NA),
+ PINGROUP(38, SOUTH, cci_i2c, NA, NA, qdss_gpio6, NA, NA, NA, NA, NA),
+ PINGROUP(39, SOUTH, cci_i2c, NA, NA, qdss_gpio7, NA, NA, NA, NA, NA),
+ PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(42, SOUTH, mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3,
- NA, qdss_gpio9, NA, NA, NA),
- PINGROUP(43, SOUTH, CCI_TIMER3, CCI_ASYNC, qspi_cs, NA, qdss_gpio10,
- NA, NA, NA, NA),
- PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi, BLSP_I2C, NA,
- qdss_gpio11, NA, NA, NA),
- PINGROUP(45, SOUTH, cci_async, NA, qdss_gpio12, NA, NA, NA, NA, NA, NA),
- PINGROUP(46, SOUTH, blsp_spi1, NA, qdss_gpio13, NA, NA, NA, NA, NA, NA),
- PINGROUP(47, SOUTH, qspi_clk, phase_flag30, qdss_gpio14, NA, NA, NA,
- NA, NA, NA),
- PINGROUP(48, SOUTH, qspi_resetn, phase_flag1, qdss_gpio15, NA, NA, NA,
+ NA, NA, qdss_gpio9, NA, NA),
+ PINGROUP(43, SOUTH, CCI_TIMER3, CCI_ASYNC, qspi_cs, NA, NA,
+ qdss_gpio10, NA, NA, NA),
+ PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi, BLSP_I2C, NA, NA,
+ qdss_gpio11, NA, NA),
+ PINGROUP(45, SOUTH, cci_async, NA, NA, qdss_gpio12, NA, NA, NA, NA, NA),
+ PINGROUP(46, SOUTH, blsp_spi1, NA, NA, qdss_gpio13, NA, NA, NA, NA, NA),
+ PINGROUP(47, SOUTH, qspi_clk, NA, phase_flag30, qdss_gpio14, NA, NA,
NA, NA, NA),
- PINGROUP(49, SOUTH, phase_flag2, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(50, SOUTH, qspi_cs, phase_flag9, qdss_cti, NA, NA, NA, NA, NA,
+ PINGROUP(48, SOUTH, NA, phase_flag1, qdss_gpio15, NA, NA, NA, NA, NA,
NA),
- PINGROUP(51, SOUTH, qspi_data3, phase_flag15, NA, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(52, EAST, CCI_TIMER2, blsp_spi, BLSP_I2C, phase_flag16, NA,
- NA, NA, NA, NA),
- PINGROUP(53, EAST, phase_flag6, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(54, EAST, NA, phase_flag29, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(55, WEST, phase_flag25, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(56, WEST, phase_flag10, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(57, SOUTH, gcc_gp1, phase_flag4, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(58, SOUTH, USB_PHY, gcc_gp2, NA, atest_char, NA, NA, NA, NA,
+ PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti, NA, NA, NA, NA,
NA),
- PINGROUP(59, EAST, mdp_vsync, gcc_gp3, NA, atest_char3, NA, NA, NA, NA,
- NA),
- PINGROUP(60, EAST, EDP_HOT, cri_trng0, NA, atest_char2, NA, NA, NA, NA,
- NA),
- PINGROUP(61, EAST, pri_mi2s, cri_trng1, NA, qdss_cti, atest_char1, NA,
+ PINGROUP(51, SOUTH, qspi_data3, NA, phase_flag15, qdss_gpio8, NA, NA,
+ NA, NA, NA),
+ PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi, BLSP_I2C, NA, phase_flag16,
+ qdss_gpio, NA, NA, NA),
+ PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(54, NORTH, NA, NA, phase_flag29, NA, NA, NA, NA, NA, NA),
+ PINGROUP(55, SOUTH, NA, phase_flag25, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(56, SOUTH, NA, phase_flag10, qdss_gpio3, NA, atest_usb20, NA,
NA, NA, NA),
- PINGROUP(62, SOUTH, sec_mi2s, audio_ref, MDP_VSYNC, cri_trng, NA,
- qdss_gpio0, atest_char0, NA, NA),
- PINGROUP(63, SOUTH, NA, NA, qdss_gpio1, NA, NA, NA, NA, NA, NA),
- PINGROUP(64, SOUTH, NAV_PPS, blsp_spi8, sp_cmu, NA, qdss_gpio2, NA, NA,
+ PINGROUP(57, SOUTH, gcc_gp1, NA, phase_flag4, atest_usb22, NA, NA, NA,
NA, NA),
- PINGROUP(65, SOUTH, NAV_PPS, blsp_spi3, NA, adsp_ext, NA, qdss_gpio3,
+ PINGROUP(58, SOUTH, USB_PHY, gcc_gp2, NA, NA, atest_char, NA, NA, NA,
+ NA),
+ PINGROUP(59, NORTH, mdp_vsync, gcc_gp3, NA, NA, atest_char3, NA, NA,
+ NA, NA),
+ PINGROUP(60, NORTH, cri_trng0, NA, NA, atest_char2, NA, NA, NA, NA, NA),
+ PINGROUP(61, NORTH, pri_mi2s, cri_trng1, NA, NA, atest_char1, NA, NA,
+ NA, NA),
+ PINGROUP(62, NORTH, sec_mi2s, audio_ref, MDP_VSYNC, cri_trng, NA, NA,
+ atest_char0, NA, NA),
+ PINGROUP(63, NORTH, NA, NA, NA, qdss_gpio1, NA, NA, NA, NA, NA),
+ PINGROUP(64, SOUTH, blsp_spi8, sp_cmu, NA, NA, qdss_gpio2, NA, NA, NA,
+ NA),
+ PINGROUP(65, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, blsp_spi3, adsp_ext,
NA, NA, NA),
- PINGROUP(66, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(67, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(68, SOUTH, isense_dbg, phase_flag0, qdss_gpio, NA, NA, NA, NA,
+ PINGROUP(66, NORTH, NA, NA, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(67, NORTH, NA, NA, qdss_gpio0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(68, NORTH, isense_dbg, NA, phase_flag0, qdss_gpio, NA, NA, NA,
NA, NA),
- PINGROUP(69, SOUTH, phase_flag7, qdss_gpio, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(70, SOUTH, phase_flag8, qdss_gpio6, NA, NA, NA, NA, NA, NA,
+ PINGROUP(69, NORTH, NA, phase_flag7, qdss_gpio, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, NORTH, NA, phase_flag8, qdss_gpio6, NA, NA, NA, NA, NA,
NA),
- PINGROUP(71, SOUTH, NA, qdss_gpio7, tsense_pwm1, tsense_pwm2, NA, NA,
+ PINGROUP(71, NORTH, NA, NA, qdss_gpio7, tsense_pwm1, tsense_pwm2, NA,
NA, NA, NA),
- PINGROUP(72, SOUTH, qdss_gpio14, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(73, SOUTH, NA, qdss_gpio15, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(74, SOUTH, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(75, WEST, NA, qdss_gpio8, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(76, WEST, blsp_spi8, NA, NA, qdss_gpio9, NA, NA, NA, NA, NA),
- PINGROUP(77, SOUTH, NA, qdss_gpio10, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(78, SOUTH, gcc_gp1, qdss_gpio13, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(79, SOUTH, NA, qdss_gpio11, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(80, SOUTH, NA, qdss_gpio12, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(81, SOUTH, mss_lte, gcc_gp2, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(82, SOUTH, mss_lte, NA, gcc_gp3, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, NORTH, NA, qdss_gpio14, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, NORTH, NA, NA, qdss_gpio15, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, NORTH, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(75, NORTH, NA, NA, qdss_gpio8, NA, NA, NA, NA, NA, NA),
+ PINGROUP(76, NORTH, blsp_spi8, NA, NA, NA, qdss_gpio9, NA, NA, NA, NA),
+ PINGROUP(77, NORTH, NA, NA, qdss_gpio10, NA, NA, NA, NA, NA, NA),
+ PINGROUP(78, NORTH, gcc_gp1, NA, qdss_gpio13, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, SOUTH, NA, NA, qdss_gpio11, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, SOUTH, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, qdss_gpio12, NA,
+ NA, NA),
+ PINGROUP(81, CENTER, mss_lte, gcc_gp2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, CENTER, mss_lte, gcc_gp3, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(83, SOUTH, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(84, SOUTH, uim2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(85, SOUTH, uim2_reset, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1494,12 +1569,12 @@ static const struct msm_pingroup msmfalcon_groups[] = {
PINGROUP(91, SOUTH, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(92, SOUTH, NA, NA, pa_indicator, NA, NA, NA, NA, NA, NA),
PINGROUP(93, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(94, SOUTH, NA, ssbi_gnss, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(94, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(95, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(96, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(97, SOUTH, NA, NA, ldo_en, NA, NA, NA, NA, NA, NA),
- PINGROUP(98, SOUTH, NA, NAV_PPS, NAV_PPS, ldo_update, NA, NA, NA, NA,
- NA),
+ PINGROUP(97, SOUTH, NA, ldo_en, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, ldo_update, NA, NA,
+ NA, NA),
PINGROUP(99, SOUTH, qlink_request, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(100, SOUTH, qlink_enable, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(101, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1508,13 +1583,20 @@ static const struct msm_pingroup msmfalcon_groups[] = {
PINGROUP(104, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(105, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(106, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(107, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(108, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(109, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(110, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- SDC_QDSD_PINGROUP(sdc2_clk, 0x999000, 14, 6),
- SDC_QDSD_PINGROUP(sdc2_cmd, 0x999000, 11, 3),
- SDC_QDSD_PINGROUP(sdc2_data, 0x999000, 9, 0),
+ PINGROUP(107, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(112, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(113, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x99a000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x99a000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x99a000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x99b000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x99b000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x99b000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc1_rclk, 0x99a000, 15, 0),
};
static const struct msm_pinctrl_soc_data msmfalcon_pinctrl = {
@@ -1524,7 +1606,7 @@ static const struct msm_pinctrl_soc_data msmfalcon_pinctrl = {
.nfunctions = ARRAY_SIZE(msmfalcon_functions),
.groups = msmfalcon_groups,
.ngroups = ARRAY_SIZE(msmfalcon_groups),
- .ngpios = 111,
+ .ngpios = 114,
};
static int msmfalcon_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c
index bd8cdf3f9770..2ab8b79acc6d 100644
--- a/drivers/platform/msm/gsi/gsi_dbg.c
+++ b/drivers/platform/msm/gsi/gsi_dbg.c
@@ -653,11 +653,11 @@ static ssize_t gsi_rst_stats(struct file *file,
} else if (ch_id < 0 || ch_id >= GSI_MAX_CHAN ||
!gsi_ctx->chan[ch_id].allocated) {
goto error;
+ } else {
+ min = ch_id;
+ max = ch_id + 1;
}
- min = ch_id;
- max = ch_id + 1;
-
for (ch_id = min; ch_id < max; ch_id++)
memset(&gsi_ctx->chan[ch_id].stats, 0,
sizeof(gsi_ctx->chan[ch_id].stats));
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 0bb863037772..005508fdcdc1 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -40,6 +40,8 @@
IPA_GENERIC_RX_BUFF_BASE_SZ) -\
IPA_GENERIC_RX_BUFF_BASE_SZ)
+#define IPA_RX_BUFF_CLIENT_HEADROOM 256
+
/* less 1 nominal MTU (1500 bytes) rounded to units of KB */
#define IPA_ADJUST_AGGR_BYTE_LIMIT(X) (((X) - IPA_MTU)/1000)
@@ -2288,6 +2290,21 @@ static void ipa_cleanup_rx(struct ipa_sys_context *sys)
}
}
+static struct sk_buff *ipa_skb_copy_for_client(struct sk_buff *skb, int len)
+{
+ struct sk_buff *skb2 = NULL;
+
+ skb2 = __dev_alloc_skb(len + IPA_RX_BUFF_CLIENT_HEADROOM, GFP_KERNEL);
+ if (likely(skb2)) {
+ /* Set the data pointer */
+ skb_reserve(skb2, IPA_RX_BUFF_CLIENT_HEADROOM);
+ memcpy(skb2->data, skb->data, len);
+ skb2->len = len;
+ skb_set_tail_pointer(skb2, len);
+ }
+
+ return skb2;
+}
static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb,
struct ipa_sys_context *sys)
@@ -2484,7 +2501,8 @@ begin:
sys->drop_packet = true;
}
- skb2 = skb_clone(skb, GFP_KERNEL);
+ skb2 = ipa_skb_copy_for_client(skb,
+ status->pkt_len + IPA_PKT_STATUS_SIZE);
if (likely(skb2)) {
if (skb->len < len + IPA_PKT_STATUS_SIZE) {
IPADBG("SPL skb len %d len %d\n",
@@ -2527,7 +2545,7 @@ begin:
IPA_PKT_STATUS_SIZE);
}
} else {
- IPAERR("fail to clone\n");
+ IPAERR("fail to alloc skb\n");
if (skb->len < len) {
sys->prev_skb = NULL;
sys->len_rem = len - skb->len +
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index b89dcfe18925..395cf62c9728 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -41,8 +41,7 @@
#define IPA_TAG_SLEEP_MAX_USEC (2000)
#define IPA_FORCE_CLOSE_TAG_PROCESS_TIMEOUT (10 * HZ)
#define IPA_BCR_REG_VAL_v3_0 (0x00000001)
-#define IPA_BCR_REG_VAL_v3_1 (0x00000003)
-#define IPA_BCR_REG_VAL_v3_5_1 (0x0000003B)
+#define IPA_BCR_REG_VAL_v3_5 (0x0000003B)
#define IPA_AGGR_GRAN_MIN (1)
#define IPA_AGGR_GRAN_MAX (32)
#define IPA_EOT_COAL_GRAN_MIN (1)
@@ -859,13 +858,12 @@ int ipa3_init_hw(void)
switch (ipa3_ctx->ipa_hw_type) {
case IPA_HW_v3_0:
- val = IPA_BCR_REG_VAL_v3_0;
- break;
case IPA_HW_v3_1:
- val = IPA_BCR_REG_VAL_v3_1;
+ val = IPA_BCR_REG_VAL_v3_0;
break;
+ case IPA_HW_v3_5:
case IPA_HW_v3_5_1:
- val = IPA_BCR_REG_VAL_v3_5_1;
+ val = IPA_BCR_REG_VAL_v3_5;
break;
default:
IPAERR("unknown HW type in dts\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 6c4d14b093c3..bcd2cb3bfd7a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -535,6 +535,11 @@ static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_IMM_CMD_MAX ; j++) {
@@ -901,6 +906,11 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
/*
* Since structure alignment is implementation dependent,
* add test to avoid different and incompatible data layouts.
@@ -1269,6 +1279,12 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base,
goto bail_free_ctx;
}
+ if (ipa_hw_type >= IPA_HW_MAX) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ result = -EINVAL;
+ goto bail_free_ctx;
+ }
+
if (!base) {
IPAHAL_ERR("invalid memory io mapping addr\n");
result = -EINVAL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index c47d353d9658..a3345d7ac305 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1066,6 +1066,11 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_REG_MAX ; j++) {
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index a45a5d103040..b1c3441b285a 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -225,9 +225,9 @@ static struct device_attribute power_supply_attrs[] = {
/* Local extensions */
POWER_SUPPLY_ATTR(usb_hc),
POWER_SUPPLY_ATTR(usb_otg),
- POWER_SUPPLY_ATTR(charge_enabled),
POWER_SUPPLY_ATTR(battery_charging_enabled),
POWER_SUPPLY_ATTR(charging_enabled),
+ POWER_SUPPLY_ATTR(pin_enabled),
POWER_SUPPLY_ATTR(input_suspend),
POWER_SUPPLY_ATTR(input_voltage_regulation),
POWER_SUPPLY_ATTR(input_current_max),
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index 11d936762e3c..e9006cfc0b9e 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -357,6 +357,8 @@ static int smb138x_init_batt_psy(struct smb138x *chip)
*****************************/
static enum power_supply_property smb138x_parallel_props[] = {
+ POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -368,8 +370,21 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
{
struct smb_charger *chg = power_supply_get_drvdata(psy);
int rc = 0;
+ u8 temp;
switch (prop) {
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = (bool)(temp & CHARGING_ENABLE_BIT);
+ break;
+ case POWER_SUPPLY_PROP_PIN_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = !(temp & DISABLE_CHARGING_BIT);
+ break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
rc = smblib_get_usb_suspend(chg, &val->intval);
break;
diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c
index e5055708a871..232bcf8fcf31 100644
--- a/drivers/regulator/cpr3-mmss-regulator.c
+++ b/drivers/regulator/cpr3-mmss-regulator.c
@@ -50,6 +50,9 @@
* @limitation: CPR limitation select fuse parameter value
* @aging_init_quot_diff: Initial quotient difference between CPR aging
* min and max sensors measured at time of manufacturing
+ * @force_highest_corner: Flag indicating that all corners must operate
+ * at the voltage of the highest corner. This is
+ * applicable to MSMCOBALT only.
*
* This struct holds the values for all of the fuses read from memory.
*/
@@ -60,6 +63,7 @@ struct cpr3_msm8996_mmss_fuses {
u64 cpr_fusing_rev;
u64 limitation;
u64 aging_init_quot_diff;
+ u64 force_highest_corner;
};
/* Fuse combos 0 - 7 map to CPR fusing revision 0 - 7 */
@@ -158,6 +162,12 @@ msmcobalt_mmss_offset_voltage_param[MSM8996_MMSS_FUSE_CORNERS][2] = {
{{65, 44, 47}, {} },
};
+static const struct cpr3_fuse_param
+msmcobalt_cpr_force_highest_corner_param[] = {
+ {100, 45, 45},
+ {},
+};
+
#define MSM8996PRO_SOC_ID 4
#define MSMCOBALT_SOC_ID 5
@@ -243,6 +253,12 @@ enum msmcobalt_cpr_partial_binning {
MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER = 0xE,
};
+/*
+ * The partial binning open-loop voltage fuse values only apply to the lowest
+ * two fuse corners (0 and 1, i.e. MinSVS and SVS).
+ */
+#define MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER 1
+
/**
* cpr3_msm8996_mmss_read_fuse_data() - load MMSS specific fuse parameter values
* @vreg: Pointer to the CPR3 regulator
@@ -338,6 +354,19 @@ static int cpr3_msm8996_mmss_read_fuse_data(struct cpr3_regulator *vreg)
}
if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID) {
+ rc = cpr3_read_fuse_param(base,
+ msmcobalt_cpr_force_highest_corner_param,
+ &fuse->force_highest_corner);
+ if (rc) {
+ cpr3_err(vreg, "Unable to read CPR force highest corner fuse, rc=%d\n",
+ rc);
+ return rc;
+ }
+ if (fuse->force_highest_corner)
+ cpr3_info(vreg, "Fusing requires all operation at the highest corner\n");
+ }
+
+ if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID) {
combo_max = CPR3_MSMCOBALT_MMSS_FUSE_COMBO_COUNT;
vreg->fuse_combo = fuse->cpr_fusing_rev;
} else if (vreg->thread->ctrl->soc_revision == MSM8996PRO_SOC_ID) {
@@ -738,7 +767,8 @@ static int cpr3_msm8996_mmss_calculate_open_loop_voltages(
*/
if (is_msmcobalt &&
(volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_NEXT_CORNER ||
- volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER))
+ volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER) &&
+ i <= MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER)
volt_init = MSM8996_MMSS_MIN_VOLTAGE_FUSE_VAL;
fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(ref_volt[i],
@@ -849,19 +879,43 @@ static int cpr3_msmcobalt_partial_binning_override(struct cpr3_regulator *vreg)
u32 proc_freq;
struct cpr3_corner *corner;
struct cpr3_corner *safe_corner;
- int i, j, low, high, safe_fuse_corner;
+ int i, j, low, high, safe_fuse_corner, max_fuse_corner;
if (vreg->thread->ctrl->soc_revision != MSMCOBALT_SOC_ID)
return 0;
- /* Loop over all fuse corners except for the highest one. */
- for (i = 0; i < vreg->fuse_corner_count - 1; i++) {
+ /* Handle the force highest corner fuse. */
+ if (fuse->force_highest_corner) {
+ cpr3_info(vreg, "overriding CPR parameters for corners 0 to %d with quotients and voltages of corner %d\n",
+ vreg->corner_count - 2, vreg->corner_count - 1);
+ corner = &vreg->corner[vreg->corner_count - 1];
+ for (i = 0; i < vreg->corner_count - 1; i++) {
+ proc_freq = vreg->corner[i].proc_freq;
+ vreg->corner[i] = *corner;
+ vreg->corner[i].proc_freq = proc_freq;
+ }
+
+ /*
+ * Return since the potential partial binning fuse values are
+ * superceded by the force highest corner fuse value.
+ */
+ return 0;
+ }
+
+ /*
+ * Allow up to the max corner which can be fused with partial
+ * binning values.
+ */
+ max_fuse_corner = min(MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER,
+ vreg->fuse_corner_count - 2);
+
+ for (i = 0; i <= max_fuse_corner; i++) {
/* Determine which higher corners to override with (if any). */
if (fuse->init_voltage[i] != next
&& fuse->init_voltage[i] != safe)
continue;
- for (j = i + 1; j < vreg->fuse_corner_count - 1; j++)
+ for (j = i + 1; j <= max_fuse_corner; j++)
if (fuse->init_voltage[j] != next
&& fuse->init_voltage[j] != safe)
break;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 3f8aa534c220..c45cbfa8a786 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -104,6 +104,16 @@ config MSM_GLINK_SMEM_NATIVE_XPRT
transport to only connecting with entities internal to the
System-on-Chip.
+config MSM_GLINK_SPI_XPRT
+ depends on MSM_GLINK
+ tristate "Generic Link (G-Link) SPI Transport"
+ help
+ G-Link SPI Transport is a Transport plug-in developed over SPI
+ bus. This transport plug-in performs marshaling of G-Link
+ commands & data to the appropriate SPI bus wire format and
+ allows for G-Link communication with remote subsystems that are
+ external to the System-on-Chip.
+
config MSM_SPCOM
depends on MSM_GLINK
bool "Secure Processor Communication over GLINK"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f8450a4868ad..269b72c68b68 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MSM_GLINK) += glink.o glink_debugfs.o glink_ssr.o
obj-$(CONFIG_MSM_GLINK_LOOPBACK_SERVER) += glink_loopback_server.o
obj-$(CONFIG_MSM_GLINK_SMD_XPRT) += glink_smd_xprt.o
obj-$(CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT)+= glink_smem_native_xprt.o
+obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o
obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o
obj-$(CONFIG_MSM_SYSMON_GLINK_COMM) += sysmon-glink.o sysmon-qmi.o
obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o
diff --git a/drivers/soc/qcom/core_hang_detect.c b/drivers/soc/qcom/core_hang_detect.c
index 42f31e320b61..e9b7f612dccc 100644
--- a/drivers/soc/qcom/core_hang_detect.c
+++ b/drivers/soc/qcom/core_hang_detect.c
@@ -33,6 +33,7 @@
#define _WRITE(x, y, z) (((~(_VAL(z))) & y) | _VALUE(x, z))
#define MODULE_NAME "msm_hang_detect"
+#define MAX_SYSFS_LEN 12
struct hang_detect {
phys_addr_t threshold[NR_CPUS];
@@ -108,8 +109,7 @@ static ssize_t show_threshold(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(device->threshold_val),
- "%u\n", device->threshold_val);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n", device->threshold_val);
}
static size_t store_threshold(struct kobject *kobj, struct attribute *attr,
@@ -147,8 +147,8 @@ static ssize_t show_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->pmu_event_sel),
- "%u\n", hang_device->pmu_event_sel);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n",
+ hang_device->pmu_event_sel);
}
static size_t store_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
@@ -188,8 +188,7 @@ static ssize_t show_enable(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->enabled),
- "%u\n", hang_device->enabled);
+ return snprintf(buf, MAX_SYSFS_LEN, "%u\n", hang_device->enabled);
}
static size_t store_enable(struct kobject *kobj, struct attribute *attr,
diff --git a/drivers/soc/qcom/gladiator_hang_detect.c b/drivers/soc/qcom/gladiator_hang_detect.c
index fd8062ca523a..e2bbe26decc8 100644
--- a/drivers/soc/qcom/gladiator_hang_detect.c
+++ b/drivers/soc/qcom/gladiator_hang_detect.c
@@ -34,6 +34,7 @@
#define NR_GLA_REG 6
#define MODULE_NAME "gladiator_hang_detect"
#define MAX_THRES 0xFFFFFFFF
+#define MAX_LEN_SYSFS 12
struct hang_detect {
phys_addr_t threshold[NR_GLA_REG];
@@ -199,8 +200,7 @@ static inline ssize_t generic_enable_show(struct kobject *kobj,
uint32_t reg_value;
get_enable(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_enable),
- "%d\n", reg_value);
+ return snprintf(buf, MAX_LEN_SYSFS, "%u\n", reg_value);
}
static inline ssize_t generic_threshold_show(struct kobject *kobj,
@@ -210,9 +210,7 @@ static inline ssize_t generic_threshold_show(struct kobject *kobj,
uint32_t reg_value;
get_threshold(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_threshold),
- "%u\n", reg_value);
-
+ return snprintf(buf, MAX_LEN_SYSFS, "0x%x\n", reg_value);
}
static inline size_t generic_threshold_store(struct kobject *kobj,
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 464fe17158cf..57e58a57fab7 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -372,10 +372,10 @@ static struct channel_ctx *ch_name_to_ch_ctx_create(
const char *name);
static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t riid);
+ uint32_t riid, void *cookie);
static int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t *riid_ptr, size_t *intent_size);
+ uint32_t *riid_ptr, size_t *intent_size, void **cookie);
static struct glink_core_rx_intent *ch_push_local_rx_intent(
struct channel_ctx *ctx, const void *pkt_priv, size_t size);
@@ -1139,11 +1139,12 @@ bool ch_check_duplicate_riid(struct channel_ctx *ctx, int riid)
* @ctx: Local channel context
* @size: Size of Intent
* @riid_ptr: Pointer to return value of remote intent ID
+ * @cookie: Transport-specific cookie to return
*
* This functions searches for an RX intent that is >= to the requested size.
*/
int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t *riid_ptr, size_t *intent_size)
+ uint32_t *riid_ptr, size_t *intent_size, void **cookie)
{
struct glink_core_rx_intent *intent;
struct glink_core_rx_intent *intent_tmp;
@@ -1177,6 +1178,7 @@ int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
intent->intent_size);
*riid_ptr = intent->id;
*intent_size = intent->intent_size;
+ *cookie = intent->cookie;
kfree(intent);
spin_unlock_irqrestore(
&ctx->rmt_rx_intent_lst_lock_lhc2, flags);
@@ -1192,11 +1194,12 @@ int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
* @ctx: Local channel context
* @size: Size of Intent
* @riid: Remote intent ID
+ * @cookie: Transport-specific cookie to cache
*
* This functions adds a remote RX intent to the remote RX intent list.
*/
void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t riid)
+ uint32_t riid, void *cookie)
{
struct glink_core_rx_intent *intent;
unsigned long flags;
@@ -1225,6 +1228,7 @@ void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
}
intent->id = riid;
intent->intent_size = size;
+ intent->cookie = cookie;
spin_lock_irqsave(&ctx->rmt_rx_intent_lst_lock_lhc2, flags);
list_add_tail(&intent->list, &ctx->rmt_rx_intent_list);
@@ -2794,6 +2798,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
bool is_atomic =
tx_flags & (GLINK_TX_SINGLE_THREADED | GLINK_TX_ATOMIC);
unsigned long flags;
+ void *cookie = NULL;
if (!size)
return -EINVAL;
@@ -2826,7 +2831,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
}
/* find matching rx intent (first-fit algorithm for now) */
- if (ch_pop_remote_rx_intent(ctx, size, &riid, &intent_size)) {
+ if (ch_pop_remote_rx_intent(ctx, size, &riid, &intent_size, &cookie)) {
if (!(tx_flags & GLINK_TX_REQ_INTENT)) {
/* no rx intent available */
GLINK_ERR_CH(ctx,
@@ -2856,7 +2861,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
}
while (ch_pop_remote_rx_intent(ctx, size, &riid,
- &intent_size)) {
+ &intent_size, &cookie)) {
rwref_get(&ctx->ch_state_lhb2);
rwref_read_put(&ctx->ch_state_lhb2);
if (is_atomic) {
@@ -2928,7 +2933,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
is_atomic ? GFP_ATOMIC : GFP_KERNEL);
if (!tx_info) {
GLINK_ERR_CH(ctx, "%s: No memory for allocation\n", __func__);
- ch_push_remote_rx_intent(ctx, intent_size, riid);
+ ch_push_remote_rx_intent(ctx, intent_size, riid, cookie);
rwref_read_put(&ctx->ch_state_lhb2);
return -ENOMEM;
}
@@ -2946,6 +2951,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
tx_info->vprovider = vbuf_provider;
tx_info->pprovider = pbuf_provider;
tx_info->intent_size = intent_size;
+ tx_info->cookie = cookie;
/* schedule packet for transmit */
if ((tx_flags & GLINK_TX_SINGLE_THREADED) &&
@@ -3577,6 +3583,10 @@ int glink_xprt_name_to_id(const char *name, uint16_t *id)
*id = SMEM_XPRT_ID;
return 0;
}
+ if (!strcmp(name, "spi")) {
+ *id = SPIV2_XPRT_ID;
+ return 0;
+ }
if (!strcmp(name, "smd_trans")) {
*id = SMD_TRANS_XPRT_ID;
return 0;
@@ -4844,7 +4854,35 @@ static void glink_core_remote_rx_intent_put(struct glink_transport_if *if_ptr,
return;
}
- ch_push_remote_rx_intent(ctx, size, riid);
+ ch_push_remote_rx_intent(ctx, size, riid, NULL);
+ rwref_put(&ctx->ch_state_lhb2);
+}
+
+/**
+ * glink_core_remote_rx_intent_put_cookie() - Receive remove intent
+ *
+ * @if_ptr: Pointer to transport instance
+ * @rcid: Remote Channel ID
+ * @riid: Remote Intent ID
+ * @size: Size of the remote intent ID
+ * @cookie: Transport-specific cookie to cache
+ */
+static void glink_core_remote_rx_intent_put_cookie(
+ struct glink_transport_if *if_ptr,
+ uint32_t rcid, uint32_t riid, size_t size, void *cookie)
+{
+ struct channel_ctx *ctx;
+
+ ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
+ if (!ctx) {
+ /* unknown rcid received - this shouldn't happen */
+ GLINK_ERR_XPRT(if_ptr->glink_core_priv,
+ "%s: invalid rcid received %u\n", __func__,
+ (unsigned)rcid);
+ return;
+ }
+
+ ch_push_remote_rx_intent(ctx, size, riid, cookie);
rwref_put(&ctx->ch_state_lhb2);
}
@@ -5050,6 +5088,7 @@ void glink_core_rx_cmd_tx_done(struct glink_transport_if *if_ptr,
struct glink_core_tx_pkt *tx_pkt;
unsigned long flags;
size_t intent_size;
+ void *cookie;
ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
if (!ctx) {
@@ -5082,11 +5121,12 @@ void glink_core_rx_cmd_tx_done(struct glink_transport_if *if_ptr,
ctx->notify_tx_done(ctx, ctx->user_priv, tx_pkt->pkt_priv,
tx_pkt->data ? tx_pkt->data : tx_pkt->iovec);
intent_size = tx_pkt->intent_size;
+ cookie = tx_pkt->cookie;
ch_remove_tx_pending_remote_done(ctx, tx_pkt);
spin_unlock_irqrestore(&ctx->tx_lists_lock_lhc3, flags);
if (reuse)
- ch_push_remote_rx_intent(ctx, intent_size, riid);
+ ch_push_remote_rx_intent(ctx, intent_size, riid, cookie);
rwref_put(&ctx->ch_state_lhb2);
}
@@ -5525,6 +5565,8 @@ static struct glink_core_if core_impl = {
.rx_get_pkt_ctx = glink_core_rx_get_pkt_ctx,
.rx_put_pkt_ctx = glink_core_rx_put_pkt_ctx,
.rx_cmd_remote_rx_intent_put = glink_core_remote_rx_intent_put,
+ .rx_cmd_remote_rx_intent_put_cookie =
+ glink_core_remote_rx_intent_put_cookie,
.rx_cmd_remote_rx_intent_req = glink_core_rx_cmd_remote_rx_intent_req,
.rx_cmd_rx_intent_req_ack = glink_core_rx_cmd_rx_intent_req_ack,
.rx_cmd_tx_done = glink_core_rx_cmd_tx_done,
diff --git a/drivers/soc/qcom/glink_core_if.h b/drivers/soc/qcom/glink_core_if.h
index 93c59d9c4aa1..14113305a50e 100644
--- a/drivers/soc/qcom/glink_core_if.h
+++ b/drivers/soc/qcom/glink_core_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -64,6 +64,7 @@ struct glink_core_version {
* iovec: Pointer to vector buffer if the transport passes a vector buffer
* vprovider: Virtual address-space buffer provider for a vector buffer
* pprovider: Physical address-space buffer provider for a vector buffer
+ * cookie: Private transport specific cookie
* pkt_priv: G-Link core owned packet-private data
* list: G-Link core owned list node
* bounce_buf: Pointer to the temporary/internal bounce buffer
@@ -78,6 +79,7 @@ struct glink_core_rx_intent {
void *iovec;
void * (*vprovider)(void *iovec, size_t offset, size_t *size);
void * (*pprovider)(void *iovec, size_t offset, size_t *size);
+ void *cookie;
/* G-Link-Core-owned elements - please ignore */
struct list_head list;
@@ -151,6 +153,9 @@ struct glink_core_if {
struct glink_core_rx_intent *intent_ptr, bool complete);
void (*rx_cmd_remote_rx_intent_put)(struct glink_transport_if *if_ptr,
uint32_t rcid, uint32_t riid, size_t size);
+ void (*rx_cmd_remote_rx_intent_put_cookie)(
+ struct glink_transport_if *if_ptr, uint32_t rcid,
+ uint32_t riid, size_t size, void *cookie);
void (*rx_cmd_tx_done)(struct glink_transport_if *if_ptr, uint32_t rcid,
uint32_t riid, bool reuse);
void (*rx_cmd_remote_rx_intent_req)(struct glink_transport_if *if_ptr,
diff --git a/drivers/soc/qcom/glink_spi_xprt.c b/drivers/soc/qcom/glink_spi_xprt.c
new file mode 100644
index 000000000000..6c91ac54821d
--- /dev/null
+++ b/drivers/soc/qcom/glink_spi_xprt.c
@@ -0,0 +1,2192 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spinlock.h>
+#include <linux/srcu.h>
+#include <linux/wait.h>
+#include <linux/component.h>
+#include <soc/qcom/tracer_pkt.h>
+#include <sound/wcd-dsp-mgr.h>
+#include <sound/wcd-spi.h>
+#include "glink_core_if.h"
+#include "glink_private.h"
+#include "glink_xprt_if.h"
+
+#define XPRT_NAME "spi"
+#define FIFO_ALIGNMENT 16
+#define FIFO_FULL_RESERVE 8
+#define TX_BLOCKED_CMD_RESERVE 16
+#define TRACER_PKT_FEATURE BIT(2)
+#define DEFAULT_FIFO_SIZE 1024
+#define SHORT_PKT_SIZE 16
+#define XPRT_ALIGNMENT 4
+
+#define MAX_INACTIVE_CYCLES 50
+#define POLL_INTERVAL_US 500
+
+#define ACTIVE_TX BIT(0)
+#define ACTIVE_RX BIT(1)
+
+#define ID_MASK 0xFFFFFF
+/**
+ * enum command_types - definition of the types of commands sent/received
+ * @VERSION_CMD: Version and feature set supported
+ * @VERSION_ACK_CMD: Response for @VERSION_CMD
+ * @OPEN_CMD: Open a channel
+ * @CLOSE_CMD: Close a channel
+ * @OPEN_ACK_CMD: Response to @OPEN_CMD
+ * @CLOSE_ACK_CMD: Response for @CLOSE_CMD
+ * @RX_INTENT_CMD: RX intent for a channel is queued
+ * @RX_DONE_CMD: Use of RX intent for a channel is complete
+ * @RX_DONE_W_REUSE_CMD: Same as @RX_DONE but also reuse the used intent
+ * @RX_INTENT_REQ_CMD: Request to have RX intent queued
+ * @RX_INTENT_REQ_ACK_CMD: Response for @RX_INTENT_REQ_CMD
+ * @TX_DATA_CMD: Start of a data transfer
+ * @TX_DATA_CONT_CMD: Continuation or end of a data transfer
+ * @READ_NOTIF_CMD: Request for a notification when this cmd is read
+ * @SIGNALS_CMD: Sideband signals
+ * @TRACER_PKT_CMD: Start of a Tracer Packet Command
+ * @TRACER_PKT_CONT_CMD: Continuation or end of a Tracer Packet Command
+ * @TX_SHORT_DATA_CMD: Transmit short packets
+ */
+enum command_types {
+ VERSION_CMD,
+ VERSION_ACK_CMD,
+ OPEN_CMD,
+ CLOSE_CMD,
+ OPEN_ACK_CMD,
+ CLOSE_ACK_CMD,
+ RX_INTENT_CMD,
+ RX_DONE_CMD,
+ RX_DONE_W_REUSE_CMD,
+ RX_INTENT_REQ_CMD,
+ RX_INTENT_REQ_ACK_CMD,
+ TX_DATA_CMD,
+ TX_DATA_CONT_CMD,
+ READ_NOTIF_CMD,
+ SIGNALS_CMD,
+ TRACER_PKT_CMD,
+ TRACER_PKT_CONT_CMD,
+ TX_SHORT_DATA_CMD,
+};
+
+/**
+ * struct glink_cmpnt - Component to cache WDSP component and its operations
+ * @master_dev: Device structure corresponding to WDSP device.
+ * @master_ops: Operations supported by the WDSP device.
+ */
+struct glink_cmpnt {
+ struct device *master_dev;
+ struct wdsp_mgr_ops *master_ops;
+};
+
+/**
+ * struct edge_info - local information for managing a single complete edge
+ * @xprt_if: The transport interface registered with the
+ * glink core associated with this edge.
+ * @xprt_cfg: The transport configuration for the glink core
+ * assocaited with this edge.
+ * @subsys_name: Name of the remote subsystem in the edge.
+ * @spi_dev: Pointer to the connectingSPI Device.
+ * @fifo_size: Size of the FIFO at the remote end.
+ * @tx_fifo_start: Base Address of the TX FIFO.
+ * @tx_fifo_end: End Address of the TX FIFO.
+ * @rx_fifo_start: Base Address of the RX FIFO.
+ * @rx_fifo_end: End Address of the RX FIFO.
+ * @tx_fifo_read_reg_addr: Address of the TX FIFO Read Index Register.
+ * @tx_fifo_write_reg_addr: Address of the TX FIFO Write Index Register.
+ * @rx_fifo_read_reg_addr: Address of the RX FIFO Read Index Register.
+ * @rx_fifo_write_reg_addr: Address of the RX FIFO Write Index Register.
+ * @kwork: Work to be executed when receiving data.
+ * @kworker: Handle to the entity processing @kwork.
+ * @task: Handle to the task context that runs @kworker.
+ * @use_ref: Active users of this transport grab a
+ * reference. Used for SSR synchronization.
+ * @in_ssr: Signals if this transport is in ssr.
+ * @write_lock: Lock to serialize write/tx operation.
+ * @tx_blocked_queue: Queue of entities waiting for the remote side to
+ * signal the resumption of TX.
+ * @tx_resume_needed: A tx resume signal needs to be sent to the glink
+ * core.
+ * @tx_blocked_signal_sent: Flag to indicate the flush signal has already
+ * been sent, and a response is pending from the
+ * remote side. Protected by @write_lock.
+ * @num_pw_states: Size of @ramp_time_us.
+ * @ramp_time_us: Array of ramp times in microseconds where array
+ * index position represents a power state.
+ * @activity_flag: Flag indicating active TX and RX.
+ * @activity_lock: Lock to synchronize access to activity flag.
+ * @cmpnt: Component to interface with the remote device.
+ */
+struct edge_info {
+ struct list_head list;
+ struct glink_transport_if xprt_if;
+ struct glink_core_transport_cfg xprt_cfg;
+ char subsys_name[GLINK_NAME_SIZE];
+ struct spi_device *spi_dev;
+
+ uint32_t fifo_size;
+ uint32_t tx_fifo_start;
+ uint32_t tx_fifo_end;
+ uint32_t rx_fifo_start;
+ uint32_t rx_fifo_end;
+ unsigned int tx_fifo_read_reg_addr;
+ unsigned int tx_fifo_write_reg_addr;
+ unsigned int rx_fifo_read_reg_addr;
+ unsigned int rx_fifo_write_reg_addr;
+
+ struct kthread_work kwork;
+ struct kthread_worker kworker;
+ struct task_struct *task;
+ struct srcu_struct use_ref;
+ bool in_ssr;
+ struct mutex write_lock;
+ wait_queue_head_t tx_blocked_queue;
+ bool tx_resume_needed;
+ bool tx_blocked_signal_sent;
+
+ uint32_t num_pw_states;
+ unsigned long *ramp_time_us;
+
+ uint32_t activity_flag;
+ spinlock_t activity_lock;
+
+ struct glink_cmpnt cmpnt;
+};
+
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+ const struct glink_core_version *version,
+ uint32_t features);
+static DEFINE_SPINLOCK(edge_infos_lock);
+static LIST_HEAD(edge_infos);
+static struct glink_core_version versions[] = {
+ {1, TRACER_PKT_FEATURE, negotiate_features_v1},
+};
+
+/**
+ * negotiate_features_v1() - determine what features of a version can be used
+ * @if_ptr: The transport for which features are negotiated for.
+ * @version: The version negotiated.
+ * @features: The set of requested features.
+ *
+ * Return: What set of the requested features can be supported.
+ */
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+ const struct glink_core_version *version,
+ uint32_t features)
+{
+ return features & version->features;
+}
+
+/**
+ * wdsp_suspend() - Vote for the WDSP device suspend
+ * @cmpnt: Component to identify the WDSP device.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int wdsp_suspend(struct glink_cmpnt *cmpnt)
+{
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops && cmpnt->master_ops->suspend)
+ return cmpnt->master_ops->suspend(cmpnt->master_dev);
+ else
+ return -EINVAL;
+}
+
+/**
+ * wdsp_resume() - Vote for the WDSP device resume
+ * @cmpnt: Component to identify the WDSP device.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int wdsp_resume(struct glink_cmpnt *cmpnt)
+{
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops && cmpnt->master_ops->resume)
+ return cmpnt->master_ops->resume(cmpnt->master_dev);
+ else
+ return -EINVAL;
+}
+
+/**
+ * glink_spi_xprt_set_poll_mode() - Set the transport to polling mode
+ * @einfo: Edge information corresponding to the transport.
+ *
+ * This helper function indicates the start of RX polling. This will
+ * prevent the system from suspending and keeps polling for RX for a
+ * pre-defined duration.
+ */
+static void glink_spi_xprt_set_poll_mode(struct edge_info *einfo)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag |= ACTIVE_RX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+}
+
+/**
+ * glink_spi_xprt_set_irq_mode() - Set the transport to IRQ mode
+ * @einfo: Edge information corresponding to the transport.
+ *
+ * This helper indicates the end of RX polling. This will allow the
+ * system to suspend and new RX data can be handled only through an IRQ.
+ */
+static void glink_spi_xprt_set_irq_mode(struct edge_info *einfo)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag &= ~ACTIVE_RX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+}
+
+/**
+ * glink_spi_xprt_rx_data() - Receive data over SPI bus
+ * @einfo: Edge from which the data has to be received.
+ * @src: Source Address of the RX data.
+ * @dst: Address of the destination RX buffer.
+ * @size: Size of the RX data.
+ *
+ * This function is used to receive data or command as a byte stream from
+ * the remote subsystem over the SPI bus.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_rx_data(struct edge_info *einfo, void *src,
+ void *dst, uint32_t size)
+{
+ struct wcd_spi_msg spi_msg;
+
+ memset(&spi_msg, 0, sizeof(spi_msg));
+ spi_msg.data = dst;
+ spi_msg.remote_addr = (uint32_t)(size_t)src;
+ spi_msg.len = (size_t)size;
+ return wcd_spi_data_read(einfo->spi_dev, &spi_msg);
+}
+
+/**
+ * glink_spi_xprt_tx_data() - Transmit data over SPI bus
+ * @einfo: Edge from which the data has to be received.
+ * @src: Address of the TX buffer.
+ * @dst: Destination Address of the TX Date.
+ * @size: Size of the TX data.
+ *
+ * This function is used to transmit data or command as a byte stream to
+ * the remote subsystem over the SPI bus.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_tx_data(struct edge_info *einfo, void *src,
+ void *dst, uint32_t size)
+{
+ struct wcd_spi_msg spi_msg;
+
+ memset(&spi_msg, 0, sizeof(spi_msg));
+ spi_msg.data = src;
+ spi_msg.remote_addr = (uint32_t)(size_t)dst;
+ spi_msg.len = (size_t)size;
+ return wcd_spi_data_write(einfo->spi_dev, &spi_msg);
+}
+
+/**
+ * glink_spi_xprt_reg_read() - Read the TX/RX FIFO Read/Write Index registers
+ * @einfo: Edge from which the registers have to be read.
+ * @reg_addr: Address of the register to be read.
+ * @data: Buffer into which the register data has to be read.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_reg_read(struct edge_info *einfo, u32 reg_addr,
+ uint32_t *data)
+{
+ int rc;
+
+ rc = glink_spi_xprt_rx_data(einfo, (void *)(unsigned long)reg_addr,
+ data, sizeof(*data));
+ if (!rc)
+ *data = *data & ID_MASK;
+ return rc;
+}
+
+/**
+ * glink_spi_xprt_reg_write() - Write the TX/RX FIFO Read/Write Index registers
+ * @einfo: Edge to which the registers have to be written.
+ * @reg_addr: Address of the registers to be written.
+ * @data: Data to be written to the registers.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_reg_write(struct edge_info *einfo, u32 reg_addr,
+ uint32_t data)
+{
+ return glink_spi_xprt_tx_data(einfo, &data,
+ (void *)(unsigned long)reg_addr, sizeof(data));
+}
+
+/**
+ * glink_spi_xprt_write_avail() - Available Write Space in the remote side
+ * @einfo: Edge information corresponding to the remote side.
+ *
+ * This function reads the TX FIFO Read & Write Index registers from the
+ * remote subsystem and calculate the available write space.
+ *
+ * Return: 0 on error, available write space on success.
+ */
+static int glink_spi_xprt_write_avail(struct edge_info *einfo)
+{
+ uint32_t read_id;
+ uint32_t write_id;
+ int write_avail;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_read_reg_addr);
+ return 0;
+ }
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return 0;
+ }
+
+ if (!read_id || !write_id)
+ return 0;
+
+ if (unlikely(!einfo->tx_fifo_start))
+ einfo->tx_fifo_start = write_id;
+
+ if (read_id > write_id)
+ write_avail = read_id - write_id;
+ else
+ write_avail = einfo->fifo_size - (write_id - read_id);
+
+ if (write_avail < FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE)
+ write_avail = 0;
+ else
+ write_avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
+
+ return write_avail;
+}
+
+/**
+ * glink_spi_xprt_read_avail() - Available Read Data from the remote side
+ * @einfo: Edge information corresponding to the remote side.
+ *
+ * This function reads the RX FIFO Read & Write Index registers from the
+ * remote subsystem and calculate the available read data size.
+ *
+ * Return: 0 on error, available read data on success.
+ */
+static int glink_spi_xprt_read_avail(struct edge_info *einfo)
+{
+ uint32_t read_id;
+ uint32_t write_id;
+ int read_avail;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return 0;
+ }
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_write_reg_addr);
+ return 0;
+ }
+
+ if (!read_id || !write_id)
+ return 0;
+
+ if (unlikely(!einfo->rx_fifo_start))
+ einfo->rx_fifo_start = read_id;
+
+ if (read_id <= write_id)
+ read_avail = write_id - read_id;
+ else
+ read_avail = einfo->fifo_size - (read_id - write_id);
+ return read_avail;
+}
+
+/**
+ * glink_spi_xprt_rx_cmd() - Receive G-Link commands
+ * @einfo: Edge information corresponding to the remote side.
+ * @dst: Destination buffer where the commands have to be read into.
+ * @size: Size of the data to be read.
+ *
+ * This function is used to receive the commands from the RX FIFO. This
+ * function updates the RX FIFO Read Index after reading the data.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
+ uint32_t size)
+{
+ uint32_t read_id;
+ uint32_t size_to_read = size;
+ uint32_t offset = 0;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return ret;
+ }
+
+ do {
+ if ((read_id + size_to_read) >=
+ (einfo->rx_fifo_start + einfo->fifo_size))
+ size_to_read = einfo->rx_fifo_start + einfo->fifo_size
+ - read_id;
+ ret = glink_spi_xprt_rx_data(einfo, (void *)(size_t)read_id,
+ dst + offset, size_to_read);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading data\n", __func__, ret);
+ return ret;
+ }
+ read_id += size_to_read;
+ offset += size_to_read;
+ if (read_id >= (einfo->rx_fifo_start + einfo->fifo_size))
+ read_id = einfo->rx_fifo_start;
+ size_to_read = size - offset;
+ } while (size_to_read);
+
+ ret = glink_spi_xprt_reg_write(einfo, einfo->rx_fifo_read_reg_addr,
+ read_id);
+ if (ret < 0)
+ pr_err("%s: Error %d writing %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return ret;
+}
+
+/**
+ * glink_spi_xprt_tx_cmd_safe() - Transmit G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @src: Source buffer containing the G-Link command.
+ * @size: Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * must be called with einfo->write_lock locked.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_tx_cmd_safe(struct edge_info *einfo, void *src,
+ uint32_t size)
+{
+ uint32_t write_id;
+ uint32_t size_to_write = size;
+ uint32_t offset = 0;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return ret;
+ }
+
+ do {
+ if ((write_id + size_to_write) >=
+ (einfo->tx_fifo_start + einfo->fifo_size))
+ size_to_write = einfo->tx_fifo_start + einfo->fifo_size
+ - write_id;
+ ret = glink_spi_xprt_tx_data(einfo, src + offset,
+ (void *)(size_t)write_id, size_to_write);
+ if (ret < 0) {
+ pr_err("%s: Error %d writing data\n", __func__, ret);
+ return ret;
+ }
+ write_id += size_to_write;
+ offset += size_to_write;
+ if (write_id >= (einfo->tx_fifo_start + einfo->fifo_size))
+ write_id = einfo->tx_fifo_start;
+ size_to_write = size - offset;
+ } while (size_to_write);
+
+ ret = glink_spi_xprt_reg_write(einfo, einfo->tx_fifo_write_reg_addr,
+ write_id);
+ if (ret < 0)
+ pr_err("%s: Error %d writing %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return ret;
+}
+
+/**
+ * send_tx_blocked_signal() - Send flow control request message
+ * @einfo: Edge information corresponding to the remote subsystem.
+ *
+ * This function is used to send a message to the remote subsystem indicating
+ * that the local subsystem is waiting for the write space. The remote
+ * subsystem on receiving this message will send a resume tx message.
+ */
+static void send_tx_blocked_signal(struct edge_info *einfo)
+{
+ struct read_notif_request {
+ uint16_t cmd;
+ uint16_t reserved;
+ uint32_t reserved2;
+ uint64_t reserved3;
+ };
+ struct read_notif_request read_notif_req = {0};
+
+ read_notif_req.cmd = READ_NOTIF_CMD;
+
+ if (!einfo->tx_blocked_signal_sent) {
+ einfo->tx_blocked_signal_sent = true;
+ glink_spi_xprt_tx_cmd_safe(einfo, &read_notif_req,
+ sizeof(read_notif_req));
+ }
+}
+
+/**
+ * glink_spi_xprt_tx_cmd() - Transmit G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @src: Source buffer containing the G-Link command.
+ * @size: Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * might sleep if the space is not available to transmit the command.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_tx_cmd(struct edge_info *einfo, void *src,
+ uint32_t size)
+{
+ int ret;
+ DEFINE_WAIT(wait);
+
+ mutex_lock(&einfo->write_lock);
+ while (glink_spi_xprt_write_avail(einfo) < size) {
+ send_tx_blocked_signal(einfo);
+ prepare_to_wait(&einfo->tx_blocked_queue, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (glink_spi_xprt_write_avail(einfo) < size &&
+ !einfo->in_ssr) {
+ mutex_unlock(&einfo->write_lock);
+ schedule();
+ mutex_lock(&einfo->write_lock);
+ }
+ finish_wait(&einfo->tx_blocked_queue, &wait);
+ if (einfo->in_ssr) {
+ mutex_unlock(&einfo->write_lock);
+ return -EFAULT;
+ }
+ }
+ ret = glink_spi_xprt_tx_cmd_safe(einfo, src, size);
+ mutex_unlock(&einfo->write_lock);
+ return ret;
+}
+
+/**
+ * process_rx_data() - process received data from an edge
+ * @einfo: The edge the data is received on.
+ * @cmd_id: ID to specify the type of data.
+ * @rcid: The remote channel id associated with the data.
+ * @intend_id: The intent the data should be put in.
+ * @src: Address of the source buffer from which the data
+ * is read.
+ * @frag_size: Size of the data fragment to read.
+ * @size_remaining: Size of data left to be read in this packet.
+ */
+static void process_rx_data(struct edge_info *einfo, uint16_t cmd_id,
+ uint32_t rcid, uint32_t intent_id, void *src,
+ uint32_t frag_size, uint32_t size_remaining)
+{
+ struct glink_core_rx_intent *intent;
+ int rc = 0;
+
+ intent = einfo->xprt_if.glink_core_if_ptr->rx_get_pkt_ctx(
+ &einfo->xprt_if, rcid, intent_id);
+ if (intent == NULL) {
+ GLINK_ERR("%s: no intent for ch %d liid %d\n", __func__, rcid,
+ intent_id);
+ return;
+ } else if (intent->data == NULL) {
+ GLINK_ERR("%s: intent for ch %d liid %d has no data buff\n",
+ __func__, rcid, intent_id);
+ return;
+ } else if (intent->intent_size - intent->write_offset < frag_size ||
+ intent->write_offset + size_remaining > intent->intent_size) {
+ GLINK_ERR("%s: rx data size:%d and remaining:%d %s %d %s:%d\n",
+ __func__, frag_size, size_remaining,
+ "will overflow ch", rcid, "intent", intent_id);
+ return;
+ }
+
+ if (cmd_id == TX_SHORT_DATA_CMD)
+ memcpy(intent->data + intent->write_offset, src, frag_size);
+ else
+ rc = glink_spi_xprt_rx_data(einfo, src,
+ intent->data + intent->write_offset, frag_size);
+ if (rc < 0) {
+ GLINK_ERR("%s: Error %d receiving data %d:%d:%d:%d\n",
+ __func__, rc, rcid, intent_id, frag_size,
+ size_remaining);
+ size_remaining += frag_size;
+ } else {
+ intent->write_offset += frag_size;
+ intent->pkt_size += frag_size;
+
+ if (unlikely((cmd_id == TRACER_PKT_CMD ||
+ cmd_id == TRACER_PKT_CONT_CMD) && !size_remaining)) {
+ tracer_pkt_log_event(intent->data, GLINK_XPRT_RX);
+ intent->tracer_pkt = true;
+ }
+ }
+ einfo->xprt_if.glink_core_if_ptr->rx_put_pkt_ctx(&einfo->xprt_if,
+ rcid, intent, size_remaining ? false : true);
+}
+
+/**
+ * process_rx_cmd() - Process incoming G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @rx_data: Buffer which contains the G-Link commands to be processed.
+ * @rx_size: Size of the buffer containing the series of G-Link commands.
+ *
+ * This function is used to parse and process a series of G-Link commands
+ * received in a buffer.
+ */
+static void process_rx_cmd(struct edge_info *einfo,
+ void *rx_data, int rx_size)
+{
+ struct command {
+ uint16_t id;
+ uint16_t param1;
+ uint32_t param2;
+ uint32_t param3;
+ uint32_t param4;
+ };
+ struct intent_desc {
+ uint32_t size;
+ uint32_t id;
+ uint64_t addr;
+ };
+ struct rx_desc {
+ uint32_t size;
+ uint32_t size_left;
+ uint64_t addr;
+ };
+ struct rx_short_data_desc {
+ unsigned char data[SHORT_PKT_SIZE];
+ };
+ struct command *cmd;
+ struct intent_desc *intents;
+ struct rx_desc *rx_descp;
+ struct rx_short_data_desc *rx_sd_descp;
+ int offset = 0;
+ int rcu_id;
+ uint16_t rcid;
+ uint16_t name_len;
+ uint16_t prio;
+ char *name;
+ bool granted;
+ int i;
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ while (offset < rx_size) {
+ cmd = (struct command *)(rx_data + offset);
+ offset += sizeof(*cmd);
+ switch (cmd->id) {
+ case VERSION_CMD:
+ if (cmd->param3)
+ einfo->fifo_size = cmd->param3;
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_version(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case VERSION_ACK_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_version_ack(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case OPEN_CMD:
+ rcid = cmd->param1;
+ name_len = (uint16_t)(cmd->param2 & 0xFFFF);
+ prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
+ name = (char *)(rx_data + offset);
+ offset += ALIGN(name_len, FIFO_ALIGNMENT);
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+ &einfo->xprt_if, rcid, name, prio);
+ break;
+
+ case CLOSE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_ch_remote_close(
+ &einfo->xprt_if, cmd->param1);
+ break;
+
+ case OPEN_ACK_CMD:
+ prio = (uint16_t)(cmd->param2 & 0xFFFF);
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+ &einfo->xprt_if, cmd->param1, prio);
+ break;
+
+ case CLOSE_ACK_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+ &einfo->xprt_if, cmd->param1);
+ break;
+
+ case RX_INTENT_CMD:
+ for (i = 0; i < cmd->param2; i++) {
+ intents = (struct intent_desc *)
+ (rx_data + offset);
+ offset += sizeof(*intents);
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_remote_rx_intent_put_cookie(
+ &einfo->xprt_if, cmd->param1,
+ intents->id, intents->size,
+ (void *)(intents->addr));
+ }
+ break;
+
+ case RX_DONE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+ &einfo->xprt_if, cmd->param1, cmd->param2,
+ false);
+ break;
+
+ case RX_INTENT_REQ_CMD:
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_remote_rx_intent_req(
+ &einfo->xprt_if, cmd->param1,
+ cmd->param2);
+ break;
+
+ case RX_INTENT_REQ_ACK_CMD:
+ granted = cmd->param2 == 1 ? true : false;
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_rx_intent_req_ack(&einfo->xprt_if,
+ cmd->param1, granted);
+ break;
+
+ case TX_DATA_CMD:
+ case TX_DATA_CONT_CMD:
+ case TRACER_PKT_CMD:
+ case TRACER_PKT_CONT_CMD:
+ rx_descp = (struct rx_desc *)(rx_data + offset);
+ offset += sizeof(*rx_descp);
+ process_rx_data(einfo, cmd->id, cmd->param1,
+ cmd->param2, (void *)rx_descp->addr,
+ rx_descp->size, rx_descp->size_left);
+ break;
+
+ case TX_SHORT_DATA_CMD:
+ rx_sd_descp = (struct rx_short_data_desc *)
+ (rx_data + offset);
+ offset += sizeof(*rx_sd_descp);
+ process_rx_data(einfo, cmd->id, cmd->param1,
+ cmd->param2, (void *)rx_sd_descp->data,
+ cmd->param3, cmd->param4);
+ break;
+
+ case READ_NOTIF_CMD:
+ break;
+
+ case SIGNALS_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case RX_DONE_W_REUSE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+ &einfo->xprt_if, cmd->param1,
+ cmd->param2, true);
+ break;
+
+ default:
+ pr_err("Unrecognized command: %d\n", cmd->id);
+ break;
+ }
+ }
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * __rx_worker() - Receive commands on a specific edge
+ * @einfo: Edge to process commands on.
+ *
+ * This function checks the size of data to be received, allocates the
+ * buffer for that data and reads the data from the remote subsytem
+ * into that buffer. This function then calls the process_rx_cmd() to
+ * parse the received G-Link command sequence. This function will also
+ * poll for the data for a predefined duration for performance reasons.
+ */
+static void __rx_worker(struct edge_info *einfo)
+{
+ uint32_t inactive_cycles = 0;
+ int rx_avail, rc;
+ void *rx_data;
+ int rcu_id;
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (unlikely(!einfo->rx_fifo_start)) {
+ rx_avail = glink_spi_xprt_read_avail(einfo);
+ if (!rx_avail) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+ einfo->in_ssr = false;
+ einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+ }
+
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ glink_spi_xprt_set_poll_mode(einfo);
+ while (inactive_cycles < MAX_INACTIVE_CYCLES) {
+ if (einfo->tx_resume_needed &&
+ glink_spi_xprt_write_avail(einfo)) {
+ einfo->tx_resume_needed = false;
+ einfo->xprt_if.glink_core_if_ptr->tx_resume(
+ &einfo->xprt_if);
+ }
+ mutex_lock(&einfo->write_lock);
+ if (einfo->tx_blocked_signal_sent) {
+ wake_up_all(&einfo->tx_blocked_queue);
+ einfo->tx_blocked_signal_sent = false;
+ }
+ mutex_unlock(&einfo->write_lock);
+
+ rx_avail = glink_spi_xprt_read_avail(einfo);
+ if (!rx_avail) {
+ usleep_range(POLL_INTERVAL_US, POLL_INTERVAL_US + 50);
+ inactive_cycles++;
+ continue;
+ }
+ inactive_cycles = 0;
+
+ rx_data = kzalloc(rx_avail, GFP_KERNEL);
+ if (!rx_data)
+ break;
+
+ rc = glink_spi_xprt_rx_cmd(einfo, rx_data, rx_avail);
+ if (rc < 0) {
+ GLINK_ERR("%s: Error %d receiving data\n",
+ __func__, rc);
+ kfree(rx_data);
+ break;
+ }
+ process_rx_cmd(einfo, rx_data, rx_avail);
+ kfree(rx_data);
+ }
+ glink_spi_xprt_set_irq_mode(einfo);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * rx_worker() - Worker function to process received commands
+ * @work: kwork associated with the edge to process commands on.
+ */
+static void rx_worker(struct kthread_work *work)
+{
+ struct edge_info *einfo;
+
+ einfo = container_of(work, struct edge_info, kwork);
+ __rx_worker(einfo);
+};
+
+/**
+ * tx_cmd_version() - Convert a version cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @version: The version number to encode.
+ * @features: The features information to encode.
+ */
+static void tx_cmd_version(struct glink_transport_if *if_ptr, uint32_t version,
+ uint32_t features)
+{
+ struct command {
+ uint16_t id;
+ uint16_t version;
+ uint32_t features;
+ uint32_t fifo_size;
+ uint32_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = VERSION_CMD;
+ cmd.version = version;
+ cmd.features = features;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_version_ack() - Convert a version ack cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @version: The version number to encode.
+ * @features: The features information to encode.
+ */
+static void tx_cmd_version_ack(struct glink_transport_if *if_ptr,
+ uint32_t version,
+ uint32_t features)
+{
+ struct command {
+ uint16_t id;
+ uint16_t version;
+ uint32_t features;
+ uint32_t fifo_size;
+ uint32_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = VERSION_ACK_CMD;
+ cmd.version = version;
+ cmd.features = features;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * set_version() - Activate a negotiated version and feature set
+ * @if_ptr: The transport to configure.
+ * @version: The version to use.
+ * @features: The features to use.
+ *
+ * Return: The supported capabilities of the transport.
+ */
+static uint32_t set_version(struct glink_transport_if *if_ptr, uint32_t version,
+ uint32_t features)
+{
+ struct edge_info *einfo;
+ uint32_t ret;
+ int rcu_id;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+ }
+
+ ret = GCAP_SIGNALS;
+ if (features & TRACER_PKT_FEATURE)
+ ret |= GCAP_TRACER_PKT;
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return ret;
+}
+
+/**
+ * tx_cmd_ch_open() - Convert a channel open cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @name: The channel name to encode.
+ * @req_xprt: The transport the core would like to migrate this channel to.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_open(struct glink_transport_if *if_ptr, uint32_t lcid,
+ const char *name, uint16_t req_xprt)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint16_t length;
+ uint16_t req_xprt;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t buf_size;
+ void *buf;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = OPEN_CMD;
+ cmd.lcid = lcid;
+ cmd.length = (uint16_t)(strlen(name) + 1);
+ cmd.req_xprt = req_xprt;
+
+ buf_size = ALIGN(sizeof(cmd) + cmd.length, FIFO_ALIGNMENT);
+
+ buf = kzalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -ENOMEM;
+ }
+
+ memcpy(buf, &cmd, sizeof(cmd));
+ memcpy(buf + sizeof(cmd), name, cmd.length);
+
+ glink_spi_xprt_tx_cmd(einfo, buf, buf_size);
+
+ kfree(buf);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_ch_close() - Convert a channel close cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_close(struct glink_transport_if *if_ptr, uint32_t lcid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t reserved1;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = CLOSE_CMD;
+ cmd.lcid = lcid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_ch_remote_open_ack() - Convert a channel open ack cmd to wire format
+ * and transmit
+ * @if_ptr: The transport to transmit on.
+ * @rcid: The remote channel id to encode.
+ * @xprt_resp: The response to a transport migration request.
+ */
+static void tx_cmd_ch_remote_open_ack(struct glink_transport_if *if_ptr,
+ uint32_t rcid, uint16_t xprt_resp)
+{
+ struct command {
+ uint16_t id;
+ uint16_t rcid;
+ uint16_t reserved1;
+ uint16_t xprt_resp;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = OPEN_ACK_CMD;
+ cmd.rcid = rcid;
+ cmd.xprt_resp = xprt_resp;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_ch_remote_close_ack() - Convert a channel close ack cmd to wire format
+ * and transmit
+ * @if_ptr: The transport to transmit on.
+ * @rcid: The remote channel id to encode.
+ */
+static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
+ uint32_t rcid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t rcid;
+ uint32_t reserved1;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = CLOSE_ACK_CMD;
+ cmd.rcid = rcid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * ssr() - Process a subsystem restart notification of a transport
+ * @if_ptr: The transport to restart
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int ssr(struct glink_transport_if *if_ptr)
+{
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ einfo->in_ssr = true;
+ wake_up_all(&einfo->tx_blocked_queue);
+
+ synchronize_srcu(&einfo->use_ref);
+ einfo->tx_resume_needed = false;
+ einfo->tx_blocked_signal_sent = false;
+ einfo->tx_fifo_start = 0;
+ einfo->rx_fifo_start = 0;
+ einfo->fifo_size = DEFAULT_FIFO_SIZE;
+ einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);
+
+ return 0;
+}
+
+/**
+ * allocate_rx_intent() - Allocate/reserve space for RX Intent
+ * @if_ptr: The transport the intent is associated with.
+ * @size: size of intent.
+ * @intent: Pointer to the intent structure.
+ *
+ * Assign "data" with the buffer created, since the transport creates
+ * a linear buffer and "iovec" with the "intent" itself, so that
+ * the data can be passed to a client that receives only vector buffer.
+ * Note that returning NULL for the pointer is valid (it means that space has
+ * been reserved, but the actual pointer will be provided later).
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int allocate_rx_intent(struct glink_transport_if *if_ptr, size_t size,
+ struct glink_core_rx_intent *intent)
+{
+ void *t;
+
+ t = kzalloc(size, GFP_KERNEL);
+ if (!t)
+ return -ENOMEM;
+
+ intent->data = t;
+ intent->iovec = (void *)intent;
+ intent->vprovider = rx_linear_vbuf_provider;
+ intent->pprovider = NULL;
+ return 0;
+}
+
+/**
+ * deallocate_rx_intent() - Deallocate space created for RX Intent
+ * @if_ptr: The transport the intent is associated with.
+ * @intent: Pointer to the intent structure.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int deallocate_rx_intent(struct glink_transport_if *if_ptr,
+ struct glink_core_rx_intent *intent)
+{
+ if (!intent || !intent->data)
+ return -EINVAL;
+
+ kfree(intent->data);
+ intent->data = NULL;
+ intent->iovec = NULL;
+ intent->vprovider = NULL;
+ return 0;
+}
+
+/**
+ * tx_cmd_local_rx_intent() - Convert an rx intent cmd to wire format and
+ * transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @size: The intent size to encode.
+ * @liid: The local intent id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_local_rx_intent(struct glink_transport_if *if_ptr,
+ uint32_t lcid, size_t size, uint32_t liid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t count;
+ uint64_t reserved;
+ uint32_t size;
+ uint32_t liid;
+ uint64_t addr;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ if (size > UINT_MAX) {
+ pr_err("%s: size %zu is too large to encode\n", __func__, size);
+ return -EMSGSIZE;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_CMD;
+ cmd.lcid = lcid;
+ cmd.count = 1;
+ cmd.size = size;
+ cmd.liid = liid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_local_rx_done() - Convert an rx done cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @liid: The local intent id to encode.
+ * @reuse: Reuse the consumed intent.
+ */
+static void tx_cmd_local_rx_done(struct glink_transport_if *if_ptr,
+ uint32_t lcid, uint32_t liid, bool reuse)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t liid;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = reuse ? RX_DONE_W_REUSE_CMD : RX_DONE_CMD;
+ cmd.lcid = lcid;
+ cmd.liid = liid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_rx_intent_req() - Convert an rx intent request cmd to wire format and
+ * transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @size: The requested intent size to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_rx_intent_req(struct glink_transport_if *if_ptr,
+ uint32_t lcid, size_t size)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t size;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ if (size > UINT_MAX) {
+ pr_err("%s: size %zu is too large to encode\n", __func__, size);
+ return -EMSGSIZE;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_REQ_CMD,
+ cmd.lcid = lcid;
+ cmd.size = size;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_rx_intent_req_ack() - Convert an rx intent request ack cmd to wire
+ * format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @granted: The request response to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_remote_rx_intent_req_ack(struct glink_transport_if *if_ptr,
+ uint32_t lcid, bool granted)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t response;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_REQ_ACK_CMD,
+ cmd.lcid = lcid;
+ if (granted)
+ cmd.response = 1;
+ else
+ cmd.response = 0;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_set_sigs() - Convert a signals ack cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @sigs: The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_set_sigs(struct glink_transport_if *if_ptr, uint32_t lcid,
+ uint32_t sigs)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t sigs;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = SIGNALS_CMD,
+ cmd.lcid = lcid;
+ cmd.sigs = sigs;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_data() - convert a data/tracer_pkt to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @cmd_id: The command ID to transmit.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_data(struct glink_transport_if *if_ptr, uint16_t cmd_id,
+ uint32_t lcid, struct glink_core_tx_pkt *pctx)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t riid;
+ uint64_t reserved;
+ uint32_t size;
+ uint32_t size_left;
+ uint64_t addr;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t size;
+ void *data_start, *dst = NULL;
+ size_t tx_size = 0;
+ int rcu_id;
+
+ if (pctx->size < pctx->size_remaining) {
+ GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
+ __func__);
+ pctx->size_remaining = pctx->size;
+ }
+ if (!pctx->size_remaining)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ if (cmd_id == TX_DATA_CMD) {
+ if (pctx->size_remaining == pctx->size)
+ cmd.id = TX_DATA_CMD;
+ else
+ cmd.id = TX_DATA_CONT_CMD;
+ } else {
+ if (pctx->size_remaining == pctx->size)
+ cmd.id = TRACER_PKT_CMD;
+ else
+ cmd.id = TRACER_PKT_CONT_CMD;
+ }
+ cmd.lcid = lcid;
+ cmd.riid = pctx->riid;
+ data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
+ &tx_size);
+ if (unlikely(!data_start)) {
+ GLINK_ERR("%s: invalid data_start\n", __func__);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EINVAL;
+ }
+ if (tx_size & (XPRT_ALIGNMENT - 1))
+ tx_size = ALIGN(tx_size - SHORT_PKT_SIZE, XPRT_ALIGNMENT);
+ if (likely(pctx->cookie))
+ dst = pctx->cookie + (pctx->size - pctx->size_remaining);
+
+ mutex_lock(&einfo->write_lock);
+ size = glink_spi_xprt_write_avail(einfo);
+ /* Need enough space to write the command */
+ if (size <= sizeof(cmd)) {
+ einfo->tx_resume_needed = true;
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EAGAIN;
+ }
+ cmd.addr = 0;
+ cmd.size = tx_size;
+ pctx->size_remaining -= tx_size;
+ cmd.size_left = pctx->size_remaining;
+ if (cmd.id == TRACER_PKT_CMD)
+ tracer_pkt_log_event((void *)(pctx->data), GLINK_XPRT_TX);
+
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+ glink_spi_xprt_tx_data(einfo, data_start, dst, tx_size);
+ glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
+ GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
+ "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
+ cmd.size_left);
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return cmd.size;
+}
+
+/**
+ * tx_short_data() - Tansmit a short packet in band along with command
+ * @if_ptr: The transport to transmit on.
+ * @cmd_id: The command ID to transmit.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_short_data(struct glink_transport_if *if_ptr,
+ uint32_t lcid, struct glink_core_tx_pkt *pctx)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t riid;
+ uint32_t size;
+ uint32_t size_left;
+ unsigned char data[SHORT_PKT_SIZE];
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t size;
+ void *data_start;
+ size_t tx_size = 0;
+ int rcu_id;
+
+ if (pctx->size < pctx->size_remaining) {
+ GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
+ __func__);
+ pctx->size_remaining = pctx->size;
+ }
+ if (!pctx->size_remaining)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = TX_SHORT_DATA_CMD;
+ cmd.lcid = lcid;
+ cmd.riid = pctx->riid;
+ data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
+ &tx_size);
+ if (unlikely(!data_start || tx_size > SHORT_PKT_SIZE)) {
+ GLINK_ERR("%s: invalid data_start %p or tx_size %zu\n",
+ __func__, data_start, tx_size);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&einfo->write_lock);
+ size = glink_spi_xprt_write_avail(einfo);
+ /* Need enough space to write the command */
+ if (size <= sizeof(cmd)) {
+ einfo->tx_resume_needed = true;
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EAGAIN;
+ }
+ cmd.size = tx_size;
+ pctx->size_remaining -= tx_size;
+ cmd.size_left = pctx->size_remaining;
+ memcpy(cmd.data, data_start, tx_size);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+ glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
+ GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
+ "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
+ cmd.size_left);
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return cmd.size;
+}
+
+/**
+ * tx() - convert a data transmit cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
+ struct glink_core_tx_pkt *pctx)
+{
+ if (pctx->size_remaining <= SHORT_PKT_SIZE)
+ return tx_short_data(if_ptr, lcid, pctx);
+ return tx_data(if_ptr, TX_DATA_CMD, lcid, pctx);
+}
+
+/**
+ * tx_cmd_tracer_pkt() - convert a tracer packet cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid,
+ struct glink_core_tx_pkt *pctx)
+{
+ return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx);
+}
+
+/**
+ * int wait_link_down() - Check status of read/write indices
+ * @if_ptr: The transport to check
+ *
+ * Return: 1 if indices are all zero, 0 otherwise
+ */
+static int wait_link_down(struct glink_transport_if *if_ptr)
+{
+ return 0;
+}
+
+/**
+ * get_power_vote_ramp_time() - Get the ramp time required for the power
+ * votes to be applied
+ * @if_ptr: The transport interface on which power voting is requested.
+ * @state: The power state for which ramp time is required.
+ *
+ * Return: The ramp time specific to the power state, standard error otherwise.
+ */
+static unsigned long get_power_vote_ramp_time(
+ struct glink_transport_if *if_ptr, uint32_t state)
+{
+ return 0;
+}
+
+/**
+ * power_vote() - Update the power votes to meet qos requirement
+ * @if_ptr: The transport interface on which power voting is requested.
+ * @state: The power state for which the voting should be done.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_vote(struct glink_transport_if *if_ptr, uint32_t state)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag |= ACTIVE_TX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ return 0;
+}
+
+/**
+ * power_unvote() - Remove the all the power votes
+ * @if_ptr: The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_unvote(struct glink_transport_if *if_ptr)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag &= ~ACTIVE_TX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_init(struct device *dev, void *priv_data)
+{
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_deinit(struct device *dev, void *priv_data)
+{
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_event_handler(struct device *dev,
+ void *priv_data, enum wdsp_event_type event, void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+ struct device *sdev;
+ struct spi_device *spi_dev;
+
+ switch (event) {
+ case WDSP_EVENT_PRE_BOOTUP:
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops &&
+ cmpnt->master_ops->get_dev_for_cmpnt)
+ sdev = cmpnt->master_ops->get_dev_for_cmpnt(
+ cmpnt->master_dev, WDSP_CMPNT_TRANSPORT);
+ else
+ sdev = NULL;
+
+ if (!sdev) {
+ dev_err(dev, "%s: Failed to get transport device\n",
+ __func__);
+ break;
+ }
+
+ spi_dev = to_spi_device(sdev);
+ einfo->spi_dev = spi_dev;
+ break;
+ case WDSP_EVENT_IPC1_INTR:
+ queue_kthread_work(&einfo->kworker, &einfo->kwork);
+ break;
+ default:
+ pr_debug("%s: unhandled event %d", __func__, event);
+ break;
+ }
+
+ return 0;
+}
+
+/* glink_wdsp_cmpnt_ops - Callback operations registered wtih WDSP framework */
+static struct wdsp_cmpnt_ops glink_wdsp_cmpnt_ops = {
+ .init = glink_wdsp_cmpnt_init,
+ .deinit = glink_wdsp_cmpnt_deinit,
+ .event_handler = glink_wdsp_cmpnt_event_handler,
+};
+
+static int glink_component_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+ int ret = 0;
+
+ cmpnt->master_dev = master;
+ cmpnt->master_ops = data;
+
+ if (cmpnt->master_ops && cmpnt->master_ops->register_cmpnt_ops)
+ ret = cmpnt->master_ops->register_cmpnt_ops(master, dev, einfo,
+ &glink_wdsp_cmpnt_ops);
+ else
+ ret = -EINVAL;
+
+ if (ret)
+ dev_err(dev, "%s: register_cmpnt_ops failed, err = %d\n",
+ __func__, ret);
+ return ret;
+}
+
+static void glink_component_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+
+ cmpnt->master_dev = NULL;
+ cmpnt->master_ops = NULL;
+}
+
+static const struct component_ops glink_component_ops = {
+ .bind = glink_component_bind,
+ .unbind = glink_component_unbind,
+};
+
+/**
+ * init_xprt_if() - Initialize the xprt_if for an edge
+ * @einfo: The edge to initialize.
+ */
+static void init_xprt_if(struct edge_info *einfo)
+{
+ einfo->xprt_if.tx_cmd_version = tx_cmd_version;
+ einfo->xprt_if.tx_cmd_version_ack = tx_cmd_version_ack;
+ einfo->xprt_if.set_version = set_version;
+ einfo->xprt_if.tx_cmd_ch_open = tx_cmd_ch_open;
+ einfo->xprt_if.tx_cmd_ch_close = tx_cmd_ch_close;
+ einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
+ einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
+ einfo->xprt_if.ssr = ssr;
+ einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
+ einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
+ einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
+ einfo->xprt_if.tx_cmd_local_rx_done = tx_cmd_local_rx_done;
+ einfo->xprt_if.tx = tx;
+ einfo->xprt_if.tx_cmd_rx_intent_req = tx_cmd_rx_intent_req;
+ einfo->xprt_if.tx_cmd_remote_rx_intent_req_ack =
+ tx_cmd_remote_rx_intent_req_ack;
+ einfo->xprt_if.tx_cmd_set_sigs = tx_cmd_set_sigs;
+ einfo->xprt_if.wait_link_down = wait_link_down;
+ einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt;
+ einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
+ einfo->xprt_if.power_vote = power_vote;
+ einfo->xprt_if.power_unvote = power_unvote;
+}
+
+/**
+ * init_xprt_cfg() - Initialize the xprt_cfg for an edge
+ * @einfo: The edge to initialize.
+ * @name: The name of the remote side this edge communicates to.
+ */
+static void init_xprt_cfg(struct edge_info *einfo, const char *name)
+{
+ einfo->xprt_cfg.name = XPRT_NAME;
+ einfo->xprt_cfg.edge = name;
+ einfo->xprt_cfg.versions = versions;
+ einfo->xprt_cfg.versions_entries = ARRAY_SIZE(versions);
+ einfo->xprt_cfg.max_cid = SZ_64K;
+ einfo->xprt_cfg.max_iid = SZ_2G;
+}
+
+/**
+ * parse_qos_dt_params() - Parse the power states from DT
+ * @dev: Reference to the platform device for a specific edge.
+ * @einfo: Edge information for the edge probe function is called.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+static int parse_qos_dt_params(struct device_node *node,
+ struct edge_info *einfo)
+{
+ int rc;
+ int i;
+ char *key;
+ uint32_t *arr32;
+ uint32_t num_states;
+
+ key = "qcom,ramp-time";
+ if (!of_find_property(node, key, &num_states))
+ return -ENODEV;
+
+ num_states /= sizeof(uint32_t);
+
+ einfo->num_pw_states = num_states;
+
+ arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL);
+ if (!arr32)
+ return -ENOMEM;
+
+ einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!einfo->ramp_time_us) {
+ rc = -ENOMEM;
+ goto mem_alloc_fail;
+ }
+
+ rc = of_property_read_u32_array(node, key, arr32, num_states);
+ if (rc) {
+ rc = -ENODEV;
+ goto invalid_key;
+ }
+ for (i = 0; i < num_states; i++)
+ einfo->ramp_time_us[i] = arr32[i];
+
+ kfree(arr32);
+ return 0;
+
+invalid_key:
+ kfree(einfo->ramp_time_us);
+mem_alloc_fail:
+ kfree(arr32);
+ return rc;
+}
+
+/**
+ * parse_qos_dt_params() - Parse any remote FIFO configuration
+ * @node: Reference to the platform device for a specific edge.
+ * @einfo: Edge information for the edge probe function is called.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+static int parse_remote_fifo_cfg(struct device_node *node,
+ struct edge_info *einfo)
+{
+ int rc;
+ char *key;
+
+ key = "qcom,out-read-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->tx_fifo_read_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,out-write-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->tx_fifo_write_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,in-read-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->rx_fifo_read_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,in-write-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->rx_fifo_write_reg_addr);
+ if (rc)
+ goto key_error;
+ return 0;
+
+key_error:
+ pr_err("%s: Error %d parsing key %s\n", __func__, rc, key);
+ return rc;
+}
+
+static int glink_spi_probe(struct platform_device *pdev)
+{
+ struct device_node *node;
+ struct device_node *phandle_node;
+ struct edge_info *einfo;
+ int rc;
+ char *key;
+ const char *subsys_name;
+ unsigned long flags;
+
+ node = pdev->dev.of_node;
+
+ einfo = kzalloc(sizeof(*einfo), GFP_KERNEL);
+ if (!einfo) {
+ rc = -ENOMEM;
+ goto edge_info_alloc_fail;
+ }
+
+ key = "label";
+ subsys_name = of_get_property(node, key, NULL);
+ if (!subsys_name) {
+ pr_err("%s: missing key %s\n", __func__, key);
+ rc = -ENODEV;
+ goto missing_key;
+ }
+ strlcpy(einfo->subsys_name, subsys_name, sizeof(einfo->subsys_name));
+
+ init_xprt_cfg(einfo, subsys_name);
+ init_xprt_if(einfo);
+
+ einfo->in_ssr = true;
+ einfo->fifo_size = DEFAULT_FIFO_SIZE;
+ init_kthread_work(&einfo->kwork, rx_worker);
+ init_kthread_worker(&einfo->kworker);
+ init_srcu_struct(&einfo->use_ref);
+ mutex_init(&einfo->write_lock);
+ init_waitqueue_head(&einfo->tx_blocked_queue);
+ spin_lock_init(&einfo->activity_lock);
+
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_add_tail(&einfo->list, &edge_infos);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+
+ einfo->task = kthread_run(kthread_worker_fn, &einfo->kworker,
+ "spi_%s", subsys_name);
+ if (IS_ERR(einfo->task)) {
+ rc = PTR_ERR(einfo->task);
+ pr_err("%s: kthread run failed %d\n", __func__, rc);
+ goto kthread_fail;
+ }
+
+ key = "qcom,remote-fifo-config";
+ phandle_node = of_parse_phandle(node, key, 0);
+ if (phandle_node)
+ parse_remote_fifo_cfg(phandle_node, einfo);
+
+ key = "qcom,qos-config";
+ phandle_node = of_parse_phandle(node, key, 0);
+ if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node,
+ &einfo->xprt_cfg)))
+ parse_qos_dt_params(node, einfo);
+
+ rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg);
+ if (rc == -EPROBE_DEFER)
+ goto reg_xprt_fail;
+ if (rc) {
+ pr_err("%s: glink core register transport failed: %d\n",
+ __func__, rc);
+ goto reg_xprt_fail;
+ }
+
+ dev_set_drvdata(&pdev->dev, einfo);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp")) {
+ rc = component_add(&pdev->dev, &glink_component_ops);
+ if (rc) {
+ pr_err("%s: component_add failed, err = %d\n",
+ __func__, rc);
+ rc = -ENODEV;
+ goto reg_cmpnt_fail;
+ }
+ }
+ return 0;
+
+reg_cmpnt_fail:
+ dev_set_drvdata(&pdev->dev, NULL);
+ glink_core_unregister_transport(&einfo->xprt_if);
+reg_xprt_fail:
+ flush_kthread_worker(&einfo->kworker);
+ kthread_stop(einfo->task);
+ einfo->task = NULL;
+kthread_fail:
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_del(&einfo->list);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+missing_key:
+ kfree(einfo);
+edge_info_alloc_fail:
+ return rc;
+}
+
+static int glink_spi_remove(struct platform_device *pdev)
+{
+ struct edge_info *einfo;
+ unsigned long flags;
+
+ einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+ glink_core_unregister_transport(&einfo->xprt_if);
+ flush_kthread_worker(&einfo->kworker);
+ kthread_stop(einfo->task);
+ einfo->task = NULL;
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_del(&einfo->list);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+ kfree(einfo);
+ return 0;
+}
+
+static int glink_spi_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int glink_spi_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+ bool suspend;
+ int rc = -EBUSY;
+
+ einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+ if (strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ return 0;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ suspend = !(einfo->activity_flag);
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ if (suspend)
+ rc = wdsp_suspend(&einfo->cmpnt);
+ if (rc < 0)
+ pr_err("%s: Could not suspend activity_flag %d, rc %d\n",
+ __func__, einfo->activity_flag, rc);
+ return rc;
+}
+
+static const struct of_device_id spi_match_table[] = {
+ { .compatible = "qcom,glink-spi-xprt" },
+ {},
+};
+
+static struct platform_driver glink_spi_driver = {
+ .probe = glink_spi_probe,
+ .remove = glink_spi_remove,
+ .resume = glink_spi_resume,
+ .suspend = glink_spi_suspend,
+ .driver = {
+ .name = "msm_glink_spi_xprt",
+ .owner = THIS_MODULE,
+ .of_match_table = spi_match_table,
+ },
+};
+
+static int __init glink_spi_xprt_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&glink_spi_driver);
+ if (rc)
+ pr_err("%s: glink_spi register failed %d\n", __func__, rc);
+
+ return rc;
+}
+module_init(glink_spi_xprt_init);
+
+static void __exit glink_spi_xprt_exit(void)
+{
+ platform_driver_unregister(&glink_spi_driver);
+}
+module_exit(glink_spi_xprt_exit);
+
+MODULE_DESCRIPTION("MSM G-Link SPI Transport");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index 6242e867fe72..f4d5a3b303db 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -28,6 +28,7 @@ enum buf_type {
enum xprt_ids {
SMEM_XPRT_ID = 100,
+ SPIV2_XPRT_ID = SMEM_XPRT_ID,
SMD_TRANS_XPRT_ID = 200,
LLOOP_XPRT_ID = 300,
MOCK_XPRT_HIGH_ID = 390,
@@ -56,6 +57,7 @@ enum xprt_ids {
* @iovec: Pointer to the vector buffer packet.
* @vprovider: Packet-specific virtual buffer provider function.
* @pprovider: Packet-specific physical buffer provider function.
+ * @cookie: Transport-specific cookie
* @pkt_ref: Active references to the packet.
*/
struct glink_core_tx_pkt {
@@ -73,6 +75,7 @@ struct glink_core_tx_pkt {
void *iovec;
void * (*vprovider)(void *iovec, size_t offset, size_t *size);
void * (*pprovider)(void *iovec, size_t offset, size_t *size);
+ void *cookie;
struct rwref_lock pkt_ref;
};
diff --git a/drivers/soc/qcom/irq-helper.c b/drivers/soc/qcom/irq-helper.c
index 270a1ba9ba19..2bb71464d165 100644
--- a/drivers/soc/qcom/irq-helper.c
+++ b/drivers/soc/qcom/irq-helper.c
@@ -18,6 +18,7 @@
#include <linux/kobject.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <soc/qcom/irq-helper.h>
struct irq_helper {
bool enable;
@@ -161,7 +162,7 @@ static int __init irq_helper_init(void)
irq_h->enable = true;
return 0;
out_put_kobj:
- koject_put(&irq_h->kobj);
+ kobject_put(&irq_h->kobj);
out_free_irq:
kfree(irq_h);
return ret;
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index b055234326b6..eaeb8d4776fe 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -813,15 +813,19 @@ int pil_boot(struct pil_desc *desc)
}
if (desc->subsys_vmid > 0) {
- /* Make sure the memory is actually assigned to Linux. In the
- * case where the shutdown sequence is not able to immediately
- * assign the memory back to Linux, we need to do this here. */
- ret = pil_assign_mem_to_linux(desc, priv->region_start,
+ /**
+ * In case of modem ssr, we need to assign memory back to linux.
+ * This is not true after cold boot since linux already owns it.
+ * Also for secure boot devices, modem memory has to be released
+ * after MBA is booted
+ */
+ if (desc->modem_ssr) {
+ ret = pil_assign_mem_to_linux(desc, priv->region_start,
(priv->region_end - priv->region_start));
- if (ret)
- pil_err(desc, "Failed to assign to linux, ret - %d\n",
+ if (ret)
+ pil_err(desc, "Failed to assign to linux, ret- %d\n",
ret);
-
+ }
ret = pil_assign_mem_to_subsys_and_linux(desc,
priv->region_start,
(priv->region_end - priv->region_start));
@@ -857,6 +861,7 @@ int pil_boot(struct pil_desc *desc)
goto err_auth_and_reset;
}
pil_info(desc, "Brought out of reset\n");
+ desc->modem_ssr = false;
err_auth_and_reset:
if (ret && desc->subsys_vmid > 0) {
pil_assign_mem_to_linux(desc, priv->region_start,
@@ -917,6 +922,7 @@ void pil_shutdown(struct pil_desc *desc)
pil_proxy_unvote(desc, 1);
else
flush_delayed_work(&priv->proxy);
+ desc->modem_ssr = true;
}
EXPORT_SYMBOL(pil_shutdown);
diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h
index c3689faf0034..802abe26a960 100644
--- a/drivers/soc/qcom/peripheral-loader.h
+++ b/drivers/soc/qcom/peripheral-loader.h
@@ -36,6 +36,7 @@ struct pil_priv;
* @unmap_fw_mem: Custom function used to undo mapping by map_fw_mem.
* This defaults to iounmap if not specified.
* @shutdown_fail: Set if PIL op for shutting down subsystem fails.
+ * @modem_ssr: true if modem is restarting, false if booting for first time.
* @subsys_vmid: memprot id for the subsystem.
*/
struct pil_desc {
@@ -54,6 +55,7 @@ struct pil_desc {
void (*unmap_fw_mem)(void *virt, size_t size, void *data);
void *map_data;
bool shutdown_fail;
+ bool modem_ssr;
u32 subsys_vmid;
};
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index af9cd189cf6d..31a5ae89174e 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -214,6 +214,7 @@ static int pil_subsys_init(struct modem_data *drv,
drv->subsys_desc.stop_ack_handler = modem_stop_ack_intr_handler;
drv->subsys_desc.wdog_bite_handler = modem_wdog_bite_intr_handler;
+ drv->q6->desc.modem_ssr = false;
drv->subsys = subsys_register(&drv->subsys_desc);
if (IS_ERR(drv->subsys)) {
ret = PTR_ERR(drv->subsys);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 3639890c0dc7..5db4fe9e3cdf 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1738,7 +1738,10 @@ void unregister_gadget_item(struct config_item *item)
{
struct gadget_info *gi = to_gadget_info(item);
+ /* to protect race with gadget_dev_desc_UDC_store*/
+ mutex_lock(&gi->lock);
unregister_gadget(gi);
+ mutex_unlock(&gi->lock);
}
EXPORT_SYMBOL_GPL(unregister_gadget_item);
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index b22ea656367e..78c1ce793b5b 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -516,7 +516,6 @@ static void usb_cser_disable(struct usb_function *f)
usb_cser_disconnect(port);
usb_ep_disable(port->port_usb.notify);
- usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
port->port_usb.notify->driver_data = NULL;
}
@@ -817,7 +816,11 @@ static void cser_free_inst(struct usb_function_instance *fi)
static void usb_cser_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_cdev *port = func_to_port(f);
+
usb_free_all_descriptors(f);
+ usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
+ port->port_usb.notify_req = NULL;
}
static int usb_cser_alloc_requests(struct usb_ep *ep, struct list_head *head,
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 48f987d77e91..c5fd3ce3ed9a 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -24,6 +24,7 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/uio.h>
+#include <linux/ipc_logging.h>
#include <asm/unaligned.h>
#include <linux/usb/composite.h>
@@ -41,6 +42,15 @@
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
+#define NUM_PAGES 10 /* # of pages for ipc logging */
+
+static void *ffs_ipc_log;
+#define ffs_log(fmt, ...) do { \
+ ipc_log_string(ffs_ipc_log, "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+
/* Reference counter handling */
static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs);
@@ -214,6 +224,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
spin_unlock_irq(&ffs->ev.waitq.lock);
+ ffs_log("enter: state %d setup_state %d flags %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
req->buf = data;
req->length = len;
@@ -238,11 +251,18 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
}
ffs->setup_state = FFS_NO_SETUP;
+
+ ffs_log("exit: state %d setup_state %d flags %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
return req->status ? req->status : req->actual;
}
static int __ffs_ep0_stall(struct ffs_data *ffs)
{
+ ffs_log("state %d setup_state %d flags %lu can_stall %d", ffs->state,
+ ffs->setup_state, ffs->flags, ffs->ev.can_stall);
+
if (ffs->ev.can_stall) {
pr_vdebug("ep0 stall\n");
usb_ep_set_halt(ffs->gadget->ep0);
@@ -263,6 +283,9 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
ENTER();
+ ffs_log("enter:len %zu state %d setup_state %d flags %lu", len,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/* Fast check if setup was canceled */
if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
return -EIDRM;
@@ -391,6 +414,9 @@ done_spin:
break;
}
+ ffs_log("exit:ret %zu state %d setup_state %d flags %lu", ret,
+ ffs->state, ffs->setup_state, ffs->flags);
+
mutex_unlock(&ffs->mutex);
return ret;
}
@@ -424,6 +450,10 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
ffs->ev.count * sizeof *ffs->ev.types);
spin_unlock_irq(&ffs->ev.waitq.lock);
+
+ ffs_log("state %d setup_state %d flags %lu #evt %zu", ffs->state,
+ ffs->setup_state, ffs->flags, n);
+
mutex_unlock(&ffs->mutex);
return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
@@ -439,6 +469,9 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
ENTER();
+ ffs_log("enter:len %zu state %d setup_state %d flags %lu", len,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/* Fast check if setup was canceled */
if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
return -EIDRM;
@@ -527,8 +560,12 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
spin_unlock_irq(&ffs->ev.waitq.lock);
done_mutex:
+ ffs_log("exit:ret %d state %d setup_state %d flags %lu", ret,
+ ffs->state, ffs->setup_state, ffs->flags);
+
mutex_unlock(&ffs->mutex);
kfree(data);
+
return ret;
}
@@ -538,6 +575,9 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
if (unlikely(ffs->state == FFS_CLOSING))
return -EBUSY;
@@ -557,6 +597,9 @@ static int ffs_ep0_release(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
ffs_data_closed(ffs);
return 0;
@@ -570,6 +613,9 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
if (code == FUNCTIONFS_INTERFACE_REVMAP) {
struct ffs_function *func = ffs->func;
ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
@@ -588,6 +634,9 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait)
unsigned int mask = POLLWRNORM;
int ret;
+ ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
poll_wait(file, &ffs->ev.waitq, wait);
ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
@@ -618,6 +667,8 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait)
break;
}
+ ffs_log("exit: mask %u", mask);
+
mutex_unlock(&ffs->mutex);
return mask;
@@ -648,6 +699,7 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
ep->status = req->status ? req->status : req->actual;
/* Set is_busy false to indicate completion of last request */
ep->is_busy = false;
+ ffs_log("ep status %d for req %p", ep->status, req);
complete(req->context);
}
}
@@ -659,6 +711,8 @@ static void ffs_user_copy_worker(struct work_struct *work)
int ret = io_data->req->status ? io_data->req->status :
io_data->req->actual;
+ ffs_log("enter: ret %d", ret);
+
if (io_data->read && ret > 0) {
use_mm(io_data->mm);
ret = copy_to_iter(io_data->buf, ret, &io_data->data);
@@ -680,6 +734,8 @@ static void ffs_user_copy_worker(struct work_struct *work)
kfree(io_data->to_free);
kfree(io_data->buf);
kfree(io_data);
+
+ ffs_log("exit");
}
static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
@@ -689,8 +745,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
ENTER();
+ ffs_log("enter");
+
INIT_WORK(&io_data->work, ffs_user_copy_worker);
schedule_work(&io_data->work);
+
+ ffs_log("exit");
}
static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
@@ -701,6 +761,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
ssize_t ret, data_len = -EINVAL;
int halt;
+ ffs_log("enter: epfile name %s epfile err %d", epfile->name,
+ atomic_read(&epfile->error));
+
smp_mb__before_atomic();
if (atomic_read(&epfile->error))
return -ENODEV;
@@ -927,6 +990,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
}
mutex_unlock(&epfile->mutex);
+
+ ffs_log("exit:ret %zu", ret);
+
return ret;
error_lock:
@@ -934,6 +1000,9 @@ error_lock:
mutex_unlock(&epfile->mutex);
error:
kfree(data);
+
+ ffs_log("exit: ret %zu", ret);
+
return ret;
}
@@ -944,6 +1013,9 @@ ffs_epfile_open(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
@@ -962,6 +1034,9 @@ ffs_epfile_open(struct inode *inode, struct file *file)
smp_mb__before_atomic();
atomic_set(&epfile->error, 0);
+ ffs_log("exit:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
return 0;
}
@@ -973,6 +1048,9 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
spin_lock_irq(&epfile->ffs->eps_lock);
if (likely(io_data && io_data->ep && io_data->req))
@@ -982,6 +1060,8 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
spin_unlock_irq(&epfile->ffs->eps_lock);
+ ffs_log("exit: value %d", value);
+
return value;
}
@@ -992,6 +1072,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
ENTER();
+ ffs_log("enter");
+
if (!is_sync_kiocb(kiocb)) {
p = kmalloc(sizeof(io_data), GFP_KERNEL);
if (unlikely(!p))
@@ -1018,6 +1100,9 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
kfree(p);
else
*from = p->data;
+
+ ffs_log("exit");
+
return res;
}
@@ -1028,6 +1113,8 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
ENTER();
+ ffs_log("enter");
+
if (!is_sync_kiocb(kiocb)) {
p = kmalloc(sizeof(io_data), GFP_KERNEL);
if (unlikely(!p))
@@ -1066,6 +1153,9 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
} else {
*to = p->data;
}
+
+ ffs_log("enter");
+
return res;
}
@@ -1076,12 +1166,17 @@ ffs_epfile_release(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
smp_mb__before_atomic();
atomic_set(&epfile->opened, 0);
atomic_set(&epfile->error, 1);
ffs_data_closed(epfile->ffs);
file->private_data = NULL;
+ ffs_log("exit");
+
return 0;
}
@@ -1093,6 +1188,9 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
@@ -1143,6 +1241,8 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
}
spin_unlock_irq(&epfile->ffs->eps_lock);
+ ffs_log("exit:ret %d", ret);
+
return ret;
}
@@ -1174,6 +1274,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
ENTER();
+ ffs_log("enter");
+
inode = new_inode(sb);
if (likely(inode)) {
@@ -1193,6 +1295,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
inode->i_op = iops;
}
+ ffs_log("exit");
+
return inode;
}
@@ -1207,6 +1311,8 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
ENTER();
+ ffs_log("enter");
+
dentry = d_alloc_name(sb->s_root, name);
if (unlikely(!dentry))
return NULL;
@@ -1218,6 +1324,9 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
}
d_add(dentry, inode);
+
+ ffs_log("exit");
+
return dentry;
}
@@ -1243,6 +1352,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
ENTER();
+ ffs_log("enter");
+
ffs->sb = sb;
data->ffs_data = NULL;
sb->s_fs_info = ffs;
@@ -1267,6 +1378,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
&ffs_ep0_operations)))
return -ENOMEM;
+ ffs_log("exit");
+
return 0;
}
@@ -1274,6 +1387,8 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
{
ENTER();
+ ffs_log("enter");
+
if (!opts || !*opts)
return 0;
@@ -1356,6 +1471,8 @@ invalid:
opts = comma + 1;
}
+ ffs_log("exit");
+
return 0;
}
@@ -1381,6 +1498,8 @@ ffs_fs_mount(struct file_system_type *t, int flags,
ENTER();
+ ffs_log("enter");
+
ret = ffs_fs_parse_opts(&data, opts);
if (unlikely(ret < 0))
return ERR_PTR(ret);
@@ -1410,6 +1529,9 @@ ffs_fs_mount(struct file_system_type *t, int flags,
ffs_release_dev(data.ffs_data);
ffs_data_put(data.ffs_data);
}
+
+ ffs_log("exit");
+
return rv;
}
@@ -1418,12 +1540,16 @@ ffs_fs_kill_sb(struct super_block *sb)
{
ENTER();
+ ffs_log("enter");
+
kill_litter_super(sb);
if (sb->s_fs_info) {
ffs_release_dev(sb->s_fs_info);
ffs_data_closed(sb->s_fs_info);
ffs_data_put(sb->s_fs_info);
}
+
+ ffs_log("exit");
}
static struct file_system_type ffs_fs_type = {
@@ -1449,6 +1575,8 @@ static int functionfs_init(void)
else
pr_err("failed registering file system (%d)\n", ret);
+ ffs_ipc_log = ipc_log_context_create(NUM_PAGES, "f_fs", 0);
+
return ret;
}
@@ -1470,14 +1598,21 @@ static void ffs_data_get(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter");
+
smp_mb__before_atomic();
atomic_inc(&ffs->ref);
+
+ ffs_log("exit");
}
static void ffs_data_opened(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
smp_mb__before_atomic();
atomic_inc(&ffs->ref);
if (atomic_add_return(1, &ffs->opened) == 1 &&
@@ -1485,12 +1620,17 @@ static void ffs_data_opened(struct ffs_data *ffs)
ffs->state = FFS_CLOSING;
ffs_data_reset(ffs);
}
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_data_put(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter");
+
smp_mb__before_atomic();
if (unlikely(atomic_dec_and_test(&ffs->ref))) {
pr_info("%s(): freeing\n", __func__);
@@ -1500,12 +1640,17 @@ static void ffs_data_put(struct ffs_data *ffs)
kfree(ffs->dev_name);
kfree(ffs);
}
+
+ ffs_log("exit");
}
static void ffs_data_closed(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
smp_mb__before_atomic();
if (atomic_dec_and_test(&ffs->opened)) {
if (ffs->no_disconnect) {
@@ -1529,6 +1674,9 @@ static void ffs_data_closed(struct ffs_data *ffs)
ffs_data_reset(ffs);
}
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
ffs_data_put(ffs);
}
@@ -1540,6 +1688,8 @@ static struct ffs_data *ffs_data_new(void)
ENTER();
+ ffs_log("enter");
+
atomic_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0);
ffs->state = FFS_READ_DESCRIPTORS;
@@ -1553,6 +1703,8 @@ static struct ffs_data *ffs_data_new(void)
/* XXX REVISIT need to update it in some places, or do we? */
ffs->ev.can_stall = 1;
+ ffs_log("exit");
+
return ffs;
}
@@ -1560,6 +1712,9 @@ static void ffs_data_clear(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n",
__func__, ffs->gadget, ffs->flags);
ffs_closed(ffs);
@@ -1578,12 +1733,18 @@ static void ffs_data_clear(struct ffs_data *ffs)
kfree(ffs->raw_descs_data);
kfree(ffs->raw_strings);
kfree(ffs->stringtabs);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_data_reset(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
ffs_data_clear(ffs);
ffs->epfiles = NULL;
@@ -1606,6 +1767,9 @@ static void ffs_data_reset(struct ffs_data *ffs)
ffs->state = FFS_READ_DESCRIPTORS;
ffs->setup_state = FFS_NO_SETUP;
ffs->flags = 0;
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
@@ -1616,6 +1780,9 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
if (WARN_ON(ffs->state != FFS_ACTIVE
|| test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
return -EBADFD;
@@ -1641,6 +1808,10 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
}
ffs->gadget = cdev->gadget;
+
+ ffs_log("exit: state %d setup_state %d flag %lu gadget %p\n",
+ ffs->state, ffs->setup_state, ffs->flags, ffs->gadget);
+
ffs_data_get(ffs);
return 0;
}
@@ -1654,6 +1825,8 @@ static void functionfs_unbind(struct ffs_data *ffs)
ffs->ep0req = NULL;
ffs->gadget = NULL;
clear_bit(FFS_FL_BOUND, &ffs->flags);
+ ffs_log("state %d setup_state %d flag %lu gadget %p\n",
+ ffs->state, ffs->setup_state, ffs->flags, ffs->gadget);
ffs_data_put(ffs);
}
}
@@ -1665,6 +1838,9 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
count = ffs->eps_count;
epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
if (!epfiles)
@@ -1690,6 +1866,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
}
ffs->epfiles = epfiles;
+
+ ffs_log("exit: epfile name %s state %d setup_state %d flag %lu",
+ epfile->name, ffs->state, ffs->setup_state, ffs->flags);
+
return 0;
}
@@ -1699,6 +1879,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
+ ffs_log("enter: epfilename %s", epfile->name);
+
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) ||
waitqueue_active(&epfile->wait));
@@ -1710,6 +1892,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
}
kfree(epfiles);
+
+ ffs_log("exit");
}
static void ffs_func_eps_disable(struct ffs_function *func)
@@ -1719,6 +1903,9 @@ static void ffs_func_eps_disable(struct ffs_function *func)
unsigned count = func->ffs->eps_count;
unsigned long flags;
+ ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state,
+ func->ffs->setup_state, func->ffs->flags);
+
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
@@ -1738,6 +1925,8 @@ static void ffs_func_eps_disable(struct ffs_function *func)
}
} while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+
+ ffs_log("exit");
}
static int ffs_func_eps_enable(struct ffs_function *func)
@@ -1749,6 +1938,9 @@ static int ffs_func_eps_enable(struct ffs_function *func)
unsigned long flags;
int ret = 0;
+ ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state,
+ func->ffs->setup_state, func->ffs->flags);
+
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
struct usb_endpoint_descriptor *ds;
@@ -1786,6 +1978,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
epfile->ep = ep;
epfile->in = usb_endpoint_dir_in(ds);
epfile->isoc = usb_endpoint_xfer_isoc(ds);
+ ffs_log("usb_ep_enable %s", ep->ep->name);
} else {
break;
}
@@ -1797,6 +1990,8 @@ static int ffs_func_eps_enable(struct ffs_function *func)
} while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -1837,6 +2032,8 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u", len);
+
/* At least two bytes are required: length and type */
if (len < 2) {
pr_vdebug("descriptor too short\n");
@@ -1953,6 +2150,8 @@ inv_length:
#undef __entity_check_STRING
#undef __entity_check_ENDPOINT
+ ffs_log("exit: desc type %d length %d", _ds->bDescriptorType, length);
+
return length;
}
@@ -1964,6 +2163,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u", len);
+
for (;;) {
int ret;
@@ -1991,6 +2192,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
data += ret;
++num;
}
+
+ ffs_log("exit: len %u", len);
}
static int __ffs_data_do_entity(enum ffs_entity_type type,
@@ -2002,6 +2205,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
ENTER();
+ ffs_log("enter: type %u", type);
+
switch (type) {
case FFS_DESCRIPTOR:
break;
@@ -2040,6 +2245,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
break;
}
+ ffs_log("exit");
+
return 0;
}
@@ -2049,6 +2256,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
u16 bcd_version = le16_to_cpu(desc->bcdVersion);
u16 w_index = le16_to_cpu(desc->wIndex);
+ ffs_log("enter");
+
if (bcd_version != 1) {
pr_vdebug("unsupported os descriptors version: %d",
bcd_version);
@@ -2066,6 +2275,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
return -EINVAL;
}
+ ffs_log("exit: size of desc %lu", sizeof(*desc));
+
return sizeof(*desc);
}
@@ -2085,6 +2296,8 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u os desc type %d", len, type);
+
/* loop over all ext compat/ext prop descriptors */
while (feature_count--) {
ret = entity(type, h, data, len, priv);
@@ -2095,6 +2308,9 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
data += ret;
len -= ret;
}
+
+ ffs_log("exit");
+
return _len - len;
}
@@ -2108,6 +2324,8 @@ static int __must_check ffs_do_os_descs(unsigned count,
ENTER();
+ ffs_log("enter: len %u", len);
+
for (num = 0; num < count; ++num) {
int ret;
enum ffs_os_desc_type type;
@@ -2157,6 +2375,9 @@ static int __must_check ffs_do_os_descs(unsigned count,
len -= ret;
data += ret;
}
+
+ ffs_log("exit");
+
return _len - len;
}
@@ -2172,6 +2393,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
ENTER();
+ ffs_log("enter: len %u", len);
+
switch (type) {
case FFS_OS_DESC_EXT_COMPAT: {
struct usb_ext_compat_desc *d = data;
@@ -2226,6 +2449,9 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
pr_vdebug("unknown descriptor: %d\n", type);
return -EINVAL;
}
+
+ ffs_log("exit");
+
return length;
}
@@ -2239,6 +2465,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
ENTER();
+ ffs_log("enter: len %zu", len);
+
if (get_unaligned_le32(data + 4) != len)
goto error;
@@ -2349,10 +2577,13 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
ffs->ss_descs_count = counts[2];
ffs->ms_os_descs_count = os_descs_count;
+ ffs_log("exit");
+
return 0;
error:
kfree(_data);
+ ffs_log("exit: ret %d", ret);
return ret;
}
@@ -2366,6 +2597,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
ENTER();
+ ffs_log("enter: len %zu", len);
+
if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
get_unaligned_le32(data + 4) != len))
goto error;
@@ -2480,12 +2713,14 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
ffs->stringtabs = stringtabs;
ffs->raw_strings = _data;
+ ffs_log("exit");
return 0;
error_free:
kfree(stringtabs);
error:
kfree(_data);
+ ffs_log("exit: -EINVAL");
return -EINVAL;
}
@@ -2498,6 +2733,9 @@ static void __ffs_event_add(struct ffs_data *ffs,
enum usb_functionfs_event_type rem_type1, rem_type2 = type;
int neg = 0;
+ ffs_log("enter: type %d state %d setup_state %d flag %lu", type,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/*
* Abort any unhandled setup
*
@@ -2557,6 +2795,9 @@ static void __ffs_event_add(struct ffs_data *ffs,
wake_up_locked(&ffs->ev.waitq);
if (ffs->ffs_eventfd)
eventfd_signal(ffs->ffs_eventfd, 1);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_event_add(struct ffs_data *ffs,
@@ -2591,6 +2832,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
int idx;
static const char *speed_names[] = { "full", "high", "super" };
+ ffs_log("enter");
+
if (type != FFS_DESCRIPTOR)
return 0;
@@ -2666,6 +2909,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
}
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
+ ffs_log("exit");
+
return 0;
}
@@ -2677,6 +2922,8 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
unsigned idx;
u8 newValue;
+ ffs_log("enter: type %d", type);
+
switch (type) {
default:
case FFS_DESCRIPTOR:
@@ -2721,6 +2968,9 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
pr_vdebug("%02x -> %02x\n", *valuep, newValue);
*valuep = newValue;
+
+ ffs_log("exit: newValue %d", newValue);
+
return 0;
}
@@ -2731,6 +2981,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
struct ffs_function *func = priv;
u8 length = 0;
+ ffs_log("enter: type %d", type);
+
switch (type) {
case FFS_OS_DESC_EXT_COMPAT: {
struct usb_ext_compat_desc *desc = data;
@@ -2800,6 +3052,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
pr_vdebug("unknown descriptor: %d\n", type);
}
+ ffs_log("exit");
+
return length;
}
@@ -2813,6 +3067,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
ENTER();
+ ffs_log("enter");
+
/*
* Legacy gadget triggers binding in functionfs_ready_callback,
* which already uses locking; taking the same lock here would
@@ -2847,6 +3103,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
ffs_opts->refcnt++;
func->function.strings = func->ffs->stringtabs;
+ ffs_log("exit");
+
return ffs_opts;
}
@@ -2889,6 +3147,9 @@ static int _ffs_func_bind(struct usb_configuration *c,
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
/* Has descriptors only for speeds gadget does not support */
if (unlikely(!(full | high | super)))
return -ENOTSUPP;
@@ -3006,10 +3267,15 @@ static int _ffs_func_bind(struct usb_configuration *c,
/* And we're done */
ffs_event_add(ffs, FUNCTIONFS_BIND);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
return 0;
error:
/* XXX Do we need to release all claimed endpoints here? */
+ ffs_log("exit: ret %d", ret);
return ret;
}
@@ -3020,6 +3286,8 @@ static int ffs_func_bind(struct usb_configuration *c,
struct ffs_function *func = ffs_func_from_usb(f);
int ret;
+ ffs_log("enter");
+
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
@@ -3027,6 +3295,8 @@ static int ffs_func_bind(struct usb_configuration *c,
if (ret && !--ffs_opts->refcnt)
functionfs_unbind(func->ffs);
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -3037,7 +3307,12 @@ static void ffs_reset_work(struct work_struct *work)
{
struct ffs_data *ffs = container_of(work,
struct ffs_data, reset_work);
+
+ ffs_log("enter");
+
ffs_data_reset(ffs);
+
+ ffs_log("exit");
}
static int ffs_func_set_alt(struct usb_function *f,
@@ -3047,6 +3322,8 @@ static int ffs_func_set_alt(struct usb_function *f,
struct ffs_data *ffs = func->ffs;
int ret = 0, intf;
+ ffs_log("enter");
+
if (alt != (unsigned)-1) {
intf = ffs_func_revmap_intf(func, interface);
if (unlikely(intf < 0))
@@ -3082,6 +3359,8 @@ static int ffs_func_set_alt(struct usb_function *f,
usb_gadget_autopm_get_async(ffs->gadget);
}
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -3090,9 +3369,13 @@ static void ffs_func_disable(struct usb_function *f)
struct ffs_function *func = ffs_func_from_usb(f);
struct ffs_data *ffs = func->ffs;
+ ffs_log("enter");
+
ffs_func_set_alt(f, 0, (unsigned)-1);
/* matching put to allow LPM on disconnect */
usb_gadget_autopm_put_async(ffs->gadget);
+
+ ffs_log("exit");
}
static int ffs_func_setup(struct usb_function *f,
@@ -3105,6 +3388,8 @@ static int ffs_func_setup(struct usb_function *f,
ENTER();
+ ffs_log("enter");
+
pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
pr_vdebug("creq->bRequest = %02x\n", creq->bRequest);
pr_vdebug("creq->wValue = %04x\n", le16_to_cpu(creq->wValue));
@@ -3148,19 +3433,31 @@ static int ffs_func_setup(struct usb_function *f,
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
+ ffs_log("exit");
+
return 0;
}
static void ffs_func_suspend(struct usb_function *f)
{
ENTER();
+
+ ffs_log("enter");
+
ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND);
+
+ ffs_log("exit");
}
static void ffs_func_resume(struct usb_function *f)
{
ENTER();
+
+ ffs_log("enter");
+
ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME);
+
+ ffs_log("exit");
}
@@ -3177,11 +3474,15 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
short *nums = func->interfaces_nums;
unsigned count = func->ffs->interfaces_count;
+ ffs_log("enter");
+
for (; count; --count, ++nums) {
if (*nums >= 0 && *nums == intf)
return nums - func->interfaces_nums;
}
+ ffs_log("exit");
+
return -EDOM;
}
@@ -3194,6 +3495,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
list_for_each_entry(dev, &ffs_devices, entry) {
if (!dev->name || !name)
continue;
@@ -3201,6 +3504,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name)
return dev;
}
+ ffs_log("exit");
+
return NULL;
}
@@ -3211,12 +3516,16 @@ static struct ffs_dev *_ffs_get_single_dev(void)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
if (list_is_singular(&ffs_devices)) {
dev = list_first_entry(&ffs_devices, struct ffs_dev, entry);
if (dev->single)
return dev;
}
+ ffs_log("exit");
+
return NULL;
}
@@ -3227,11 +3536,17 @@ static struct ffs_dev *_ffs_find_dev(const char *name)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
dev = _ffs_get_single_dev();
if (dev)
return dev;
- return _ffs_do_find_dev(name);
+ dev = _ffs_do_find_dev(name);
+
+ ffs_log("exit");
+
+ return dev;
}
/* Configfs support *********************************************************/
@@ -3353,6 +3668,10 @@ static void ffs_func_unbind(struct usb_configuration *c,
unsigned long flags;
ENTER();
+
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
if (ffs->func == func) {
ffs_func_eps_disable(func);
ffs->func = NULL;
@@ -3383,6 +3702,9 @@ static void ffs_func_unbind(struct usb_configuration *c,
func->interfaces_nums = NULL;
ffs_event_add(ffs, FUNCTIONFS_UNBIND);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
@@ -3445,12 +3767,16 @@ static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
{
struct ffs_dev *existing;
+ ffs_log("enter");
+
existing = _ffs_do_find_dev(name);
if (existing)
return -EBUSY;
dev->name = name;
+ ffs_log("exit");
+
return 0;
}
@@ -3461,10 +3787,14 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name)
{
int ret;
+ ffs_log("enter");
+
ffs_dev_lock();
ret = _ffs_name_dev(dev, name);
ffs_dev_unlock();
+ ffs_log("exit");
+
return ret;
}
EXPORT_SYMBOL_GPL(ffs_name_dev);
@@ -3473,6 +3803,8 @@ int ffs_single_dev(struct ffs_dev *dev)
{
int ret;
+ ffs_log("enter");
+
ret = 0;
ffs_dev_lock();
@@ -3482,6 +3814,9 @@ int ffs_single_dev(struct ffs_dev *dev)
dev->single = true;
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ret;
}
EXPORT_SYMBOL_GPL(ffs_single_dev);
@@ -3491,12 +3826,17 @@ EXPORT_SYMBOL_GPL(ffs_single_dev);
*/
static void _ffs_free_dev(struct ffs_dev *dev)
{
+
+ ffs_log("enter");
+
list_del(&dev->entry);
if (dev->name_allocated)
kfree(dev->name);
kfree(dev);
if (list_empty(&ffs_devices))
functionfs_cleanup();
+
+ ffs_log("exit");
}
static void *ffs_acquire_dev(const char *dev_name)
@@ -3504,6 +3844,9 @@ static void *ffs_acquire_dev(const char *dev_name)
struct ffs_dev *ffs_dev;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_dev = _ffs_find_dev(dev_name);
@@ -3518,6 +3861,9 @@ static void *ffs_acquire_dev(const char *dev_name)
ffs_dev->mounted = true;
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ffs_dev;
}
@@ -3526,6 +3872,9 @@ static void ffs_release_dev(struct ffs_data *ffs_data)
struct ffs_dev *ffs_dev;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_dev = ffs_data->private_data;
@@ -3537,6 +3886,8 @@ static void ffs_release_dev(struct ffs_data *ffs_data)
}
ffs_dev_unlock();
+
+ ffs_log("exit");
}
static int ffs_ready(struct ffs_data *ffs)
@@ -3545,6 +3896,9 @@ static int ffs_ready(struct ffs_data *ffs)
int ret = 0;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_obj = ffs->private_data;
@@ -3569,6 +3923,9 @@ static int ffs_ready(struct ffs_data *ffs)
set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
done:
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ret;
}
@@ -3578,11 +3935,16 @@ static void ffs_closed(struct ffs_data *ffs)
struct f_fs_opts *opts;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_obj = ffs->private_data;
- if (!ffs_obj)
+ if (!ffs_obj) {
+ ffs_dev_unlock();
goto done;
+ }
ffs_obj->desc_ready = false;
@@ -3590,20 +3952,29 @@ static void ffs_closed(struct ffs_data *ffs)
ffs_obj->ffs_closed_callback)
ffs_obj->ffs_closed_callback(ffs);
- if (ffs_obj->opts)
+ if (ffs_obj->opts) {
opts = ffs_obj->opts;
- else
+ } else {
+ ffs_dev_unlock();
goto done;
+ }
smp_mb__before_atomic();
if (opts->no_configfs || !opts->func_inst.group.cg_item.ci_parent
- || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
+ || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) {
+ ffs_dev_unlock();
goto done;
+ }
+
+ ffs_dev_unlock();
- unregister_gadget_item(ffs_obj->opts->
+ if (test_bit(FFS_FL_BOUND, &ffs->flags)) {
+ unregister_gadget_item(opts->
func_inst.group.cg_item.ci_parent->ci_parent);
+ ffs_log("unreg gadget done");
+ }
done:
- ffs_dev_unlock();
+ ffs_log("exit");
}
/* Misc helper functions ****************************************************/
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 5612645d7237..a629723d19cb 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -39,6 +39,8 @@ static struct workqueue_struct *ipa_usb_wq;
static void ipa_disconnect_handler(struct gsi_data_port *d_port);
static int gsi_ctrl_send_notification(struct f_gsi *gsi,
enum gsi_ctrl_notify_state);
+static int gsi_alloc_trb_buffer(struct f_gsi *gsi);
+static void gsi_free_trb_buffer(struct f_gsi *gsi);
void post_event(struct gsi_data_port *port, u8 event)
{
@@ -474,6 +476,9 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port)
if (gsi->d_port.out_ep)
usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS);
+
+ /* free buffers allocated with each TRB */
+ gsi_free_trb_buffer(gsi);
}
static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
@@ -547,6 +552,7 @@ static void ipa_work_handler(struct work_struct *w)
struct usb_gadget *gadget = d_port->gadget;
struct device *dev;
struct device *gad_dev;
+ struct f_gsi *gsi;
event = read_event(d_port);
@@ -566,31 +572,27 @@ static void ipa_work_handler(struct work_struct *w)
return;
}
+ gsi = d_port_to_gsi(d_port);
+
switch (d_port->sm_state) {
case STATE_UNINITIALIZED:
break;
case STATE_INITIALIZED:
if (event == EVT_CONNECT_IN_PROGRESS) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
+ /* allocate buffers used with each TRB */
+ ret = gsi_alloc_trb_buffer(gsi);
+ if (ret) {
+ log_event_err("%s: gsi_alloc_trb_failed\n",
+ __func__);
+ break;
+ }
ipa_connect_channels(d_port);
d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG",
__func__);
- } else if (event == EVT_HOST_READY) {
- /*
- * When in a composition such as RNDIS + ADB,
- * RNDIS host sends a GEN_CURRENT_PACKET_FILTER msg
- * to enable/disable flow control eg. during RNDIS
- * adaptor disable/enable from device manager.
- * In the case of the msg to disable flow control,
- * connect IPA channels and enable data path.
- * EVT_HOST_READY is posted to the state machine
- * in the handler for this msg.
- */
- ipa_connect_channels(d_port);
- ipa_data_path_enable(d_port);
- d_port->sm_state = STATE_CONNECTED;
- log_event_dbg("%s: ST_INIT_EVT_HOST_READY",
- __func__);
}
break;
case STATE_CONNECT_IN_PROGRESS:
@@ -648,6 +650,7 @@ static void ipa_work_handler(struct work_struct *w)
&gad_dev->power.usage_count));
} else if (event == EVT_SUSPEND) {
if (peek_event(d_port) == EVT_DISCONNECTED) {
+ read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
usb_gadget_autopm_put_async(d_port->gadget);
@@ -718,19 +721,12 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPENDED:
if (event == EVT_RESUMED) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
ipa_resume_work_handler(d_port);
d_port->sm_state = STATE_CONNECTED;
- /*
- * Increment usage count here to disallow gadget
- * parent suspend. This counter will decrement
- * after IPA handshake is done in disconnect work
- * (due to cable disconnect) or in suspended state.
- */
- usb_gadget_autopm_get_noresume(d_port->gadget);
- log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
- log_event_dbg("%s: get_nores2 = %d", __func__,
- atomic_read(
- &gad_dev->power.usage_count));
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
@@ -1714,6 +1710,92 @@ static int gsi_get_alt(struct usb_function *f, unsigned intf)
return -EINVAL;
}
+static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
+{
+ u32 len_in = 0, len_out = 0;
+ int ret = 0;
+
+ log_event_dbg("allocate trb's buffer\n");
+
+ if (gsi->d_port.in_ep && !gsi->d_port.in_request.buf_base_addr) {
+ log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n",
+ gsi->d_port.in_request.num_bufs,
+ gsi->d_port.in_request.buf_len);
+
+ len_in = gsi->d_port.in_request.buf_len *
+ gsi->d_port.in_request.num_bufs;
+ gsi->d_port.in_request.buf_base_addr =
+ dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ len_in, &gsi->d_port.in_request.dma, GFP_KERNEL);
+ if (!gsi->d_port.in_request.buf_base_addr) {
+ dev_err(&gsi->d_port.gadget->dev,
+ "IN buf_base_addr allocate failed %s\n",
+ gsi->function.name);
+ ret = -ENOMEM;
+ goto fail1;
+ }
+ }
+
+ if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) {
+ log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n",
+ gsi->d_port.out_request.num_bufs,
+ gsi->d_port.out_request.buf_len);
+
+ len_out = gsi->d_port.out_request.buf_len *
+ gsi->d_port.out_request.num_bufs;
+ gsi->d_port.out_request.buf_base_addr =
+ dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ len_out, &gsi->d_port.out_request.dma, GFP_KERNEL);
+ if (!gsi->d_port.out_request.buf_base_addr) {
+ dev_err(&gsi->d_port.gadget->dev,
+ "OUT buf_base_addr allocate failed %s\n",
+ gsi->function.name);
+ ret = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ log_event_dbg("finished allocating trb's buffer\n");
+ return ret;
+
+fail:
+ if (len_in && gsi->d_port.in_request.buf_base_addr) {
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len_in,
+ gsi->d_port.in_request.buf_base_addr,
+ gsi->d_port.in_request.dma);
+ gsi->d_port.in_request.buf_base_addr = NULL;
+ }
+fail1:
+ return ret;
+}
+
+static void gsi_free_trb_buffer(struct f_gsi *gsi)
+{
+ u32 len;
+
+ log_event_dbg("freeing trb's buffer\n");
+
+ if (gsi->d_port.out_ep &&
+ gsi->d_port.out_request.buf_base_addr) {
+ len = gsi->d_port.out_request.buf_len *
+ gsi->d_port.out_request.num_bufs;
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ gsi->d_port.out_request.buf_base_addr,
+ gsi->d_port.out_request.dma);
+ gsi->d_port.out_request.buf_base_addr = NULL;
+ }
+
+ if (gsi->d_port.in_ep &&
+ gsi->d_port.in_request.buf_base_addr) {
+ len = gsi->d_port.in_request.buf_len *
+ gsi->d_port.in_request.num_bufs;
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ gsi->d_port.in_request.buf_base_addr,
+ gsi->d_port.in_request.dma);
+ gsi->d_port.in_request.buf_base_addr = NULL;
+ }
+}
+
static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_gsi *gsi = func_to_gsi(f);
@@ -1827,14 +1909,14 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (gsi->prot_id == IPA_USB_ECM)
gsi->d_port.cdc_filter = DEFAULT_FILTER;
+ post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
/*
- * Increment usage count upon cable connect. Decrement
- * after IPA disconnect is done in disconnect work
- * (due to cable disconnect) or in suspend work.
+ * For RNDIS the event is posted from the flow control
+ * handler which is invoked when the host sends the
+ * GEN_CURRENT_PACKET_FILTER message.
*/
- usb_gadget_autopm_get_noresume(gsi->d_port.gadget);
-
- post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
+ if (gsi->prot_id != IPA_USB_RNDIS)
+ post_event(&gsi->d_port, EVT_HOST_READY);
queue_work(gsi->d_port.ipa_usb_wq,
&gsi->d_port.usb_ipa_w);
}
@@ -2042,7 +2124,6 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
struct usb_ep *ep;
struct usb_cdc_notification *event;
struct usb_function *f = &gsi->function;
- u32 len = 0;
int status;
/* maybe allocate device-global string IDs */
@@ -2162,37 +2243,9 @@ skip_string_id_alloc:
gsi->d_port.in_request.buf_len = info->in_req_buf_len;
gsi->d_port.in_request.num_bufs = info->in_req_num_buf;
- len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs;
- dev_dbg(&cdev->gadget->dev, "%zu %zu\n", gsi->d_port.in_request.buf_len,
- gsi->d_port.in_request.num_bufs);
- gsi->d_port.in_request.buf_base_addr =
- dma_zalloc_coherent(cdev->gadget->dev.parent, len,
- &gsi->d_port.in_request.dma, GFP_KERNEL);
- if (!gsi->d_port.in_request.buf_base_addr) {
- dev_err(&cdev->gadget->dev,
- "IN buf_base_addr allocate failed %s\n",
- gsi->function.name);
- goto fail;
- }
-
if (gsi->d_port.out_ep) {
gsi->d_port.out_request.buf_len = info->out_req_buf_len;
gsi->d_port.out_request.num_bufs = info->out_req_num_buf;
- len =
- gsi->d_port.out_request.buf_len *
- gsi->d_port.out_request.num_bufs;
- dev_dbg(&cdev->gadget->dev, "%zu %zu\n",
- gsi->d_port.out_request.buf_len,
- gsi->d_port.out_request.num_bufs);
- gsi->d_port.out_request.buf_base_addr =
- dma_zalloc_coherent(cdev->gadget->dev.parent, len,
- &gsi->d_port.out_request.dma, GFP_KERNEL);
- if (!gsi->d_port.out_request.buf_base_addr) {
- dev_err(&cdev->gadget->dev,
- "OUT buf_base_addr allocate failed %s\n",
- gsi->function.name);
- goto fail;
- }
}
/* Initialize event queue */
@@ -2263,14 +2316,6 @@ fail:
gsi->d_port.out_ep->driver_data = NULL;
if (gsi->d_port.in_ep && gsi->d_port.in_ep->desc)
gsi->d_port.in_ep->driver_data = NULL;
- if (len && gsi->d_port.in_request.buf_base_addr)
- dma_free_coherent(cdev->gadget->dev.parent, len,
- gsi->d_port.in_request.buf_base_addr,
- gsi->d_port.in_request.dma);
- if (len && gsi->d_port.out_request.buf_base_addr)
- dma_free_coherent(cdev->gadget->dev.parent, len,
- gsi->d_port.out_request.buf_base_addr,
- gsi->d_port.out_request.dma);
log_event_err("%s: bind failed for %s", __func__, f->name);
return -ENOMEM;
}
@@ -2564,8 +2609,6 @@ fail:
static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_gsi *gsi = func_to_gsi(f);
- struct usb_composite_dev *cdev = c->cdev;
- u32 len;
/*
* Use drain_workqueue to accomplish below conditions:
@@ -2600,19 +2643,7 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
if (gsi->c_port.notify) {
kfree(gsi->c_port.notify_req->buf);
usb_ep_free_request(gsi->c_port.notify, gsi->c_port.notify_req);
-
- len =
- gsi->d_port.out_request.buf_len *
- gsi->d_port.out_request.num_bufs;
- dma_free_coherent(&cdev->gadget->dev, len,
- gsi->d_port.out_request.buf_base_addr,
- gsi->d_port.out_request.dma);
}
-
- len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs;
- dma_free_coherent(&cdev->gadget->dev, len,
- gsi->d_port.in_request.buf_base_addr,
- gsi->d_port.in_request.dma);
}
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index dd8149ef097d..f8121eb4f63a 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -799,7 +799,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
of_property_read_u32_array(dev->of_node,
- "qcom,qemu-init-seq",
+ "qcom,emu-init-seq",
qphy->emu_init_seq,
qphy->emu_init_seq_len);
} else {
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 325f5fcf161b..5ec08098d197 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -878,7 +878,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
of_property_read_u32_array(dev->of_node,
- "qcom,qemu-init-seq",
+ "qcom,emu-init-seq",
qphy->emu_init_seq,
qphy->emu_init_seq_len);
} else {
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index eefea9f117c0..0ac5ef4f750c 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -33,6 +33,7 @@
#include "mdss.h"
#include "mdss_dp.h"
#include "mdss_dp_util.h"
+#include "mdss_hdmi_panel.h"
#include "mdss_debug.h"
#define RGB_COMPONENTS 3
@@ -863,7 +864,7 @@ int mdss_dp_wait4train(struct mdss_dp_drv_pdata *dp_drv)
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
-static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
+static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
{
struct mdss_panel_info *pinfo;
struct msm_hdmi_mode_timing_info timing = {0};
@@ -875,8 +876,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
}
dp_drv->ds_data.ds_registered = false;
- ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data,
- DEFAULT_VIDEO_RESOLUTION);
+ ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data, vic);
pinfo = &dp_drv->panel_data.panel_info;
if (ret || !timing.supported || !pinfo) {
@@ -884,6 +884,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
return -EINVAL;
}
+ dp_drv->vic = vic;
pinfo->xres = timing.active_h;
pinfo->yres = timing.active_v;
pinfo->clk_rate = timing.pixel_freq * 1000;
@@ -895,7 +896,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
pinfo->lcdc.v_front_porch = timing.front_porch_v;
pinfo->lcdc.v_pulse_width = timing.pulse_width_v;
- pinfo->type = EDP_PANEL;
+ pinfo->type = DP_PANEL;
pinfo->pdest = DISPLAY_4;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
@@ -904,6 +905,10 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
+ pinfo->is_pluggable = true;
+
+ pr_debug("update res. vic= %d, pclk_rate = %llu\n",
+ dp_drv->vic, pinfo->clk_rate);
return 0;
} /* dp_init_panel_info */
@@ -963,6 +968,9 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
}
+ if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
+ dp_init_panel_info(dp_drv, dp_drv->new_vic);
+
mdss_dp_phy_aux_setup(&dp_drv->phy_io);
mdss_dp_irq_enable(dp_drv);
@@ -1072,6 +1080,44 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return 0;
}
+static void mdss_dp_send_cable_notification(
+ struct mdss_dp_drv_pdata *dp, int val)
+{
+ int state = 0;
+
+ if (!dp) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+ state = dp->sdev.state;
+
+ switch_set_state(&dp->sdev, val);
+
+ DEV_INFO("%s: cable state %s %d\n", __func__,
+ dp->sdev.state == state ?
+ "is same" : "switched to",
+ dp->sdev.state);
+}
+
+static int mdss_dp_register_switch_event(struct mdss_dp_drv_pdata *dp)
+{
+ int rc = -EINVAL;
+
+ if (!dp) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ goto end;
+ }
+
+ dp->sdev.name = "hdmi";
+ rc = switch_dev_register(&dp->sdev);
+ if (rc) {
+ DEV_ERR("%s: display switch registration failed\n", __func__);
+ goto end;
+ }
+end:
+ return rc;
+}
+
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
@@ -1097,9 +1143,6 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
return -ENODEV;
}
- edid_init_data.buf = edid_init_data.buf;
- edid_init_data.buf_size = edid_init_data.buf_size;
-
/* Use the existing EDID buffer for 1080p */
memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1));
dp_drv->panel_data.panel_info.edid_data = edid_data;
@@ -1152,6 +1195,8 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
goto edid_parser_error;
}
+ mdss_dp_send_cable_notification(dp_drv, true);
+
return ret;
edid_parser_error:
@@ -1162,6 +1207,44 @@ vreg_error:
return ret;
}
+static int mdss_dp_check_params(struct mdss_dp_drv_pdata *dp, void *arg)
+{
+ struct mdss_panel_info *var_pinfo, *pinfo;
+ int rc = 0;
+ int new_vic = -1;
+
+ if (!dp || !arg)
+ return 0;
+
+ pinfo = &dp->panel_data.panel_info;
+ var_pinfo = (struct mdss_panel_info *)arg;
+
+ pr_debug("reconfig xres: %d yres: %d, current xres: %d yres: %d\n",
+ var_pinfo->xres, var_pinfo->yres,
+ pinfo->xres, pinfo->yres);
+
+ new_vic = hdmi_panel_get_vic(var_pinfo, &dp->ds_data);
+
+ if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
+ DEV_ERR("%s: invalid or not supported vic\n", __func__);
+ goto end;
+ }
+
+ /*
+ * return value of 1 lets mdss know that panel
+ * needs a reconfig due to new resolution and
+ * it will issue close and open subsequently.
+ */
+ if (new_vic != dp->vic) {
+ rc = 1;
+ DEV_ERR("%s: res change %d ==> %d\n", __func__,
+ dp->vic, new_vic);
+ }
+ dp->new_vic = new_vic;
+end:
+ return rc;
+}
+
static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -1194,9 +1277,13 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
dp->kobj = &fbi->dev->kobj;
dp->fb_node = fbi->node;
mdss_dp_edid_init(pdata);
+ mdss_dp_register_switch_event(dp);
+ break;
+ case MDSS_EVENT_CHECK_PARAMS:
+ rc = mdss_dp_check_params(dp, arg);
break;
default:
- pr_debug("%s: unhandled event=%d\n", __func__, event);
+ pr_debug("unhandled event=%d\n", event);
break;
}
return rc;
@@ -1220,7 +1307,7 @@ static int mdss_dp_device_register(struct mdss_dp_drv_pdata *dp_drv)
{
int ret;
- ret = dp_init_panel_info(dp_drv);
+ ret = dp_init_panel_info(dp_drv, DEFAULT_VIDEO_RESOLUTION);
if (ret) {
DEV_ERR("%s: dp_init_panel_info failed\n", __func__);
return ret;
@@ -1493,6 +1580,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
mutex_lock(&dp_drv->pd_msg_mutex);
dp_drv->cable_connected = false;
mutex_unlock(&dp_drv->pd_msg_mutex);
+ mdss_dp_send_cable_notification(dp_drv, false);
}
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 10fcdec49515..03646cd7cc65 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -21,6 +21,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/usb/usbpd.h>
+#include <linux/switch.h>
#include "mdss_hdmi_util.h"
#include "mdss_hdmi_edid.h"
@@ -430,8 +431,11 @@ struct mdss_dp_drv_pdata {
spinlock_t event_lock;
spinlock_t lock;
struct hdmi_util_ds_data ds_data;
+ struct switch_dev sdev;
struct kobject *kobj;
u32 max_pclk_khz;
+ u32 vic;
+ u32 new_vic;
int fb_node;
};
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 2e54f335e948..4bd705bdc05f 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -389,8 +389,10 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
}
gpio_set_value((ctrl_pdata->rst_gpio), 0);
gpio_free(ctrl_pdata->rst_gpio);
- if (gpio_is_valid(ctrl_pdata->lcd_mode_sel_gpio))
+ if (gpio_is_valid(ctrl_pdata->lcd_mode_sel_gpio)) {
+ gpio_set_value(ctrl_pdata->lcd_mode_sel_gpio, 0);
gpio_free(ctrl_pdata->lcd_mode_sel_gpio);
+ }
}
exit:
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 99a924c38d65..b2c0c78d3f2b 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -331,8 +331,8 @@ static ssize_t mdss_fb_get_type(struct device *dev,
case WRITEBACK_PANEL:
ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
break;
- case EDP_PANEL:
- ret = snprintf(buf, PAGE_SIZE, "edp panel\n");
+ case DP_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "dp panel\n");
break;
default:
ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
index b4d3dad50d45..0335bf900866 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
@@ -150,7 +150,7 @@ enum hdmi_scaling_info {
HDMI_SCALING_HORZ_VERT,
};
-static int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
+int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
struct hdmi_util_ds_data *ds_data)
{
int new_vic = -1;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
index 24d3b9b52798..e5cc1486f222 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
@@ -104,4 +104,7 @@ void *hdmi_panel_init(struct hdmi_panel_init_data *data);
*/
void hdmi_panel_deinit(void *input);
+int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
+ struct hdmi_util_ds_data *ds_data);
+
#endif /* __MDSS_HDMI_PANEL_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 1a0ba8f0e2a7..2218e9c4ac81 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2668,7 +2668,7 @@ int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff)
{
switch (ctl->panel_data->panel_info.type) {
case MIPI_VIDEO_PANEL:
- case EDP_PANEL:
+ case DP_PANEL:
case DTV_PANEL:
return mdss_mdp_video_reconfigure_splash_done(ctl, handoff);
case MIPI_CMD_PANEL:
@@ -3686,7 +3686,7 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
ctl->disable_prefill = false;
switch (pdata->panel_info.type) {
- case EDP_PANEL:
+ case DP_PANEL:
ctl->is_video_mode = true;
ctl->intf_num = MDSS_MDP_INTF0;
ctl->intf_type = MDSS_INTF_EDP;
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 7a49f37660dd..bde137269422 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -51,7 +51,7 @@ struct panel_id {
#define MIPI_CMD_PANEL 9 /* MIPI */
#define WRITEBACK_PANEL 10 /* Wifi display */
#define LVDS_PANEL 11 /* LVDS */
-#define EDP_PANEL 12 /* LVDS */
+#define DP_PANEL 12 /* LVDS */
#define DSC_PPS_LEN 128
@@ -61,7 +61,7 @@ static inline const char *mdss_panel2str(u32 panel)
#define PANEL_NAME(n) [n ## _PANEL] = __stringify(n)
PANEL_NAME(MIPI_VIDEO),
PANEL_NAME(MIPI_CMD),
- PANEL_NAME(EDP),
+ PANEL_NAME(DP),
PANEL_NAME(HDMI),
PANEL_NAME(DTV),
PANEL_NAME(WRITEBACK),
@@ -811,7 +811,7 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info)
case MIPI_CMD_PANEL:
frame_rate = panel_info->mipi.frame_rate;
break;
- case EDP_PANEL:
+ case DP_PANEL:
frame_rate = panel_info->edp.frame_rate;
break;
case WRITEBACK_PANEL:
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index a9577b62cb07..08ccbc9bd71c 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver header file.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -18,12 +18,28 @@
#ifndef __LINUX_FT5X06_TS_H__
#define __LINUX_FT5X06_TS_H__
+#define FT5X06_ID 0x55
+#define FT5X16_ID 0x0A
+#define FT5X36_ID 0x14
+#define FT6X06_ID 0x06
+
struct ft5x06_ts_platform_data {
- unsigned long irqflags;
- u32 x_max;
- u32 y_max;
+ u32 irqflags;
u32 irq_gpio;
+ u32 irq_gpio_flags;
u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ bool no_force_update;
+ bool i2c_pull_up;
int (*power_init)(bool);
int (*power_on)(bool);
};
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 52277f26b5a4..7bf2bff2f173 100755
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -189,6 +189,7 @@ struct wcd9xxx_pdata {
u32 mclk_rate;
u32 dmic_sample_rate;
u32 mad_dmic_sample_rate;
+ u32 ecpp_dmic_sample_rate;
u32 dmic_clk_drv;
u16 use_pinctrl;
};
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 7d1e374e176c..56e78254286e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -174,9 +174,9 @@ enum power_supply_property {
/* Local extensions */
POWER_SUPPLY_PROP_USB_HC,
POWER_SUPPLY_PROP_USB_OTG,
- POWER_SUPPLY_PROP_CHARGE_ENABLED,
POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
diff --git a/include/soc/qcom/irq-helper.h b/include/soc/qcom/irq-helper.h
new file mode 100644
index 000000000000..d992fb6f470a
--- /dev/null
+++ b/include/soc/qcom/irq-helper.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOC_QCOM_IRQ_HELPER_H
+#define __SOC_QCOM_IRQ_HELPER_H
+
+int irq_blacklist_on(void);
+int irq_blacklist_off(void);
+
+#endif
+
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2cf0469712b6..643c68f4c449 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -815,6 +815,12 @@ enum v4l2_mpeg_vidc_extradata {
#define V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO \
V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO
V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO = 28,
+#define V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY \
+ V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY
+ V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY = 29,
+#define V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE \
+ V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE
+ V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE = 30,
};
#define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26)
@@ -1176,6 +1182,23 @@ enum v4l2_mpeg_vidc_video_h264_transform_8x8 {
V4L2_MPEG_VIDC_VIDEO_H264_TRANSFORM_8x8_ENABLE = 1,
};
+#define V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 94)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 95)
+
+enum v4l2_cid_mpeg_vidc_video_full_range {
+ V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE = 0,
+ V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_ENABLE = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 96)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 97)
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h
index 45cc81aaaf17..b259bdef8a93 100644
--- a/include/uapi/media/msm_vidc.h
+++ b/include/uapi/media/msm_vidc.h
@@ -55,6 +55,18 @@ struct msm_vidc_mpeg2_seqdisp_payload {
unsigned int disp_height;
};
+struct msm_vidc_vc1_seqdisp_payload {
+ unsigned int prog_seg_format;
+ unsigned int uv_sampl_fmt;
+ unsigned int color_format;
+ unsigned int color_primaries;
+ unsigned int transfer_char;
+ unsigned int matrix_coeffs;
+ unsigned int aspect_ratio;
+ unsigned int aspect_horiz;
+ unsigned int aspect_vert;
+};
+
struct msm_vidc_input_crop_payload {
unsigned int size;
unsigned int version;
@@ -154,6 +166,13 @@ struct msm_vidc_yuv_stats_payload {
unsigned int frame_difference;
};
+struct msm_vidc_vpx_colorspace_payload {
+ unsigned int color_space;
+ unsigned int yuv_range_flag;
+ unsigned int sumsampling_x;
+ unsigned int sumsampling_y;
+};
+
struct msm_vidc_roi_qp_payload {
int upper_qp_offset;
int lower_qp_offset;
@@ -176,6 +195,23 @@ struct msm_vidc_content_light_level_sei_payload {
unsigned int nMaxPicAverageLight;
};
+struct msm_vidc_vui_display_info_payload {
+ unsigned int video_signal_present_flag;
+ unsigned int video_format;
+ unsigned int bit_depth_y;
+ unsigned int bit_depth_c;
+ unsigned int video_full_range_flag;
+ unsigned int color_description_present_flag;
+ unsigned int color_primaries;
+ unsigned int transfer_characteristics;
+ unsigned int matrix_coefficients;
+ unsigned int chroma_location_info_present_flag;
+ unsigned int chroma_format_idc;
+ unsigned int separate_color_plane_flag;
+ unsigned int chroma_sample_loc_type_top_field;
+ unsigned int chroma_sample_loc_type_bottom_field;
+};
+
enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_NONE = 0x00000000,
MSM_VIDC_EXTRADATA_MB_QUANTIZATION = 0x00000001,
@@ -207,6 +243,9 @@ enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_OUTPUT_CROP
MSM_VIDC_EXTRADATA_OUTPUT_CROP = 0x0700000F,
MSM_VIDC_EXTRADATA_DIGITAL_ZOOM = 0x07000010,
+#define MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO \
+ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO
+ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x070000011,
MSM_VIDC_EXTRADATA_MULTISLICE_INFO = 0x7F100000,
MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
MSM_VIDC_EXTRADATA_INDEX = 0x7F100002,
@@ -214,6 +253,9 @@ enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_METADATA_LTR = 0x7F100004,
MSM_VIDC_EXTRADATA_METADATA_FILLER = 0x7FE00002,
MSM_VIDC_EXTRADATA_METADATA_MBI = 0x7F100005,
+#define MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO \
+ MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO
+ MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO = 0x7F100006,
MSM_VIDC_EXTRADATA_YUVSTATS_INFO = 0x7F100007,
};
enum msm_vidc_interlace_type {
@@ -243,12 +285,90 @@ enum msm_vidc_userdata_type {
MSM_VIDC_USERDATA_TYPE_BOTTOM_FIELD = 0x3,
};
+/* See colour_primaries of ISO/IEC 14496 for significance */
+enum msm_vidc_h264_color_primaries_values {
+ MSM_VIDC_RESERVED_1 = 0,
+ MSM_VIDC_BT709_5 = 1,
+ MSM_VIDC_UNSPECIFIED = 2,
+ MSM_VIDC_RESERVED_2 = 3,
+ MSM_VIDC_BT470_6_M = 4,
+ MSM_VIDC_BT601_6_625 = 5,
+ MSM_VIDC_BT470_6_BG = MSM_VIDC_BT601_6_625,
+ MSM_VIDC_BT601_6_525 = 6,
+ MSM_VIDC_SMPTE_240M = 7,
+ MSM_VIDC_GENERIC_FILM = 8,
+ MSM_VIDC_BT2020 = 9,
+};
+
+enum msm_vidc_vp9_color_primaries_values {
+ MSM_VIDC_CS_UNKNOWN,
+ MSM_VIDC_CS_BT_601,
+ MSM_VIDC_CS_BT_709,
+ MSM_VIDC_CS_SMPTE_170,
+ MSM_VIDC_CS_SMPTE_240,
+ MSM_VIDC_CS_BT_2020,
+ MSM_VIDC_CS_RESERVED,
+ MSM_VIDC_CS_RGB,
+};
+
+enum msm_vidc_h264_matrix_coeff_values {
+ MSM_VIDC_MATRIX_RGB = 0,
+ MSM_VIDC_MATRIX_BT_709_5 = 1,
+ MSM_VIDC_MATRIX_UNSPECIFIED = 2,
+ MSM_VIDC_MATRIX_RESERVED = 3,
+ MSM_VIDC_MATRIX_FCC_47 = 4,
+ MSM_VIDC_MATRIX_601_6_625 = 5,
+ MSM_VIDC_MATRIX_BT470_BG = MSM_VIDC_MATRIX_601_6_625,
+ MSM_VIDC_MATRIX_601_6_525 = 6,
+ MSM_VIDC_MATRIX_SMPTE_170M = MSM_VIDC_MATRIX_601_6_525,
+ MSM_VIDC_MATRIX_SMPTE_240M = 7,
+ MSM_VIDC_MATRIX_Y_CG_CO = 8,
+ MSM_VIDC_MATRIX_BT_2020 = 9,
+ MSM_VIDC_MATRIX_BT_2020_CONST = 10,
+};
+
+enum msm_vidc_h264_transfer_chars_values {
+ MSM_VIDC_TRANSFER_RESERVED_1 = 0,
+ MSM_VIDC_TRANSFER_BT709_5 = 1,
+ MSM_VIDC_TRANSFER_UNSPECIFIED = 2,
+ MSM_VIDC_TRANSFER_RESERVED_2 = 3,
+ MSM_VIDC_TRANSFER_BT_470_6_M = 4,
+ MSM_VIDC_TRANSFER_BT_470_6_BG = 5,
+ MSM_VIDC_TRANSFER_601_6_625 = 6,
+ MSM_VIDC_TRANSFER_601_6_525 = MSM_VIDC_TRANSFER_601_6_625,
+ MSM_VIDC_TRANSFER_SMPTE_240M = 7,
+ MSM_VIDC_TRANSFER_LINEAR = 8,
+ MSM_VIDC_TRANSFER_LOG_100_1 = 9,
+ MSM_VIDC_TRANSFER_LOG_100_SQRT10_1 = 10,
+ MSM_VIDC_TRANSFER_IEC_61966 = 11,
+ MSM_VIDC_TRANSFER_BT_1361 = 12,
+ MSM_VIDC_TRANSFER_SRGB = 13,
+ MSM_VIDC_TRANSFER_BT_2020_10 = 14,
+ MSM_VIDC_TRANSFER_BT_2020_12 = 15,
+};
+
enum msm_vidc_pixel_depth {
MSM_VIDC_BIT_DEPTH_8,
MSM_VIDC_BIT_DEPTH_10,
MSM_VIDC_BIT_DEPTH_UNSUPPORTED = 0XFFFFFFFF,
};
+enum msm_vidc_video_format {
+ MSM_VIDC_COMPONENT,
+ MSM_VIDC_PAL,
+ MSM_VIDC_NTSC,
+ MSM_VIDC_SECAM,
+ MSM_VIDC_MAC,
+ MSM_VIDC_UNSPECIFIED_FORMAT,
+ MSM_VIDC_RESERVED_1_FORMAT,
+ MSM_VIDC_RESERVED_2_FORMAT,
+};
+
+enum msm_vidc_color_desc_flag {
+ MSM_VIDC_COLOR_DESC_NOT_PRESENT,
+ MSM_VIDC_COLOR_DESC_PRESENT,
+};
+
/*enum msm_vidc_pic_struct */
#define MSM_VIDC_PIC_STRUCT_MAYBE_INTERLACED 0x0
#define MSM_VIDC_PIC_STRUCT_PROGRESSIVE 0x1
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 37731292f8a1..1cfd381642da 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -365,21 +365,6 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
goto out_release;
}
- /*
- * By now we've cleared cpu_active_mask, wait for all preempt-disabled
- * and RCU users of this state to go away such that all new such users
- * will observe it.
- *
- * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might
- * not imply sync_sched(), so wait for both.
- *
- * Do sync before park smpboot threads to take care the rcu boost case.
- */
- if (IS_ENABLED(CONFIG_PREEMPT))
- synchronize_rcu_mult(call_rcu, call_rcu_sched);
- else
- synchronize_rcu();
-
smpboot_park_threads(cpu);
/*
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 1626d1553986..8e1aff46ac23 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -375,13 +375,13 @@ country DK: DFS-ETSI
country DM: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
country DO: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -417,8 +417,8 @@ country EE: DFS-ETSI
country EG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (20)
- (5250 - 5330 @ 20), (20), DFS
+ (5170 - 5250 @ 20), (23)
+ (5250 - 5330 @ 20), (23), DFS
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -654,14 +654,14 @@ country IE: DFS-ETSI
country IL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country IN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5735 - 5835 @ 80), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
country IR:
(2402 - 2482 @ 40), (20)
@@ -737,8 +737,8 @@ country KH: DFS-ETSI
country KN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -758,8 +758,8 @@ country KP: DFS-ETSI
country KW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country KY: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -781,7 +781,7 @@ country LB: DFS-FCC
country LC: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5250 - 5330 @ 80), (30), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -866,8 +866,8 @@ country LV: DFS-ETSI
country MA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -984,19 +984,19 @@ country MX: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country NA: DFS-ETSI
- (2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5735 - 5815 @ 80), (30)
-
country MY: DFS-FCC
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (24), AUTO-BW
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5650 @ 160), (24), DFS
- (5735 - 5835 @ 80), (24)
+ (5735 - 5815 @ 80), (24)
+
+country NA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (33)
country NG: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1065,7 +1065,7 @@ country OM: DFS-ETSI
country PA: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -1207,8 +1207,8 @@ country RS: DFS-ETSI
country RU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5730 @ 160), (30), DFS
(5735 - 5835 @ 80), (30)
@@ -1298,7 +1298,7 @@ country SR: DFS-ETSI
country SV: DFS-FCC
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (17)
+ (5170 - 5250 @ 20), (23)
(5250 - 5330 @ 20), (23), DFS
(5735 - 5835 @ 20), (30)
@@ -1333,8 +1333,8 @@ country TH: DFS-FCC
country TN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country TR: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1416,7 +1416,7 @@ country UY: DFS-FCC
country UZ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (20), DFS, AUTO-BW
country VC: DFS-ETSI
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 0af7314f1b7b..11993bb9a639 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -5820,6 +5820,18 @@ static u32 tasha_get_dmic_sample_rate(struct snd_soc_codec *codec,
tx_stream_fs = snd_soc_read(codec, tx_fs_reg) & 0x0F;
dmic_fs = tx_stream_fs <= 4 ? WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ :
WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
+
+ /*
+ * Check for ECPP path selection and DEC1 not connected to
+ * any other audio path to apply ECPP DMIC sample rate
+ */
+ if ((adc_mux_index == 1) &&
+ ((snd_soc_read(codec, WCD9335_CPE_SS_US_EC_MUX_CFG)
+ & 0x0F) == 0x0A) &&
+ ((snd_soc_read(codec, WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0)
+ & 0x0C) == 0x00)) {
+ dmic_fs = pdata->ecpp_dmic_sample_rate;
+ }
} else {
dmic_fs = pdata->dmic_sample_rate;
}
@@ -12476,6 +12488,17 @@ static int tasha_handle_pdata(struct tasha_priv *tasha,
*/
pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
}
+ if (pdata->ecpp_dmic_sample_rate ==
+ WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
+ dev_info(codec->dev,
+ "%s: ecpp_dmic_rate invalid default = %d\n",
+ __func__, def_dmic_rate);
+ /*
+ * use dmic_sample_rate as the default for ECPP DMIC
+ * if ecpp dmic sample rate is undefined
+ */
+ pdata->ecpp_dmic_sample_rate = pdata->dmic_sample_rate;
+ }
if (pdata->dmic_clk_drv ==
WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c
index 45eed236c5c9..8270cfb98de8 100644
--- a/sound/soc/msm/msm-cpe-lsm.c
+++ b/sound/soc/msm/msm-cpe-lsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 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
@@ -1208,6 +1208,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev, "%s: No memory for sound model\n",
__func__);
kfree(session->conf_levels);
+ session->conf_levels = NULL;
return -ENOMEM;
}
session->snd_model_size = snd_model.data_size;
@@ -1219,6 +1220,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
__func__);
kfree(session->conf_levels);
kfree(session->snd_model_data);
+ session->conf_levels = NULL;
+ session->snd_model_data = NULL;
return -EFAULT;
}
@@ -1230,6 +1233,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
__func__, rc);
kfree(session->snd_model_data);
kfree(session->conf_levels);
+ session->snd_model_data = NULL;
+ session->conf_levels = NULL;
return rc;
}
@@ -1243,6 +1248,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
kfree(session->snd_model_data);
kfree(session->conf_levels);
+ session->snd_model_data = NULL;
+ session->conf_levels = NULL;
return rc;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index f577637ee2b2..26528e6a2bb8 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -1070,6 +1070,7 @@ static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream,
__func__, ddp->params_length);
return -EINVAL;
}
+ params_length = ddp->params_length*sizeof(int);
if (params_length > MAX_AC3_PARAM_SIZE) {
/*MAX is 36*sizeof(int) this should not happen*/
pr_err("%s: params_length(%d) is greater than %zd\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-slim.c b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
index 2d8177c9712d..7c56f4ad8884 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-slim.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 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
@@ -467,7 +467,9 @@ static void msm_dai_slim_remove_dai_data(
dai_data_t = &drv_data->slim_dai_data[i];
kfree(dai_data_t->chan_h);
+ dai_data_t->chan_h = NULL;
kfree(dai_data_t->sh_ch);
+ dai_data_t->sh_ch = NULL;
}
}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 8efa04c3807e..b76cb7f4b210 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -3312,7 +3312,7 @@ int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
sizeof(struct afe_port_param_data_v2);
lb_cmd.dst_port_id = rx_port;
- lb_cmd.routing_mode = LB_MODE_EC_REF_VOICE_AUDIO;
+ lb_cmd.routing_mode = LB_MODE_DEFAULT;
lb_cmd.enable = (enable ? 1 : 0);
lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index d0250535c69b..2bf0c490e834 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 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
@@ -348,6 +348,7 @@ void q6lsm_client_free(struct lsm_client *client)
q6lsm_mmap_apr_dereg();
mutex_destroy(&client->cmd_lock);
kfree(client);
+ client = NULL;
}
/*