Merge "soc: qcom: dcc_v2: Avoid dcc_sram_writel overstep"
diff --git a/Documentation/devicetree/bindings/input/qti-haptics.txt b/Documentation/devicetree/bindings/input/qti-haptics.txt
new file mode 100644
index 0000000..2c4f4f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qti-haptics.txt
@@ -0,0 +1,202 @@
+Qualcomm Technologies, Inc. Haptics driver
+
+Haptics peripheral in QTI PMICs can support different type of actuators or
+vibrators:
+ 1) Eccentric Rotation Mass (ERM);
+ 2) Linear Resonant Actuator (LRA).
+This binding document describes the properties for this module.
+
+Properties:
+
+- compatible
+ Usage: required
+ Value type: <string>
+ Definition: It can be one of the following:
+ "qcom,haptics",
+ "qcom,pm660-haptics",
+ "qcom,pm8150b-haptics".
+
+- reg
+ Usage: required
+ Value type: <u32>
+ Definition: Base address of haptics peripheral.
+
+- interrupts
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+ Usage: required
+ Value type: <stringlist>
+ Definition: Interrupt names. This list must match up 1-to-1 with the
+ interrupts specified in the 'interrupts' property. Following
+ interrupts are required: "hap_play_irq", "hap_sc_irq".
+
+- qcom,actuator-type
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the type of the actuator connected on the output of
+ haptics module. Allowed values: "erm", "lra". If this is
+ not specified, then LRA type will be used by default.
+
+- qcom,vmax-mv
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the maximum allowed output voltage in millivolts
+ for the actuator. Value specified here will be rounded
+ off to the closest multiple of 116 mV. Allowed values:
+ 0 to 3596. If this is not specified, then 1800 mV will be
+ used by default.
+
+- qcom,ilim-ma
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the maximum allowed output current in mA for the
+ actuator. Allowed values: 400 or 800. If this is not
+ specified, 400 mA will be used by default.
+
+- qcom,play-rate-us
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the period at which each sample of the 8-byte waveform
+ registers is played. For ERM, this period is flexible and it
+ can be chosen based on the desired shape of the pattern.
+ For LRA, it should be set equal to the resonance period
+ specified in the LRA actuator datasheet. Allowed values are:
+ 0 to 20475. If this is not specified, 5715us play rate is used.
+
+- qcom,external-waveform-source
+ Usage: optional
+ Value type: <string>
+ Definition: The haptics module supports to play with internal constant
+ Vmax strength or play with patterns specified in its internal
+ 8-bytes waveform buffer. It can also play with the audio
+ LINE-IN signal or PWM waveform coming from LINE-IN/PWM pin.
+ This property specify the kind of the waveform resources
+ on the LINE-IN/PWM pins. Allowed values are: "audio", "pwm".
+ If this is not specified, internal signals (Vmax or buffer)
+ will be selected according to the requriement of the playing
+ waveforms.
+
+- vdd-supply
+ Usage: optional
+ Value type: <phandle>
+ Definition: Specifies the phandle of the regulator device which supplies
+ haptics module through VDD_HAP pin. This is only needed if VDD_HAP
+ is supplied from an external boost regulator instead of VPH_PWR.
+
+Following properties are specific only when LRA actuator is used:
+
+- qcom,lra-resonance-sig-shape
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the shape of the LRA resonance drive signal. Allowed
+ values: "sine", "square". If this is not specified, sinusoid
+ resonance driver signal is used.
+
+- qcom,lra-allow-variable-play-rate
+ Usage: optional
+ Value type: <empty>
+ Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each
+ effect could be different with the resonance period of the
+ LRA actuator.
+
+- qcom,lra-auto-resonance-mode
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the auto resonance technique for LRA. Allowed values are:
+ "zxd": zero crossing based discontinuous method;
+ "qwd": quarter wave drive method;
+
+Following properties could be specified in child nodes for defining vibrating
+waveforms/effects:
+
+- qcom,effect-id
+ Usage: required
+ Value type: <u32>
+ Definition: Specifies the effect ID that the client can request to play the
+ corresponding waveform defined in this child node. The ID is
+ normaly defined and sent from userspace for certain user
+ notification event.
+
+- qcom,wf-pattern
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Specifies the waveform pattern in a byte array that will be
+ played for the effect-id. The bit fields of each byte are:
+ [7]: drive direction, 0 - forward; 1 - reverse
+ [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive
+ [5:1]: waveform amplitude
+ [0]: reserved.
+
+- qcom,wf-play-rate-us
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the play period in microseconds for each byte pattern.
+ Allowed values are: 0 to 20475. For LRA actuator, if
+ "qcom,lra-allow-variable-play-rate" is defined, it could be
+ set to other values not equal to the resonance period of the
+ LRA actuator.
+
+- qcom,wf-repeat-count
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the repeat times for the waveform pattern. Allowed
+ values are: 1, 2, 4, 8, 16, 32, 64, 128.
+
+- qcom,wf-s-repeat-count
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the repeat times for each sample defined in
+ qcom,wf-pattern. Allowed values are: 1, 2, 4, 8.
+
+- qcom,wf-brake-pattern
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Specifies the brake pattern with 4 elements used to enable the
+ internal reverse braking. Allowed values for each element are:
+ 0: no brake
+ 1: brake with (Vmax / 2) strength
+ 2: brake with Vmax strength
+ 3: brake with (2 * Vmax) strength
+ If this property is specified with an array of non-zero values,
+ then the brake pattern is applied at the end of the playing
+ waveform.
+
+- qcom,lra-auto-resonance-disable
+ Usage: optional
+ Value type: <empty>
+ Definition: If specified, the hardware feature of LRA auto resonance detection
+ is disabled.
+
+Example:
+ qcom,haptics@c000 {
+ compatible = "qcom,haptics";
+ reg = <0xc000 0x100>;
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "hap-sc-irq", "hap-play-irq";
+ qcom,actuator-type = "lra";
+ qcom,vmax-mv = <1800>;
+ qcom,ilim-ma = <400>;
+ qcom,play-rate-us = <8000>;
+ qcom,lra-resonance-sig-shape = "sine";
+ qcom,lra-auto-resonance-mode = "qwd";
+ qcom,lra-allow-variable-play-rate;
+
+ wf_0 {
+ /* CLICK effect */
+ qcom,effect-id = <0>;
+ qcom,wf-play-rate-us = <6250>;
+ qcom,wf-pattern = [3e 3e 3e];
+ qcom,lra-auto-resonance-disable;
+ };
+
+ wf_5 {
+ /* HEAVY_CLICK effect */
+ qcom,effect-id = <5>;
+ qcom,wf-play-rate-us = <6250>;
+ qcom,wf-pattern = [7e 7e 7e];
+ };
+ };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 642a541..0d36f2a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -33,6 +33,7 @@
qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
qcom,num-gsi-evt-buffs = <0x3>;
qcom,use-pdc-interrupts;
+ qcom,pm-qos-latency = <2 241 271>;
clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
<&clock_gcc GCC_SYS_NOC_USB3_CLK>,
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
index a49003e..eef2ffb 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
@@ -16,3 +16,7 @@
compatible = "qcom,sdxpoorwills";
qcom,msm-id = <334 0x20000>, <335 0x20000>;
};
+
+&emac_hw {
+ emac-core-version = <5>;
+};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index b4ae846..b5474db 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -437,6 +437,7 @@
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_STM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 4d1bda0..787b38e 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -479,6 +479,7 @@
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/sdm670-perf_defconfig b/arch/arm/configs/sdm670-perf_defconfig
index eddab29..33d53db 100644
--- a/arch/arm/configs/sdm670-perf_defconfig
+++ b/arch/arm/configs/sdm670-perf_defconfig
@@ -342,9 +342,12 @@
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
@@ -528,6 +531,7 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
CONFIG_PAGE_EXTENSION=y
CONFIG_DETECT_HUNG_TASK=y
diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig
index 949b279..51ca98d 100644
--- a/arch/arm/configs/sdm670_defconfig
+++ b/arch/arm/configs/sdm670_defconfig
@@ -352,9 +352,12 @@
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
@@ -552,6 +555,7 @@
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index e1fed15..cdbfebd 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -366,6 +366,8 @@
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 54072cc..b3fef2f 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -371,6 +371,8 @@
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 15f53ee..ef0ac4d 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -223,7 +223,7 @@
qcs605-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
-qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc.dtb
+qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc-ipcamera-base.dtb
qcs605-360camera-overlay.dtbo-base := qcs605.dtb
qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
sdm710-cdp-overlay.dtbo-base := sdm710.dtb
@@ -499,8 +499,11 @@
apq8053-lite-dragon-v2.0.dtb \
apq8053-lite-dragon-v2.1.dtb \
apq8053-lite-dragon-v2.2.dtb \
+ apq8053-lite-dragon-v2.2.1.dtb \
apq8053-lite-dragon-v2.3.dtb \
apq8053-lite-dragon-v2.4.dtb \
+ apq8053-lat-concam-dev.dtb \
+ apq8053-lat-concam-proto.dtb \
msm8953-pmi8940-cdp.dtb \
msm8953-pmi8940-mtp.dtb \
msm8953-pmi8937-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
new file mode 100644
index 0000000..b0fee57
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* picked up from base file msm8953-audio.dtsi, enables internal codec config */
+
+&soc {
+ &i2c_2 {
+ status = "okay";
+ wsa881x_i2c_f: wsa881x-i2c-codec@f {
+ status = "okay";
+
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x0f>;
+ qcom,msm-gpios = "wsa_clk",
+ "wsa_reset",
+ "wsa_vi";
+ qcom,pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+ pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+ pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+ pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+ pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+ pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+ pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+ pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+ };
+
+ wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+ status = "okay";
+
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x45>;
+ qcom,msm-gpios = "wsa_clk",
+ "wsa_reset",
+ "wsa_vi";
+ qcom,pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+ pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+ pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+ pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+ pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+ pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+ pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+ pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+ };
+ };
+
+ pcm0: qcom,msm-pcm {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
+ };
+
+ routing: qcom,msm-pcm-routing {
+ compatible = "qcom,msm-pcm-routing";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ pcm1: qcom,msm-pcm-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <1>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "regular";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ cpe: qcom,msm-cpe-lsm {
+ compatible = "qcom,msm-cpe-lsm";
+ };
+
+ lpa: qcom,msm-pcm-lpa {
+ compatible = "qcom,msm-pcm-lpa";
+ };
+
+ compress: qcom,msm-compress-dsp {
+ compatible = "qcom,msm-compress-dsp";
+ };
+
+ voip: qcom,msm-voip-dsp {
+ compatible = "qcom,msm-voip-dsp";
+ };
+
+ voice: qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ qcom,destroy-cvd;
+ };
+
+ stub_codec: qcom,msm-stub-codec {
+ compatible = "qcom,msm-stub-codec";
+ };
+
+ qcom,msm-dai-fe {
+ compatible = "qcom,msm-dai-fe";
+ };
+
+ afe: qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
+ loopback: qcom,msm-pcm-loopback {
+ compatible = "qcom,msm-pcm-loopback";
+ };
+
+ qcom,msm-dai-mi2s {
+ compatible = "qcom,msm-dai-mi2s";
+ dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <0>;
+ qcom,msm-mi2s-rx-lines = <3>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s1: qcom,msm-dai-q6-mi2s-sec {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <1>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <3>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <2>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+
+ dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <5>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <6>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+ };
+
+ lsm: qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
+ qcom,msm-dai-q6 {
+ compatible = "qcom,msm-dai-q6";
+ sb_0_rx: qcom,msm-dai-q6-sb-0-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16384>;
+ };
+
+ sb_0_tx: qcom,msm-dai-q6-sb-0-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16385>;
+ };
+
+ sb_1_rx: qcom,msm-dai-q6-sb-1-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16386>;
+ };
+
+ sb_1_tx: qcom,msm-dai-q6-sb-1-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16387>;
+ };
+
+ sb_2_rx: qcom,msm-dai-q6-sb-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16388>;
+ };
+
+ sb_2_tx: qcom,msm-dai-q6-sb-2-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16389>;
+ };
+
+
+ sb_3_rx: qcom,msm-dai-q6-sb-3-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16390>;
+ };
+
+ sb_3_tx: qcom,msm-dai-q6-sb-3-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16391>;
+ };
+
+ sb_4_rx: qcom,msm-dai-q6-sb-4-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16392>;
+ };
+
+ sb_4_tx: qcom,msm-dai-q6-sb-4-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16393>;
+ };
+
+ sb_5_tx: qcom,msm-dai-q6-sb-5-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16395>;
+ };
+
+ sb_5_rx: qcom,msm-dai-q6-sb-5-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16394>;
+ };
+
+ bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12288>;
+ };
+
+ bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12289>;
+ };
+
+ int_fm_rx: qcom,msm-dai-q6-int-fm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12292>;
+ };
+
+ int_fm_tx: qcom,msm-dai-q6-int-fm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12293>;
+ };
+
+ afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
+
+ incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
+
+ incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32770>;
+ };
+
+ sb_6_rx: qcom,msm-dai-q6-sb-6-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16396>;
+ };
+ };
+
+ hostless: qcom,msm-pcm-hostless {
+ compatible = "qcom,msm-pcm-hostless";
+ };
+
+ dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "primary";
+ };
+
+ hdmi_dba: qcom,msm-hdmi-dba-codec-rx {
+ compatible = "qcom,msm-hdmi-dba-codec-rx";
+ qcom,dba-bridge-chip = "adv7533";
+ };
+
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,smmu-version = <1>;
+ qcom,smmu-enabled;
+ iommus = <&adsp_io 1>;
+ };
+
+ qcom,msm-adsp-loader {
+ compatible = "qcom,adsp-loader";
+ qcom,adsp-state = <0>;
+ };
+
+ qcom,avtimer@c0a300c {
+ compatible = "qcom,avtimer";
+ reg = <0x0c0a300c 0x4>,
+ <0x0c0a3010 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ qcom,clk-div = <27>;
+ };
+
+ int_codec: sound {
+ status = "okay";
+ compatible = "qcom,msm8952-audio-codec";
+ qcom,model = "msm8953-snd-card";
+ reg = <0xc051000 0x4>,
+ <0xc051004 0x4>,
+ <0xc055000 0x4>,
+ <0xc052000 0x4>;
+ reg-names = "csr_gp_io_mux_mic_ctl",
+ "csr_gp_io_mux_spkr_ctl",
+ "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+ "csr_gp_io_mux_quin_ctl";
+
+ qcom,msm-ext-pa = "primary";
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-hs-micbias-type = "external";
+ qcom,msm-micbias1-ext-cap;
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS External", "Handset Mic",
+ "MIC BIAS External2", "Headset Mic",
+ "MIC BIAS External", "Secondary Mic",
+ "AMIC1", "MIC BIAS External",
+ "AMIC2", "MIC BIAS External2",
+ "AMIC3", "MIC BIAS External",
+ "DMIC1", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic1",
+ "DMIC2", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic2",
+ "WSA_SPK OUT", "VDD_WSA_SWITCH",
+ "SpkrMono WSA_IN", "WSA_SPK OUT";
+
+ qcom,hdmi-dba-codec-rx;
+
+ qcom,msm-gpios =
+ "pri_i2s",
+ "dmic_gpio",
+ "quin_i2s",
+ "comp_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "pri_i2s_act",
+ "dmic_gpio_act",
+ "pri_i2s_dmic_gpio_act",
+ "quin_act",
+ "quin_pri_i2s_act",
+ "quin_dmic_gpio_act",
+ "quin_dmic_gpio_pri_i2s_act",
+ "comp_gpio_act",
+ "comp_gpio_pri_i2s_act",
+ "comp_gpio_dmic_gpio_act",
+ "comp_gpio_pri_i2s_dmic_gpio_act",
+ "comp_gpio_quin_act",
+ "comp_gpio_quin_pri_i2s_act",
+ "comp_gpio_quin_dmic_gpio_act",
+ "comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+ pinctrl-names =
+ "all_off",
+ "pri_i2s_act",
+ "dmic_gpio_act",
+ "pri_i2s_dmic_gpio_act",
+ "quin_act",
+ "quin_pri_i2s_act",
+ "quin_dmic_gpio_act",
+ "quin_dmic_gpio_pri_i2s_act",
+ "comp_gpio_act",
+ "comp_gpio_pri_i2s_act",
+ "comp_gpio_dmic_gpio_act",
+ "comp_gpio_pri_i2s_dmic_gpio_act",
+ "comp_gpio_quin_act",
+ "comp_gpio_quin_pri_i2s_act",
+ "comp_gpio_quin_dmic_gpio_act",
+ "comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+ pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-4 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-5 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-6 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-7 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-8 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-9 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-10 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-11 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-12 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-13 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-14 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-15 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_lines_act &pri_tlmm_lines_act
+ &pri_tlmm_ws_act>;
+
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&lpa>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-pcm-lpa";
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s0>, <&dai_mi2s1>,
+ <&dai_mi2s2>, <&dai_mi2s3>,
+ <&dai_mi2s5>, <&dai_mi2s6>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+ <&bt_sco_rx>, <&bt_sco_tx>,
+ <&int_fm_rx>, <&int_fm_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>,
+ <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>;
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+
+ asoc-codec = <&stub_codec>, <&pm8953_diangu_dig>, <&hdmi_dba>;
+ asoc-codec-names = "msm-stub-codec.1", "cajon_codec",
+ "msm-hdmi-dba-codec-rx";
+ asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+ asoc-wsa-codec-prefixes = "SpkrMono";
+
+ msm-vdd-wsa-switch-supply = <&pm8953_l5>;
+ qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+ qcom,msm-vdd-wsa-switch-current = <10000>;
+ };
+
+ clock_audio: audio_ext_clk {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ clock-names = "osr_clk";
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ };
+
+};
+
+&adsp_io {
+ qcom,virtual-addr-pool = <0x10000000 0x0fffffff>;
+ #iommu-cells = <1>;
+};
+
+&clock_audio {
+ status = "okay";
+ qcom,audio-ref-clk-gpio = <&pm8953_gpios 1 0>;
+ qcom,lpass-mclk-id = "pri_mclk";
+ clocks = <&clock_gcc clk_div_clk2>;
+ pinctrl-names = "sleep", "active";
+ pinctrl-0 = <&cdc_mclk2_sleep>;
+ pinctrl-1 = <&cdc_mclk2_active>;
+};
+
+&pm8953_1 {
+ status = "okay";
+ pm8953_diangu_dig: 8953_wcd_codec@f000 {
+ status = "okay";
+ compatible = "qcom,msm8x16_wcd_codec";
+ reg = <0xf000 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0>,
+ <0x1 0xf0 0x1>,
+ <0x1 0xf0 0x2>,
+ <0x1 0xf0 0x3>,
+ <0x1 0xf0 0x4>,
+ <0x1 0xf0 0x5>,
+ <0x1 0xf0 0x6>,
+ <0x1 0xf0 0x7>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int";
+
+ cdc-vdda-cp-supply = <&pm8953_s4>;
+ qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
+ qcom,cdc-vdda-cp-current = <500000>;
+
+ cdc-vdd-io-supply = <&pm8953_l5>;
+ qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-io-current = <5000>;
+
+ cdc-vdd-pa-supply = <&pm8953_s4>;
+ qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+ qcom,cdc-vdd-pa-current = <260000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8953_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3125000 3125000>;
+ qcom,cdc-vdd-mic-bias-current = <5000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-io",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+
+ pm8953_diangu_analog: 8953_wcd_codec@f100 {
+ status = "okay";
+ compatible = "qcom,msm8x16_wcd_codec";
+ reg = <0xf100 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf1 0x0>,
+ <0x1 0xf1 0x1>,
+ <0x1 0xf1 0x2>,
+ <0x1 0xf1 0x3>,
+ <0x1 0xf1 0x4>,
+ <0x1 0xf1 0x5>;
+ interrupt-names = "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
new file mode 100644
index 0000000..7947008
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+ compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+ qcom,board-id= <0x56 0x30>;
+};
+
+&pm8953_mpps {
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ qcom,mode = <4>; // A-input
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+ qcom,master-en = <1>; //Enable MPP
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a200 {
+ /* MPP3 - PA_THERM config */
+ reg = <0xa200 0x100>;
+ com,pin-num = <3>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <2>; /* AMUX 7 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a300 {
+ /* MPP4 - CASE_THERM config */
+ reg = <0xa300 0x100>;
+ com,pin-num = <4>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+};
+
+&tlmm {
+ button_active: button_active {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ icr_int {
+ qcom,pins = <&tlmm 53>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "icr-int";
+ icr_int_default: icr_int_default {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-up; /* PULL UP*/
+ };
+ };
+
+ gcc_gp1_clk_pin {
+ qcom,pins = <&tlmm 33>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "gp1-clk-pin";
+ gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable;
+ };
+ };
+
+ bt_host_wake_default: bt_host_wake_default {
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>;
+ };
+ };
+};
+
+&soc {
+ usb_detect: usb_detect {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+ qcom,enable-button-mode;
+
+ pinctrl-names = "button_active";
+ pinctrl-0 = <&button_active>;
+ };
+
+ hbtp {
+ status = "disabled";
+ };
+};
+
+&usb3 {
+ extcon = <&usb_detect>;
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&modem_mem {
+ reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+ config {
+ /delete-property/ bias-pull-up;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
new file mode 100644
index 0000000..f3124bc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+ compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+ qcom,board-id= <0x56 0x31>;
+};
+
+
+
+&pm8953_mpps {
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ qcom,mode = <4>; // A-input
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+ qcom,master-en = <1>; //Enable MPP
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a200 {
+ /* MPP3 - PA_THERM config */
+ reg = <0xa200 0x100>;
+ com,pin-num = <3>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <2>; /* AMUX 7 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a300 {
+ /* MPP4 - CASE_THERM config */
+ reg = <0xa300 0x100>;
+ com,pin-num = <4>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+};
+
+&tlmm {
+ button_active: button_active {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ icr_int {
+ qcom,pins = <&tlmm 53>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "icr-int";
+ icr_int_default: icr_int_default {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-up; /* PULL UP*/
+ };
+ };
+
+ gcc_gp1_clk_pin {
+ qcom,pins = <&tlmm 33>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "gp1-clk-pin";
+ gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable;
+ };
+ };
+
+ bt_host_wake_default: bt_host_wake_default {
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>;
+ };
+ };
+};
+
+&soc {
+ usb_detect: usb_detect {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+ qcom,enable-button-mode;
+
+ pinctrl-names = "button_active";
+ pinctrl-0 = <&button_active>;
+ };
+
+ hbtp {
+ status = "disabled";
+ };
+};
+
+&usb3 {
+ extcon = <&usb_detect>;
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&modem_mem {
+ reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+ config {
+ /delete-property/ bias-pull-up;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
new file mode 100644
index 0000000..8fae286
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+ rpm-regulator-ldoa18 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ pm8953_l18: regulator-l18 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l18";
+ qcom,set = <3>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <2700000>;
+ };
+
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l9";
+ qcom,set = <3>;
+ regulator-boot-on;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ regulator-boot-on;
+ regulator-always-on;
+ pm8953_l10: regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l10";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+
+ /* L4 for ALS, TMP, Moisture, Image Sensor, PD Control, Thermistor */
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ regulator-boot-on;
+ regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l4";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l2, l7 and l17 for cci */
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l2";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l7";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l17";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l6 for eeprom/ Image sensor */
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l6";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l5 for WSA8815 Speaker amp */
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l5";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
new file mode 100644
index 0000000..b359db3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8953.dtsi"
+#include "msm8953-pinctrl.dtsi"
+/ {
+ model = "Qualcomm Technologies, Inc. APQ 8953";
+ compatible = "qcom,apq8053";
+ qcom,msm-id = <304 0x0>;
+};
+
+/ {
+ /delete-property/ aliases;
+
+ aliases {
+ /* smdtty devices */
+ smd1 = &smdtty_apps_fm;
+ smd2 = &smdtty_apps_riva_bt_acl;
+ smd3 = &smdtty_apps_riva_bt_cmd;
+ smd4 = &smdtty_mbalbridge;
+ smd5 = &smdtty_apps_riva_ant_cmd;
+ smd6 = &smdtty_apps_riva_ant_data;
+ smd7 = &smdtty_data1;
+ smd8 = &smdtty_data4;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd36 = &smdtty_loopback;
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+ sdhc2 = &sdhc_2; /* SDC2 for SD card */
+ i2c1 = &i2c_1;
+ i2c2 = &i2c_2;
+ i2c3 = &i2c_3;
+ i2c4 = &i2c_4;
+ i2c5 = &i2c_5;
+ i2c7 = &i2c_7;
+ i2c8 = &i2c_8;
+ spi3 = &spi_3;
+ };
+
+};
+
+&sdhc_2 {
+ nest,workaround-ocr-add-vio = "VIO_3_3";
+};
+
+&soc {
+ i2c_4: i2c@78b8000 { /* BLSP1 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x78b8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 98 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_4_active>;
+ pinctrl-1 = <&i2c_4_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <86>;
+ dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+ <&dma_blsp1 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c_7: i2c@7AF7000 { /* BLSP2 QUP2 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x7AF7000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 301 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup3_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_7_active>;
+ pinctrl-1 = <&i2c_7_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <84>;
+ dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
+ <&dma_blsp1 9 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c_8: i2c@7AF8000 { /* BLSP2 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x7AF8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 302 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup4_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_8_active>;
+ pinctrl-1 = <&i2c_8_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <84>;
+ dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+ <&dma_blsp1 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-0 = <&gpio_key_active>;
+ pinctrl-1 = <&gpio_key_suspend>;
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&tlmm 87 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ debounce-interval = <15>;
+ };
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&tlmm 86 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&tlmm 85 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ debounce-interval = <15>;
+ };
+ };
+
+ hbtp {
+ compatible = "qcom,hbtp-input";
+ vcc_ana-supply = <&pm8953_l10>;
+ vcc_dig-supply = <&pm8953_l5>;
+ qcom,afe-load = <50000>;
+ qcom,afe-vtg-min = <2850000>;
+ qcom,afe-vtg-max = <2850000>;
+ qcom,dig-load = <15000>;
+ qcom,dig-vtg-min = <1800000>;
+ qcom,dig-vtg-max = <1800000>;
+ };
+};
+
+&soc {
+ qcom,rmnet-ipa {
+ status = "disabled";
+ };
+};
+
+&ipa_hw {
+ status = "disabled";
+};
+
+&secure_mem {
+ status = "disabled";
+};
+
+&tlmm {
+ i2c_4 {
+ i2c_4_active: i2c_4_active {
+ /* active state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_7 {
+ i2c_7_active: i2c_7_active {
+ /* active state */
+ mux {
+ pins = "gpio135", "gpio136";
+ function = "blsp_i2c7";
+ };
+
+ config {
+ pins = "gpio135", "gpio136";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_7_sleep: i2c_7_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio135", "gpio136";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio135", "gpio136";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_8 {
+ i2c_8_active: i2c_8_active {
+ /* active state */
+ mux {
+ pins = "gpio98", "gpio99";
+ function = "blsp_i2c8";
+ };
+
+ config {
+ pins = "gpio98", "gpio99";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_8_sleep: i2c_8_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio98", "gpio99";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio98", "gpio99";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+};
+
+&blsp1_uart0 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+&i2c_4 {
+ status = "ok";
+
+ opt3001@44 {
+ compatible = "ti,opt3001";
+ reg = <0x44>; /* ALS_ADDR connected to ground */
+ status = "okay";
+ };
+
+ ina231@40 {
+ compatible = "ti,ina231";
+ reg = <0x40>;
+ shunt-resistor = <10000>;
+ };
+};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l8>;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+ 384000000>;
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS200_1p8v";
+
+ status = "ok";
+};
+
+&i2c_8 {
+ status = "ok";
+
+ tlc59108@42 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #gpio-cells = <2>;
+ enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+ compatible = "ti,tlc59108";
+ label = "tlc59108";
+ reg = <0x42>;
+
+ chan0@0 {
+ label = "tlc59108:chan0";
+ reg = <0x0>;
+ };
+
+ chan1@1 {
+ label = "tlc59108:chan1";
+ reg = <0x1>;
+ };
+
+ chan2@2 {
+ label = "tlc59108:chan2";
+ reg = <0x2>;
+ };
+
+ chan3@3 {
+ label = "tlc59108:chan3";
+ reg = <0x3>;
+ };
+
+ chan4@4 {
+ label = "tlc59108:chan4";
+ reg = <0x4>;
+ };
+
+ chan5@5 {
+ label = "tlc59108:chan5";
+ reg = <0x5>;
+ };
+
+ chan6@6 {
+ label = "tlc59108:chan6";
+ reg = <0x6>;
+ };
+
+ chan7@7 {
+ label = "tlc59108:chan7";
+ reg = <0x7>;
+ };
+ };
+
+ tlc59116@68 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #gpio-cells = <2>;
+ enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+ compatible = "ti,tlc59116";
+ label = "tlc59116";
+ reg = <0x68>;
+
+ chan0@0 {
+ label = "tlc59116:chan0";
+ reg = <0x0>;
+ };
+
+ chan1@1 {
+ label = "tlc59116:chan1";
+ reg = <0x1>;
+ };
+
+ chan2@2 {
+ label = "tlc59116:chan2";
+ reg = <0x2>;
+ };
+
+ chan3@3 {
+ label = "tlc59116:chan3";
+ reg = <0x3>;
+ };
+
+ chan4@4 {
+ label = "tlc59116:chan4";
+ reg = <0x4>;
+ };
+
+ chan5@5 {
+ label = "tlc59116:chan5";
+ reg = <0x5>;
+ };
+
+ chan6@6 {
+ label = "tlc59116:chan6";
+ reg = <0x6>;
+ };
+
+ chan7@7 {
+ label = "tlc59116:chan7";
+ reg = <0x7>;
+ };
+
+ chan8@8 {
+ label = "tlc59116:chan8";
+ reg = <0x8>;
+ };
+
+ chan9@9 {
+ label = "tlc59116:chan9";
+ reg = <0x9>;
+ };
+
+ chan10@10 {
+ label = "tlc59116:chan10";
+ reg = <0xa>;
+ };
+
+ chan11@11 {
+ label = "tlc59116:chan11";
+ reg = <0xb>;
+ };
+
+ chan12@12 {
+ label = "tlc59116:chan12";
+ reg = <0xc>;
+ };
+
+ chan13@13 {
+ label = "tlc59116:chan13";
+ reg = <0xd>;
+ };
+
+ chan14@14 {
+ label = "tlc59116:chan14";
+ reg = <0xe>;
+ };
+
+ chan15@15 {
+ label = "tlc59116:chan15";
+ reg = <0xf>;
+ };
+ };
+
+};
+
+&i2c_3 {
+ status = "ok";
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0x56>;
+ qcom,eeprom-name = "cat24c512";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x56>;
+ qcom,cci-master = <0>;
+ /* For 512 Kb eeprom chip
+ * add 8 logic eeprom blcoks each is 8KB
+ */
+ qcom,num-blocks = <8>;
+
+ qcom,page0 = <0 0 0 0 0 0>;
+ qcom,poll0 = <0 0 0 0 0 0>;
+ qcom,saddr0 = <0x56>;
+ qcom,mem0 = <8192 0x0000 2 0 1 0>;
+
+ qcom,page1 = <0 0 0 0 0 0>;
+ qcom,poll1 = <0 0 0 0 0 0>;
+ qcom,saddr1 = <0x56>;
+ qcom,mem1 = <8192 0x2000 2 0 1 0>;
+
+ qcom,page2 = <0 0 0 0 0 0>;
+ qcom,poll2 = <0 0 0 0 0 0>;
+ qcom,saddr2 = <0x56>;
+ qcom,mem2 = <8192 0x4000 2 0 1 0>;
+
+ qcom,page3 = <0 0 0 0 0 0>;
+ qcom,poll3 = <0 0 0 0 0 0>;
+ qcom,saddr3 = <0x56>;
+ qcom,mem3 = <8192 0x6000 2 0 1 0>;
+
+ qcom,page4 = <0 0 0 0 0 0>;
+ qcom,poll4 = <0 0 0 0 0 0>;
+ qcom,saddr4 = <0x56>;
+ qcom,mem4 = <8192 0x8000 2 0 1 0>;
+
+ qcom,page5 = <0 0 0 0 0 0>;
+ qcom,poll5 = <0 0 0 0 0 0>;
+ qcom,saddr5 = <0x56>;
+ qcom,mem5 = <8192 0xA000 2 0 1 0>;
+
+ qcom,page6 = <0 0 0 0 0 0>;
+ qcom,poll6 = <0 0 0 0 0 0>;
+ qcom,saddr6 = <0x56>;
+ qcom,mem6 = <8192 0xC000 2 0 1 0>;
+
+ qcom,page7 = <0 0 0 0 0 0>;
+ qcom,poll7 = <0 0 0 0 0 0>;
+ qcom,saddr7 = <0x56>;
+ qcom,mem7 = <8192 0xE000 2 0 1 0>;
+
+ cam_vio-supply = <&pm8953_l6>;
+ qcom,cam-vreg-name = "cam_vio";
+ qcom,cam-vreg-min-voltage = <0>;
+ qcom,cam-vreg-max-voltage = <0>;
+ qcom,cam-vreg-op-mode = <0>;
+ qcom,cam-power-seq-type = "sensor_vreg";
+ qcom,cam-power-seq-val = "cam_vio";
+ qcom,cam-power-seq-cfg-val = <1>;
+ qcom,cam-power-seq-delay = <1>;
+ status = "ok";
+ };
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l10>;
+ qcom,vdd-voltage-level = <18000000 1800000>;
+ qcom,vdd-current-level = <200 22000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l12>;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &tlmm 45 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+ /*cd-gpios = <&tlmm 45 0x1>;*/
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
+&pm8953_typec {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
new file mode 100644
index 0000000..ef4c7a1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lite.dtsi"
+#include "apq8053-lite-dragon-v2.2.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 Lite DragonBoard V2.2.1";
+ compatible = "qcom,apq8053-lite-dragonboard", "qcom,apq8053",
+ "qcom,dragonboard";
+ qcom,board-id = <0x01010320 0>;
+};
+
+&blsp2_uart0 {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_inxnt51021_1200p_video>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index 84c08533..6638aac 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -159,7 +159,7 @@
android {
vbmeta {
compatible = "android,vbmeta";
- parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,dsp,oem";
};
fstab {
/delete-node/ system;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
new file mode 100644
index 0000000..eae1118
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lite.dtsi"
+#include "msm8953-pinctrl.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
+#include "msm8953-mdss-panels.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 Lite SoM";
+};
+
+&soc {
+ vreg_5p0: vreg_5p0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_5p0";
+ status = "ok";
+ enable-active-high;
+ };
+
+ eldo_cam0_vreg: eldo_cam0_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam0_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam1_vreg: eldo_cam1_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam1_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam2_vreg: eldo_cam2_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam2_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam1_vcm_vreg: eldo_cam1_vcm_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam1_vcm_vreg";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ status = "ok";
+ enable-active-high;
+ };
+
+ cnss_sdio: qcom,cnss_sdio {
+ compatible = "qcom,cnss_sdio";
+ subsys-name = "AR6320";
+
+ /**
+ * There is no vdd-wlan on board and this is not for DSRC.
+ * IO and XTAL share the same vreg.
+ */
+ vdd-wlan-io-supply = <&pm8953_l6>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
+ qcom,msm-bus,name = "msm-cnss";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <79 512 0 0>, /* No vote */
+ <79 512 6250 200000>, /* 50 Mbps */
+ <79 512 25000 200000>, /* 200 Mbps */
+ <79 512 2048000 4096000>; /* MAX */
+ };
+
+ bluetooth: bt_qca9379 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&tlmm 76 0>; /* BT_EN */
+ };
+
+ cdc_dmic_gpios: cdc_dmic_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+ pinctrl-1 = <&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+ };
+
+ cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&sec_tlmm_lines_act &ext_amp_ctrl_active>;
+ pinctrl-1 = <&sec_tlmm_lines_sus &ext_amp_ctrl_sleep>;
+ };
+};
+
+&cdc_pdm_comp_lines_act {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>;
+ };
+};
+
+&cdc_pdm_comp_lines_sus {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&rpm_bus {
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+
+ pm8953_l4: regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l4";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+};
+
+&int_codec {
+ status = "ok";
+ qcom,model = "msm8953-openq624-snd-card";
+
+ /delete-property/ qcom,cdc-us-euro-gpios;
+ qcom,msm-hs-micbias-type = "internal";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS Internal1", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "MIC BIAS Internal1", "Secondary Mic",
+ "AMIC1", "MIC BIAS Internal1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS Internal1",
+ "DMIC1", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic1",
+ "DMIC2", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic2";
+
+ qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+ qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+ /delete-property/ asoc-wsa-codec-names;
+ /delete-property/ asoc-wsa-codec-prefixes;
+ /delete-property/ msm-vdd-wsa-switch-supply;
+ /delete-property/ qcom,msm-vdd-wsa-switch-voltage;
+ /delete-property/ qcom,msm-vdd-wsa-switch-current;
+};
+
+&soc {
+ /delete-node/ hbtp;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>;
+};
+
+&blsp1_uart0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+
+&blsp2_uart0 {
+ status = "okay";
+};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l8>;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+ 384000000>;
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ status = "ok";
+};
+
+&tlmm {
+ sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+ mux {
+ pins = "gpio75";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75";
+ drive-strength = <10>;
+ bias-pull-up;
+ output-high;
+ };
+ };
+ sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+ mux {
+ pins = "gpio75";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+};
+
+&sdhc_2 {
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l12>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ qcom,core_3_0v_support;
+ qcom,nonremovable;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_wlan_gpio_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_wlan_gpio_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
+&spmi_bus {
+ qcom,pm8953@0 {
+ qcom,power-on@800 {
+ qcom,resin-gpiobase = <1019>;
+ qcom,pon_2 {
+ /delete-property/ linux,code;
+ };
+ };
+ };
+ qcom,pmi8950@2 {
+ qcom,leds@a100 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa100 0x100>;
+ label = "mpp";
+
+ qcom,led_mpp_2 {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "manual";
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x60>;
+ };
+ };
+
+ qcom,leds@a300 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa300 0x100>;
+ label = "mpp";
+
+ qcom,led_mpp_4 {
+ label = "mpp";
+ linux,name = "blue";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "manual";
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x60>;
+ };
+ };
+ };
+};
+
+&pm8953_typec {
+ ss-mux-supply = <&pm8953_l13>;
+ qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec_ssmux_config>;
+};
+
+/{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&pmi_haptic{
+ status = "disabled";
+ qcom,actuator-type = "lra";
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
+&flash_led {
+ status = "disabled";
+};
+
+&pm8953_pwm {
+ status = "ok";
+};
+
+&pm8953_vadc {
+ /delete-node/ chan@13;
+};
+
+&pmi8950_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmi_gpio1_default>;
+ pmi_gpio1_default: pmi8950_gpio1 {
+ pins = "gpio1";
+ function = "normal";
+ input-enable;
+ power-source = <0>;
+ status = "okay";
+ };
+};
+
+&pmi8950_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_fet_wled_pwr_en_default>;
+ ext_fet_wled_pwr_en_default: pmi8950_mpp3 {
+ pins = "mpp3"; /* MPP_3 */
+ function = "digital"; /* Digital */
+ output-high; /* Output */
+ drive-strength = <2>; /* 1.8 mA */
+ power-source = <1>;
+ bias-disable = <0>; /* no pull */
+ status = "okay";
+ };
+};
+
+&pm8953_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm_gpio1_div_clk2_default>;
+ pm_gpio1_div_clk2_default: pm8953_gpio1 {
+ pins = "gpio1";
+ function = "normal";
+ output-high;
+ power-source = <1>;
+ status = "okay";
+ };
+};
+
+&pm8953_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm_mpp4_wled_pwm_ctrl_default>;
+ pm_mpp4_wled_pwm_ctrl_default: pm8953_mpp4 {
+ pins = "mpp4"; /* WLED_PWM_CTRL */
+ function = "digital"; /* Digital */
+ output-high; /* Output */
+ drive-strength = <2>; /* 1.8 mA */
+ power-source = <0>; /* VPH_PWR */
+ qcom,dtest = <1>; /* DTEST1 */
+ bias-disable = <0>; /* no pull */
+ status = "okay";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
new file mode 100644
index 0000000..2131aec
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
@@ -0,0 +1,106 @@
+/* Novatek Android Driver Sample Code for Novatek chipset
+*
+* Copyright (C) 2015 Novatek Microelectronics Corp.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+*/
+
+&mdss_mdp {
+ dsi_inxnt51021_1200p_video: qcom,mdss_dsi_inxnt51021_1200p_video {
+ qcom,mdss-dsi-panel-name = "inxnt51021 1200p video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1200>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <100>;
+ qcom,mdss-dsi-h-back-porch = <32>;
+ qcom,mdss-dsi-h-pulse-width = <1>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <14>;
+ qcom,mdss-dsi-v-front-porch = <25>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 23 01 00 00 01 00 02 8F A5
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 00 00 02 84 00
+ 23 01 00 00 00 00 02 8C 84
+ 23 01 00 00 00 00 02 C5 50
+ 23 01 00 00 00 00 02 C7 50
+ 23 01 00 00 00 00 02 85 04
+ 23 01 00 00 00 00 02 86 08
+ 23 01 00 00 00 00 02 83 AA
+ 23 01 00 00 00 00 02 84 11
+ 23 01 00 00 00 00 02 9C 10
+ 23 01 00 00 00 00 02 A9 4B
+ 23 01 00 00 00 00 02 A0 36
+ 23 01 00 00 00 00 02 A1 36
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 83 BB
+ 23 01 00 00 00 00 02 84 22
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 83 CC
+ 23 01 00 00 00 00 02 84 33
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 8F 00
+ ];
+ qcom,mdss-dsi-off-command = [
+ 23 01 00 00 01 00 02 8F A5
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 78 00 02 84 00
+ 05 01 00 00 78 00 02 10 00
+ ];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ //qcom,cont-splash-enabled;
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [f2 3a 28 00 6c 70 2c 3e 2e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0e>;
+ qcom,mdss-dsi-t-clk-pre = <0x33>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-force-clock-lane-hs;
+ //qcom,platform-bklight-en-gpio = <&tlmm 46 0>;
+ //qcom,mdss-dsi-lcden-ctrl = <&tlmm 61 0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ //qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ //qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ //qcom,mdss-dsi-pwm-gpio = <&pm8953_mpps 4 0>;
+ qcom,mdss-pan-physical-width-dimension = <135>;
+ qcom,mdss-pan-physical-height-dimension = <216>;
+ //qcom,mdss-dsi-reset-sequence = <1 10>, <0 5>, <1 50>;
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
index e2fbc9e..ee2d0ac 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -113,17 +113,17 @@
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
- pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-names = "default";
pinctrl-0 = <&gpio_key_active>;
- pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
gpios = <&msm_gpio 91 0x1>;
linux,input-type = <1>;
linux,code = <0x210>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
camera_snapshot {
@@ -131,8 +131,9 @@
gpios = <&msm_gpio 92 0x1>;
linux,input-type = <1>;
linux,code = <0x2fe>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
vol_up {
@@ -140,8 +141,9 @@
gpios = <&msm_gpio 90 0x1>;
linux,input-type = <1>;
linux,code = <115>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index be6ab79..fa218ca 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -27,6 +27,7 @@
#include "dsi-panel-hx83100a-800p-video.dtsi"
#include "dsi-panel-boent51021-1200p-video.dtsi"
#include "dsi-panel-hx8394d-wxga-video.dtsi"
+#include "dsi-panel-inxnt51021-1200p-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -187,9 +188,17 @@
};
&dsi_hx8394d_kingdisplay_vid {
- qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 07 02 03 01 03 04 a0];
+ qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 07 02 03 01 03 04 a0];
+};
+
+&dsi_inxnt51021_1200p_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 1D 08 0A 06 03 04 a0];
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
new file mode 100644
index 0000000..622230c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QCS605 LC SoC Ipcam base";
+ compatible = "qcom,qcs605";
+ qcom,board-id = <0 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
index c7912d6..0cb7c33 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
@@ -26,5 +26,5 @@
model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
qcom,msm-id = <347 0x0>;
- qcom,board-id = <8 6>;
+ qcom,board-id = <0x020208 4>;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
index 90dcd7b..37dc8e0 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
@@ -20,5 +20,5 @@
/ {
model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
- qcom,board-id = <8 6>;
+ qcom,board-id = <0x020208 4>;
};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
index 378c4a1..d89a60e 100644
--- a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -91,3 +91,8 @@
qcom,afe-power-off-delay-us = <6>;
};
};
+
+&qupv3_se5_i2c {
+ status = "disabled";
+};
+
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 6420837..02d853a 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -72,6 +72,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 4040863..a2b4abb 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -75,6 +75,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f3c1e7b..698857a 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -73,6 +73,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 8401173c..6434a8e 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -76,6 +76,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b7e61c8..c582701 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -313,6 +313,7 @@
unsigned int latency;
bool glink;
bool legacy;
+ bool secure_flag;
spinlock_t ctxlock;
struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX];
};
@@ -3215,7 +3216,8 @@
if (err)
goto bail;
/* Check to see if the device node is non-secure */
- if (fl->dev_minor == MINOR_NUM_DEV) {
+ if (fl->dev_minor == MINOR_NUM_DEV &&
+ fl->apps->secure_flag == true) {
/*
* For non secure device node check and make sure that
* the channel allows non-secure access
@@ -3863,10 +3865,13 @@
VERIFY(err, !of_property_read_u32(dev->of_node,
"qcom,secure-domains",
&secure_domains));
- if (!err)
+ if (!err) {
+ me->secure_flag = true;
configure_secure_channels(secure_domains);
- else
+ } else {
+ me->secure_flag = false;
pr_info("adsprpc: unable to read the domain configuration from dts\n");
+ }
}
}
if (of_device_is_compatible(dev->of_node,
@@ -4021,6 +4026,7 @@
fastrpc_init(me);
me->dev = NULL;
me->glink = true;
+ me->secure_flag = false;
VERIFY(err, 0 == platform_driver_register(&fastrpc_driver));
if (err)
goto register_bail;
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index e692f660..3c75997 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -83,7 +83,7 @@
};
static struct system_pm_ops *sys_pm_ops;
-
+static DEFINE_SPINLOCK(bc_timer_lock);
struct lpm_cluster *lpm_root_node;
@@ -1029,6 +1029,7 @@
struct lpm_cluster_level *level = &cluster->levels[idx];
struct cpumask online_cpus, cpumask;
unsigned int cpu;
+ int ret = 0;
cpumask_and(&online_cpus, &cluster->num_children_in_sync,
cpu_online_mask);
@@ -1067,9 +1068,13 @@
clear_predict_history();
clear_cl_predict_history();
- if (sys_pm_ops && sys_pm_ops->enter)
- if ((sys_pm_ops->enter(&cpumask)))
+ if (sys_pm_ops && sys_pm_ops->enter) {
+ spin_lock(&bc_timer_lock);
+ ret = sys_pm_ops->enter(&cpumask);
+ spin_unlock(&bc_timer_lock);
+ if (ret)
return -EBUSY;
+ }
}
/* Notify cluster enter event after successfully config completion */
cluster_notify(cluster, level, true);
@@ -1202,8 +1207,11 @@
level = &cluster->levels[cluster->last_level];
if (level->notify_rpm)
- if (sys_pm_ops && sys_pm_ops->exit)
+ if (sys_pm_ops && sys_pm_ops->exit) {
+ spin_lock(&bc_timer_lock);
sys_pm_ops->exit();
+ spin_unlock(&bc_timer_lock);
+ }
update_debug_pc_event(CLUSTER_EXIT, cluster->last_level,
cluster->num_children_in_sync.bits[0],
@@ -1298,6 +1306,7 @@
{
int affinity_level = 0, state_id = 0, power_state = 0;
bool success = false;
+ int ret = 0;
/*
* idx = 0 is the default LPM state
*/
@@ -1310,7 +1319,17 @@
}
if (from_idle && cpu->levels[idx].use_bc_timer) {
- if (tick_broadcast_enter())
+ /*
+ * tick_broadcast_enter can change the affinity of the
+ * broadcast timer interrupt, during which interrupt will
+ * be disabled and enabled back. To avoid system pm ops
+ * doing any interrupt state save or restore in between
+ * this window hold the lock.
+ */
+ spin_lock(&bc_timer_lock);
+ ret = tick_broadcast_enter();
+ spin_unlock(&bc_timer_lock);
+ if (ret)
return success;
}
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index f8a987a..ee32e1a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -184,6 +184,15 @@
reporting the change in status of the KPDPWR_N line (connected to the
power-key) as well as reset features.
+config INPUT_QTI_HAPTICS
+ tristate "Haptics support for QTI PMIC"
+ depends on MFD_SPMI_PMIC
+ help
+ This option enables device driver support for the haptics peripheral
+ found on Qualcomm Technologies, Inc. PMICs. The haptics peripheral
+ is capable of driving both LRA and ERM vibrators. This module provides
+ haptic feedback for user actions such as a long press on the touch screen.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 149273c..c08ee8f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -61,6 +61,7 @@
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_QPNP_POWER_ON) += qpnp-power-on.o
+obj-$(CONFIG_INPUT_QTI_HAPTICS) += qti-haptics.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c
new file mode 100644
index 0000000..d63ced7
--- /dev/null
+++ b/drivers/input/misc/qti-haptics.c
@@ -0,0 +1,1471 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+enum actutor_type {
+ ACT_LRA,
+ ACT_ERM,
+};
+
+enum lra_res_sig_shape {
+ RES_SIG_SINE,
+ RES_SIG_SQUARE,
+};
+
+enum lra_auto_res_mode {
+ AUTO_RES_MODE_ZXD,
+ AUTO_RES_MODE_QWD,
+};
+
+enum wf_src {
+ INT_WF_VMAX,
+ INT_WF_BUFFER,
+ EXT_WF_AUDIO,
+ EXT_WF_PWM,
+};
+
+enum haptics_custom_effect_param {
+ CUSTOM_DATA_EFFECT_IDX,
+ CUSTOM_DATA_TIMEOUT_SEC_IDX,
+ CUSTOM_DATA_TIMEOUT_MSEC_IDX,
+ CUSTOM_DATA_LEN,
+};
+
+/* common definitions */
+#define HAP_BRAKE_PATTERN_MAX 4
+#define HAP_WAVEFORM_BUFFER_MAX 8
+#define HAP_VMAX_MV_DEFAULT 1800
+#define HAP_VMAX_MV_MAX 3596
+#define HAP_ILIM_MA_DEFAULT 400
+#define HAP_ILIM_MA_MAX 800
+#define HAP_PLAY_RATE_US_DEFAULT 5715
+#define HAP_PLAY_RATE_US_MAX 20475
+#define HAP_PLAY_RATE_US_LSB 5
+#define VMAX_MIN_PLAY_TIME_US 20000
+#define HAP_SC_DET_MAX_COUNT 5
+#define HAP_SC_DET_TIME_US 1000000
+#define FF_EFFECT_COUNT_MAX 32
+
+/* haptics module register definitions */
+#define REG_HAP_STATUS1 0x0A
+#define HAP_SC_DET_BIT BIT(3)
+#define HAP_BUSY_BIT BIT(1)
+
+#define REG_HAP_EN_CTL1 0x46
+#define HAP_EN_BIT BIT(7)
+
+#define REG_HAP_EN_CTL2 0x48
+#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
+#define HAP_BRAKE_EN_BIT BIT(0)
+
+#define REG_HAP_EN_CTL3 0x4A
+#define HAP_HBRIDGE_EN_BIT BIT(7)
+#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
+#define HAP_ILIM_EN_BIT BIT(5)
+#define HAP_ILIM_CC_EN_BIT BIT(4)
+#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
+#define HAP_DAC_EN_BIT BIT(2)
+#define HAP_ZX_HYST_EN_BIT BIT(1)
+#define HAP_PWM_CTL_EN_BIT BIT(0)
+
+#define REG_HAP_AUTO_RES_CTRL 0x4B
+#define HAP_AUTO_RES_EN_BIT BIT(7)
+#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
+#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
+#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
+#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
+#define AUTO_RES_EN_DLY(x) x
+
+#define REG_HAP_CFG1 0x4C
+#define REG_HAP_CFG2 0x4D
+#define HAP_LRA_RES_TYPE_BIT BIT(0)
+
+#define REG_HAP_SEL 0x4E
+#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
+#define HAP_WF_SOURCE_SHIFT 4
+#define HAP_WF_TRIGGER_BIT BIT(0)
+#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
+
+#define REG_HAP_AUTO_RES_CFG 0x4F
+#define HAP_AUTO_RES_MODE_BIT BIT(7)
+#define HAP_AUTO_RES_MODE_SHIFT 7
+#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
+#define HAP_CAL_EOP_EN_BIT BIT(3)
+#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
+#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
+
+#define REG_HAP_SLEW_CFG 0x50
+#define REG_HAP_VMAX_CFG 0x51
+#define HAP_VMAX_SIGN_BIT BIT(7)
+#define HAP_VMAX_OVD_BIT BIT(6)
+#define HAP_VMAX_MV_MASK GENMASK(5, 1)
+#define HAP_VMAX_MV_SHIFT 1
+#define HAP_VMAX_MV_LSB 116
+
+#define REG_HAP_ILIM_CFG 0x52
+#define REG_HAP_SC_DEB_CFG 0x53
+#define REG_HAP_RATE_CFG1 0x54
+#define REG_HAP_RATE_CFG2 0x55
+#define REG_HAP_INTERNAL_PWM 0x56
+#define REG_HAP_EXTERNAL_PWM 0x57
+#define REG_HAP_PWM 0x58
+
+#define REG_HAP_SC_CLR 0x59
+#define HAP_SC_CLR_BIT BIT(0)
+
+#define REG_HAP_ZX_CFG 0x5A
+#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
+#define ZX_DET_DEB_10US 0
+#define ZX_DET_DEB_20US 1
+#define ZX_DET_DEB_40US 2
+#define ZX_DET_DEB_80US 3
+
+#define REG_HAP_BRAKE 0x5C
+#define HAP_BRAKE_PATTERN_MASK 0x3
+#define HAP_BRAKE_PATTERN_SHIFT 2
+
+#define REG_HAP_WF_REPEAT 0x5E
+#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
+#define HAP_WF_REPEAT_SHIFT 4
+#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
+
+#define REG_HAP_WF_S1 0x60
+#define HAP_WF_SIGN_BIT BIT(7)
+#define HAP_WF_OVD_BIT BIT(6)
+#define HAP_WF_AMP_BIT GENMASK(5, 1)
+#define HAP_WF_AMP_SHIFT 1
+
+#define REG_HAP_PLAY 0x70
+#define HAP_PLAY_BIT BIT(7)
+
+#define REG_HAP_SEC_ACCESS 0xD0
+
+struct qti_hap_effect {
+ int id;
+ u8 *pattern;
+ int pattern_length;
+ u16 play_rate_us;
+ u8 wf_repeat_n;
+ u8 wf_s_repeat_n;
+ u8 brake[HAP_BRAKE_PATTERN_MAX];
+ int brake_pattern_length;
+ bool brake_en;
+ bool lra_auto_res_disable;
+};
+
+struct qti_hap_play_info {
+ struct qti_hap_effect *effect;
+ u16 vmax_mv;
+ int length_us;
+ int playing_pos;
+ bool playing_pattern;
+};
+
+struct qti_hap_config {
+ enum actutor_type act_type;
+ enum lra_res_sig_shape lra_shape;
+ enum lra_auto_res_mode lra_auto_res_mode;
+ enum wf_src ext_src;
+ u16 vmax_mv;
+ u16 ilim_ma;
+ u16 play_rate_us;
+ bool lra_allow_variable_play_rate;
+ bool use_ext_wf_src;
+};
+
+struct qti_hap_chip {
+ struct platform_device *pdev;
+ struct device *dev;
+ struct regmap *regmap;
+ struct input_dev *input_dev;
+ struct pwm_device *pwm_dev;
+ struct qti_hap_config config;
+ struct qti_hap_play_info play;
+ struct qti_hap_effect *predefined;
+ struct qti_hap_effect constant;
+ struct regulator *vdd_supply;
+ struct hrtimer stop_timer;
+ spinlock_t bus_lock;
+ ktime_t last_sc_time;
+ int play_irq;
+ int sc_irq;
+ int effects_count;
+ int sc_det_count;
+ u16 reg_base;
+ bool perm_disable;
+ bool play_irq_en;
+ bool vdd_enabled;
+};
+
+static int wf_repeat[8] = {1, 2, 4, 8, 16, 32, 64, 128};
+static int wf_s_repeat[4] = {1, 2, 4, 8};
+
+static inline bool is_secure(u8 addr)
+{
+ return ((addr & 0xFF) > 0xD0);
+}
+
+static int qti_haptics_read(struct qti_hap_chip *chip,
+ u8 addr, u8 *val, int len)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+
+ rc = regmap_bulk_read(chip->regmap, chip->reg_base + addr, val, len);
+ if (rc < 0)
+ dev_err(chip->dev, "Reading addr 0x%x failed, rc=%d\n",
+ addr, rc);
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+ return rc;
+}
+
+static int qti_haptics_write(struct qti_hap_chip *chip,
+ u8 addr, u8 *val, int len)
+{
+ int rc = 0, i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+ if (is_secure(addr)) {
+ for (i = 0; i < len; i++) {
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + REG_HAP_SEC_ACCESS,
+ 0xA5);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+ rc);
+ goto unlock;
+ }
+
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + addr + i, val[i]);
+ if (rc < 0) {
+ dev_err(chip->dev, "write val 0x%x to addr 0x%x failed, rc=%d\n",
+ val[i], addr + i, rc);
+ goto unlock;
+ }
+ }
+ } else {
+ if (len > 1)
+ rc = regmap_bulk_write(chip->regmap,
+ chip->reg_base + addr, val, len);
+ else
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + addr, *val);
+
+ if (rc < 0)
+ dev_err(chip->dev, "write addr 0x%x failed, rc=%d\n",
+ addr, rc);
+ }
+
+ for (i = 0; i < len; i++)
+ dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x\n",
+ addr + i, val[i]);
+
+unlock:
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+ return rc;
+}
+
+static int qti_haptics_masked_write(struct qti_hap_chip *chip, u8 addr,
+ u8 mask, u8 val)
+{
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+ if (is_secure(addr)) {
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + REG_HAP_SEC_ACCESS,
+ 0xA5);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+ rc);
+ goto unlock;
+ }
+ }
+
+ rc = regmap_update_bits(chip->regmap, chip->reg_base + addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
+ addr, val, mask, rc);
+
+ dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x\n",
+ addr, val, mask);
+unlock:
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+ return rc;
+}
+
+static void construct_constant_waveform_in_pattern(
+ struct qti_hap_play_info *play)
+{
+ struct qti_hap_chip *chip = container_of(play,
+ struct qti_hap_chip, play);
+ struct qti_hap_config *config = &chip->config;
+ struct qti_hap_effect *effect = play->effect;
+ int total_samples, samples, left, magnitude, i, j, k;
+ int delta = INT_MAX, delta_min = INT_MAX;
+
+ /* Using play_rate_us in config for constant waveform */
+ effect->play_rate_us = config->play_rate_us;
+ total_samples = play->length_us / effect->play_rate_us;
+ left = play->length_us % effect->play_rate_us;
+
+ if (total_samples <= HAP_WAVEFORM_BUFFER_MAX) {
+ effect->pattern_length = total_samples;
+ effect->wf_s_repeat_n = 0;
+ effect->wf_repeat_n = 0;
+ } else {
+ /*
+ * Find a closest setting to achieve the constant waveform
+ * with the required length by using buffer waveform source:
+ * play_length_us = pattern_length * wf_s_repeat_n
+ * * wf_repeat_n * play_rate_us
+ */
+ for (i = 0; i < ARRAY_SIZE(wf_repeat); i++) {
+ for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++) {
+ for (k = 1; k <= HAP_WAVEFORM_BUFFER_MAX; k++) {
+ samples = k * wf_s_repeat[j] *
+ wf_repeat[i];
+ delta = abs(total_samples - samples);
+ if (delta < delta_min) {
+ delta_min = delta;
+ effect->pattern_length = k;
+ effect->wf_s_repeat_n = j;
+ effect->wf_repeat_n = i;
+ }
+ if (samples > total_samples)
+ break;
+ }
+ }
+ }
+ }
+
+ if (left > 0 && effect->pattern_length < HAP_WAVEFORM_BUFFER_MAX)
+ effect->pattern_length++;
+
+ play->length_us = effect->pattern_length * effect->play_rate_us;
+ dev_dbg(chip->dev, "total_samples = %d, pattern_length = %d, wf_s_repeat = %d, wf_repeat = %d\n",
+ total_samples, effect->pattern_length,
+ wf_s_repeat[effect->wf_s_repeat_n],
+ wf_repeat[effect->wf_repeat_n]);
+
+ for (i = 0; i < effect->pattern_length; i++) {
+ magnitude = play->vmax_mv / HAP_VMAX_MV_LSB;
+ effect->pattern[i] = (u8)magnitude << HAP_WF_AMP_SHIFT;
+ }
+}
+
+static int qti_haptics_config_wf_buffer(struct qti_hap_chip *chip)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_effect *effect = play->effect;
+ u8 addr, pattern[HAP_WAVEFORM_BUFFER_MAX] = {0};
+ int rc = 0;
+ size_t len;
+
+ if (play->playing_pos == effect->pattern_length) {
+ dev_dbg(chip->dev, "pattern playing done\n");
+ return 0;
+ }
+
+ if (effect->pattern_length - play->playing_pos
+ >= HAP_WAVEFORM_BUFFER_MAX)
+ len = HAP_WAVEFORM_BUFFER_MAX;
+ else
+ len = effect->pattern_length - play->playing_pos;
+
+ dev_dbg(chip->dev, "copy %d bytes start from %d\n",
+ (int)len, play->playing_pos);
+ memcpy(pattern, &effect->pattern[play->playing_pos], len);
+
+ play->playing_pos += len;
+
+ addr = REG_HAP_WF_S1;
+ rc = qti_haptics_write(chip, REG_HAP_WF_S1, pattern,
+ HAP_WAVEFORM_BUFFER_MAX);
+ if (rc < 0)
+ dev_err(chip->dev, "Program WF_SAMPLE failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_wf_repeat(struct qti_hap_chip *chip)
+{
+ struct qti_hap_effect *effect = chip->play.effect;
+ u8 addr, mask, val;
+ int rc = 0;
+
+ addr = REG_HAP_WF_REPEAT;
+ mask = HAP_WF_REPEAT_MASK | HAP_WF_S_REPEAT_MASK;
+ val = effect->wf_repeat_n << HAP_WF_REPEAT_SHIFT;
+ val |= effect->wf_s_repeat_n;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "Program WF_REPEAT failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_play(struct qti_hap_chip *chip, bool play)
+{
+ int rc = 0;
+ u8 val = play ? HAP_PLAY_BIT : 0;
+
+ rc = qti_haptics_write(chip,
+ REG_HAP_PLAY, &val, 1);
+ if (rc < 0)
+ dev_err(chip->dev, "%s playing haptics failed, rc=%d\n",
+ play ? "start" : "stop", rc);
+
+ return rc;
+}
+
+static int qti_haptics_module_en(struct qti_hap_chip *chip, bool en)
+{
+ int rc = 0;
+ u8 val = en ? HAP_EN_BIT : 0;
+
+ rc = qti_haptics_write(chip,
+ REG_HAP_EN_CTL1, &val, 1);
+ if (rc < 0)
+ dev_err(chip->dev, "%s haptics failed, rc=%d\n",
+ en ? "enable" : "disable", rc);
+
+
+ return rc;
+}
+
+static int qti_haptics_config_vmax(struct qti_hap_chip *chip, int vmax_mv)
+{
+ u8 addr, mask, val;
+ int rc;
+
+ addr = REG_HAP_VMAX_CFG;
+ mask = HAP_VMAX_MV_MASK;
+ val = (vmax_mv / HAP_VMAX_MV_LSB) << HAP_VMAX_MV_SHIFT;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "write VMAX_CFG failed, rc=%d\n",
+ rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_wf_src(struct qti_hap_chip *chip,
+ enum wf_src src)
+{
+ u8 addr, mask, val = 0;
+ int rc;
+
+ addr = REG_HAP_SEL;
+ mask = HAP_WF_SOURCE_MASK | HAP_WF_TRIGGER_BIT;
+ val = src << HAP_WF_SOURCE_SHIFT;
+ if (src == EXT_WF_AUDIO || src == EXT_WF_PWM)
+ val |= HAP_WF_TRIGGER_BIT;
+
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set HAP_SEL failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_play_rate_us(struct qti_hap_chip *chip,
+ int play_rate_us)
+{
+ u8 addr, val[2];
+ int tmp, rc;
+
+ addr = REG_HAP_RATE_CFG1;
+ tmp = play_rate_us / HAP_PLAY_RATE_US_LSB;
+ val[0] = tmp & 0xff;
+ val[1] = (tmp >> 8) & 0xf;
+ rc = qti_haptics_write(chip, addr, val, 2);
+ if (rc < 0)
+ dev_err(chip->dev, "write play_rate failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake)
+{
+ u8 addr, mask, val;
+ int i, rc;
+ bool en = true;
+
+ addr = REG_HAP_BRAKE;
+ for (val = 0, i = 0; i < HAP_BRAKE_PATTERN_MAX; i++)
+ val |= (brake[i] & HAP_BRAKE_PATTERN_MASK) <<
+ i * HAP_BRAKE_PATTERN_SHIFT;
+
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write brake pattern failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (val == 0)
+ en = false;
+
+ /* Set BRAKE_EN only if brake pattern is non-zero */
+ addr = REG_HAP_EN_CTL2;
+ mask = HAP_BRAKE_EN_BIT;
+ val = en;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set EN_CTL2 failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en)
+{
+ int rc;
+ u8 addr, val, mask;
+
+ addr = REG_HAP_AUTO_RES_CTRL;
+ mask = HAP_AUTO_RES_EN_BIT;
+ val = en ? HAP_AUTO_RES_EN_BIT : 0;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_config *config = &chip->config;
+ int rc = 0;
+
+ rc = qti_haptics_module_en(chip, true);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Using VMAX waveform source if playing length is >= 20ms,
+ * otherwise using buffer waveform source and calculate the
+ * pattern length and repeating times to achieve accurate
+ * playing time accuracy.
+ */
+ if (play->length_us >= VMAX_MIN_PLAY_TIME_US) {
+ rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ /* Enable Auto-Resonance when VMAX wf-src is selected */
+ if (config->act_type == ACT_LRA) {
+ rc = qti_haptics_lra_auto_res_enable(chip, true);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Set WF_SOURCE to VMAX */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = false;
+ } else {
+ rc = qti_haptics_config_vmax(chip, config->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ play->effect = &chip->constant;
+ play->playing_pos = 0;
+ /* Format and config waveform in patterns */
+ construct_constant_waveform_in_pattern(play);
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ return rc;
+
+ /* Set WF_SOURCE to buffer */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = true;
+ }
+
+ return 0;
+}
+
+static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip,
+ int effect_idx)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_config *config = &chip->config;
+ int rc = 0;
+
+ if (effect_idx >= chip->effects_count)
+ return -EINVAL;
+
+ play->effect = &chip->predefined[effect_idx];
+ play->playing_pos = 0;
+
+ rc = qti_haptics_module_en(chip, true);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us);
+ if (rc < 0)
+ return rc;
+
+ if (config->act_type == ACT_LRA) {
+ rc = qti_haptics_lra_auto_res_enable(chip,
+ !play->effect->lra_auto_res_disable);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Set brake pattern in the effect */
+ rc = qti_haptics_config_brake(chip, play->effect->brake);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ return rc;
+
+ /* Set WF_SOURCE to buffer */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = true;
+
+ return 0;
+}
+
+static irqreturn_t qti_haptics_play_irq_handler(int irq, void *data)
+{
+ struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_effect *effect = play->effect;
+ int rc;
+
+ dev_dbg(chip->dev, "play_irq triggered\n");
+ if (play->playing_pos == effect->pattern_length) {
+ dev_dbg(chip->dev, "waveform playing done\n");
+ qti_haptics_play(chip, false);
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+
+ goto handled;
+ }
+
+ /* Config to play remaining patterns */
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ goto handled;
+
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ goto handled;
+
+handled:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data)
+{
+ struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+ u8 addr, val;
+ ktime_t temp;
+ s64 sc_delta_time_us;
+ int rc;
+
+ dev_dbg(chip->dev, "sc_irq triggered\n");
+ addr = REG_HAP_STATUS1;
+ rc = qti_haptics_read(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "read HAP_STATUS1 failed, rc=%d\n", rc);
+ goto handled;
+ }
+
+ if (!(val & HAP_SC_DET_BIT))
+ goto handled;
+
+ temp = ktime_get();
+ sc_delta_time_us = ktime_us_delta(temp, chip->last_sc_time);
+ chip->last_sc_time = temp;
+
+ if (sc_delta_time_us > HAP_SC_DET_TIME_US)
+ chip->sc_det_count = 0;
+ else
+ chip->sc_det_count++;
+
+ addr = REG_HAP_SC_CLR;
+ val = HAP_SC_CLR_BIT;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SC_CLR failed, rc=%d\n", rc);
+ goto handled;
+ }
+
+ if (chip->sc_det_count > HAP_SC_DET_MAX_COUNT) {
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ goto handled;
+
+ dev_crit(chip->dev, "Short circuit persists, disable haptics\n");
+ chip->perm_disable = true;
+ }
+
+handled:
+ return IRQ_HANDLED;
+}
+
+static inline void get_play_length(struct qti_hap_play_info *play,
+ int *length_us)
+{
+ struct qti_hap_effect *effect = play->effect;
+ int tmp;
+
+ tmp = effect->pattern_length * effect->play_rate_us;
+ tmp *= wf_s_repeat[effect->wf_s_repeat_n];
+ tmp *= wf_repeat[effect->wf_repeat_n];
+ if (effect->brake_en)
+ tmp += effect->play_rate_us * effect->brake_pattern_length;
+
+ *length_us = tmp;
+}
+
+static int qti_haptics_upload_effect(struct input_dev *dev,
+ struct ff_effect *effect, struct ff_effect *old)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ struct qti_hap_config *config = &chip->config;
+ struct qti_hap_play_info *play = &chip->play;
+ int rc = 0, tmp, i;
+ s16 level, data[CUSTOM_DATA_LEN];
+
+ if (chip->vdd_supply && !chip->vdd_enabled) {
+ rc = regulator_enable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Enable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = true;
+ }
+
+ switch (effect->type) {
+ case FF_CONSTANT:
+ play->length_us = effect->replay.length * USEC_PER_MSEC;
+ level = effect->u.constant.level;
+ tmp = level * config->vmax_mv;
+ play->vmax_mv = tmp / 0x7fff;
+ dev_dbg(chip->dev, "upload constant effect, length = %dus, vmax_mv=%d\n",
+ play->length_us, play->vmax_mv);
+
+ rc = qti_haptics_load_constant_waveform(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "Play constant waveform failed, rc=%d\n",
+ rc);
+ goto disable_vdd;
+ }
+ break;
+
+ case FF_PERIODIC:
+ if (chip->effects_count == 0) {
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ if (effect->u.periodic.waveform != FF_CUSTOM) {
+ dev_err(chip->dev, "Only accept custom waveforms\n");
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ level = effect->u.periodic.magnitude;
+ tmp = level * config->vmax_mv;
+ play->vmax_mv = tmp / 0x7fff;
+
+ if (copy_from_user(data, effect->u.periodic.custom_data,
+ sizeof(s16) * CUSTOM_DATA_LEN)) {
+ rc = -EFAULT;
+ goto disable_vdd;
+ }
+
+ for (i = 0; i < chip->effects_count; i++)
+ if (chip->predefined[i].id ==
+ data[CUSTOM_DATA_EFFECT_IDX])
+ break;
+
+ if (i == chip->effects_count) {
+ dev_err(chip->dev, "predefined effect %d is NOT supported\n",
+ data[0]);
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ dev_dbg(chip->dev, "upload effect %d, vmax_mv=%d\n",
+ chip->predefined[i].id, play->vmax_mv);
+ rc = qti_haptics_load_predefined_effect(chip, i);
+ if (rc < 0) {
+ dev_err(chip->dev, "Play predefined effect %d failed, rc=%d\n",
+ chip->predefined[i].id, rc);
+ goto disable_vdd;
+ }
+
+ get_play_length(play, &play->length_us);
+ data[CUSTOM_DATA_TIMEOUT_SEC_IDX] =
+ play->length_us / USEC_PER_SEC;
+ data[CUSTOM_DATA_TIMEOUT_MSEC_IDX] =
+ (play->length_us % USEC_PER_SEC) / USEC_PER_MSEC;
+
+ /*
+ * Copy the custom data contains the play length back to
+ * userspace so that the userspace client can wait and
+ * send stop playing command after it's done.
+ */
+ if (copy_to_user(effect->u.periodic.custom_data, data,
+ sizeof(s16) * CUSTOM_DATA_LEN)) {
+ rc = -EFAULT;
+ goto disable_vdd;
+ }
+ break;
+
+ default:
+ dev_err(chip->dev, "Unsupported effect type: %d\n",
+ effect->type);
+ break;
+ }
+
+ return 0;
+disable_vdd:
+ if (chip->vdd_supply && chip->vdd_enabled) {
+ rc = regulator_disable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = false;
+ }
+ return rc;
+}
+
+static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ struct qti_hap_play_info *play = &chip->play;
+ s64 secs;
+ unsigned long nsecs;
+ int rc = 0;
+
+ dev_dbg(chip->dev, "playback, val = %d\n", val);
+ if (!!val) {
+ rc = qti_haptics_play(chip, true);
+ if (rc < 0)
+ return rc;
+
+ if (play->playing_pattern) {
+ if (!chip->play_irq_en) {
+ enable_irq(chip->play_irq);
+ chip->play_irq_en = true;
+ }
+ } else {
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+ secs = play->length_us / USEC_PER_SEC;
+ nsecs = (play->length_us % USEC_PER_SEC) *
+ NSEC_PER_USEC;
+ hrtimer_start(&chip->stop_timer, ktime_set(secs, nsecs),
+ HRTIMER_MODE_REL);
+ }
+ } else {
+ play->length_us = 0;
+ rc = qti_haptics_play(chip, false);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ return rc;
+
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+ }
+
+ return rc;
+}
+
+static int qti_haptics_erase(struct input_dev *dev, int effect_id)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ int rc = 0;
+
+ if (chip->vdd_supply && chip->vdd_enabled) {
+ rc = regulator_disable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = false;
+ }
+
+ return rc;
+}
+
+static int qti_haptics_hw_init(struct qti_hap_chip *chip)
+{
+ struct qti_hap_config *config = &chip->config;
+ u8 addr, val, mask;
+ int rc = 0;
+
+ /* Config actuator type */
+ addr = REG_HAP_CFG1;
+ val = config->act_type;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write actuator type failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Config ilim_ma */
+ addr = REG_HAP_ILIM_CFG;
+ val = config->ilim_ma == 400 ? 0 : 1;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write ilim_ma failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Set HAP_EN_CTL3 */
+ addr = REG_HAP_EN_CTL3;
+ val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT |
+ HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT |
+ HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Set ZX_CFG */
+ addr = REG_HAP_ZX_CFG;
+ mask = HAP_ZX_DET_DEB_MASK;
+ val = ZX_DET_DEB_80US;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0) {
+ dev_err(chip->dev, "write ZX_CFG failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * Config play rate: this is the resonance period for LRA,
+ * or the play duration of each waveform sample for ERM.
+ */
+ rc = qti_haptics_config_play_rate_us(chip, config->play_rate_us);
+ if (rc < 0)
+ return rc;
+
+ /* Set external waveform source if it's used */
+ if (config->use_ext_wf_src) {
+ rc = qti_haptics_config_wf_src(chip, config->ext_src);
+ if (rc < 0)
+ return rc;
+ }
+
+ /*
+ * Skip configurations below for ERM actuator
+ * as they're only for LRA actuators
+ */
+ if (config->act_type == ACT_ERM)
+ return 0;
+
+ addr = REG_HAP_CFG2;
+ val = config->lra_shape;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write lra_sig_shape failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ addr = REG_HAP_AUTO_RES_CFG;
+ mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK;
+ val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT;
+ val |= HAP_CAL_EOP_EN_BIT | HAP_CAL_OPT3_EVERY_8_PERIOD;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0) {
+ dev_err(chip->dev, "set AUTO_RES_CFG failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ addr = REG_HAP_AUTO_RES_CTRL;
+ val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD |
+ AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT |
+ AUTO_RES_EN_DLY(4);
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static enum hrtimer_restart qti_hap_stop_timer(struct hrtimer *timer)
+{
+ struct qti_hap_chip *chip = container_of(timer, struct qti_hap_chip,
+ stop_timer);
+ int rc;
+
+ chip->play.length_us = 0;
+ rc = qti_haptics_play(chip, false);
+ if (rc < 0) {
+ dev_err(chip->dev, "Stop playing failed, rc=%d\n", rc);
+ goto err_out;
+ }
+
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ dev_err(chip->dev, "Disable module failed, rc=%d\n", rc);
+err_out:
+ return HRTIMER_NORESTART;
+}
+
+static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
+{
+ struct qti_hap_config *config = &chip->config;
+ const struct device_node *node = chip->dev->of_node;
+ struct device_node *child_node;
+ struct qti_hap_effect *effect;
+ const char *str;
+ int rc = 0, tmp, i = 0, j;
+ u8 val;
+
+ rc = of_property_read_u32(node, "reg", &tmp);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to reg base, rc=%d\n", rc);
+ return rc;
+ }
+ chip->reg_base = (u16)tmp;
+
+ chip->sc_irq = platform_get_irq_byname(chip->pdev, "hap-sc-irq");
+ if (chip->sc_irq < 0) {
+ dev_err(chip->dev, "Failed to get hap-sc-irq\n");
+ return chip->sc_irq;
+ }
+
+ chip->play_irq = platform_get_irq_byname(chip->pdev, "hap-play-irq");
+ if (chip->play_irq < 0) {
+ dev_err(chip->dev, "Failed to get hap-play-irq\n");
+ return chip->play_irq;
+ }
+
+ config->act_type = ACT_LRA;
+ rc = of_property_read_string(node, "qcom,actuator-type", &str);
+ if (!rc) {
+ if (strcmp(str, "erm") == 0) {
+ config->act_type = ACT_ERM;
+ } else if (strcmp(str, "lra") == 0) {
+ config->act_type = ACT_LRA;
+ } else {
+ dev_err(chip->dev, "Invalid actuator type: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+
+ config->vmax_mv = HAP_VMAX_MV_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vmax-mv", &tmp);
+ if (!rc)
+ config->vmax_mv = (tmp > HAP_VMAX_MV_MAX) ?
+ HAP_VMAX_MV_MAX : tmp;
+
+ config->ilim_ma = HAP_ILIM_MA_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ilim-ma", &tmp);
+ if (!rc)
+ config->ilim_ma = (tmp >= HAP_ILIM_MA_MAX) ?
+ HAP_ILIM_MA_MAX : HAP_ILIM_MA_DEFAULT;
+
+ config->play_rate_us = HAP_PLAY_RATE_US_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,play-rate-us", &tmp);
+ if (!rc)
+ config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ?
+ HAP_PLAY_RATE_US_MAX : tmp;
+
+ if (of_find_property(node, "qcom,external-waveform-source", NULL)) {
+ if (!of_property_read_string(node,
+ "qcom,external-waveform-source", &str)) {
+ if (strcmp(str, "audio") == 0) {
+ config->ext_src = EXT_WF_AUDIO;
+ } else if (strcmp(str, "pwm") == 0) {
+ config->ext_src = EXT_WF_PWM;
+ } else {
+ dev_err(chip->dev, "Invalid external waveform source: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+ config->use_ext_wf_src = true;
+ }
+
+ if (of_find_property(node, "vdd-supply", NULL)) {
+ chip->vdd_supply = devm_regulator_get(chip->dev, "vdd");
+ if (IS_ERR(chip->vdd_supply)) {
+ rc = PTR_ERR(chip->vdd_supply);
+ if (rc != -EPROBE_DEFER)
+ dev_err(chip->dev, "Failed to get vdd regulator");
+ return rc;
+ }
+ }
+
+ if (config->act_type == ACT_LRA) {
+ config->lra_shape = RES_SIG_SINE;
+ rc = of_property_read_string(node,
+ "qcom,lra-resonance-sig-shape", &str);
+ if (!rc) {
+ if (strcmp(str, "sine") == 0) {
+ config->lra_shape = RES_SIG_SINE;
+ } else if (strcmp(str, "square") == 0) {
+ config->lra_shape = RES_SIG_SQUARE;
+ } else {
+ dev_err(chip->dev, "Invalid resonance signal shape: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+
+ config->lra_allow_variable_play_rate = of_property_read_bool(
+ node, "qcom,lra-allow-variable-play-rate");
+
+ config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+ rc = of_property_read_string(node,
+ "qcom,lra-auto-resonance-mode", &str);
+ if (!rc) {
+ if (strcmp(str, "zxd") == 0) {
+ config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+ } else if (strcmp(str, "qwd") == 0) {
+ config->lra_auto_res_mode = AUTO_RES_MODE_QWD;
+ } else {
+ dev_err(chip->dev, "Invalid auto resonance mode: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+ }
+
+ chip->constant.pattern = devm_kcalloc(chip->dev,
+ HAP_WAVEFORM_BUFFER_MAX,
+ sizeof(u8), GFP_KERNEL);
+ if (!chip->constant.pattern)
+ return -ENOMEM;
+
+ tmp = of_get_available_child_count(node);
+ if (tmp == 0)
+ return 0;
+
+ chip->predefined = devm_kcalloc(chip->dev, tmp,
+ sizeof(*chip->predefined), GFP_KERNEL);
+ if (!chip->predefined)
+ return -ENOMEM;
+
+ chip->effects_count = tmp;
+
+ for_each_available_child_of_node(node, child_node) {
+ effect = &chip->predefined[i++];
+ rc = of_property_read_u32(child_node, "qcom,effect-id",
+ &effect->id);
+ if (rc < 0) {
+ dev_err(chip->dev, "Read qcom,effect-id failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_count_elems_of_size(child_node,
+ "qcom,wf-pattern", sizeof(u8));
+ if (rc < 0) {
+ dev_err(chip->dev, "Count qcom,wf-pattern property failed, rc=%d\n",
+ rc);
+ return rc;
+ } else if (rc == 0) {
+ dev_dbg(chip->dev, "qcom,wf-pattern has no data\n");
+ return -EINVAL;
+ }
+
+ effect->pattern_length = rc;
+ effect->pattern = devm_kcalloc(chip->dev,
+ effect->pattern_length, sizeof(u8), GFP_KERNEL);
+ if (!effect->pattern)
+ return -ENOMEM;
+
+ rc = of_property_read_u8_array(child_node, "qcom,wf-pattern",
+ effect->pattern, effect->pattern_length);
+ if (rc < 0) {
+ dev_err(chip->dev, "Read qcom,wf-pattern property failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ effect->play_rate_us = config->play_rate_us;
+ rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us",
+ &tmp);
+ if (rc < 0)
+ dev_dbg(chip->dev, "Read qcom,wf-play-rate-us failed, rc=%d\n",
+ rc);
+ else
+ effect->play_rate_us = tmp;
+
+ if (config->act_type == ACT_LRA &&
+ !config->lra_allow_variable_play_rate &&
+ config->play_rate_us != effect->play_rate_us) {
+ dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n");
+ effect->play_rate_us = config->play_rate_us;
+ }
+
+ rc = of_property_read_u32(child_node, "qcom,wf-repeat-count",
+ &tmp);
+ if (rc < 0) {
+ dev_dbg(chip->dev, "Read qcom,wf-repeat-count failed, rc=%d\n",
+ rc);
+ } else {
+ for (j = 0; j < ARRAY_SIZE(wf_repeat); j++)
+ if (tmp <= wf_repeat[j])
+ break;
+
+ effect->wf_repeat_n = j;
+ }
+
+ rc = of_property_read_u32(child_node, "qcom,wf-s-repeat-count",
+ &tmp);
+ if (rc < 0) {
+ dev_dbg(chip->dev, "Read qcom,wf-s-repeat-count failed, rc=%d\n",
+ rc);
+ } else {
+ for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++)
+ if (tmp <= wf_s_repeat[j])
+ break;
+
+ effect->wf_s_repeat_n = j;
+ }
+
+ effect->lra_auto_res_disable = of_property_read_bool(node,
+ "qcom,lra-auto-resonance-disable");
+
+ tmp = of_property_count_elems_of_size(child_node,
+ "qcom,wf-brake-pattern", sizeof(u8));
+ if (tmp <= 0)
+ continue;
+
+ if (tmp > HAP_BRAKE_PATTERN_MAX) {
+ dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n",
+ HAP_BRAKE_PATTERN_MAX);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u8_array(child_node,
+ "qcom,wf-brake-pattern", effect->brake, tmp);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ effect->brake_pattern_length = tmp;
+ for (j = tmp - 1; j >= 0; j--) {
+ if (effect->brake[j] != 0)
+ break;
+ effect->brake_pattern_length--;
+ }
+
+ for (val = 0, j = 0; j < effect->brake_pattern_length; j++)
+ val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK)
+ << j * HAP_BRAKE_PATTERN_SHIFT;
+
+ effect->brake_en = (val != 0);
+ }
+
+ return 0;
+}
+
+static int qti_haptics_probe(struct platform_device *pdev)
+{
+ struct qti_hap_chip *chip;
+ struct input_dev *input_dev;
+ struct ff_device *ff;
+ int rc = 0, effect_count_max;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ chip->pdev = pdev;
+ chip->dev = &pdev->dev;
+ chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+ if (!chip->regmap) {
+ dev_err(chip->dev, "Failed to get regmap handle\n");
+ return -ENXIO;
+ }
+
+ rc = qti_haptics_parse_dt(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ spin_lock_init(&chip->bus_lock);
+
+ rc = qti_haptics_hw_init(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = devm_request_threaded_irq(chip->dev, chip->play_irq, NULL,
+ qti_haptics_play_irq_handler,
+ IRQF_ONESHOT, "hap_play_irq", chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "request play-irq failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ disable_irq(chip->play_irq);
+ chip->play_irq_en = false;
+
+ rc = devm_request_threaded_irq(chip->dev, chip->sc_irq, NULL,
+ qti_haptics_sc_irq_handler,
+ IRQF_ONESHOT, "hap_sc_irq", chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "request sc-irq failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ hrtimer_init(&chip->stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ chip->stop_timer.function = qti_hap_stop_timer;
+
+ input_dev->name = "vibrator";
+ input_set_drvdata(input_dev, chip);
+ chip->input_dev = input_dev;
+
+ input_set_capability(input_dev, EV_FF, FF_CONSTANT);
+ if (chip->effects_count != 0) {
+ input_set_capability(input_dev, EV_FF, FF_PERIODIC);
+ input_set_capability(input_dev, EV_FF, FF_CUSTOM);
+ }
+
+ if (chip->effects_count + 1 > FF_EFFECT_COUNT_MAX)
+ effect_count_max = chip->effects_count + 1;
+ else
+ effect_count_max = FF_EFFECT_COUNT_MAX;
+ rc = input_ff_create(input_dev, effect_count_max);
+ if (rc < 0) {
+ dev_err(chip->dev, "create FF input device failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ ff = input_dev->ff;
+ ff->upload = qti_haptics_upload_effect;
+ ff->playback = qti_haptics_playback;
+ ff->erase = qti_haptics_erase;
+
+ rc = input_register_device(input_dev);
+ if (rc < 0) {
+ dev_err(chip->dev, "register input device failed, rc=%d\n",
+ rc);
+ goto destroy_ff;
+ }
+
+ dev_set_drvdata(chip->dev, chip);
+ return 0;
+
+destroy_ff:
+ input_ff_destroy(chip->input_dev);
+ return rc;
+}
+
+static int qti_haptics_remove(struct platform_device *pdev)
+{
+ struct qti_hap_chip *chip = dev_get_drvdata(&pdev->dev);
+
+ input_ff_destroy(chip->input_dev);
+ dev_set_drvdata(chip->dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id haptics_match_table[] = {
+ { .compatible = "qcom,haptics" },
+ { .compatible = "qcom,pm660-haptics" },
+ { .compatible = "qcom,pm8150b-haptics" },
+ {},
+};
+
+static struct platform_driver qti_haptics_driver = {
+ .driver = {
+ .name = "qcom,haptics",
+ .of_match_table = haptics_match_table,
+ },
+ .probe = qti_haptics_probe,
+ .remove = qti_haptics_remove,
+};
+module_platform_driver(qti_haptics_driver);
+
+MODULE_DESCRIPTION("QTI haptics driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 6fc1afb..f975409 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -120,7 +120,7 @@
},
{
.key = "qcom,max-secure-instances",
- .value = 5,
+ .value = 2,
},
{
.key = "qcom,max-hw-load",
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 2f64594..6909bd1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1455,7 +1455,7 @@
* Statically choose the GPIOs for mapping to PDC. Dynamic mux mapping
* is very difficult.
*/
- for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+ for (i = 0; i < pctrl->soc->n_gpio_mux_in; i++) {
unsigned int irq;
struct irq_data *d;
struct msm_gpio_mux_input *gpio_in =
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index c5f1307..c3081cb 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -50,6 +50,7 @@
.intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
.intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
.intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .dir_conn_reg = REG_BASE + 0xab000,\
.mux_bit = 2, \
.pull_bit = 0, \
.drv_bit = 6, \
@@ -64,6 +65,7 @@
.intr_polarity_bit = 1, \
.intr_detection_bit = 2, \
.intr_detection_width = 2, \
+ .dir_conn_en_bit = 8, \
}
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
@@ -1151,7 +1153,7 @@
{42, 80},
{43, 82},
{44, 83},
- {45, 84},
+ {45, 84, 1},
{46, 86},
{47, 87},
{48, 88},
@@ -1196,6 +1198,17 @@
{0, 195},
};
+static struct msm_dir_conn sdxpoorwills_dir_conn[] = {
+ {0, 220},
+ {0, 219},
+ {0, 218},
+ {0, 217},
+ {0, 216},
+ {0, 215},
+ {0, 214},
+ {0, 213},
+};
+
static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
.pins = sdxpoorwills_pins,
.npins = ARRAY_SIZE(sdxpoorwills_pins),
@@ -1209,6 +1222,9 @@
.n_pdc_mux_out = ARRAY_SIZE(sdxpoorwills_mux_out),
.n_pdc_mux_offset = 20,
.ngpios = 100,
+ .dir_conn_irq_base = 220,
+ .dir_conn = sdxpoorwills_dir_conn,
+ .n_dir_conns = ARRAY_SIZE(sdxpoorwills_dir_conn),
};
static int sdxpoorwills_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 736c0fb..2212b00 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -908,6 +908,20 @@
return 0;
}
+static int __ipa_rt_validate_rule_id(u16 rule_id)
+{
+ if (!rule_id)
+ return 0;
+
+ if ((rule_id < ipahal_get_rule_id_hi_bit()) ||
+ (rule_id >= ((ipahal_get_rule_id_hi_bit()<<1)-1))) {
+ IPAERR_RL("Invalid rule_id provided 0x%x\n",
+ rule_id);
+ return -EPERM;
+ }
+
+ return 0;
+}
static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule,
struct ipa3_hdr_entry **hdr,
struct ipa3_hdr_proc_ctx_entry **proc_ctx)
@@ -1023,6 +1037,8 @@
if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx))
goto error;
+ if (__ipa_rt_validate_rule_id(rule_id))
+ goto error;
tbl = __ipa_add_rt_tbl(ip, name);
if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) {
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 56a09c6..e3e4f2b 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -985,6 +985,7 @@
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_QNOVO,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1076,6 +1077,10 @@
val->intval = get_client_vote(chg->fcc_votable,
BATT_PROFILE_VOTER);
break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ val->intval = get_client_vote(chg->fcc_votable,
+ FG_ESR_VOTER);
+ break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
@@ -1183,6 +1188,12 @@
chg->batt_profile_fcc_ua = val->intval;
vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ if (val->intval)
+ vote(chg->fcc_votable, FG_ESR_VOTER, true, val->intval);
+ else
+ vote(chg->fcc_votable, FG_ESR_VOTER, false, 0);
+ break;
case POWER_SUPPLY_PROP_SET_SHIP_MODE:
/* Not in ship mode as long as the device is active */
if (!val->intval)
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 3b8bc1f..729118d 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -71,6 +71,7 @@
#define MOISTURE_VOTER "MOISTURE_VOTER"
#define HVDCP2_ICL_VOTER "HVDCP2_ICL_VOTER"
#define OV_VOTER "OV_VOTER"
+#define FG_ESR_VOTER "FG_ESR_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 0ae6979..4dfd8d3 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -897,17 +897,16 @@
req = lrbp->cmd->request;
else
return 0;
- /*
- * Right now ICE do not support variable dun but can be
- * taken as future enhancement
- * if (bio_dun(req->bio)) {
- * dun @bio can be split, so we have to adjust offset
- * *dun = bio_dun(req->bio);
- * } else
- */
+
+ /* Use request LBA or given dun as the DUN value */
if (req->bio) {
- *dun = req->bio->bi_iter.bi_sector;
- *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+ if (bio_dun(req->bio)) {
+ /* dun @bio can be split, so we have to adjust offset */
+ *dun = bio_dun(req->bio);
+ } else {
+ *dun = req->bio->bi_iter.bi_sector;
+ *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+ }
}
ret = ufs_qcom_ice_req_setup(host, lrbp->cmd, cc_index, enable);
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index bef0757..3f4ad5d 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -39,8 +39,6 @@
#define dcc_readl(drvdata, off) \
__raw_readl(drvdata->base + off)
-#define dcc_sram_writel(drvdata, val, off) \
- __raw_writel((val), drvdata->ram_base + off)
#define dcc_sram_readl(drvdata, off) \
__raw_readl(drvdata->ram_base + off)
@@ -129,6 +127,16 @@
uint64_t xpu_addr;
uint32_t xpu_unlock_count;
};
+static int dcc_sram_writel(struct dcc_drvdata *drvdata,
+ uint32_t val, uint32_t off)
+{
+ if (unlikely(off > (drvdata->ram_size - 4)))
+ return -EINVAL;
+
+ __raw_writel((val), drvdata->ram_base + off);
+
+ return 0;
+}
static int dcc_cfg_xpu(struct dcc_drvdata *drvdata, bool enable)
{
@@ -277,12 +285,17 @@
if (!prev_addr || prev_addr != addr || prev_off > off) {
/* Check if we need to write link of prev entry */
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
/* Write address */
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata, addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Reset link and prev_off */
@@ -322,7 +335,9 @@
((entry->len << 8) & BM(8, 14))) << pos;
if (pos) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
link = 0;
}
@@ -332,12 +347,16 @@
}
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
/* Setting zero to indicate end of the list */
- dcc_sram_writel(drvdata, 0, sram_offset);
+ ret = dcc_sram_writel(drvdata, 0, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* check if the data will overstep */
diff --git a/fs/crypto/fscrypt_ice.h b/fs/crypto/fscrypt_ice.h
index c540506..d448eae 100644
--- a/fs/crypto/fscrypt_ice.h
+++ b/fs/crypto/fscrypt_ice.h
@@ -21,7 +21,7 @@
{
if (!inode->i_sb->s_cop)
return 0;
- if (!inode->i_sb->s_cop->is_encrypted((struct inode *)inode))
+ if (!IS_ENCRYPTED((struct inode *)inode))
return 0;
return fscrypt_using_hardware_encryption(inode);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 03ff3aa..6563f88 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -105,7 +105,8 @@
filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS)
return true;
- if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE)
+ if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE &&
+ filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
return true;
return false;
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index 737b6fc..1866733 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -267,7 +267,7 @@
static int fscrypt_data_encryption_mode(struct inode *inode)
{
- return fscrypt_should_be_processed_by_ice(inode) ?
+ return fscrypt_is_ice_capable(inode->i_sb) ?
FS_ENCRYPTION_MODE_PRIVATE : FS_ENCRYPTION_MODE_AES_256_XTS;
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 30fa14a..ab72207 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1180,11 +1180,6 @@
EXT4_NAME_LEN;
}
-static inline bool ext4_is_encrypted(struct inode *inode)
-{
- return ext4_encrypted_inode(inode);
-}
-
static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:",
.get_context = ext4_get_context,
@@ -1192,7 +1187,6 @@
.dummy_context = ext4_dummy_context,
.empty_dir = ext4_empty_dir,
.max_namelen = ext4_max_namelen,
- .is_encrypted = ext4_is_encrypted,
};
#endif
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9efe77e..062529c 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1548,9 +1548,9 @@
bio = NULL;
goto set_error_page;
}
+ if (bio_encrypted)
+ fscrypt_set_ice_dun(inode, bio, dun);
}
- if (bio_encrypted)
- fscrypt_set_ice_dun(inode, bio, dun);
if (bio_add_page(bio, page, blocksize, 0) < blocksize)
goto submit_and_realloc;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a7711d7..c850618 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1344,6 +1344,8 @@
seq_printf(seq, ",fsync_mode=%s", "posix");
else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT)
seq_printf(seq, ",fsync_mode=%s", "strict");
+ else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_NOBARRIER)
+ seq_printf(seq, ",fsync_mode=%s", "nobarrier");
return 0;
}
@@ -1940,11 +1942,6 @@
inode->i_sb->s_blocksize : F2FS_NAME_LEN;
}
-static inline bool f2fs_is_encrypted(struct inode *inode)
-{
- return f2fs_encrypted_file(inode);
-}
-
static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:",
.get_context = f2fs_get_context,
@@ -1952,7 +1949,6 @@
.dummy_context = f2fs_dummy_context,
.empty_dir = f2fs_empty_dir,
.max_namelen = f2fs_max_namelen,
- .is_encrypted = f2fs_is_encrypted,
};
#endif
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 8f4e90c..7a7fce9 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -19,12 +19,9 @@
struct fscrypt_ctx;
-/* iv sector for security/pfe/pfk_fscrypt.c and f2fs. sizeof is required
- * to accommodate 32 bit targets.
- */
+/* iv sector for security/pfe/pfk_fscrypt.c and f2fs */
#define PG_DUN(i, p) \
- ((((i)->i_ino & 0xffffffff) << (sizeof((i)->i_ino)/2)) | \
- ((p)->index & 0xffffffff))
+ (((((u64)(i)->i_ino) & 0xffffffff) << 32) | ((p)->index & 0xffffffff))
struct fscrypt_info;
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 32e2b6c..2f62d5b 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -29,7 +29,6 @@
bool (*dummy_context)(struct inode *);
bool (*empty_dir)(struct inode *);
unsigned (*max_namelen)(struct inode *);
- bool (*is_encrypted)(struct inode *);
};
struct fscrypt_ctx {
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3fbfe96..6b20f91 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2986,6 +2986,8 @@
return __skb_grow(skb, len);
}
+#define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode)
+
#define skb_queue_walk(queue, skb) \
for (skb = (queue)->next; \
skb != (struct sk_buff *)(queue); \
diff --git a/include/uapi/media/msmb_qca.h b/include/uapi/media/msmb_qca.h
index 02a6b1f..22b1006 100644
--- a/include/uapi/media/msmb_qca.h
+++ b/include/uapi/media/msmb_qca.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2018, The Linux Foundation.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
#ifndef __UAPI_LINUX_MSMB_QCA402X_H
#define __UAPI_LINUX_MSMB_QCA402X_H
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 91a909f..335b40e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10540,8 +10540,12 @@
rcu_read_lock();
sd = rcu_dereference_check_sched_domain(rq->sd);
if (sd) {
- cpumask_and(&cpumask, nohz.idle_cpus_mask,
- sched_domain_span(sd));
+ if (energy_aware() && rq->misfit_task)
+ cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
+ sched_domain_span(sd));
+ else
+ cpumask_and(&cpumask, nohz.idle_cpus_mask,
+ sched_domain_span(sd));
cpumask_andnot(&cpumask, &cpumask,
cpu_isolated_mask);
ilb = cpumask_first(&cpumask);
@@ -10552,7 +10556,7 @@
if (!energy_aware() ||
(capacity_orig_of(cpu) ==
cpu_rq(cpu)->rd->max_cpu_capacity.val ||
- cpu_overutilized(cpu))) {
+ (cpu_overutilized(cpu) && rq->nr_running > 1))) {
cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
cpu_isolated_mask);
ilb = cpumask_first(&cpumask);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 59c1581..340a3db 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -889,12 +889,9 @@
now = jiffies;
next = now + HZ;
- if (!(state & NUD_IN_TIMER)) {
- if (neigh_probe_enable && (state & NUD_STALE))
- neigh_dbg(2, "neigh %pK is still alive\n", neigh);
- else
- goto out;
- }
+ if (!(state & NUD_IN_TIMER))
+ goto out;
+
if (state & NUD_REACHABLE) {
if (time_before_eq(now,
neigh->confirmed + neigh->parms->reachable_time)) {
@@ -1185,10 +1182,7 @@
neigh_del_timer(neigh);
if (new & NUD_PROBE)
atomic_set(&neigh->probes, 0);
- if (new & NUD_IN_TIMER || (
- neigh_probe_enable &&
- (neigh->tbl->family == AF_INET6) &&
- (new & NUD_STALE)))
+ if (new & NUD_IN_TIMER)
neigh_add_timer(neigh, (jiffies +
((new & NUD_REACHABLE) ?
neigh->parms->reachable_time :
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index f0fc835..c244b72 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4909,6 +4909,7 @@
static void tcp_collapse_ofo_queue(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
+ u32 range_truesize, sum_tiny = 0;
struct sk_buff *skb, *head;
struct rb_node *p;
u32 start, end;
@@ -4927,6 +4928,7 @@
}
start = TCP_SKB_CB(skb)->seq;
end = TCP_SKB_CB(skb)->end_seq;
+ range_truesize = skb->truesize;
for (head = skb;;) {
skb = tcp_skb_next(skb, NULL);
@@ -4937,11 +4939,20 @@
if (!skb ||
after(TCP_SKB_CB(skb)->seq, end) ||
before(TCP_SKB_CB(skb)->end_seq, start)) {
- tcp_collapse(sk, NULL, &tp->out_of_order_queue,
- head, skb, start, end);
+ /* Do not attempt collapsing tiny skbs */
+ if (range_truesize != head->truesize ||
+ end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) {
+ tcp_collapse(sk, NULL, &tp->out_of_order_queue,
+ head, skb, start, end);
+ } else {
+ sum_tiny += range_truesize;
+ if (sum_tiny > sk->sk_rcvbuf >> 3)
+ return;
+ }
goto new_range;
}
+ range_truesize += skb->truesize;
if (unlikely(before(TCP_SKB_CB(skb)->seq, start)))
start = TCP_SKB_CB(skb)->seq;
if (after(TCP_SKB_CB(skb)->end_seq, end))
@@ -4956,6 +4967,7 @@
* 2) not add too big latencies if thousands of packets sit there.
* (But if application shrinks SO_RCVBUF, we could still end up
* freeing whole queue here)
+ * 3) Drop at least 12.5 % of sk_rcvbuf to avoid malicious attacks.
*
* Return true if queue has shrunk.
*/
@@ -4963,20 +4975,26 @@
{
struct tcp_sock *tp = tcp_sk(sk);
struct rb_node *node, *prev;
+ int goal;
if (RB_EMPTY_ROOT(&tp->out_of_order_queue))
return false;
NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED);
+ goal = sk->sk_rcvbuf >> 3;
node = &tp->ooo_last_skb->rbnode;
do {
prev = rb_prev(node);
rb_erase(node, &tp->out_of_order_queue);
+ goal -= rb_to_skb(node)->truesize;
tcp_drop(sk, rb_entry(node, struct sk_buff, rbnode));
- sk_mem_reclaim(sk);
- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
- !tcp_under_memory_pressure(sk))
- break;
+ if (!prev || goal <= 0) {
+ sk_mem_reclaim(sk);
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
+ !tcp_under_memory_pressure(sk))
+ break;
+ goal = sk->sk_rcvbuf >> 3;
+ }
node = prev;
} while (node);
tp->ooo_last_skb = rb_entry(prev, struct sk_buff, rbnode);
@@ -5011,6 +5029,9 @@
else if (tcp_under_memory_pressure(sk))
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
+ return 0;
+
tcp_collapse_ofo_queue(sk);
if (!skb_queue_empty(&sk->sk_receive_queue))
tcp_collapse(sk, &sk->sk_receive_queue, NULL,