summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DMA-attributes.txt9
-rw-r--r--Documentation/devicetree/bindings/cnss/icnss.txt12
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt5
-rw-r--r--Documentation/devicetree/bindings/misc/qpnp-misc.txt24
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt10
-rw-r--r--arch/arm/boot/dts/qcom/Makefile1
-rw-r--r--arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts23
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-audio.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-cdp.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-gpu.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi138
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts128
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi29
-rw-r--r--arch/arm/boot/dts/qcom/sdm658.dtsi65
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-bus.dtsi46
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-coresight.dtsi24
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-gpu.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-regulator.dtsi20
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi23
-rw-r--r--arch/arm/configs/sdm660-perf_defconfig2
-rw-r--r--arch/arm/configs/sdm660_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig3
-rw-r--r--arch/arm64/configs/msmcortex_mediabox_defconfig1
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig3
-rw-r--r--arch/arm64/configs/sdm660_defconfig3
-rw-r--r--arch/arm64/kernel/entry.S2
-rw-r--r--arch/arm64/mm/dma-mapping.c4
-rw-r--r--arch/arm64/mm/fault.c8
-rw-r--r--drivers/char/adsprpc.c138
-rw-r--r--drivers/char/diag/diag_masks.c12
-rw-r--r--drivers/clk/qcom/clk-rcg2.c3
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c8
-rw-r--r--drivers/clk/qcom/mmcc-sdm660.c2
-rw-r--r--drivers/clocksource/arm_arch_timer.c1
-rw-r--r--drivers/cpuidle/lpm-levels.c7
-rw-r--r--drivers/gpu/drm/msm/sde/sde_formats.c6
-rw-r--r--drivers/gpu/msm/adreno.c25
-rw-r--r--drivers/gpu/msm/adreno_compat.c26
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c31
-rw-r--r--drivers/gpu/msm/adreno_dispatch.h3
-rw-r--r--drivers/gpu/msm/kgsl_device.h1
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c48
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c14
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h6
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c1
-rw-r--r--drivers/input/touchscreen/gt9xx/goodix_tool.c47
-rw-r--r--drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h1
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c22
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c11
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c5
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c2
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c6
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c390
-rw-r--r--drivers/misc/compat_qseecom.c6
-rw-r--r--drivers/misc/compat_qseecom.h4
-rw-r--r--drivers/misc/qpnp-misc.c136
-rw-r--r--drivers/misc/qseecom.c67
-rw-r--r--drivers/mmc/core/bus.c13
-rw-r--r--drivers/mmc/core/debugfs.c31
-rw-r--r--drivers/mmc/core/mmc.c36
-rw-r--r--drivers/mmc/host/cmdq_hci.c9
-rw-r--r--drivers/mmc/host/cmdq_hci.h1
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.c31
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.h6
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/mmc/host/sdhci.c37
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c2
-rw-r--r--drivers/platform/msm/gsi/gsi.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa.c12
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_intf.c26
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_intf.c26
-rw-r--r--drivers/platform/msm/msm_ext_display.c5
-rw-r--r--drivers/power/supply/qcom/Makefile8
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c10
-rw-r--r--drivers/power/supply/qcom/smb-lib.c127
-rw-r--r--drivers/power/supply/qcom/smb-lib.h2
-rw-r--r--drivers/regulator/qpnp-lcdb-regulator.c138
-rw-r--r--drivers/soc/qcom/glink.c3
-rw-r--r--drivers/soc/qcom/icnss.c10
-rw-r--r--drivers/soc/qcom/qdsp6v2/voice_svc.c57
-rw-r--r--drivers/soc/qcom/qpnp-haptic.c373
-rw-r--r--drivers/soc/qcom/service-notifier.c13
-rw-r--r--drivers/thermal/msm_lmh_dcvs.c10
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/function/f_fs.c6
-rw-r--r--drivers/usb/gadget/function/f_gsi.c62
-rw-r--r--drivers/usb/gadget/function/f_gsi.h4
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c265
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_cec.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c28
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_trace.h20
-rw-r--r--include/dt-bindings/clock/qcom,rpmcc.h6
-rw-r--r--include/linux/clocksource.h1
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/qpnp-misc.h22
-rw-r--r--include/sound/apr_audio-v2.h101
-rw-r--r--include/sound/q6asm-v2.h8
-rw-r--r--include/uapi/linux/msm_kgsl.h6
-rw-r--r--include/uapi/linux/qseecom.h4
-rw-r--r--include/uapi/linux/v4l2-controls.h16
-rw-r--r--include/uapi/media/msm_media_info.h16
-rw-r--r--include/uapi/media/msmb_pproc.h3
-rw-r--r--include/uapi/sound/compress_offload.h22
-rw-r--r--include/uapi/video/msm_hdmi_modes.h2
-rw-r--r--kernel/time/clocksource.c48
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--kernel/watchdog.c14
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c163
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h21
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c48
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h5
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c1
-rw-r--r--sound/soc/msm/msm8998.c17
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c163
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c32
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c3
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c185
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c3
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c19
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h3
-rw-r--r--sound/soc/msm/qdsp6v2/q6adm.c3
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c19
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c186
-rw-r--r--sound/soc/msm/qdsp6v2/q6audio-v2.c5
-rw-r--r--sound/soc/msm/sdm660-internal.c25
-rw-r--r--sound/soc/soc-compress.c5
-rw-r--r--sound/soc/soc-pcm.c4
157 files changed, 3332 insertions, 1006 deletions
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index 6eadd564a247..2ad68dbbaaae 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -132,6 +132,11 @@ DMA_ATTR_FORCE_COHERENT
When passed to a DMA map call the DMA_ATTR_FORCE_COHERENT DMA
attribute can be used to force a buffer to be mapped as IO coherent.
+
+When the DMA_ATTR_FORCE_COHERENT attribute is set during a map call ensure
+that it is also set during for the matching unmap call to ensure that the
+correct cache maintenance is carried out.
+
This DMA attribute is only currently supported for arm64 stage 1 IOMMU
mappings.
@@ -143,5 +148,9 @@ coherent.
The DMA_ATTR_FORCE_NON_COHERENT DMA attribute overrides the buffer IO
coherency configuration set by making the device IO coherent.
+When the DMA_ATTR_FORCE_NON_COHERENT attribute is set during a map call
+ensure that it is also set during for the matching unmap call to ensure
+that the correct cache maintenance is carried out.
+
This DMA attribute is only currently supported for arm64 stage 1 IOMMU
mappings.
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index 4b70e670798d..c801e8486f87 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -17,14 +17,14 @@ Required properties:
- iommus: SMMUs and corresponding Stream IDs needed by WLAN
- qcom,wlan-smmu-iova-address: I/O virtual address range as <start length>
format to be used for allocations associated between WLAN and SMMU
- - <supply-name>-supply: phandle to the regulator device tree node
- Required "supply-name" is "vdd-0.8-cx-mx".
- - qcom,<supply>-config: Specifies voltage levels for supply. Should be
- specified in pairs (min, max), units uV. There can
- be optional load in uA and Regulator settle delay in
- uS.
Optional properties:
+ - <supply-name>-supply: phandle to the regulator device tree node
+ optional "supply-name" is "vdd-0.8-cx-mx".
+ - qcom,<supply>-config: Specifies voltage levels for supply. Should be
+ specified in pairs (min, max), units uV. There can
+ be optional load in uA and Regulator settle delay in
+ uS.
- qcom,icnss-vadc: VADC handle for vph_pwr read APIs.
- qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs.
- qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 1ca89b587077..d8c3a7c35465 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -150,6 +150,11 @@ Optional Properties:
baseAddr - base address of the gpu channels in the qdss stm memory region
size - size of the gpu stm region
+- qcom,gpu-qtimer:
+ <baseAddr size>
+ baseAddr - base address of the qtimer memory region
+ size - size of the qtimer region
+
- qcom,tsens-name:
Specify the name of GPU temperature sensor. This name will be used
to get the temperature from the thermal driver API.
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
index 9de6857a2643..a34cbde456e4 100644
--- a/Documentation/devicetree/bindings/misc/qpnp-misc.txt
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -17,23 +17,9 @@ Optional properties:
"qcom,pwm-sel" property.
Example:
- qcom,spmi@fc4c0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <3>;
-
- qcom,pm8941@0 {
- spmi-slave-container;
- reg = <0x0>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- qcom,misc@900 {
- compatible = "qcom,qpnp-misc";
- reg = <0x900 0x100>;
- qcom,pwm-sel = <2>;
- qcom,enable-gp-driver;
- };
- }
+ qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ qcom,pwm-sel = <2>;
+ qcom,enable-gp-driver;
};
diff --git a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
index a7848153f83c..6574cfe30ce5 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
@@ -10,6 +10,7 @@ pwm(pulse width modulation) and audio.
Required Properties:
- compatible: must be "qcom,qpnp-haptic"
- reg: address of device
+ - qcom,pmic-revid : phandle to fetch PMIC revid
- qcom,actuator-type: must be one of "erm" or "lra"
- qcom,play-mode : must be one of "buffer", "direct", "pwm" or "audio"
@@ -63,7 +64,13 @@ Optional properties when qcom,actuator-type is "lra"
"max-qwd" : Maximum QWD
"zxd-eop" : ZXD + End of pattern (This is the Default)
- qcom,lra-high-z : High Z configuration for auto resonance. Possible string values are
- "none", "opt1", "opt2" and "opt3" (default)
+ "none", "opt1", "opt2" and "opt3" (default). For PM660,
+ "opt0" is valid value for 1 LRA period.
+ - qcom,lra-qwd-drive-duration : Drive duration of LRA in QWD mode for PM660.
+ Possible values are: 0: 1/4 LRA PERIOD and 1: 3/8 LRA PERIOD
+ - qcom,lra-calibrate-at-eop : To calibrate at End of Pattern for PM660.
+ Possible values are: 0 to disable and 1 to enable Calibration
+ at End of Pattern
- qcom,lra-res-cal-period : Auto resonance calibration period. The values range from
4 to 32(default)
- qcom,perform-lra-auto-resonance-search : boolean, define this property if:
@@ -109,6 +116,7 @@ Example:
interrupts = <0x3 0xc0 0x0>,
<0x3 0xc0 0x1>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pm660_revid>;
vcc_pon-supply = <&pon_perph_reg>;
qcom,play-mode = "direct";
qcom,wave-play-rate-us = <5263>;
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index db37dc6f31bb..a2e7311705e3 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -123,6 +123,7 @@ dtb-$(CONFIG_ARCH_MSM8998) += msm8998-sim.dtb \
apq8998-v2-mtp.dtb \
apq8998-v2-cdp.dtb \
apq8998-v2-qrd.dtb \
+ apq8998-v2-qrd-skuk-hdk.dtb \
msm8998-v2.1-mtp.dtb \
msm8998-v2.1-cdp.dtb \
msm8998-v2.1-qrd.dtb \
diff --git a/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts b/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts
new file mode 100644
index 000000000000..6406fe52242d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts
@@ -0,0 +1,23 @@
+/* Copyright (c) 2017, 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 "apq8998-v2.dtsi"
+#include "msm8998-qrd-skuk-hdk.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ 8998 SKUK HDK";
+ compatible = "qcom,msm8998-qrd", "qcom,msm8998", "qcom,qrd";
+ qcom,board-id = <0x06000b 0x10>;
+};
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
index ebd73ceaa8ce..f4829eb7f799 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 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
@@ -82,7 +82,6 @@
15 01 00 00 10 00 02 ff 24
15 01 00 00 10 00 02 fb 01
15 01 00 00 10 00 02 c6 06
- 15 01 00 00 10 00 02 9d 30 /* Enable IMGSWAP */
15 01 00 00 10 00 02 ff 10
05 01 00 00 a0 00 02 11 00
05 01 00 00 a0 00 02 29 00];
diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
index 067f2c35eecd..97a134b46713 100644
--- a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 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
@@ -187,11 +187,6 @@
qcom,msm-dai-q6-dev-id = <16393>;
};
- sb_4_tx_vi: qcom,msm-dai-q6-sb-4-tx-vi {
- compatible = "qcom,msm-dai-q6-dev";
- qcom,msm-dai-q6-dev-id = <20233>;
- };
-
sb_5_tx: qcom,msm-dai-q6-sb-5-tx {
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <16395>;
diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index 9c4890a84a37..463d352f8791 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -607,6 +607,7 @@
interrupts = <0x1 0xc0 0x0 IRQ_TYPE_NONE>,
<0x1 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pm660_revid>;
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
qcom,vmax-mv = <3200>;
@@ -619,9 +620,9 @@
qcom,brake-pattern = [03 03 00 00];
qcom,use-play-irq;
qcom,use-sc-irq;
- qcom,lra-high-z = "opt1";
+ qcom,lra-high-z = "opt0";
qcom,lra-auto-res-mode = "qwd";
- qcom,lra-res-cal-period = <4>;
+ qcom,lra-calibrate-at-eop = <0>;
qcom,correct-lra-drive-freq;
qcom,misc-trim-error-rc19p2-clk-reg-present;
};
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
index 0356942cbe95..bcdbc4ed7c55 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -394,6 +394,9 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <0xec00 0x100>;
+ interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "sc-irq";
+
qcom,force-module-reenable;
lcdb_ldo_vreg: ldo {
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index fba0aed42146..111d0b51b6c2 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -631,6 +631,7 @@
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_NONE>,
<0x3 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pmi8998_revid>;
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
qcom,vmax-mv = <3200>;
diff --git a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
index 3f81da7c3ebc..1396f27159df 100644
--- a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -308,6 +308,32 @@
23 1e 07 08 05 03 04 a0
23 1e 07 08 05 03 04 a0
23 18 07 08 04 03 04 a0];
+
+ qcom,mdss-dsi-on-command = [15 01 00 00 10 00 02 ff 10
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 ba 03
+ 15 01 00 00 10 00 02 e5 01
+ 15 01 00 00 10 00 02 35 00
+ 15 01 00 00 10 00 02 bb 10
+ 15 01 00 00 10 00 02 b0 03
+ 15 01 00 00 10 00 02 ff e0
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 6b 3d
+ 15 01 00 00 10 00 02 6c 3d
+ 15 01 00 00 10 00 02 6d 3d
+ 15 01 00 00 10 00 02 6e 3d
+ 15 01 00 00 10 00 02 6f 3d
+ 15 01 00 00 10 00 02 35 02
+ 15 01 00 00 10 00 02 36 72
+ 15 01 00 00 10 00 02 37 10
+ 15 01 00 00 10 00 02 08 c0
+ 15 01 00 00 10 00 02 ff 24
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 c6 06
+ 15 01 00 00 10 00 02 9d 30 /* Enable IMGSWAP */
+ 15 01 00 00 10 00 02 ff 10
+ 05 01 00 00 a0 00 02 11 00
+ 05 01 00 00 a0 00 02 29 00];
};
&dsi_nt35597_dsc_video {
diff --git a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
index ac1e37fa1d63..c4e6393997ec 100644
--- a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
@@ -105,8 +105,7 @@
<&dai_tert_auxpcm>, <&dai_quat_auxpcm>,
<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
- <&sb_4_rx>, <&sb_4_tx>, <&sb_4_tx_vi>,
- <&sb_5_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
<&afe_proxy_tx>, <&incall_record_rx>,
<&incall_record_tx>, <&incall_music_rx>,
@@ -127,7 +126,6 @@
"msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
- "msm-dai-q6-dev.20233",
"msm-dai-q6-dev.16395", "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",
@@ -164,7 +162,7 @@
};
};
- sound-tavil {
+ snd_934x: sound-tavil {
compatible = "qcom,msm8998-asoc-snd-tavil";
qcom,model = "msm8998-tavil-snd-card";
qcom,ext-disp-audio-rx;
@@ -239,8 +237,7 @@
<&dai_tert_auxpcm>, <&dai_quat_auxpcm>,
<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
- <&sb_4_rx>, <&sb_4_tx>, <&sb_4_tx_vi>,
- <&sb_5_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
<&afe_proxy_tx>, <&incall_record_rx>,
<&incall_record_tx>, <&incall_music_rx>,
@@ -261,7 +258,6 @@
"msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
- "msm-dai-q6-dev.20233",
"msm-dai-q6-dev.16395", "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",
diff --git a/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi
index 48415eb81406..2b925250c5c0 100644
--- a/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi
@@ -516,6 +516,10 @@
qcom,mbhc-audio-jack-type = "6-pole-jack";
};
+&snd_934x {
+ qcom,mbhc-audio-jack-type = "6-pole-jack";
+};
+
&soc {
gpio_keys {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
index 144d319d9121..cc20c57a8099 100644
--- a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
@@ -75,6 +75,8 @@
qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
+ qcom,gpu-qtimer = <0x17921000 0x1000>; // base addr, size
+
qcom,tsens-name = "tsens_tz_sensor12";
/* Quirks */
diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi
new file mode 100644
index 000000000000..7ed28e4c8813
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi
@@ -0,0 +1,138 @@
+/* Copyright (c) 2017, 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 "msm8998-qrd-skuk.dtsi"
+#include "msm8998-camera-sensor-skuk-hdk.dtsi"
+
+&soc {
+ sound-tavil {
+ qcom,msm-mbhc-hphl-swh = <0>;
+ };
+};
+
+&pmx_mdss {
+ mdss_dsi_active: mdss_dsi_active {
+ mux {
+ pins = "gpio52", "gpio94";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52", "gpio94";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable = <0>; /* no pull */
+ };
+ };
+
+ mdss_dsi_suspend: mdss_dsi_suspend {
+ mux {
+ pins = "gpio52", "gpio94";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52", "gpio94";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "split_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-enable-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
+ qcom,platform-bklight-en-gpio-invert;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-enable-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
+ qcom,platform-bklight-en-gpio-invert;
+};
+
+&pmi8998_wled {
+ qcom,disp-type-amoled;
+};
+
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "amoled";
+ qcom,swire-control;
+};
+
+&pmi8998_gpios {
+ /* GPIO 1 for WLED power enable */
+ gpio@c000 {
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,out-strength = <1>;
+ qcom,src-sel = <0>;
+ qcom,invert = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&dsi_dual_s6e3ha3_amoled_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&i2c_5 {
+ status = "okay";
+ st_fts@49 {
+ compatible = "st,fts";
+ reg = <0x49>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 0x2008>;
+ vdd-supply = <&pm8998_l6>;
+ avdd-supply = <&pm8998_l28>;
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+ pinctrl-0 = <&ts_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ st,irq-gpio = <&tlmm 125 0x2008>;
+ st,reset-gpio = <&tlmm 89 0x00>;
+ st,regulator_dvdd = "vdd";
+ st,regulator_avdd = "avdd";
+ };
+};
+
+&soc {
+ /* HDK835 do not use improveTouch. If do not remove this node,
+ * legacy TOUCH could not work.
+ */
+ /delete-node/hbtp;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
index 73debc374fda..f3ba42e4dfd9 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
+++ b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
@@ -10,139 +10,13 @@
* GNU General Public License for more details.
*/
-
/dts-v1/;
#include "msm8998-v2.dtsi"
-#include "msm8998-qrd-skuk.dtsi"
-#include "msm8998-camera-sensor-skuk-hdk.dtsi"
+#include "msm8998-qrd-skuk-hdk.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM 8998 SKUK HDK";
compatible = "qcom,msm8998-qrd", "qcom,msm8998", "qcom,qrd";
qcom,board-id = <0x06000b 0x10>;
};
-
-&soc {
- sound-tavil {
- qcom,msm-mbhc-hphl-swh = <0>;
- };
-};
-
-&pmx_mdss {
- mdss_dsi_active: mdss_dsi_active {
- mux {
- pins = "gpio52", "gpio94";
- function = "gpio";
- };
-
- config {
- pins = "gpio52", "gpio94";
- drive-strength = <8>; /* 8 mA */
- bias-disable = <0>; /* no pull */
- };
- };
-
- mdss_dsi_suspend: mdss_dsi_suspend {
- mux {
- pins = "gpio52", "gpio94";
- function = "gpio";
- };
-
- config {
- pins = "gpio52", "gpio94";
- drive-strength = <2>; /* 2 mA */
- bias-pull-down; /* pull down */
- };
- };
-};
-
-&mdss_mdp {
- qcom,mdss-pref-prim-intf = "dsi";
-};
-
-&mdss_dsi {
- hw-config = "split_dsi";
-};
-
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 10 0>;
- qcom,platform-enable-gpio = <&tlmm 52 0>;
- qcom,platform-reset-gpio = <&tlmm 94 0>;
- qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
- qcom,platform-bklight-en-gpio-invert;
-};
-
-&mdss_dsi1 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 10 0>;
- qcom,platform-enable-gpio = <&tlmm 52 0>;
- qcom,platform-reset-gpio = <&tlmm 94 0>;
- qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
- qcom,platform-bklight-en-gpio-invert;
-};
-
-&pmi8998_wled {
- qcom,disp-type-amoled;
-};
-
-&labibb {
- status = "ok";
- qcom,qpnp-labibb-mode = "amoled";
- qcom,swire-control;
-};
-
-&pmi8998_gpios {
- /* GPIO 1 for WLED power enable */
- gpio@c000 {
- qcom,mode = <1>;
- qcom,output-type = <0>;
- qcom,pull = <5>;
- qcom,vin-sel = <0>;
- qcom,out-strength = <1>;
- qcom,src-sel = <0>;
- qcom,invert = <0>;
- qcom,master-en = <1>;
- status = "okay";
- };
-};
-
-&dsi_dual_s6e3ha3_amoled_cmd {
- qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
- qcom,mdss-dsi-bl-min-level = <1>;
- qcom,mdss-dsi-bl-max-level = <255>;
- qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-};
-
-&i2c_5 {
- status = "okay";
- st_fts@49 {
- compatible = "st,fts";
- reg = <0x49>;
- interrupt-parent = <&tlmm>;
- interrupts = <125 0x2008>;
- vdd-supply = <&pm8998_l6>;
- avdd-supply = <&pm8998_l28>;
- pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
- pinctrl-0 = <&ts_active>;
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- st,irq-gpio = <&tlmm 125 0x2008>;
- st,reset-gpio = <&tlmm 89 0x00>;
- st,regulator_dvdd = "vdd";
- st,regulator_avdd = "avdd";
- };
-};
-
-&soc {
- /* HDK835 do not use improveTouch. If do not remove this node,
- * legacy TOUCH could not work.
- */
- /delete-node/hbtp;
-};
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index f21707db590a..cb083c0a8aa0 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -318,6 +318,10 @@
};
&soc {
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
+
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index cd895a067f65..48cdb9ca2805 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -322,6 +322,18 @@
reg = <0x0 0x92a00000 0x0 0x1e00000>;
};
+ pil_mba_mem: pil_mba_region@94800000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x94800000 0x0 0x200000>;
+ };
+
+ buffer_mem: buffer_region@94a00000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x94a00000 0x0 0x100000>;
+ };
+
venus_fw_mem: venus_fw_region {
compatible = "shared-dma-pool";
alloc-ranges = <0x0 0x80000000 0x0 0x20000000>;
@@ -335,7 +347,7 @@
alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
reusable;
alignment = <0x0 0x400000>;
- size = <0x0 0xa00000>;
+ size = <0x0 0x800000>;
};
qseecom_mem: qseecom_region {
@@ -722,7 +734,6 @@
clock-names = "osm";
clocks = <&clock_cpu PERFCL_CLK>;
- qcom,cxip-lm-enable = <0>;
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
@@ -1742,6 +1753,10 @@
/* GPIO output to mss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
status = "ok";
+ qcom,mba-mem@0 {
+ compatible = "qcom,pil-mba-mem";
+ memory-region = <&pil_mba_mem>;
+ };
};
qcom,msm-rtb {
@@ -1782,6 +1797,11 @@
reg = <0x6b0 32>;
};
+ kaslr_offset@6d0 {
+ compatible = "qcom,msm-imem-kaslr_offset";
+ reg = <0x6d0 12>;
+ };
+
pil@94c {
compatible = "qcom,msm-imem-pil";
reg = <0x94c 200>;
@@ -2216,4 +2236,9 @@
debounce-interval = <15>;
};
};
+
+ devfreq_spdm_cpu {
+ qcom,bw-dwnstep = <6750>;
+ qcom,max-vote = <6750>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm658.dtsi b/arch/arm/boot/dts/qcom/sdm658.dtsi
index 3eca3dc30e50..3387482dbc18 100644
--- a/arch/arm/boot/dts/qcom/sdm658.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm658.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,4 +16,67 @@
model = "Qualcomm Technologies, Inc. SDM 658";
compatible = "qcom,sdm658";
qcom,msm-id = <325 0x0>;
+
+ cpus {
+ /delete-node/ cpu@102;
+ /delete-node/ cpu@103;
+
+ cpu-map {
+ cluster1 {
+ /delete-node/ core2;
+ /delete-node/ core3;
+ };
+ };
+ };
+};
+
+&soc {
+ /delete-node/ jtagmm@7e40000;
+ /delete-node/ jtagmm@7f40000;
+ /delete-node/ etm@7e40000;
+ /delete-node/ etm@7f40000;
+ /delete-node/ cti@7e20000;
+ /delete-node/ cti@7f20000;
+
+ devfreq_memlat_4: qcom,arm-memlat-mon-4 {
+ qcom,cpulist = <&CPU4 &CPU5>;
+ };
+
+ cpuss_dump {
+ /delete-node/ qcom,l1_i_cache102;
+ /delete-node/ qcom,l1_i_cache103;
+ /delete-node/ qcom,l1_d_cache102;
+ /delete-node/ qcom,l1_d_cache103;
+ /delete-node/ qcom,l1_tlb_dump102;
+ /delete-node/ qcom,l1_tlb_dump103;
+ };
+
+ funnel@7b60000 {
+ ports {
+ /delete-node/ port@7;
+ /delete-node/ port@8;
+ };
+ };
+
+ qcom,msm-thermal {
+ qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>,
+ <1 2 &CPU4 &CPU5>;
+ };
+
+ qcom,bcl {
+ qcom,bcl-hotplug-list = <&CPU4 &CPU5>;
+ qcom,bcl-soc-hotplug-list = <&CPU4 &CPU5>;
+ };
+
+ qcom,spm@178120000 {
+ qcom,cpu-vctl-list = <&CPU4 &CPU5>;
+ };
+
+ qcom,lpm-levels {
+ qcom,pm-cluster@0 {
+ qcom,pm-cluster@1 {
+ qcom,cpu = <&CPU4 &CPU5>;
+ };
+ };
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
index 68ff96829d4f..d555da4cbd08 100644
--- a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
@@ -38,8 +38,8 @@
qcom,qos-off = <4096>;
qcom,base-offset = <16384>;
clock-names = "bus_clk", "bus_a_clk";
- clocks = <&clock_rpmcc RPM_AGGR2_NOC_CLK>,
- <&clock_rpmcc RPM_AGGR2_NOC_A_CLK>;
+ clocks = <&clock_rpmcc AGGR2_NOC_MSMBUS_CLK>,
+ <&clock_rpmcc AGGR2_NOC_MSMBUS_A_CLK>;
qcom,node-qos-clks {
clock-names =
"clk-ipa-clk",
@@ -1248,4 +1248,46 @@
qcom,slv-rpm-id = <ICBID_SLAVE_SERVICE_SNOC>;
};
};
+
+ devfreq_spdm_cpu {
+ compatible = "qcom,devfreq_spdm";
+ qcom,msm-bus,name = "devfreq_spdm";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 512 0 0>,
+ <1 512 0 0>;
+ qcom,msm-bus,active-only;
+ qcom,spdm-client = <0>;
+
+ qcom,bw-upstep = <450>;
+ qcom,bw-dwnstep = <8200>;
+ qcom,max-vote = <8200>;
+ qcom,up-step-multp = <2>;
+ qcom,spdm-interval = <30>;
+
+ qcom,ports = <24>;
+ qcom,alpha-up = <8>;
+ qcom,alpha-down = <15>;
+ qcom,bucket-size = <8>;
+
+ /*max pl1 freq, max pl2 freq*/
+ qcom,pl-freqs = <210000 610000>;
+
+ /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+ qcom,reject-rate = <5000 5000 5000 5000 5000 5000>;
+ /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+ qcom,response-time-us = <5000 5000 5000 5000 5000 5000>;
+
+ /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+ qcom,cci-response-time-us = <10000 10000 10000
+ 10000 10000 10000>;
+ qcom,max-cci-freq = <1036800>;
+ };
+
+ devfreq_spdm_gov {
+ compatible = "qcom,gov_spdm_hyp";
+ interrupt-names = "spdm-irq";
+ interrupts = <0 192 IRQ_TYPE_EDGE_RISING>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
index e6bd0c06e444..14b009656890 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -392,6 +392,7 @@
<106 512 0 0>,
<106 512 0 0>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,cpp-cx-ipeak = <&cx_ipeak_lm 2>;
resets = <&clock_mmss CAMSS_MICRO_BCR>;
reset-names = "micro_iface_reset";
qcom,src-clock-rates = <120000000 256000000 384000000
@@ -577,6 +578,7 @@
<29 512 0 0>,
<29 512 100000000 100000000>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,vfe-cx-ipeak = <&cx_ipeak_lm 2>;
};
vfe1: qcom,vfe1@ca14000 {
@@ -657,6 +659,7 @@
<29 512 0 0>,
<29 512 100000000 100000000>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,vfe-cx-ipeak = <&cx_ipeak_lm 2>;
};
qcom,vfe {
diff --git a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
index dce86a7ceec3..51903c8b028d 100644
--- a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
@@ -942,30 +942,6 @@
clock-names = "core_clk", "core_a_clk";
};
- cti_lpass0: cti@7060000 {
- compatible = "arm,coresight-cti";
- reg = <0x7060000 0x1000>;
- reg-names = "cti-base";
-
- coresight-name = "coresight-cti-lpass0";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
- };
-
- cti_lpass1: cti@7061000 {
- compatible = "arm,coresight-cti";
- reg = <0x7061000 0x1000>;
- reg-names = "cti-base";
-
- coresight-name = "coresight-cti-lpass1";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
- };
-
cti_turing: cti@7068000 {
compatible = "arm,coresight-cti";
reg = <0x7068000 0x1000>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
index a47a788874fa..c3c776be3209 100644
--- a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
@@ -118,6 +118,10 @@
vddcx-supply = <&gdsc_gpu_cx>;
vdd-supply = <&gdsc_gpu_gx>;
+ /* Cx ipeak limit supprt */
+ qcom,gpu-cx-ipeak = <&cx_ipeak_lm 1>;
+ qcom,gpu-cx-ipeak-clk = <700000000>;
+
/* CPU latency parameter */
qcom,pm-qos-active-latency = <518>;
qcom,pm-qos-wakeup-latency = <518>;
@@ -137,6 +141,9 @@
qcom,gpu-speed-bin = <0x41a0 0x1fe00000 21>;
+ /* Enable midframe sampling */
+ qcom,enable-midframe-timer;
+
/* GPU Mempools */
qcom,gpu-mempools {
#address-cells= <1>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index 9c3862ce6a1f..0fc24dc6e72b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -133,6 +133,10 @@
23 18 07 08 04 03 04 a0];
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-min-refresh-rate = <53>;
+ qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
};
&dsi_dual_nt35597_truly_cmd {
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
index 6e32c1282d3e..4794e648752b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
@@ -50,6 +50,7 @@
qcom,vbif-settings = <0x00ac 0x00008040>,
<0x00d0 0x00002828>;
+ qcom,mdss-cx-ipeak = <&cx_ipeak_lm 3>;
qcom,mdss-has-panic-ctrl;
qcom,mdss-per-pipe-panic-luts = <0x000f>,
<0xffff>,
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index 57565134788c..37a88ea0dcec 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -52,12 +52,12 @@
trigout_a: trigout_a {
mux {
pins = "gpio49";
- function = "qdss_cti_trig_out_a";
+ function = "qdss_cti0_a";
};
config {
pins = "gpio49";
- drive-strength = <2>;
+ drive-strength = <16>;
bias-disable;
output-low;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
index 5e2793c3b05b..77e8505408d0 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
@@ -52,6 +52,13 @@
status = "ok";
};
+&sdc2_cd_on {
+ config {
+ /delete-property/ bias-pull-up;
+ bias-disable;
+ };
+};
+
&sdhc_2 {
/* device core power supply */
vdd-supply = <&pm660l_l5>;
@@ -249,6 +256,9 @@
};
};
+/delete-node/ &tasha_hph_en0;
+/delete-node/ &tasha_hph_en1;
+
&tasha_snd {
qcom,model = "sdm660-tasha-skus-snd-card";
qcom,audio-routing =
diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
index 47db57b3dc0a..462a76ef8bfe 100644
--- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
@@ -695,8 +695,8 @@
qcom,cpr-corner-fmax-map = <2 3 4 5 8>;
qcom,cpr-voltage-ceiling =
- <724000 724000 724000 788000 868000
- 924000 988000 1068000>;
+ < 724000 724000 724000 788000 868000
+ 1068000 1068000 1068000>;
qcom,cpr-voltage-floor =
<588000 588000 596000 652000 712000
@@ -729,13 +729,14 @@
4370 4780>;
qcom,cpr-open-loop-voltage-fuse-adjustment =
- <13000 31000 27000 37000 21000>;
+ < (-4000) 4000 7000 19000 (-8000)>;
qcom,cpr-closed-loop-voltage-fuse-adjustment =
- <0 0 0 0 8000>;
+ <(-32000) (-30000) (-29000) (-23000)
+ (-21000)>;
qcom,cpr-floor-to-ceiling-max-range =
- <32000 32000 32000 40000 40000
+ <32000 32000 32000 40000 44000
40000 40000 40000>;
};
};
@@ -801,7 +802,7 @@
qcom,cpr-voltage-ceiling =
<724000 724000 788000 868000
- 924000 988000 1068000>;
+ 988000 988000 1068000>;
qcom,cpr-voltage-floor =
<588000 596000 652000 712000
@@ -840,14 +841,15 @@
2620 2280>;
qcom,cpr-open-loop-voltage-fuse-adjustment =
- <31000 39000 53000 40000 29000>;
+ <16000 27000 39000 39000 20000>;
qcom,cpr-closed-loop-voltage-fuse-adjustment =
- <0 3000 19000 23000 28000>;
+ <(-22000) (-9000) (-7000) (-2000)
+ 11000>;
qcom,cpr-floor-to-ceiling-max-range =
<40000 40000 40000 40000
- 40000 40000 40000>;
+ 66000 66000 40000>;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index c14449289594..8f875e2f5ce2 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -345,7 +345,7 @@
alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
reusable;
alignment = <0x0 0x400000>;
- size = <0x0 0xa00000>;
+ size = <0x0 0x800000>;
};
qseecom_mem: qseecom_region {
@@ -382,9 +382,9 @@
bluetooth: bt_wcn3990 {
compatible = "qca,wcn3990";
- qca,bt-vdd-core-supply = <&pm660_l9_pin_ctrl>;
- qca,bt-vdd-pa-supply = <&pm660_l6_pin_ctrl>;
- qca,bt-vdd-ldo-supply = <&pm660_l19_pin_ctrl>;
+ qca,bt-vdd-core-supply = <&pm660_l9>;
+ qca,bt-vdd-pa-supply = <&pm660_l6>;
+ qca,bt-vdd-ldo-supply = <&pm660_l19>;
qca,bt-chip-pwd-supply = <&pm660l_bob_pin1>;
clocks = <&clock_rpmcc RPM_RF_CLK1_PIN>;
clock-names = "rf_clk1";
@@ -818,6 +818,11 @@
};
};
+ cx_ipeak_lm: cx_ipeak@1fe5040 {
+ compatible = "qcom,cx-ipeak-sdm660";
+ reg = <0x1fe5040 0x28>;
+ };
+
qcom,bcl {
compatible = "qcom,bcl";
qcom,bcl-enable;
@@ -2050,6 +2055,11 @@
reg = <0x6b0 32>;
};
+ kaslr_offset@6d0 {
+ compatible = "qcom,msm-imem-kaslr_offset";
+ reg = <0x6d0 12>;
+ };
+
pil@94c {
compatible = "qcom,msm-imem-pil";
reg = <0x94c 200>;
@@ -2515,6 +2525,11 @@
};
};
+&msm_vidc {
+ qcom,cx-ipeak-data = <&cx_ipeak_lm 4>;
+ qcom,clock-freq-threshold = <518400000>;
+};
+
&soc {
gpio_keys {
status = "okay";
diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig
index 309d7a802d07..a7691544b4cf 100644
--- a/arch/arm/configs/sdm660-perf_defconfig
+++ b/arch/arm/configs/sdm660-perf_defconfig
@@ -243,6 +243,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
CONFIG_UID_CPUTIME=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -560,6 +561,7 @@ CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
# CONFIG_WCD_DSP_GLINK is not set
CONFIG_QCOM_SMCINVOKE=y
+CONFIG_QCOM_CX_IPEAK=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig
index ba22d7864d1c..d5559221cefb 100644
--- a/arch/arm/configs/sdm660_defconfig
+++ b/arch/arm/configs/sdm660_defconfig
@@ -242,6 +242,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
CONFIG_UID_CPUTIME=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -565,6 +566,7 @@ CONFIG_MSM_RPM_STATS_LOG=y
# CONFIG_WCD_DSP_GLINK is not set
CONFIG_QCOM_SMCINVOKE=y
CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_QCOM_CX_IPEAK=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 91224fc7ae68..811779ba58b2 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -240,6 +240,7 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index d5f30e9a8b16..e5ee3b307e65 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -243,6 +243,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
CONFIG_UID_CPUTIME=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -643,6 +644,8 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
diff --git a/arch/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig
index 9ebe740c7d91..b6035abef7c8 100644
--- a/arch/arm64/configs/msmcortex_mediabox_defconfig
+++ b/arch/arm64/configs/msmcortex_mediabox_defconfig
@@ -242,6 +242,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
CONFIG_UID_CPUTIME=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index b0bdabf58d62..cf073304e0b5 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -67,6 +67,7 @@ CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_RANDOMIZE_BASE=y
# CONFIG_EFI is not set
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -238,6 +239,7 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -575,6 +577,7 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_QCOM_SMCINVOKE=y
CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_QCOM_CX_IPEAK=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index 7b21409c3266..46786b90e067 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -67,6 +67,7 @@ CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
@@ -242,6 +243,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
CONFIG_HDCP_QSEECOM=y
CONFIG_UID_CPUTIME=y
+CONFIG_QPNP_MISC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -596,6 +598,7 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_QCOM_SMCINVOKE=y
CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_QCOM_CX_IPEAK=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7f4e5cba0b13..da99a728a5f9 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -411,7 +411,7 @@ ENDPROC(el1_error_invalid)
*/
.align 6
el1_sync:
-#ifdef CONFIG_TLB_EL2_HANDLER
+#ifdef CONFIG_QCOM_TLB_EL2_HANDLER
smc #0xffff
#endif
kernel_entry 1
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 45c365290553..2445db9bbd4f 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1821,10 +1821,8 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
mapping->domain, iova));
int offset = handle & ~PAGE_MASK;
int len = PAGE_ALIGN(size + offset);
- bool iova_coherent = iommu_is_iova_coherent(mapping->domain,
- handle);
- if (!(iova_coherent ||
+ if (!(is_dma_coherent(dev, attrs) ||
dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)))
__dma_page_dev_to_cpu(page, offset, size, dir);
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index c3efb77d1229..aee116e842e2 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -334,10 +334,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
}
if (addr < USER_DS && is_permission_fault(esr, regs)) {
- /* regs->orig_addr_limit may be 0 if we entered from EL0 */
- if (regs->orig_addr_limit == KERNEL_DS)
- die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
-
if (is_el1_instruction_abort(esr))
die("Attempting to execute userspace memory", regs, esr);
@@ -461,7 +457,7 @@ no_context:
* so that, do_mem_abort would not crash kernel thinking TLB conflict not
* handled.
*/
-#ifdef QCOM_TLB_EL2_HANDLER
+#ifdef CONFIG_QCOM_TLB_EL2_HANDLER
static int do_tlb_conf_fault(unsigned long addr,
unsigned int esr,
struct pt_regs *regs)
@@ -560,7 +556,7 @@ static const struct fault_info {
{ do_bad, SIGBUS, 0, "unknown 45" },
{ do_bad, SIGBUS, 0, "unknown 46" },
{ do_bad, SIGBUS, 0, "unknown 47" },
-#ifdef QCOM_TLB_EL2_HANDLER
+#ifdef CONFIG_QCOM_TLB_EL2_HANDLER
{ do_tlb_conf_fault, SIGBUS, 0, "TLB conflict abort" },
#else
{ do_bad, SIGBUS, 0, "TLB conflict abort" },
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 9ca46ae54ce3..7820f5625266 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -217,6 +217,7 @@ struct fastrpc_channel_ctx {
int ssrcount;
void *handle;
int prevssrcount;
+ int issubsystemup;
int vmid;
int ramdumpenabled;
void *remoteheap_ramdump_dev;
@@ -230,6 +231,7 @@ struct fastrpc_apps {
struct mutex smd_mutex;
struct smq_phy_page range;
struct hlist_head maps;
+ uint32_t staticpd_flags;
dev_t dev_no;
int compat;
struct hlist_head drivers;
@@ -1518,10 +1520,15 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init_attrs *uproc)
{
int err = 0;
+ struct fastrpc_apps *me = &gfa;
struct fastrpc_ioctl_invoke_attrs ioctl;
struct fastrpc_ioctl_init *init = &uproc->init;
struct smq_phy_page pages[1];
struct fastrpc_mmap *file = 0, *mem = 0;
+ int srcVM[1] = {VMID_HLOS};
+ int destVM[1] = {VMID_ADSP_Q6};
+ int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+ int hlosVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
VERIFY(err, !fastrpc_channel_open(fl));
if (err)
@@ -1609,12 +1616,9 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
if (err)
goto bail;
} else if (init->flags == FASTRPC_INIT_CREATE_STATIC) {
- int srcVM[1] = {VMID_HLOS};
- int destVM[1] = {VMID_ADSP_Q6};
- int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
remote_arg_t ra[3];
uint64_t phys = 0;
- ssize_t size;
+ ssize_t size = 0;
int fds[3];
char *proc_name = (unsigned char *)init->file;
struct {
@@ -1624,15 +1628,27 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
} inbuf;
inbuf.pgid = current->tgid;
inbuf.namelen = strlen(proc_name)+1;
- inbuf.pageslen = 1;
- VERIFY(err, !fastrpc_mmap_create(fl, -1, 0, init->mem,
- init->memlen, ADSP_MMAP_HEAP_ADDR, &mem));
- phys = mem->phys;
- size = mem->size;
- VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size,
- srcVM, 1, destVM, destVMperm, 1));
- if (err)
- goto bail;
+ inbuf.pageslen = 0;
+ if (!me->staticpd_flags) {
+ inbuf.pageslen = 1;
+ VERIFY(err, !fastrpc_mmap_create(fl, -1, 0, init->mem,
+ init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR,
+ &mem));
+ if (err)
+ goto bail;
+ phys = mem->phys;
+ size = mem->size;
+ VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size,
+ srcVM, 1, destVM, destVMperm, 1));
+ if (err) {
+ pr_err("ADSPRPC: hyp_assign_phys fail err %d",
+ err);
+ pr_err("map->phys %llx, map->size %d\n",
+ phys, (int)size);
+ goto bail;
+ }
+ me->staticpd_flags = 1;
+ }
ra[0].buf.pv = (void *)&inbuf;
ra[0].buf.len = sizeof(inbuf);
@@ -1662,8 +1678,14 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
err = -ENOTTY;
}
bail:
- if (mem && err)
+ if (err && (init->flags == FASTRPC_INIT_CREATE_STATIC))
+ me->staticpd_flags = 0;
+ if (mem && err) {
+ if (mem->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)
+ hyp_assign_phys(mem->phys, (uint64_t)mem->size,
+ destVM, 1, srcVM, hlosVMperm, 1);
fastrpc_mmap_free(mem);
+ }
if (file)
fastrpc_mmap_free(file);
return err;
@@ -1790,6 +1812,8 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
ioctl.inv.pra = ra;
ioctl.fds = 0;
ioctl.attrs = 0;
+ if (fl == NULL)
+ goto bail;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
@@ -1824,12 +1848,6 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
uintptr_t vaddrout;
ssize_t size;
} inargs;
- if (map->flags == ADSP_MMAP_HEAP_ADDR ||
- map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
- VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map));
- if (err)
- goto bail;
- }
inargs.pid = current->tgid;
inargs.size = map->size;
@@ -1847,6 +1865,14 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
ioctl.attrs = 0;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
+ if (err)
+ goto bail;
+ if (map->flags == ADSP_MMAP_HEAP_ADDR ||
+ map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map));
+ if (err)
+ goto bail;
+ }
bail:
return err;
}
@@ -1858,35 +1884,38 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl)
int err = 0, ret = 0;
struct fastrpc_apps *me = &gfa;
struct ramdump_segment *ramdump_segments_rh = NULL;
-
- spin_lock(&me->hlock);
- hlist_for_each_entry_safe(map, n, &me->maps, hn) {
+ do {
+ match = 0;
+ spin_lock(&me->hlock);
+ hlist_for_each_entry_safe(map, n, &me->maps, hn) {
match = map;
hlist_del_init(&map->hn);
break;
- }
- spin_unlock(&me->hlock);
+ }
+ spin_unlock(&me->hlock);
- if (match) {
- VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match));
- if (err)
- goto bail;
- if (me->channel[0].ramdumpenabled) {
- ramdump_segments_rh = kcalloc(1,
+ if (match) {
+ VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match));
+ if (err)
+ goto bail;
+ if (me->channel[0].ramdumpenabled) {
+ ramdump_segments_rh = kcalloc(1,
sizeof(struct ramdump_segment), GFP_KERNEL);
- if (ramdump_segments_rh) {
- ramdump_segments_rh->address = match->phys;
- ramdump_segments_rh->size = match->size;
- ret = do_elf_ramdump(
- me->channel[0].remoteheap_ramdump_dev,
- ramdump_segments_rh, 1);
- if (ret < 0)
- pr_err("ADSPRPC: unable to dump heap");
- kfree(ramdump_segments_rh);
+ if (ramdump_segments_rh) {
+ ramdump_segments_rh->address =
+ match->phys;
+ ramdump_segments_rh->size = match->size;
+ ret = do_elf_ramdump(
+ me->channel[0].remoteheap_ramdump_dev,
+ ramdump_segments_rh, 1);
+ if (ret < 0)
+ pr_err("ADSPRPC: unable to dump heap");
+ kfree(ramdump_segments_rh);
+ }
}
+ fastrpc_mmap_free(match);
}
- fastrpc_mmap_free(match);
- }
+ } while (match);
bail:
if (err && match)
fastrpc_mmap_add(match);
@@ -2085,6 +2114,10 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
hlist_del_init(&fl->hn);
spin_unlock(&fl->apps->hlock);
+ if (!fl->sctx) {
+ kfree(fl);
+ return 0;
+ }
(void)fastrpc_release_current_dsp_process(fl);
fastrpc_context_list_dtor(fl);
fastrpc_buf_list_free(fl);
@@ -2349,6 +2382,14 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
if (err)
goto bail;
cid = fl->cid;
+ if (me->channel[cid].ssrcount !=
+ me->channel[cid].prevssrcount) {
+ if (!me->channel[cid].issubsystemup) {
+ VERIFY(err, 0);
+ if (err)
+ goto bail;
+ }
+ }
VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
if (err)
goto bail;
@@ -2386,13 +2427,15 @@ bail:
static int fastrpc_device_open(struct inode *inode, struct file *filp)
{
int err = 0;
+ struct dentry *debugfs_file;
struct fastrpc_file *fl = 0;
struct fastrpc_apps *me = &gfa;
VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL));
if (err)
return err;
-
+ debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root,
+ fl, &debugfs_fops);
context_list_ctor(&fl->clst);
spin_lock_init(&fl->hlock);
INIT_HLIST_HEAD(&fl->maps);
@@ -2402,6 +2445,9 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->apps = me;
fl->mode = FASTRPC_MODE_SERIAL;
fl->cid = -1;
+ if (debugfs_file != NULL)
+ fl->debugfs_file = debugfs_file;
+ memset(&fl->perf, 0, sizeof(fl->perf));
filp->private_data = fl;
spin_lock(&me->hlock);
hlist_add_head(&fl->hn, &me->drivers);
@@ -2578,6 +2624,7 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
if (code == SUBSYS_BEFORE_SHUTDOWN) {
mutex_lock(&me->smd_mutex);
ctx->ssrcount++;
+ ctx->issubsystemup = 0;
if (ctx->chan) {
fastrpc_glink_close(ctx->chan, cid);
ctx->chan = 0;
@@ -2585,12 +2632,16 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
gcinfo[cid].name, MAJOR(me->dev_no), cid);
}
mutex_unlock(&me->smd_mutex);
+ if (cid == 0)
+ me->staticpd_flags = 0;
fastrpc_notify_drivers(me, cid);
} else if (code == SUBSYS_RAMDUMP_NOTIFICATION) {
if (me->channel[0].remoteheap_ramdump_dev &&
notifdata->enable_ramdump) {
me->channel[0].ramdumpenabled = 1;
}
+ } else if (code == SUBSYS_AFTER_POWERUP) {
+ ctx->issubsystemup = 1;
}
return NOTIFY_DONE;
@@ -2882,6 +2933,7 @@ static int __init fastrpc_device_init(void)
me->channel[i].dev = dev;
me->channel[i].ssrcount = 0;
me->channel[i].prevssrcount = 0;
+ me->channel[i].issubsystemup = 1;
me->channel[i].ramdumpenabled = 0;
me->channel[i].remoteheap_ramdump_dev = 0;
me->channel[i].nb.notifier_call = fastrpc_restart_notifier_cb;
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index a1721a3b80cc..44e71a704e6a 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, 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
@@ -112,10 +112,12 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id)
else
mask_info = &log_mask;
- if (!mask_info)
+ if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
return;
mask = (struct diag_log_mask_t *)mask_info->ptr;
+ if (!mask->ptr)
+ return;
buf = mask_info->update_buf;
switch (mask_info->status) {
@@ -224,7 +226,7 @@ static void diag_send_event_mask_update(uint8_t peripheral)
else
mask_info = &event_mask;
- if (!mask_info)
+ if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
return;
buf = mask_info->update_buf;
@@ -305,10 +307,12 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
else
mask_info = &msg_mask;
- if (!mask_info)
+ if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
return;
mask = (struct diag_msg_mask_t *)mask_info->ptr;
+ if (!mask->ptr)
+ return;
buf = mask_info->update_buf;
mutex_lock(&mask_info->lock);
switch (mask_info->status) {
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index c9ba7f97eebe..632d0f4ac9c1 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -580,6 +580,9 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
rcg->curr_index = 0;
else {
f = qcom_find_freq(rcg->freq_tbl, rcg->current_freq);
+ if (!f)
+ return -EINVAL;
+
rcg->curr_index = qcom_find_src_index(hw,
rcg->parent_map, f->src);
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 0d76b6b28985..5345e9086627 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -570,6 +570,10 @@ static DEFINE_CLK_VOTER(pnoc_msmbus_clk, pnoc_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, pnoc_a_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_pm_clk, pnoc_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_sps_clk, pnoc_clk, 0);
+static DEFINE_CLK_VOTER(aggre2_noc_msmbus_clk, aggre2_noc_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(aggre2_noc_msmbus_a_clk, aggre2_noc_a_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(aggre2_noc_usb_clk, aggre2_noc_clk, 19200000);
+static DEFINE_CLK_VOTER(aggre2_noc_smmu_clk, aggre2_noc_clk, 1000);
/* Voter Branch clocks */
static DEFINE_CLK_BRANCH_VOTER(cxo_dwc3_clk, cxo);
@@ -738,6 +742,10 @@ static struct clk_hw *sdm660_clks[] = {
[CXO_PIL_LPASS_CLK] = &cxo_pil_lpass_clk.hw,
[CXO_PIL_CDSP_CLK] = &cxo_pil_cdsp_clk.hw,
[CNOC_PERIPH_KEEPALIVE_A_CLK] = &cnoc_periph_keepalive_a_clk.hw,
+ [AGGR2_NOC_MSMBUS_CLK] = &aggre2_noc_msmbus_clk.hw,
+ [AGGR2_NOC_MSMBUS_A_CLK] = &aggre2_noc_msmbus_a_clk.hw,
+ [AGGR2_NOC_SMMU_CLK] = &aggre2_noc_smmu_clk.hw,
+ [AGGR2_NOC_USB_CLK] = &aggre2_noc_usb_clk.hw,
};
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c
index 87e6f8c6be0a..0bf7ef05ed06 100644
--- a/drivers/clk/qcom/mmcc-sdm660.c
+++ b/drivers/clk/qcom/mmcc-sdm660.c
@@ -1041,7 +1041,7 @@ static const struct freq_tbl ftbl_mclk0_clk_src[] = {
F(9600000, P_CXO, 2, 0, 0),
F(16666667, P_GPLL0_OUT_MAIN_DIV, 2, 1, 9),
F(19200000, P_CXO, 1, 0, 0),
- F(24000000, P_GPLL0_OUT_MAIN_DIV, 1, 2, 25),
+ F(24000000, P_MMPLL10_PLL_OUT_MAIN, 1, 1, 24),
F(33333333, P_GPLL0_OUT_MAIN_DIV, 1, 1, 9),
F(48000000, P_GPLL0_OUT_MAIN, 1, 2, 25),
F(66666667, P_GPLL0_OUT_MAIN, 1, 1, 9),
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 900d37ca0d7c..5dc26d29e4a4 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -687,6 +687,7 @@ static void __init arch_timer_common_init(void)
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
arch_timer_arch_init();
+ clocksource_select_force();
}
static void __init arch_timer_init(void)
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index d8e571981c35..64c4bf8f58a8 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1542,11 +1542,14 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int idx)
{
struct lpm_cluster *cluster = per_cpu(cpu_cluster, dev->cpu);
- bool success = true;
+ bool success = false;
const struct cpumask *cpumask = get_cpu_mask(dev->cpu);
int64_t start_time = ktime_to_ns(ktime_get()), end_time;
struct power_params *pwr_params;
+ if (idx < 0)
+ return -EINVAL;
+
pwr_params = &cluster->cpu->levels[idx].pwr;
sched_set_cpu_cstate(smp_processor_id(), idx + 1,
pwr_params->energy_overhead, pwr_params->latency_us);
@@ -1559,7 +1562,7 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev,
trace_cpu_idle_enter(idx);
lpm_stats_cpu_enter(idx, start_time);
- if (need_resched() || (idx < 0))
+ if (need_resched())
goto exit;
BUG_ON(!use_psci);
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index dc7827872276..23ffa9b554dd 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -384,19 +384,19 @@ static const struct sde_format sde_format_map[] = {
* the data will be passed by user-space.
*/
static const struct sde_format sde_format_map_ubwc[] = {
- INTERLEAVED_RGB_FMT(BGR565,
+ INTERLEAVED_RGB_FMT(RGB565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
false, 2, 0,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(ABGR8888,
+ INTERLEAVED_RGB_FMT(RGBA8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, 0,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(XBGR8888,
+ INTERLEAVED_RGB_FMT(RGBX8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
false, 4, 0,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 0f582cf35e6b..3faa5aaf9d03 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1720,6 +1720,30 @@ static int adreno_getproperty(struct kgsl_device *device,
status = 0;
}
break;
+ case KGSL_PROP_DEVICE_QTIMER:
+ {
+ struct kgsl_qtimer_prop qtimerprop = {0};
+ struct kgsl_memdesc *qtimer_desc =
+ kgsl_mmu_get_qtimer_global_entry(device);
+
+ if (sizebytes != sizeof(qtimerprop)) {
+ status = -EINVAL;
+ break;
+ }
+
+ if (qtimer_desc) {
+ qtimerprop.gpuaddr = qtimer_desc->gpuaddr;
+ qtimerprop.size = qtimer_desc->size;
+ }
+
+ if (copy_to_user(value, &qtimerprop,
+ sizeof(qtimerprop))) {
+ status = -EFAULT;
+ break;
+ }
+ status = 0;
+ }
+ break;
case KGSL_PROP_MMU_ENABLE:
{
/* Report MMU only if we can handle paged memory */
@@ -2771,6 +2795,7 @@ static const struct kgsl_functable adreno_functable = {
.regulator_disable_poll = adreno_regulator_disable_poll,
.clk_set_options = adreno_clk_set_options,
.gpu_model = adreno_gpu_model,
+ .stop_fault_timer = adreno_dispatcher_stop_fault_timer,
};
static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno_compat.c b/drivers/gpu/msm/adreno_compat.c
index d86a0c60f0b4..5a8d587d4536 100644
--- a/drivers/gpu/msm/adreno_compat.c
+++ b/drivers/gpu/msm/adreno_compat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -113,6 +113,30 @@ int adreno_getproperty_compat(struct kgsl_device *device,
status = 0;
}
break;
+ case KGSL_PROP_DEVICE_QTIMER:
+ {
+ struct kgsl_qtimer_prop qtimerprop = {0};
+ struct kgsl_memdesc *qtimer_desc =
+ kgsl_mmu_get_qtimer_global_entry(device);
+
+ if (sizebytes != sizeof(qtimerprop)) {
+ status = -EINVAL;
+ break;
+ }
+
+ if (qtimer_desc) {
+ qtimerprop.gpuaddr = qtimer_desc->gpuaddr;
+ qtimerprop.size = qtimer_desc->size;
+ }
+
+ if (copy_to_user(value, &qtimerprop,
+ sizeof(qtimerprop))) {
+ status = -EFAULT;
+ break;
+ }
+ status = 0;
+ }
+ break;
default:
/*
* Call the adreno_getproperty to check if the property type
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 89218b62bb7d..f084ca9a62a1 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -208,6 +208,9 @@ static inline bool _isidle(struct adreno_device *adreno_dev)
if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev)))
goto ret;
+ if (adreno_rb_empty(adreno_dev->cur_rb))
+ goto ret;
+
/* only check rbbm status to determine if GPU is idle */
adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, &reg_rbbm_status);
@@ -2051,6 +2054,18 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
return 0;
/*
+ * In the very unlikely case that the power is off, do nothing - the
+ * state will be reset on power up and everybody will be happy
+ */
+
+ if (!kgsl_state_is_awake(device) && (fault & ADRENO_SOFT_FAULT)) {
+ /* Clear the existing register values */
+ memset(adreno_ft_regs_val, 0,
+ adreno_ft_regs_num * sizeof(unsigned int));
+ return 0;
+ }
+
+ /*
* On A5xx, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24) to
* tell if this function was entered after a pagefault. If so, only
* proceed if the fault handler has already run in the IRQ thread,
@@ -2505,7 +2520,7 @@ static void adreno_dispatcher_fault_timer(unsigned long data)
if (!fault_detect_read_compare(adreno_dev)) {
adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT);
adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
- } else {
+ } else if (dispatcher->inflight > 0) {
mod_timer(&dispatcher->fault_timer,
jiffies + msecs_to_jiffies(_fault_timer_interval));
}
@@ -2550,6 +2565,20 @@ void adreno_dispatcher_stop(struct adreno_device *adreno_dev)
}
/**
+ * adreno_dispatcher_stop() - stop the dispatcher fault timer
+ * @adreno_dev: pointer to the adreno device structure
+ *
+ * Stop the dispatcher fault timer
+ */
+void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
+
+ del_timer_sync(&dispatcher->fault_timer);
+}
+
+/**
* adreno_dispatcher_close() - close the dispatcher
* @adreno_dev: pointer to the adreno device structure
*
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index cb9106fedc82..72545db12f90 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, 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
@@ -108,6 +108,7 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev);
int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
void adreno_dispatcher_irq_fault(struct adreno_device *adreno_dev);
void adreno_dispatcher_stop(struct adreno_device *adreno_dev);
+void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device);
int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
struct kgsl_context *context, struct kgsl_drawobj *drawobj[],
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 0a2c39b82781..aca484618268 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -169,6 +169,7 @@ struct kgsl_functable {
const char *name, struct clk *clk);
void (*gpu_model)(struct kgsl_device *device, char *str,
size_t bufsz);
+ void (*stop_fault_timer)(struct kgsl_device *device);
};
struct kgsl_ioctl {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 6c667cb62896..af9fc1c15236 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -106,6 +106,7 @@ static struct kgsl_memdesc *kgsl_global_secure_pt_entry;
static int global_pt_count;
uint64_t global_pt_alloc;
static struct kgsl_memdesc gpu_qdss_desc;
+static struct kgsl_memdesc gpu_qtimer_desc;
void kgsl_print_global_pt_entries(struct seq_file *s)
{
@@ -261,6 +262,50 @@ static inline void kgsl_cleanup_qdss_desc(struct kgsl_mmu *mmu)
kgsl_sharedmem_free(&gpu_qdss_desc);
}
+struct kgsl_memdesc *kgsl_iommu_get_qtimer_global_entry(void)
+{
+ return &gpu_qtimer_desc;
+}
+
+static void kgsl_setup_qtimer_desc(struct kgsl_device *device)
+{
+ int result = 0;
+ uint32_t gpu_qtimer_entry[2];
+
+ if (!of_find_property(device->pdev->dev.of_node,
+ "qcom,gpu-qtimer", NULL))
+ return;
+
+ if (of_property_read_u32_array(device->pdev->dev.of_node,
+ "qcom,gpu-qtimer", gpu_qtimer_entry, 2)) {
+ KGSL_CORE_ERR("Failed to read gpu qtimer dts entry\n");
+ return;
+ }
+
+ gpu_qtimer_desc.flags = 0;
+ gpu_qtimer_desc.priv = 0;
+ gpu_qtimer_desc.physaddr = gpu_qtimer_entry[0];
+ gpu_qtimer_desc.size = gpu_qtimer_entry[1];
+ gpu_qtimer_desc.pagetable = NULL;
+ gpu_qtimer_desc.ops = NULL;
+ gpu_qtimer_desc.dev = device->dev->parent;
+ gpu_qtimer_desc.hostptr = NULL;
+
+ result = memdesc_sg_dma(&gpu_qtimer_desc, gpu_qtimer_desc.physaddr,
+ gpu_qtimer_desc.size);
+ if (result) {
+ KGSL_CORE_ERR("memdesc_sg_dma failed: %d\n", result);
+ return;
+ }
+
+ kgsl_mmu_add_global(device, &gpu_qtimer_desc, "gpu-qtimer");
+}
+
+static inline void kgsl_cleanup_qtimer_desc(struct kgsl_mmu *mmu)
+{
+ kgsl_iommu_remove_global(mmu, &gpu_qtimer_desc);
+ kgsl_sharedmem_free(&gpu_qtimer_desc);
+}
static inline void _iommu_sync_mmu_pc(bool lock)
{
@@ -1403,6 +1448,7 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
kgsl_iommu_remove_global(mmu, &iommu->setstate);
kgsl_sharedmem_free(&iommu->setstate);
kgsl_cleanup_qdss_desc(mmu);
+ kgsl_cleanup_qtimer_desc(mmu);
}
static int _setstate_alloc(struct kgsl_device *device,
@@ -1474,6 +1520,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
kgsl_iommu_add_global(mmu, &iommu->setstate, "setstate");
kgsl_setup_qdss_desc(device);
+ kgsl_setup_qtimer_desc(device);
done:
if (status)
@@ -2616,6 +2663,7 @@ struct kgsl_mmu_ops kgsl_iommu_ops = {
.mmu_remove_global = kgsl_iommu_remove_global,
.mmu_getpagetable = kgsl_iommu_getpagetable,
.mmu_get_qdss_global_entry = kgsl_iommu_get_qdss_global_entry,
+ .mmu_get_qtimer_global_entry = kgsl_iommu_get_qtimer_global_entry,
.probe = kgsl_iommu_probe,
};
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 46bb6f4656fb..aa7157e882ac 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2017, 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
@@ -619,6 +619,18 @@ struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device)
}
EXPORT_SYMBOL(kgsl_mmu_get_qdss_global_entry);
+struct kgsl_memdesc *kgsl_mmu_get_qtimer_global_entry(
+ struct kgsl_device *device)
+{
+ struct kgsl_mmu *mmu = &device->mmu;
+
+ if (MMU_OP_VALID(mmu, mmu_get_qtimer_global_entry))
+ return mmu->mmu_ops->mmu_get_qtimer_global_entry();
+
+ return NULL;
+}
+EXPORT_SYMBOL(kgsl_mmu_get_qtimer_global_entry);
+
/*
* NOMMU defintions - NOMMU really just means that the MMU is kept in pass
* through and the GPU directly accesses physical memory. Used in debug mode and
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index bc448d424ccb..505fe591a53e 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2017, 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
@@ -81,6 +81,7 @@ struct kgsl_mmu_ops {
struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu,
unsigned long name);
struct kgsl_memdesc* (*mmu_get_qdss_global_entry)(void);
+ struct kgsl_memdesc* (*mmu_get_qtimer_global_entry)(void);
};
struct kgsl_mmu_pt_ops {
@@ -231,6 +232,9 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device);
+struct kgsl_memdesc *kgsl_mmu_get_qtimer_global_entry(
+ struct kgsl_device *device);
+
int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index e639e197de93..e4c431546d2a 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2600,6 +2600,7 @@ _nap(struct kgsl_device *device)
return -EBUSY;
}
+ device->ftbl->stop_fault_timer(device);
kgsl_pwrscale_midframe_timer_cancel(device);
/*
diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c
index ded8c88fdac9..02fa0cbbe392 100644
--- a/drivers/input/touchscreen/gt9xx/goodix_tool.c
+++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c
@@ -27,7 +27,7 @@
#include <linux/debugfs.h>
#define DATA_LENGTH_UINT 512
-#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *))
+#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head))
static char procname[20] = {0};
struct st_cmd_head {
@@ -44,10 +44,10 @@ struct st_cmd_head {
u8 addr_len; /* address length */
u8 addr[2]; /* address */
u8 res[3]; /* reserved */
- u8 *data; /* data pointer */
} __packed;
static struct st_cmd_head cmd_head;
+static u8 *cmd_data;
static struct i2c_client *gt_client;
@@ -191,7 +191,7 @@ static void unregister_i2c_func(void)
void uninit_wr_node(void)
{
- cmd_head.data = NULL;
+ cmd_data = NULL;
unregister_i2c_func();
proc_remove(goodix_proc_entry);
}
@@ -308,7 +308,6 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
size_t count, loff_t *ppos)
{
s32 ret = 0;
- u8 *dataptr = NULL;
mutex_lock(&lock);
ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH);
@@ -340,7 +339,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
}
if (cmd_head.wr == GTP_RW_WRITE) {
- ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+ ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH],
&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
if (ret) {
dev_err(&gt_client->dev, "copy_from_user failed");
@@ -348,7 +347,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
goto exit;
}
- memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
+ memcpy(&cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len],
cmd_head.addr, cmd_head.addr_len);
if (cmd_head.flag == GTP_NEED_FLAG) {
@@ -361,7 +360,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
/* Need interrupt! */
}
if (tool_i2c_write(
- &cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
+ &cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len],
cmd_head.data_len + cmd_head.addr_len) <= 0) {
dev_err(&gt_client->dev, "Write data failed");
ret = -EIO;
@@ -374,7 +373,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
ret = cmd_head.data_len + CMD_HEAD_LENGTH;
goto exit;
} else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) { /* Write ic type */
- ret = copy_from_user(&cmd_head.data[0],
+ ret = copy_from_user(&cmd_data[0],
&userbuf[CMD_HEAD_LENGTH],
cmd_head.data_len);
if (ret) {
@@ -390,7 +389,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
ret = -EINVAL;
goto exit;
}
- memcpy(ic_type, cmd_head.data, cmd_head.data_len);
+ memcpy(ic_type, cmd_data, cmd_head.data_len);
register_i2c_func();
@@ -418,13 +417,13 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
} else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) {
struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
- ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+ ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH],
&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
if (ret) {
dev_err(&gt_client->dev, "copy_from_user failed");
goto exit;
}
- if (cmd_head.data[GTP_ADDR_LENGTH]) {
+ if (cmd_data[GTP_ADDR_LENGTH]) {
pr_debug("gtp enter rawdiff\n");
ts->gtp_rawdiff_mode = true;
} else {
@@ -452,11 +451,11 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
ret = -EINVAL;
goto exit;
}
- memset(cmd_head.data, 0, cmd_head.data_len + 1);
- memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH],
+ memset(cmd_data, 0, cmd_head.data_len + 1);
+ memcpy(cmd_data, &userbuf[CMD_HEAD_LENGTH],
cmd_head.data_len);
- if (gup_update_proc((void *)cmd_head.data) == FAIL) {
+ if (gup_update_proc((void *)cmd_data) == FAIL) {
ret = -EBUSY;
goto exit;
}
@@ -464,10 +463,8 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf,
ret = CMD_HEAD_LENGTH;
exit:
- dataptr = cmd_head.data;
memset(&cmd_head, 0, sizeof(cmd_head));
cmd_head.wr = 0xFF;
- cmd_head.data = dataptr;
mutex_unlock(&lock);
return ret;
@@ -507,10 +504,10 @@ static ssize_t goodix_tool_read(struct file *file, char __user *user_buf,
/* Need interrupt! */
}
- memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len);
+ memcpy(cmd_data, cmd_head.addr, cmd_head.addr_len);
- pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.\n", cmd_head.data[0],
- cmd_head.data[1]);
+ pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.\n", cmd_data[0],
+ cmd_data[1]);
pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.\n", cmd_head.addr[0],
cmd_head.addr[1]);
@@ -527,13 +524,13 @@ static ssize_t goodix_tool_read(struct file *file, char __user *user_buf,
if (data_len > count)
data_len = count;
- if (tool_i2c_read(cmd_head.data, data_len) <= 0) {
+ if (tool_i2c_read(cmd_data, data_len) <= 0) {
dev_err(&gt_client->dev, "Read data failed\n");
ret = -EIO;
goto exit;
}
ret = simple_read_from_buffer(user_buf, count, ppos,
- &cmd_head.data[GTP_ADDR_LENGTH], data_len);
+ &cmd_data[GTP_ADDR_LENGTH], data_len);
break;
case GTP_RW_FILL_INFO:
ret = fill_update_info(user_buf, count, ppos);
@@ -568,13 +565,13 @@ s32 init_wr_node(struct i2c_client *client)
gt_client = client;
memset(&cmd_head, 0, sizeof(cmd_head));
- cmd_head.data = NULL;
+ cmd_data = NULL;
i = GTP_I2C_RETRY_5;
- while ((!cmd_head.data) && i) {
- cmd_head.data = devm_kzalloc(&client->dev,
+ while ((!cmd_data) && i) {
+ cmd_data = devm_kzalloc(&client->dev,
i * DATA_LENGTH_UINT, GFP_KERNEL);
- if (cmd_head.data)
+ if (cmd_data)
break;
i--;
}
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
index 52bd5cfc37c8..168318f85e53 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
@@ -2218,10 +2218,12 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id)
__func__);
return -ENOMEM;
}
- while (strptr[index] >= '0' && strptr[index] <= '9') {
+ while ((index < MAX_FIRMWARE_ID_LEN - 1) && strptr[index] >= '0'
+ && strptr[index] <= '9') {
firmware_id[index] = strptr[index];
index++;
}
+ firmware_id[index] = '\0';
retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id);
kfree(firmware_id);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index aca8e99650ba..e54342e3935a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -795,6 +795,7 @@ struct vfe_device {
struct msm_vfe_error_info error_info;
struct msm_vfe_fetch_engine_info fetch_engine_info;
enum msm_vfe_hvx_streaming_cmd hvx_cmd;
+ uint8_t cur_hvx_state;
/* State variables */
uint32_t vfe_hw_version;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 57373c1fc74c..d829aefe6c98 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1495,6 +1495,10 @@ void msm_vfe47_configure_hvx(struct vfe_device *vfe_dev,
uint32_t val;
int rc = 0;
+ if (is_stream_on == vfe_dev->cur_hvx_state) {
+ ISP_DBG("already in same hvx state\n");
+ return;
+ }
if (vfe_dev->buf_mgr->secure_enable == SECURE_MODE) {
pr_err("%s: Cannot configure hvx, secure_mode: %d\n",
__func__,
@@ -1528,6 +1532,7 @@ void msm_vfe47_configure_hvx(struct vfe_device *vfe_dev,
val &= 0xFFFFFFF7;
msm_camera_io_w_mb(val, vfe_dev->vfe_base + 0x50);
}
+ vfe_dev->cur_hvx_state = is_stream_on;
}
void msm_vfe47_update_camif_state(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 1ddf51407884..4e74851dc67d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -39,13 +39,13 @@ static int msm_isp_axi_create_stream(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
struct msm_vfe_axi_stream *stream_info)
{
- uint32_t i;
+ uint32_t i = 0;
int rc = 0;
if (stream_info->state != AVAILABLE) {
- pr_err("%s:%d invalid state %d expected %d for src %d\n",
+ pr_err("%s:%d invalid state %d expected %d\n",
__func__, __LINE__, stream_info->state,
- AVAILABLE, i);
+ AVAILABLE);
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index df9691be0c28..86b500973538 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -26,6 +26,7 @@
#define MAX_ISP_V4l2_EVENTS 100
+#define MAX_ISP_REG_LIST 100
static DEFINE_MUTEX(bandwidth_mgr_mutex);
static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
@@ -630,6 +631,13 @@ static int msm_isp_set_dual_HW_master_slave_mode(
}
ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id,
dual_hw_ms_cmd->num_src);
+ if (dual_hw_ms_cmd->num_src > VFE_SRC_MAX) {
+ pr_err("%s: Error! Invalid num_src %d\n", __func__,
+ dual_hw_ms_cmd->num_src);
+ spin_unlock_irqrestore(&vfe_dev->common_data->
+ common_dev_data_lock, flags);
+ return -EINVAL;
+ }
/* This for loop is for non-primary intf to be marked with Master/Slave
* in order for frame id sync. But their timestamp is not saved.
* So no sof_info resource is allocated */
@@ -662,6 +670,7 @@ static int msm_isp_set_dual_HW_master_slave_mode(
static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0;
+ uint32_t count = 0;
struct msm_vfe_cfg_cmd_list *proc_cmd =
(struct msm_vfe_cfg_cmd_list *)arg;
struct msm_vfe_cfg_cmd_list cmd, cmd_next;
@@ -685,6 +694,12 @@ static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg)
sizeof(struct msm_vfe_cfg_cmd_list));
break;
}
+ if (++count >= MAX_ISP_REG_LIST) {
+ pr_err("%s:%d Error exceeding the max register count:%u\n",
+ __func__, __LINE__, count);
+ rc = -EINVAL;
+ break;
+ }
if (copy_from_user(&cmd_next, (void __user *)cmd.next,
sizeof(struct msm_vfe_cfg_cmd_list))) {
rc = -EFAULT;
@@ -731,6 +746,7 @@ static void msm_isp_compat_to_proc_cmd(struct msm_vfe_cfg_cmd2 *proc_cmd,
static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0;
+ uint32_t count = 0;
struct msm_vfe_cfg_cmd_list_32 *proc_cmd =
(struct msm_vfe_cfg_cmd_list_32 *)arg;
struct msm_vfe_cfg_cmd_list_32 cmd, cmd_next;
@@ -755,6 +771,12 @@ static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg)
sizeof(struct msm_vfe_cfg_cmd_list));
break;
}
+ if (++count >= MAX_ISP_REG_LIST) {
+ pr_err("%s:%d Error exceeding the max register count:%u\n",
+ __func__, __LINE__, count);
+ rc = -EINVAL;
+ break;
+ }
if (copy_from_user(&cmd_next, compat_ptr(cmd.next),
sizeof(struct msm_vfe_cfg_cmd_list_32))) {
rc = -EFAULT;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 064c1e8c5bab..08aab077eec7 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -2116,6 +2116,8 @@ static int msm_cpp_check_buf_type(struct msm_buf_mngr_info *buff_mgr_info,
/* More or equal bufs as Input buffer */
num_output_bufs = new_frame->batch_info.batch_size;
}
+ if (num_output_bufs > MSM_OUTPUT_BUF_CNT)
+ return 0;
for (i = 0; i < num_output_bufs; i++) {
new_frame->output_buffer_info[i].index =
buff_mgr_info->user_buf.buf_idx[i];
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 12d5d7eeb368..b067c4916341 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -291,7 +291,6 @@ static uint32_t msm_cci_wait(struct cci_device *cci_dev,
__func__, __LINE__);
if (rc <= 0) {
- msm_cci_dump_registers(cci_dev, master, queue);
pr_err("%s: %d wait for queue: %d\n",
__func__, __LINE__, queue);
if (rc == 0)
@@ -1284,6 +1283,10 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd,
CDBG("%s:%d master %d\n", __func__, __LINE__, master);
if (master < MASTER_MAX && master >= 0) {
mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ mutex_lock(&cci_dev->cci_master_info[master].
+ mutex_q[PRIORITY_QUEUE]);
+ mutex_lock(&cci_dev->cci_master_info[master].
+ mutex_q[SYNC_QUEUE]);
flush_workqueue(cci_dev->write_wq[master]);
/* Re-initialize the completion */
reinit_completion(&cci_dev->
@@ -1308,6 +1311,10 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd,
if (rc <= 0)
pr_err("%s:%d wait failed %d\n", __func__,
__LINE__, rc);
+ mutex_unlock(&cci_dev->cci_master_info[master].
+ mutex_q[SYNC_QUEUE]);
+ mutex_unlock(&cci_dev->cci_master_info[master].
+ mutex_q[PRIORITY_QUEUE]);
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
}
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
index 5a891592b44f..c94ee509631f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -452,7 +452,8 @@ static int32_t msm_ois_config(struct msm_ois_ctrl_t *o_ctrl,
break;
}
- if (!conf_array.size) {
+ if (!conf_array.size ||
+ conf_array.size > I2C_SEQ_REG_DATA_MAX) {
pr_err("%s:%d failed\n", __func__, __LINE__);
rc = -EFAULT;
break;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index c3ed1f39c2be..1e85923c20b1 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -1975,7 +1975,7 @@ static void sde_rotator_cancel_request(struct sde_rot_mgr *mgr,
devm_kfree(&mgr->pdev->dev, req);
}
-static void sde_rotator_cancel_all_requests(struct sde_rot_mgr *mgr,
+void sde_rotator_cancel_all_requests(struct sde_rot_mgr *mgr,
struct sde_rot_file_private *private)
{
struct sde_rot_entry_container *req, *req_next;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index 7b27497ac6ef..2073c6d9f115 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -428,6 +428,9 @@ int sde_rotator_validate_request(struct sde_rot_mgr *rot_dev,
int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable);
+void sde_rotator_cancel_all_requests(struct sde_rot_mgr *mgr,
+ struct sde_rot_file_private *private);
+
static inline void sde_rot_mgr_lock(struct sde_rot_mgr *mgr)
{
mutex_lock(&mgr->lock);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 63c53c188637..5c7b4df40d5d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -457,11 +457,15 @@ static void sde_rotator_stop_streaming(struct vb2_queue *q)
(atomic_read(&ctx->command_pending) == 0),
msecs_to_jiffies(rot_dev->streamoff_timeout));
mutex_lock(q->lock);
- if (!ret)
+ if (!ret) {
SDEDEV_ERR(rot_dev->dev,
"timeout to stream off s:%d t:%d p:%d\n",
ctx->session_id, q->type,
atomic_read(&ctx->command_pending));
+ sde_rot_mgr_lock(rot_dev->mgr);
+ sde_rotator_cancel_all_requests(rot_dev->mgr, ctx->private);
+ sde_rot_mgr_unlock(rot_dev->mgr);
+ }
sde_rotator_return_all_buffers(q, VB2_BUF_STATE_ERROR);
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index ce6736509d61..ca9d7fba4ee3 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -468,7 +468,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
- .name = "I Frame Quantization",
+ .name = "H264 I Frame Quantization",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 1,
.maximum = 51,
@@ -479,7 +479,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
- .name = "P Frame Quantization",
+ .name = "H264 P Frame Quantization",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 1,
.maximum = 51,
@@ -490,7 +490,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
- .name = "B Frame Quantization",
+ .name = "H264 B Frame Quantization",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 1,
.maximum = 51,
@@ -500,6 +500,61 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.qmenu = NULL,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
+ .name = "H263 I Frame Quantization",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 31,
+ .default_value = I_FRAME_QP,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
+ .name = "H263 P Frame Quantization",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 31,
+ .default_value = P_FRAME_QP,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP,
+ .name = "H263 B Frame Quantization",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 31,
+ .default_value = B_FRAME_QP,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP,
+ .name = "VPX I Frame Quantization",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 0,
+ .maximum = 127,
+ .default_value = I_FRAME_QP,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP,
+ .name = "VPX P Frame Quantization",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 0,
+ .maximum = 127,
+ .default_value = P_FRAME_QP,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ },
+ {
.id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
.name = "H264 Minimum QP",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -522,6 +577,24 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.qmenu = NULL,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_VPX_MIN_QP,
+ .name = "VPX Minimum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 0,
+ .maximum = 127,
+ .default_value = 0,
+ .step = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VPX_MAX_QP,
+ .name = "VPX Maximum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 0,
+ .maximum = 127,
+ .default_value = 127,
+ .step = 1,
+ },
+ {
.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP,
.name = "VP8 Minimum QP",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -540,6 +613,24 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.step = 1,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+ .name = "MPEG4 Minimum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 31,
+ .default_value = 1,
+ .step = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+ .name = "MPEG4 Maximum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 31,
+ .default_value = 31,
+ .step = 1,
+ },
+ {
.id = V4L2_CID_MPEG_VIDEO_MIN_QP_PACKED,
.name = "H264 Minimum QP PACKED",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -940,6 +1031,36 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.step = 0,
},
{
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_I_FRAME_QP,
+ .name = "Iframe initial QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 127,
+ .default_value = 1,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_P_FRAME_QP,
+ .name = "Pframe initial QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 127,
+ .default_value = 1,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_B_FRAME_QP,
+ .name = "Bframe initial QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 127,
+ .default_value = 1,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
.id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
.name = "Iframe initial QP",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -1122,7 +1243,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.name = "Set frame level QP",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 1,
- .maximum = 51,
+ .maximum = 127,
.default_value = 1,
.step = 1,
.qmenu = NULL,
@@ -2230,6 +2351,9 @@ unknown_value:
return -EINVAL;
}
+static int msm_venc_validate_qp_value(struct msm_vidc_inst *inst,
+ struct v4l2_ctrl *ctrl);
+
static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
{
int rc = 0;
@@ -2649,6 +2773,81 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
pdata = &quantization;
break;
}
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: {
+ struct v4l2_ctrl *qpp, *qpb;
+
+ qpp = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP);
+ qpb = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP);
+
+ property_id = HAL_PARAM_VENC_SESSION_QP;
+ quantization.qpi = ctrl->val;
+ quantization.qpp = qpp->val;
+ quantization.qpb = qpb->val;
+ quantization.layer_id = 0;
+
+ pdata = &quantization;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: {
+ struct v4l2_ctrl *qpi, *qpb;
+
+ qpi = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP);
+ qpb = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP);
+
+ property_id = HAL_PARAM_VENC_SESSION_QP;
+ quantization.qpp = ctrl->val;
+ quantization.qpi = qpi->val;
+ quantization.qpb = qpb->val;
+ quantization.layer_id = 0;
+
+ pdata = &quantization;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: {
+ struct v4l2_ctrl *qpi, *qpp;
+
+ qpi = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP);
+ qpp = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP);
+
+ property_id = HAL_PARAM_VENC_SESSION_QP;
+ quantization.qpb = ctrl->val;
+ quantization.qpi = qpi->val;
+ quantization.qpp = qpp->val;
+ quantization.layer_id = 0;
+
+ pdata = &quantization;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP: {
+ struct v4l2_ctrl *qpp;
+
+ qpp = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP);
+
+ property_id = HAL_PARAM_VENC_SESSION_QP;
+ quantization.qpi = ctrl->val;
+ quantization.qpp = qpp->val;
+ /* Bframes are not supported for VPX */
+ quantization.qpb = 0;
+ quantization.layer_id = 0;
+
+ pdata = &quantization;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: {
+ struct v4l2_ctrl *qpi;
+
+ qpi = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP);
+
+ property_id = HAL_PARAM_VENC_SESSION_QP;
+ quantization.qpp = ctrl->val;
+ quantization.qpi = qpi->val;
+ /* Bframes are not supported for VPX */
+ quantization.qpb = 0;
+ quantization.layer_id = 0;
+
+ pdata = &quantization;
+ break;
+ }
case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: {
struct v4l2_ctrl *qp_max;
@@ -2689,8 +2888,85 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
pdata = &qp_range;
break;
}
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: {
+ struct v4l2_ctrl *qp_max;
+
+ qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP);
+ if (ctrl->val >= qp_max->val) {
+ dprintk(VIDC_ERR,
+ "Bad range: Min QP (%d) > Max QP(%d)\n",
+ ctrl->val, qp_max->val);
+ rc = -ERANGE;
+ break;
+ }
+
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = qp_max->val;
+ qp_range.min_qp = ctrl->val;
+
+ pdata = &qp_range;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: {
+ struct v4l2_ctrl *qp_min;
+
+ qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP);
+ if (ctrl->val <= qp_min->val) {
+ dprintk(VIDC_ERR,
+ "Bad range: Max QP (%d) < Min QP(%d)\n",
+ ctrl->val, qp_min->val);
+ rc = -ERANGE;
+ break;
+ }
+
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = ctrl->val;
+ qp_range.min_qp = qp_min->val;
+
+ pdata = &qp_range;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP: {
+ struct v4l2_ctrl *qp_max;
+
+ qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MAX_QP);
+ if (ctrl->val >= qp_max->val) {
+ dprintk(VIDC_ERR,
+ "Bad range: Min QP (%d) > Max QP(%d)\n",
+ ctrl->val, qp_max->val);
+ rc = -ERANGE;
+ break;
+ }
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = qp_max->val;
+ qp_range.min_qp = ctrl->val;
+ pdata = &qp_range;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP: {
+ struct v4l2_ctrl *qp_min;
+
+ qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MIN_QP);
+ if (ctrl->val <= qp_min->val) {
+ dprintk(VIDC_ERR,
+ "Bad range: Max QP (%d) < Min QP(%d)\n",
+ ctrl->val, qp_min->val);
+ rc = -ERANGE;
+ break;
+ }
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = ctrl->val;
+ qp_range.min_qp = qp_min->val;
+ pdata = &qp_range;
+ break;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP: {
struct v4l2_ctrl *qp_max;
+
qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP);
property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
qp_range.layer_id = 0;
@@ -2701,6 +2977,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
}
case V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP: {
struct v4l2_ctrl *qp_min;
+
qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP);
property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
qp_range.layer_id = 0;
@@ -3222,6 +3499,14 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
pdata = &baselayerid;
break;
case V4L2_CID_MPEG_VIDC_VIDEO_CONFIG_QP:
+ /* Sanity check for the QP boundaries as we are using
+ * same control to set dynamic QP for all the codecs
+ */
+ rc = msm_venc_validate_qp_value(inst, ctrl);
+ if (rc) {
+ dprintk(VIDC_ERR, "Invalid QP Config QP Range\n");
+ break;
+ }
property_id = HAL_CONFIG_VENC_FRAME_QP;
frameqp = ctrl->val;
pdata = &frameqp;
@@ -3380,7 +3665,6 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
}
v4l2_ctrl_lock(ctrl);
-#undef TRY_GET_CTRL
if (!rc && property_id) {
dprintk(VIDC_DBG, "Control: HAL property=%x,ctrl_value=%d\n",
@@ -3393,6 +3677,59 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
return rc;
}
+static int msm_venc_validate_qp_value(struct msm_vidc_inst *inst,
+ struct v4l2_ctrl *ctrl)
+{
+ int rc = 0, min, max;
+ struct v4l2_ctrl *temp_ctrl = NULL;
+ int qp_value = ctrl->val;
+
+#define VALIDATE_BOUNDARIES(__min, __max, __val) ({\
+ int __rc = __val >= __min && \
+ __val <= __max; \
+ if (!__rc) \
+ dprintk(VIDC_ERR, "QP beyond range: min(%d) max(%d) val(%d)", \
+ __min, __max, __val); \
+ __rc; \
+})
+
+ switch (inst->fmts[CAPTURE_PORT].fourcc) {
+ case V4L2_PIX_FMT_VP8:
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MAX_QP);
+ max = temp_ctrl->maximum;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MIN_QP);
+ min = temp_ctrl->minimum;
+ if (!VALIDATE_BOUNDARIES(min, max, qp_value))
+ rc = -EINVAL;
+ break;
+ case V4L2_PIX_FMT_H263:
+ case V4L2_PIX_FMT_MPEG4:
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP);
+ max = temp_ctrl->maximum;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP);
+ min = temp_ctrl->minimum;
+ if (!VALIDATE_BOUNDARIES(min, max, qp_value))
+ rc = -EINVAL;
+ break;
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_HEVC:
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MAX_QP);
+ max = temp_ctrl->maximum;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MIN_QP);
+ min = temp_ctrl->minimum;
+ if (!VALIDATE_BOUNDARIES(min, max, qp_value))
+ rc = -EINVAL;
+ break;
+ default:
+ dprintk(VIDC_ERR, "%s Invalid Codec\n", __func__);
+ return -EINVAL;
+ }
+ return rc;
+#undef VALIDATE_BOUNDARIES
+}
+
+#undef TRY_GET_CTRL
+
static int try_set_ext_ctrl(struct msm_vidc_inst *inst,
struct v4l2_ext_controls *ctrl)
{
@@ -3408,6 +3745,7 @@ static int try_set_ext_ctrl(struct msm_vidc_inst *inst,
struct hal_aspect_ratio sar;
struct hal_bitrate bitrate;
struct hal_frame_size blur_res;
+ struct v4l2_ctrl *temp_ctrl;
if (!inst || !inst->core || !inst->core->device || !ctrl) {
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -3470,6 +3808,48 @@ static int try_set_ext_ctrl(struct msm_vidc_inst *inst,
property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
pdata = &quant;
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_I_FRAME_QP:
+ /* Sanity check for the QP boundaries as we are using
+ * same control to set Initial QP for all the codecs
+ */
+ temp_ctrl->id =
+ V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_I_FRAME_QP;
+ temp_ctrl->val = control[i].value;
+ rc = msm_venc_validate_qp_value(inst, temp_ctrl);
+ if (rc) {
+ dprintk(VIDC_ERR, "Invalid Initial I QP\n");
+ break;
+ }
+ quant.qpi = control[i].value;
+ property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+ pdata = &quant;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_P_FRAME_QP:
+ temp_ctrl->id =
+ V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_P_FRAME_QP;
+ temp_ctrl->val = control[i].value;
+ rc = msm_venc_validate_qp_value(inst, temp_ctrl);
+ if (rc) {
+ dprintk(VIDC_ERR, "Invalid Initial P QP\n");
+ break;
+ }
+ quant.qpp = control[i].value;
+ property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+ pdata = &quant;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_B_FRAME_QP:
+ temp_ctrl->id =
+ V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_B_FRAME_QP;
+ temp_ctrl->val = control[i].value;
+ rc = msm_venc_validate_qp_value(inst, temp_ctrl);
+ if (rc) {
+ dprintk(VIDC_ERR, "Invalid Initial B QP\n");
+ break;
+ }
+ quant.qpb = control[i].value;
+ property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+ pdata = &quant;
+ break;
case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE:
search_range.i_frame.x_subsampled = control[i].value;
property_id = HAL_PARAM_VENC_SEARCH_RANGE;
diff --git a/drivers/misc/compat_qseecom.c b/drivers/misc/compat_qseecom.c
index 60bb86a08af7..2e9ffc71e452 100644
--- a/drivers/misc/compat_qseecom.c
+++ b/drivers/misc/compat_qseecom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015,2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -52,7 +52,7 @@ static int compat_get_qseecom_load_img_req(
compat_ulong_t img_len;
compat_long_t ifd_data_fd;
compat_ulong_t app_arch;
- compat_int_t app_id;
+ compat_uint_t app_id;
err = get_user(mdt_len, &data32->mdt_len);
err |= put_user(mdt_len, &data->mdt_len);
@@ -164,7 +164,7 @@ static int compat_get_qseecom_qseos_app_load_query(
{
int err = 0;
unsigned int i;
- compat_int_t app_id;
+ compat_uint_t app_id;
char app_name;
compat_ulong_t app_arch;
diff --git a/drivers/misc/compat_qseecom.h b/drivers/misc/compat_qseecom.h
index 5167bf1cc6af..c934ef87e20a 100644
--- a/drivers/misc/compat_qseecom.h
+++ b/drivers/misc/compat_qseecom.h
@@ -93,7 +93,7 @@ struct compat_qseecom_load_img_req {
compat_long_t ifd_data_fd; /* in */
char img_name[MAX_APP_NAME_SIZE]; /* in */
compat_ulong_t app_arch; /* in */
- compat_int_t app_id; /* out*/
+ compat_uint_t app_id; /* out*/
};
struct compat_qseecom_set_sb_mem_param_req {
@@ -117,7 +117,7 @@ struct compat_qseecom_qseos_version_req {
*/
struct compat_qseecom_qseos_app_load_query {
char app_name[MAX_APP_NAME_SIZE]; /* in */
- compat_int_t app_id; /* out */
+ compat_uint_t app_id; /* out */
compat_ulong_t app_arch;
};
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
index 5b321b17c43e..8f244811f740 100644
--- a/drivers/misc/qpnp-misc.c
+++ b/drivers/misc/qpnp-misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014,2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014,2016-2017, 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
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/spmi.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/qpnp-misc.h>
@@ -45,8 +45,7 @@ struct qpnp_misc_version {
* exclusion between probing and accessing misc
* driver information
* @dev: Device pointer to the misc device
- * @resource: Resource pointer that holds base address
- * @spmi: Spmi pointer which holds spmi information
+ * @regmap: Regmap pointer to the misc device
* @version: struct that holds the subtype and dig_major_rev
* of the chip.
*/
@@ -54,10 +53,10 @@ struct qpnp_misc_dev {
struct list_head list;
struct mutex mutex;
struct device *dev;
- struct resource *resource;
- struct spmi_device *spmi;
+ struct regmap *regmap;
struct qpnp_misc_version version;
+ u32 base;
u8 pwm_sel;
bool enable_gp_driver;
};
@@ -83,26 +82,29 @@ static struct qpnp_misc_version irq_support_version[] = {
{0x16, 0x00}, /* PMDCALIFORNIUM */
};
-static int qpnp_write_byte(struct spmi_device *spmi, u16 addr, u8 val)
+static int qpnp_write_byte(struct qpnp_misc_dev *mdev, u16 addr, u8 val)
{
int rc;
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, &val, 1);
+ rc = regmap_write(mdev->regmap, mdev->base + addr, val);
if (rc)
- pr_err("SPMI write failed rc=%d\n", rc);
+ pr_err("regmap write failed rc=%d\n", rc);
return rc;
}
-static int qpnp_read_byte(struct spmi_device *spmi, u16 addr, u8 *val)
+static int qpnp_read_byte(struct qpnp_misc_dev *mdev, u16 addr, u8 *val)
{
+ unsigned int temp;
int rc;
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, 1);
+ rc = regmap_read(mdev->regmap, mdev->base + addr, &temp);
if (rc) {
- pr_err("SPMI read failed rc=%d\n", rc);
+ pr_err("regmap read failed rc=%d\n", rc);
return rc;
}
+
+ *val = (u8)temp;
return rc;
}
@@ -128,6 +130,47 @@ static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
return 1;
}
+int qpnp_misc_read_reg(struct device_node *node, u16 addr, u8 *val)
+{
+ struct qpnp_misc_dev *mdev = NULL;
+ struct qpnp_misc_dev *mdev_found = NULL;
+ int rc;
+ u8 temp;
+
+ if (IS_ERR_OR_NULL(node)) {
+ pr_err("Invalid device node pointer\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&qpnp_misc_dev_list_mutex);
+ list_for_each_entry(mdev, &qpnp_misc_dev_list, list) {
+ if (mdev->dev->of_node == node) {
+ mdev_found = mdev;
+ break;
+ }
+ }
+ mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+ if (!mdev_found) {
+ /*
+ * No MISC device was found. This API should only
+ * be called by drivers which have specified the
+ * misc phandle in their device tree node.
+ */
+ pr_err("no probed misc device found\n");
+ return -EPROBE_DEFER;
+ }
+
+ rc = qpnp_read_byte(mdev, addr, &temp);
+ if (rc < 0) {
+ dev_err(mdev->dev, "Failed to read addr %x, rc=%d\n", addr, rc);
+ return rc;
+ }
+
+ *val = temp;
+ return 0;
+}
+
int qpnp_misc_irqs_available(struct device *consumer_dev)
{
struct device_node *misc_node = NULL;
@@ -168,16 +211,24 @@ int qpnp_misc_irqs_available(struct device *consumer_dev)
static int qpnp_misc_dt_init(struct qpnp_misc_dev *mdev)
{
+ struct device_node *node = mdev->dev->of_node;
u32 val;
+ int rc;
+
+ rc = of_property_read_u32(node, "reg", &mdev->base);
+ if (rc < 0 || !mdev->base) {
+ dev_err(mdev->dev, "Base address not defined or invalid\n");
+ return -EINVAL;
+ }
- if (!of_property_read_u32(mdev->dev->of_node, "qcom,pwm-sel", &val)) {
+ if (!of_property_read_u32(node, "qcom,pwm-sel", &val)) {
if (val > PWM_SEL_MAX) {
dev_err(mdev->dev, "Invalid value for pwm-sel\n");
return -EINVAL;
}
mdev->pwm_sel = (u8)val;
}
- mdev->enable_gp_driver = of_property_read_bool(mdev->dev->of_node,
+ mdev->enable_gp_driver = of_property_read_bool(node,
"qcom,enable-gp-driver");
WARN((mdev->pwm_sel > 0 && !mdev->enable_gp_driver),
@@ -197,18 +248,15 @@ static int qpnp_misc_config(struct qpnp_misc_dev *mdev)
switch (version_name) {
case PMDCALIFORNIUM:
if (mdev->pwm_sel > 0 && mdev->enable_gp_driver) {
- rc = qpnp_write_byte(mdev->spmi,
- mdev->resource->start + REG_PWM_SEL,
- mdev->pwm_sel);
+ rc = qpnp_write_byte(mdev, REG_PWM_SEL, mdev->pwm_sel);
if (rc < 0) {
dev_err(mdev->dev,
"Failed to write PWM_SEL reg\n");
return rc;
}
- rc = qpnp_write_byte(mdev->spmi,
- mdev->resource->start + REG_GP_DRIVER_EN,
- GP_DRIVER_EN_BIT);
+ rc = qpnp_write_byte(mdev, REG_GP_DRIVER_EN,
+ GP_DRIVER_EN_BIT);
if (rc < 0) {
dev_err(mdev->dev,
"Failed to write GP_DRIVER_EN reg\n");
@@ -223,35 +271,38 @@ static int qpnp_misc_config(struct qpnp_misc_dev *mdev)
return 0;
}
-static int qpnp_misc_probe(struct spmi_device *spmi)
+static int qpnp_misc_probe(struct platform_device *pdev)
{
- struct resource *resource;
struct qpnp_misc_dev *mdev = ERR_PTR(-EINVAL);
int rc;
- resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!resource) {
- pr_err("Unable to get spmi resource for MISC\n");
- return -EINVAL;
- }
-
- mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
if (!mdev)
return -ENOMEM;
- mdev->spmi = spmi;
- mdev->dev = &(spmi->dev);
- mdev->resource = resource;
+ mdev->dev = &pdev->dev;
+ mdev->regmap = dev_get_regmap(mdev->dev->parent, NULL);
+ if (!mdev->regmap) {
+ dev_err(mdev->dev, "Parent regmap is unavailable\n");
+ return -ENXIO;
+ }
+
+ rc = qpnp_misc_dt_init(mdev);
+ if (rc < 0) {
+ dev_err(mdev->dev,
+ "Error reading device tree properties, rc=%d\n", rc);
+ return rc;
+ }
+
- rc = qpnp_read_byte(spmi, resource->start + REG_SUBTYPE,
- &mdev->version.subtype);
+ rc = qpnp_read_byte(mdev, REG_SUBTYPE, &mdev->version.subtype);
if (rc < 0) {
dev_err(mdev->dev, "Failed to read subtype, rc=%d\n", rc);
return rc;
}
- rc = qpnp_read_byte(spmi, resource->start + REG_DIG_MAJOR_REV,
- &mdev->version.dig_major_rev);
+ rc = qpnp_read_byte(mdev, REG_DIG_MAJOR_REV,
+ &mdev->version.dig_major_rev);
if (rc < 0) {
dev_err(mdev->dev, "Failed to read dig_major_rev, rc=%d\n", rc);
return rc;
@@ -261,13 +312,6 @@ static int qpnp_misc_probe(struct spmi_device *spmi)
list_add_tail(&mdev->list, &qpnp_misc_dev_list);
mutex_unlock(&qpnp_misc_dev_list_mutex);
- rc = qpnp_misc_dt_init(mdev);
- if (rc < 0) {
- dev_err(mdev->dev,
- "Error reading device tree properties, rc=%d\n", rc);
- return rc;
- }
-
rc = qpnp_misc_config(mdev);
if (rc < 0) {
dev_err(mdev->dev,
@@ -279,7 +323,7 @@ static int qpnp_misc_probe(struct spmi_device *spmi)
return 0;
}
-static struct spmi_driver qpnp_misc_driver = {
+static struct platform_driver qpnp_misc_driver = {
.probe = qpnp_misc_probe,
.driver = {
.name = QPNP_MISC_DEV_NAME,
@@ -290,12 +334,12 @@ static struct spmi_driver qpnp_misc_driver = {
static int __init qpnp_misc_init(void)
{
- return spmi_driver_register(&qpnp_misc_driver);
+ return platform_driver_register(&qpnp_misc_driver);
}
static void __exit qpnp_misc_exit(void)
{
- return spmi_driver_unregister(&qpnp_misc_driver);
+ return platform_driver_unregister(&qpnp_misc_driver);
}
module_init(qpnp_misc_init);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 8d03c36858b3..78f03fc75761 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2167,7 +2167,8 @@ static void __qseecom_reentrancy_check_if_this_app_blocked(
}
}
-static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req)
+static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req,
+ uint32_t *app_id)
{
int32_t ret;
struct qseecom_command_scm_resp resp;
@@ -2175,6 +2176,12 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req)
struct qseecom_registered_app_list *entry = NULL;
unsigned long flags = 0;
+ if (!app_id) {
+ pr_err("Null pointer to app_id\n");
+ return -EINVAL;
+ }
+ *app_id = 0;
+
/* check if app exists and has been registered locally */
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
@@ -2187,7 +2194,8 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req)
spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
if (found_app) {
pr_debug("Found app with id %d\n", entry->app_id);
- return entry->app_id;
+ *app_id = entry->app_id;
+ return 0;
}
memset((void *)&resp, 0, sizeof(resp));
@@ -2210,7 +2218,8 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req)
pr_err("resp type is of listener type instead of app");
return -EINVAL;
case QSEOS_APP_ID:
- return resp.data;
+ *app_id = resp.data;
+ return 0;
default:
pr_err("invalid resp type (%d) from qsee",
resp.resp_type);
@@ -2286,11 +2295,10 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
strlcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
- ret = __qseecom_check_app_exists(req);
+ ret = __qseecom_check_app_exists(req, &app_id);
if (ret < 0)
goto loadapp_err;
- app_id = ret;
if (app_id) {
pr_debug("App id %d (%s) already exists\n", app_id,
(char *)(req.app_name));
@@ -4038,7 +4046,8 @@ static void __qseecom_free_img_data(struct ion_handle **ihandle)
*ihandle = NULL;
}
-static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname)
+static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname,
+ uint32_t *app_id)
{
int ret = -1;
uint32_t fw_size = 0;
@@ -4052,6 +4061,11 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname)
size_t cmd_len;
uint32_t app_arch = 0;
+ if (!data || !appname || !app_id) {
+ pr_err("Null pointer to data or appname or appid\n");
+ return -EINVAL;
+ }
+ *app_id = 0;
if (__qseecom_get_fw_size(appname, &fw_size, &app_arch))
return -EIO;
data->client.app_arch = app_arch;
@@ -4143,14 +4157,14 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname)
switch (resp.result) {
case QSEOS_RESULT_SUCCESS:
- ret = resp.data;
+ *app_id = resp.data;
break;
case QSEOS_RESULT_INCOMPLETE:
ret = __qseecom_process_incomplete_cmd(data, &resp);
if (ret)
pr_err("process_incomplete_cmd FAILED\n");
else
- ret = resp.data;
+ *app_id = resp.data;
break;
case QSEOS_RESULT_FAILURE:
pr_err("scm call failed with response QSEOS_RESULT FAILURE\n");
@@ -4343,6 +4357,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
size_t len;
ion_phys_addr_t pa;
uint32_t fw_size, app_arch;
+ uint32_t app_id = 0;
if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
pr_err("Not allowed to be called in %d state\n",
@@ -4397,18 +4412,18 @@ int qseecom_start_app(struct qseecom_handle **handle,
app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
- ret = __qseecom_check_app_exists(app_ireq);
- if (ret < 0)
+ ret = __qseecom_check_app_exists(app_ireq, &app_id);
+ if (ret)
goto err;
strlcpy(data->client.app_name, app_name, MAX_APP_NAME_SIZE);
- if (ret > 0) {
- pr_warn("App id %d for [%s] app exists\n", ret,
+ if (app_id) {
+ pr_warn("App id %d for [%s] app exists\n", app_id,
(char *)app_ireq.app_name);
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
&qseecom.registered_app_list_head, list){
- if (entry->app_id == ret) {
+ if (entry->app_id == app_id) {
entry->ref_cnt++;
found_app = true;
break;
@@ -4423,11 +4438,11 @@ int qseecom_start_app(struct qseecom_handle **handle,
/* load the app and get the app_id */
pr_debug("%s: Loading app for the first time'\n",
qseecom.pdev->init_name);
- ret = __qseecom_load_fw(data, app_name);
+ ret = __qseecom_load_fw(data, app_name, &app_id);
if (ret < 0)
goto err;
}
- data->client.app_id = ret;
+ data->client.app_id = app_id;
if (!found_app) {
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
@@ -4435,7 +4450,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
ret = -ENOMEM;
goto err;
}
- entry->app_id = ret;
+ entry->app_id = app_id;
entry->ref_cnt = 1;
strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE);
if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) {
@@ -5272,7 +5287,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
struct qseecom_check_app_ireq req;
struct qseecom_registered_app_list *entry = NULL;
unsigned long flags = 0;
- uint32_t app_arch = 0;
+ uint32_t app_arch = 0, app_id = 0;
bool found_app = false;
/* Copy the relevant information needed for loading the image */
@@ -5287,18 +5302,18 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0';
strlcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE);
- ret = __qseecom_check_app_exists(req);
-
- if ((ret == -EINVAL) || (ret == -ENODEV)) {
+ ret = __qseecom_check_app_exists(req, &app_id);
+ if (ret) {
pr_err(" scm call to check if app is loaded failed");
return ret; /* scm call failed */
- } else if (ret > 0) {
- pr_debug("App id %d (%s) already exists\n", ret,
+ }
+ if (app_id) {
+ pr_debug("App id %d (%s) already exists\n", app_id,
(char *)(req.app_name));
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
&qseecom.registered_app_list_head, list){
- if (entry->app_id == ret) {
+ if (entry->app_id == app_id) {
app_arch = entry->app_arch;
entry->ref_cnt++;
found_app = true;
@@ -5307,8 +5322,8 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
}
spin_unlock_irqrestore(
&qseecom.registered_app_list_lock, flags);
- data->client.app_id = ret;
- query_req.app_id = ret;
+ data->client.app_id = app_id;
+ query_req.app_id = app_id;
if (app_arch) {
data->client.app_arch = app_arch;
query_req.app_arch = app_arch;
@@ -5330,7 +5345,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
pr_err("kmalloc for app entry failed\n");
return -ENOMEM;
}
- entry->app_id = ret;
+ entry->app_id = app_id;
entry->ref_cnt = 1;
entry->app_arch = data->client.app_arch;
strlcpy(entry->app_name, data->client.app_name,
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 8101b77c2acf..ec6075ec5767 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -167,6 +167,19 @@ static int mmc_bus_suspend(struct device *dev)
if (mmc_bus_needs_resume(host))
return 0;
ret = host->bus_ops->suspend(host);
+
+ /*
+ * bus_ops->suspend may fail due to some reason
+ * In such cases if we return error to PM framework
+ * from here without calling pm_generic_resume then mmc
+ * request may get stuck since PM framework will assume
+ * that mmc bus is not suspended (because of error) and
+ * it won't call resume again.
+ *
+ * So in case of error call pm_generic_resume().
+ */
+ if (ret)
+ pm_generic_resume(dev);
return ret;
}
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index a0d31ded04db..594fba08e623 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -348,6 +348,33 @@ static int mmc_force_err_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(mmc_force_err_fops, NULL, mmc_force_err_set, "%llu\n");
+static int mmc_err_state_get(void *data, u64 *val)
+{
+ struct mmc_host *host = data;
+
+ if (!host)
+ return -EINVAL;
+
+ *val = host->err_occurred ? 1 : 0;
+
+ return 0;
+}
+
+static int mmc_err_state_clear(void *data, u64 val)
+{
+ struct mmc_host *host = data;
+
+ if (!host)
+ return -EINVAL;
+
+ host->err_occurred = false;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(mmc_err_state, mmc_err_state_get,
+ mmc_err_state_clear, "%llu\n");
+
void mmc_add_host_debugfs(struct mmc_host *host)
{
struct dentry *root;
@@ -393,6 +420,10 @@ void mmc_add_host_debugfs(struct mmc_host *host)
root, host, &mmc_ring_buffer_fops))
goto err_node;
#endif
+ if (!debugfs_create_file("err_state", S_IRUSR | S_IWUSR, root, host,
+ &mmc_err_state))
+ goto err_node;
+
#ifdef CONFIG_MMC_CLKGATE
if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
root, &host->clk_delay))
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 414877874190..4567b7526469 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2494,7 +2494,7 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host)
static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
{
- int err = 0;
+ int err = 0, ret;
BUG_ON(!host);
BUG_ON(!host->card);
@@ -2503,6 +2503,8 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
if (err) {
pr_err("%s: %s: fail to suspend clock scaling (%d)\n",
mmc_hostname(host), __func__, err);
+ if (host->card->cmdq_init)
+ wake_up(&host->cmdq_ctx.wait);
return err;
}
@@ -2527,12 +2529,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
if (mmc_card_doing_bkops(host->card)) {
err = mmc_stop_bkops(host->card);
if (err)
- goto out;
+ goto out_err;
}
err = mmc_flush_cache(host->card);
if (err)
- goto out;
+ goto out_err;
if (mmc_can_sleepawake(host)) {
/*
@@ -2549,16 +2551,38 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
err = mmc_deselect_cards(host);
}
- if (!err) {
- mmc_power_off(host);
- mmc_card_set_suspended(host->card);
+ if (err)
+ goto out_err;
+ mmc_power_off(host);
+ mmc_card_set_suspended(host->card);
+
+ goto out;
+
+out_err:
+ /*
+ * In case of err let's put controller back in cmdq mode and unhalt
+ * the controller.
+ * We expect cmdq_enable and unhalt won't return any error
+ * since it is anyway enabling few registers.
+ */
+ if (host->card->cmdq_init) {
+ mmc_host_clk_hold(host);
+ ret = host->cmdq_ops->enable(host);
+ if (ret)
+ pr_err("%s: %s: enabling CMDQ mode failed (%d)\n",
+ mmc_hostname(host), __func__, ret);
+ mmc_host_clk_release(host);
+ mmc_cmdq_halt(host, false);
}
+
out:
/* Kick CMDQ thread to process any requests came in while suspending */
if (host->card->cmdq_init)
wake_up(&host->cmdq_ctx.wait);
mmc_release_host(host);
+ if (err)
+ mmc_resume_clk_scaling(host);
return err;
}
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 1ad5fd0e0a78..a83960fd474f 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -852,6 +852,7 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
struct mmc_request *mrq;
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
int offset = 0;
+ int err = 0;
if (cq_host->offset_changed)
offset = CQ_V5_VENDOR_CFG;
@@ -865,6 +866,14 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG + offset);
cmdq_runtime_pm_put(cq_host);
+
+ if (cq_host->ops->crypto_cfg_end) {
+ err = cq_host->ops->crypto_cfg_end(mmc, mrq);
+ if (err) {
+ pr_err("%s: failed to end ice config: err %d tag %d\n",
+ mmc_hostname(mmc), err, tag);
+ }
+ }
if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) &&
cq_host->ops->crypto_cfg_reset)
cq_host->ops->crypto_cfg_reset(mmc, tag);
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index db0cd956ae90..ee5e6549fa4a 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -223,6 +223,7 @@ struct cmdq_host_ops {
int (*reset)(struct mmc_host *mmc);
int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
u32 slot, u64 *ice_ctx);
+ int (*crypto_cfg_end)(struct mmc_host *mmc, struct mmc_request *mrq);
void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot);
void (*post_cqe_halt)(struct mmc_host *mmc);
};
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index a6ef06aa6f1d..2799b21fb6e3 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -414,6 +414,37 @@ int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
return 0;
}
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ int err = 0;
+ struct request *req;
+
+ if (!host->is_crypto_en)
+ return 0;
+
+ if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
+ pr_err("%s: ice is in invalid state %d\n",
+ mmc_hostname(host->mmc), msm_host->ice.state);
+ return -EINVAL;
+ }
+
+ req = mrq->req;
+ if (req) {
+ if (msm_host->ice.vops->config_end) {
+ err = msm_host->ice.vops->config_end(req);
+ if (err) {
+ pr_err("%s: ice config end failed %d\n",
+ mmc_hostname(host->mmc), err);
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
int sdhci_msm_ice_reset(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h
index d8d640437522..7699464cf71e 100644
--- a/drivers/mmc/host/sdhci-msm-ice.h
+++ b/drivers/mmc/host/sdhci-msm-ice.h
@@ -107,6 +107,7 @@ int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
u32 slot);
int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq);
int sdhci_msm_ice_reset(struct sdhci_host *host);
int sdhci_msm_ice_resume(struct sdhci_host *host);
int sdhci_msm_ice_suspend(struct sdhci_host *host);
@@ -143,6 +144,11 @@ inline int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
{
return 0;
}
+inline int sdhci_msm_ice_cfg_end(struct sdhci_host *host,
+ struct mmc_request *mrq)
+{
+ return 0;
+}
inline int sdhci_msm_ice_reset(struct sdhci_host *host)
{
return 0;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 15d1eface2d4..7274a6d2cce0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -4008,6 +4008,7 @@ static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host)
static struct sdhci_ops sdhci_msm_ops = {
.crypto_engine_cfg = sdhci_msm_ice_cfg,
.crypto_engine_cmdq_cfg = sdhci_msm_ice_cmdq_cfg,
+ .crypto_engine_cfg_end = sdhci_msm_ice_cfg_end,
.crypto_cfg_reset = sdhci_msm_ice_cfg_reset,
.crypto_engine_reset = sdhci_msm_ice_reset,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 21d2a4b8f7ae..083cb8cdf1ca 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -179,6 +179,8 @@ static void sdhci_dumpregs(struct sdhci_host *host)
readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
}
+ host->mmc->err_occurred = true;
+
if (host->ops->dump_vendor_regs)
host->ops->dump_vendor_regs(host);
sdhci_dump_state(host);
@@ -1666,6 +1668,22 @@ out:
return err;
}
+static int sdhci_crypto_cfg_end(struct sdhci_host *host,
+ struct mmc_request *mrq)
+{
+ int err = 0;
+
+ if (host->ops->crypto_engine_cfg_end) {
+ err = host->ops->crypto_engine_cfg_end(host, mrq);
+ if (err) {
+ pr_err("%s: failed to configure crypto\n",
+ mmc_hostname(host->mmc));
+ return err;
+ }
+ }
+ return 0;
+}
+
static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdhci_host *host;
@@ -2785,6 +2803,7 @@ static void sdhci_tasklet_finish(unsigned long param)
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
+ sdhci_crypto_cfg_end(host, mrq);
mmc_request_done(host->mmc, mrq);
sdhci_runtime_pm_put(host);
}
@@ -3663,6 +3682,17 @@ out:
return err;
}
+static int sdhci_cmdq_crypto_cfg_end(struct mmc_host *mmc,
+ struct mmc_request *mrq)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ if (!host->is_crypto_en)
+ return 0;
+
+ return sdhci_crypto_cfg_end(host, mrq);
+}
+
static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -3728,6 +3758,12 @@ static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc,
return 0;
}
+static int sdhci_cmdq_crypto_cfg_end(struct mmc_host *mmc,
+ struct mmc_request *mrq)
+{
+ return 0;
+}
+
static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
{
@@ -3745,6 +3781,7 @@ static const struct cmdq_host_ops sdhci_cmdq_ops = {
.clear_set_dumpregs = sdhci_cmdq_clear_set_dumpregs,
.enhanced_strobe_mask = sdhci_enhanced_strobe_mask,
.crypto_cfg = sdhci_cmdq_crypto_cfg,
+ .crypto_cfg_end = sdhci_cmdq_crypto_cfg_end,
.crypto_cfg_reset = sdhci_cmdq_crypto_cfg_reset,
.post_cqe_halt = sdhci_cmdq_post_cqe_halt,
.set_transfer_params = sdhci_cmdq_set_transfer_params,
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c4bbdd80f29c..93129b26dc5e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -659,6 +659,8 @@ struct sdhci_ops {
struct mmc_request *mrq, u32 slot);
int (*crypto_engine_cmdq_cfg)(struct sdhci_host *host,
struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+ int (*crypto_engine_cfg_end)(struct sdhci_host *host,
+ struct mmc_request *mrq);
int (*crypto_engine_reset)(struct sdhci_host *host);
void (*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot);
void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 210ea654c83f..acd5347f2cae 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -15,6 +15,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/moduleparam.h>
#include "wil6210.h"
#include "wmi.h"
#include "ftm.h"
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 7bc6149480f2..f8e5ccd7b9ca 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -90,7 +90,7 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
done = budget - quota;
if (done < budget) {
- napi_complete(napi);
+ napi_complete_done(napi, done);
wil6210_unmask_irq_rx(wil);
wil_dbg_txrx(wil, "NAPI RX complete\n");
}
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index f48182cc04df..dff565d9e206 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -22,7 +22,7 @@
#include "gsi_reg.h"
#define GSI_CMD_TIMEOUT (5*HZ)
-#define GSI_STOP_CMD_TIMEOUT_MS 10
+#define GSI_STOP_CMD_TIMEOUT_MS 20
#define GSI_MAX_CH_LOW_WEIGHT 15
#define GSI_MHI_ER_START 10
#define GSI_MHI_ER_END 16
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index d4b0dd9910e1..553480660722 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3418,11 +3418,14 @@ void ipa_inc_acquire_wakelock(enum ipa_wakelock_ref_client ref_client)
return;
spin_lock_irqsave(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
if (ipa_ctx->wakelock_ref_cnt.cnt & (1 << ref_client))
- IPAERR("client enum %d mask already set. ref cnt = %d\n",
+ IPADBG("client enum %d mask already set. ref cnt = %d\n",
ref_client, ipa_ctx->wakelock_ref_cnt.cnt);
ipa_ctx->wakelock_ref_cnt.cnt |= (1 << ref_client);
- if (ipa_ctx->wakelock_ref_cnt.cnt)
+ if (ipa_ctx->wakelock_ref_cnt.cnt &&
+ !ipa_ctx->wakelock_ref_cnt.wakelock_acquired) {
__pm_stay_awake(&ipa_ctx->w_lock);
+ ipa_ctx->wakelock_ref_cnt.wakelock_acquired = true;
+ }
IPADBG_LOW("active wakelock ref cnt = %d client enum %d\n",
ipa_ctx->wakelock_ref_cnt.cnt, ref_client);
spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
@@ -3446,8 +3449,11 @@ void ipa_dec_release_wakelock(enum ipa_wakelock_ref_client ref_client)
ipa_ctx->wakelock_ref_cnt.cnt &= ~(1 << ref_client);
IPADBG_LOW("active wakelock ref cnt = %d client enum %d\n",
ipa_ctx->wakelock_ref_cnt.cnt, ref_client);
- if (ipa_ctx->wakelock_ref_cnt.cnt == 0)
+ if (ipa_ctx->wakelock_ref_cnt.cnt == 0 &&
+ ipa_ctx->wakelock_ref_cnt.wakelock_acquired) {
__pm_relax(&ipa_ctx->w_lock);
+ ipa_ctx->wakelock_ref_cnt.wakelock_acquired = false;
+ }
spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 7b48991cba65..a2665c9e9688 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -3147,6 +3147,8 @@ static int ipa_assign_policy_v2(struct ipa_sys_connect_params *in,
IPA_GENERIC_AGGR_TIME_LIMIT;
if (in->client == IPA_CLIENT_APPS_LAN_CONS) {
sys->pyld_hdlr = ipa_lan_rx_pyld_hdlr;
+ sys->rx_pool_sz =
+ ipa_ctx->lan_rx_ring_size;
if (nr_cpu_ids > 1) {
sys->repl_hdlr =
ipa_fast_replenish_rx_cache;
@@ -3156,8 +3158,6 @@ static int ipa_assign_policy_v2(struct ipa_sys_connect_params *in,
sys->repl_hdlr =
ipa_replenish_rx_cache;
}
- sys->rx_pool_sz =
- ipa_ctx->lan_rx_ring_size;
in->ipa_ep_cfg.aggr.aggr_byte_limit =
IPA_GENERIC_AGGR_BYTE_LIMIT;
in->ipa_ep_cfg.aggr.aggr_pkt_limit =
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 94d76db6f993..a14d1fee9c35 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -841,6 +841,7 @@ struct ipa_active_clients {
struct ipa_wakelock_ref_cnt {
spinlock_t spinlock;
u32 cnt;
+ bool wakelock_acquired;
};
struct ipa_tag_completion {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index dfc3e06f452b..f8f8fd12161a 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -272,6 +272,14 @@ int ipa_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx)
mutex_lock(&ipa_ctx->lock);
list_for_each_entry(entry, &ipa_ctx->intf_list, link) {
if (!strncmp(entry->name, tx->name, IPA_RESOURCE_NAME_MAX)) {
+ /* add the entry check */
+ if (entry->num_tx_props != tx->num_tx_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_tx_props,
+ tx->num_tx_props);
+ mutex_unlock(&ipa_ctx->lock);
+ return result;
+ }
memcpy(tx->tx, entry->tx, entry->num_tx_props *
sizeof(struct ipa_ioc_tx_intf_prop));
result = 0;
@@ -305,6 +313,14 @@ int ipa_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx)
mutex_lock(&ipa_ctx->lock);
list_for_each_entry(entry, &ipa_ctx->intf_list, link) {
if (!strncmp(entry->name, rx->name, IPA_RESOURCE_NAME_MAX)) {
+ /* add the entry check */
+ if (entry->num_rx_props != rx->num_rx_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_rx_props,
+ rx->num_rx_props);
+ mutex_unlock(&ipa_ctx->lock);
+ return result;
+ }
memcpy(rx->rx, entry->rx, entry->num_rx_props *
sizeof(struct ipa_ioc_rx_intf_prop));
result = 0;
@@ -338,6 +354,14 @@ int ipa_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext)
mutex_lock(&ipa_ctx->lock);
list_for_each_entry(entry, &ipa_ctx->intf_list, link) {
if (!strcmp(entry->name, ext->name)) {
+ /* add the entry check */
+ if (entry->num_ext_props != ext->num_ext_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_ext_props,
+ ext->num_ext_props);
+ mutex_unlock(&ipa_ctx->lock);
+ return result;
+ }
memcpy(ext->ext, entry->ext, entry->num_ext_props *
sizeof(struct ipa_ioc_ext_intf_prop));
result = 0;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 9cab7e010c3a..d53121292c03 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5161,7 +5161,8 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type,
*/
u32 ipa_get_sys_yellow_wm(struct ipa_sys_context *sys)
{
- if (ipa_ctx->ipa_hw_type == IPA_HW_v2_6L) {
+ if (ipa_ctx->ipa_hw_type == IPA_HW_v2_6L &&
+ ipa_ctx->ipa_uc_monitor_holb) {
return ipa_read_reg(ipa_ctx->mmio,
IPA_YELLOW_MARKER_SYS_CFG_OFST);
} else {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index b9f57552533e..b687b711dc20 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -275,6 +275,14 @@ int ipa3_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx)
mutex_lock(&ipa3_ctx->lock);
list_for_each_entry(entry, &ipa3_ctx->intf_list, link) {
if (!strcmp(entry->name, tx->name)) {
+ /* add the entry check */
+ if (entry->num_tx_props != tx->num_tx_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_tx_props,
+ tx->num_tx_props);
+ mutex_unlock(&ipa3_ctx->lock);
+ return result;
+ }
memcpy(tx->tx, entry->tx, entry->num_tx_props *
sizeof(struct ipa_ioc_tx_intf_prop));
result = 0;
@@ -314,6 +322,14 @@ int ipa3_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx)
mutex_lock(&ipa3_ctx->lock);
list_for_each_entry(entry, &ipa3_ctx->intf_list, link) {
if (!strcmp(entry->name, rx->name)) {
+ /* add the entry check */
+ if (entry->num_rx_props != rx->num_rx_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_rx_props,
+ rx->num_rx_props);
+ mutex_unlock(&ipa3_ctx->lock);
+ return result;
+ }
memcpy(rx->rx, entry->rx, entry->num_rx_props *
sizeof(struct ipa_ioc_rx_intf_prop));
result = 0;
@@ -348,6 +364,14 @@ int ipa3_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext)
mutex_lock(&ipa3_ctx->lock);
list_for_each_entry(entry, &ipa3_ctx->intf_list, link) {
if (!strcmp(entry->name, ext->name)) {
+ /* add the entry check */
+ if (entry->num_ext_props != ext->num_ext_props) {
+ IPAERR("invalid entry number(%u %u)\n",
+ entry->num_ext_props,
+ ext->num_ext_props);
+ mutex_unlock(&ipa3_ctx->lock);
+ return result;
+ }
memcpy(ext->ext, entry->ext, entry->num_ext_props *
sizeof(struct ipa_ioc_ext_intf_prop));
result = 0;
diff --git a/drivers/platform/msm/msm_ext_display.c b/drivers/platform/msm/msm_ext_display.c
index bb1259e3cfa1..a35ed1afc720 100644
--- a/drivers/platform/msm/msm_ext_display.c
+++ b/drivers/platform/msm/msm_ext_display.c
@@ -285,11 +285,6 @@ static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp,
/* if already connected, block a new connection */
if (ext_disp->current_disp != type)
return false;
-
- /* if same display connected, block same connection type */
- if (ext_disp->flags & flags)
- return false;
-
end:
ext_disp->flags |= flags;
ext_disp->current_disp = type;
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index dfa83f2304b2..de6c86984e3f 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -1,9 +1,9 @@
obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o
obj-$(CONFIG_SMB135X_CHARGER) += smb135x-charger.o pmic-voter.o
-obj-$(CONFIG_SMB1351_USB_CHARGER) += smb1351-charger.o pmic-voter.o battery.o
+obj-$(CONFIG_SMB1351_USB_CHARGER) += battery.o smb1351-charger.o pmic-voter.o
obj-$(CONFIG_MSM_BCL_CTL) += msm_bcl.o
obj-$(CONFIG_MSM_BCL_PERIPHERAL_CTL) += bcl_peripheral.o
obj-$(CONFIG_BATTERY_BCL) += battery_current_limit.o
-obj-$(CONFIG_QPNP_SMB2) += qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o battery.o
-obj-$(CONFIG_SMB138X_CHARGER) += smb138x-charger.o smb-lib.o pmic-voter.o storm-watch.o battery.o
-obj-$(CONFIG_QPNP_QNOVO) += qpnp-qnovo.o battery.o
+obj-$(CONFIG_QPNP_SMB2) += battery.o qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o
+obj-$(CONFIG_SMB138X_CHARGER) += battery.o smb138x-charger.o smb-lib.o pmic-voter.o storm-watch.o
+obj-$(CONFIG_QPNP_QNOVO) += battery.o qpnp-qnovo.o
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 64f4d46df9a0..bf7aa7a36784 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -239,7 +239,6 @@ static struct smb_params pm660_params = {
struct smb_dt_props {
int fcc_ua;
int usb_icl_ua;
- int otg_cl_ua;
int dc_icl_ua;
int boost_threshold_ua;
int fv_uv;
@@ -323,9 +322,9 @@ static int smb2_parse_dt(struct smb2 *chip)
chip->dt.usb_icl_ua = -EINVAL;
rc = of_property_read_u32(node,
- "qcom,otg-cl-ua", &chip->dt.otg_cl_ua);
+ "qcom,otg-cl-ua", &chg->otg_cl_ua);
if (rc < 0)
- chip->dt.otg_cl_ua = MICRO_1P5A;
+ chg->otg_cl_ua = MICRO_1P5A;
rc = of_property_read_u32(node,
"qcom,dc-icl-ua", &chip->dt.dc_icl_ua);
@@ -1386,7 +1385,8 @@ static int smb2_init_hw(struct smb2 *chip)
/* set OTG current limit */
rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
- chip->dt.otg_cl_ua);
+ (chg->wa_flags & OTG_WA) ?
+ chg->param.otg_cl.min_u : chg->otg_cl_ua);
if (rc < 0) {
pr_err("Couldn't set otg current limit rc=%d\n", rc);
return rc;
@@ -1649,7 +1649,7 @@ static int smb2_chg_config_init(struct smb2 *chip)
break;
case PM660_SUBTYPE:
chip->chg.smb_version = PM660_SUBTYPE;
- chip->chg.wa_flags |= BOOST_BACK_WA;
+ chip->chg.wa_flags |= BOOST_BACK_WA | OTG_WA;
chg->param.freq_buck = pm660_params.freq_buck;
chg->param.freq_boost = pm660_params.freq_boost;
chg->chg_freq.freq_5V = 600;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index a8427c5e3107..4f126854728f 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -489,7 +489,7 @@ static int smblib_set_adapter_allowance(struct smb_charger *chg,
if (chg->smb_version == PM660_SUBTYPE) {
smblib_dbg(chg, PR_MISC, "voltage not supported=%d\n",
allowed_voltage);
- allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_9V;
+ allowed_voltage = USBIN_ADAPTER_ALLOW_5V_OR_9V;
}
break;
}
@@ -548,6 +548,26 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
* HELPER FUNCTIONS *
********************/
+static void smblib_rerun_apsd(struct smb_charger *chg)
+{
+ int rc;
+
+ smblib_dbg(chg, PR_MISC, "re-running APSD\n");
+ if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
+ rc = smblib_masked_write(chg,
+ USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
+ AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't enable HVDCP auth IRQ rc=%d\n",
+ rc);
+ }
+
+ rc = smblib_masked_write(chg, CMD_APSD_REG,
+ APSD_RERUN_BIT, APSD_RERUN_BIT);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc);
+}
+
static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
{
const struct apsd_result *apsd_result;
@@ -565,11 +585,7 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
chg->hvdcp_disable_votable_indirect)) {
apsd_result = smblib_get_apsd_result(chg);
if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) {
- /* rerun APSD */
- smblib_dbg(chg, PR_MISC, "rerun APSD\n");
- smblib_masked_write(chg, CMD_APSD_REG,
- APSD_RERUN_BIT,
- APSD_RERUN_BIT);
+ smblib_rerun_apsd(chg);
}
}
}
@@ -581,12 +597,13 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
/* if PD is active, APSD is disabled so won't have a valid result */
- if (chg->pd_active) {
+ if (chg->pd_active)
chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
- return apsd_result;
- }
+ else
+ chg->usb_psy_desc.type = apsd_result->pst;
- chg->usb_psy_desc.type = apsd_result->pst;
+ smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
+ apsd_result->name, chg->pd_active);
return apsd_result;
}
@@ -764,16 +781,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg)
apsd_result = smblib_get_apsd_result(chg);
if ((apsd_result->pst == POWER_SUPPLY_TYPE_UNKNOWN)
|| (apsd_result->pst == POWER_SUPPLY_TYPE_USB)) {
- /* rerun APSD */
- pr_info("Reruning APSD type = %s at bootup\n",
- apsd_result->name);
- rc = smblib_masked_write(chg, CMD_APSD_REG,
- APSD_RERUN_BIT,
- APSD_RERUN_BIT);
- if (rc < 0) {
- smblib_err(chg, "Couldn't rerun APSD rc = %d\n", rc);
- return rc;
- }
+ smblib_rerun_apsd(chg);
}
return 0;
@@ -1282,11 +1290,14 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev)
/*****************
* OTG REGULATOR *
*****************/
-
+#define MAX_RETRY 15
+#define MIN_DELAY_US 2000
+#define MAX_DELAY_US 9000
static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev)
{
struct smb_charger *chg = rdev_get_drvdata(rdev);
- int rc;
+ int rc, retry_count = 0, min_delay = MIN_DELAY_US;
+ u8 stat;
smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n");
rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
@@ -1305,6 +1316,42 @@ static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev)
return rc;
}
+ if (chg->wa_flags & OTG_WA) {
+ /* check for softstart */
+ do {
+ usleep_range(min_delay, min_delay + 100);
+ rc = smblib_read(chg, OTG_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't read OTG status rc=%d\n",
+ rc);
+ goto out;
+ }
+
+ if (stat & BOOST_SOFTSTART_DONE_BIT) {
+ rc = smblib_set_charge_param(chg,
+ &chg->param.otg_cl, chg->otg_cl_ua);
+ if (rc < 0)
+ smblib_err(chg,
+ "Couldn't set otg limit\n");
+ break;
+ }
+
+ /* increase the delay for following iterations */
+ if (retry_count > 5)
+ min_delay = MAX_DELAY_US;
+ } while (retry_count++ < MAX_RETRY);
+
+ if (retry_count >= MAX_RETRY) {
+ smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n");
+ goto out;
+ }
+ }
+
+ return 0;
+out:
+ /* disable OTG if softstart failed */
+ smblib_write(chg, CMD_OTG_REG, 0);
return rc;
}
@@ -1338,6 +1385,17 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc);
}
+ if (chg->wa_flags & OTG_WA) {
+ /* set OTG current limit to minimum value */
+ rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
+ chg->param.otg_cl.min_u);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't set otg current limit rc=%d\n", rc);
+ return rc;
+ }
+ }
+
smblib_dbg(chg, PR_OTG, "disabling OTG\n");
rc = smblib_write(chg, CMD_OTG_REG, 0);
if (rc < 0) {
@@ -1346,7 +1404,6 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
}
smblib_dbg(chg, PR_OTG, "start 1 in 8 mode\n");
- rc = smblib_write(chg, CMD_OTG_REG, 0);
rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0);
if (rc < 0) {
@@ -2947,6 +3004,14 @@ irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data)
return IRQ_HANDLED;
}
+ if (chg->wa_flags & OTG_WA) {
+ if (stat & OTG_OC_DIS_SW_STS_RT_STS_BIT)
+ smblib_err(chg, "OTG disabled by hw\n");
+
+ /* not handling software based hiccups for PM660 */
+ return IRQ_HANDLED;
+ }
+
if (stat & OTG_OVERCURRENT_RT_STS_BIT)
schedule_work(&chg->otg_oc_work);
@@ -3162,6 +3227,7 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data)
|| (stat & AICL_DONE_BIT))
delay = 0;
+ cancel_delayed_work_sync(&chg->icl_change_work);
schedule_delayed_work(&chg->icl_change_work,
msecs_to_jiffies(delay));
}
@@ -3271,11 +3337,22 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
if (chg->mode == PARALLEL_MASTER)
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);
+ /* the APSD done handler will set the USB supply type */
+ apsd_result = smblib_get_apsd_result(chg);
+ if (get_effective_result(chg->hvdcp_hw_inov_dis_votable)) {
+ if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ /* force HVDCP2 to 9V if INOV is disabled */
+ rc = smblib_masked_write(chg, CMD_HVDCP_2_REG,
+ FORCE_9V_BIT, FORCE_9V_BIT);
+ if (rc < 0)
+ smblib_err(chg,
+ "Couldn't force 9V HVDCP rc=%d\n", rc);
+ }
+ }
+
/* QC authentication done, parallel charger can be enabled now */
vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0);
- /* the APSD done handler will set the USB supply type */
- apsd_result = smblib_get_apsd_result(chg);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n",
apsd_result->name);
}
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 21ccd3ce57c7..d6afca010502 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -80,6 +80,7 @@ enum {
BOOST_BACK_WA = BIT(1),
TYPEC_CC2_REMOVAL_WA_BIT = BIT(2),
QC_AUTH_INTERRUPT_WA_BIT = BIT(3),
+ OTG_WA = BIT(4),
};
enum smb_irq_index {
@@ -305,6 +306,7 @@ struct smb_charger {
int otg_attempts;
int vconn_attempts;
int default_icl_ua;
+ int otg_cl_ua;
/* workaround flag */
u32 wa_flags;
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 19b1d319ef45..aef28dbeb931 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
@@ -31,6 +32,13 @@
#define INT_RT_STATUS_REG 0x10
#define VREG_OK_RT_STS_BIT BIT(0)
+#define SC_ERROR_RT_STS_BIT BIT(1)
+
+#define LCDB_STS3_REG 0x0A
+#define LDO_VREG_OK_BIT BIT(7)
+
+#define LCDB_STS4_REG 0x0B
+#define NCP_VREG_OK_BIT BIT(7)
#define LCDB_AUTO_TOUCH_WAKE_CTL_REG 0x40
#define EN_AUTO_TOUCH_WAKE_BIT BIT(7)
@@ -185,6 +193,7 @@ struct qpnp_lcdb {
struct platform_device *pdev;
struct regmap *regmap;
u32 base;
+ int sc_irq;
/* TTW params */
bool ttw_enable;
@@ -196,6 +205,9 @@ struct qpnp_lcdb {
/* status parameters */
bool lcdb_enabled;
bool settings_saved;
+ bool lcdb_sc_disable;
+ int sc_count;
+ ktime_t sc_module_enable_time;
struct mutex lcdb_mutex;
struct mutex read_write_mutex;
@@ -572,8 +584,11 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
int rc = 0, timeout, delay;
u8 val = 0;
- if (lcdb->lcdb_enabled)
+ if (lcdb->lcdb_enabled || lcdb->lcdb_sc_disable) {
+ pr_debug("lcdb_enabled=%d lcdb_sc_disable=%d\n",
+ lcdb->lcdb_enabled, lcdb->lcdb_sc_disable);
return 0;
+ }
if (lcdb->ttw_enable) {
rc = qpnp_lcdb_ttw_exit(lcdb);
@@ -676,6 +691,111 @@ static int qpnp_lcdb_disable(struct qpnp_lcdb *lcdb)
return rc;
}
+#define LCDB_SC_RESET_CNT_DLY_US 1000000
+#define LCDB_SC_CNT_MAX 10
+static int qpnp_lcdb_handle_sc_event(struct qpnp_lcdb *lcdb)
+{
+ int rc = 0;
+ s64 elapsed_time_us;
+
+ mutex_lock(&lcdb->lcdb_mutex);
+ rc = qpnp_lcdb_disable(lcdb);
+ if (rc < 0) {
+ pr_err("Failed to disable lcdb rc=%d\n", rc);
+ goto unlock_mutex;
+ }
+
+ /* Check if the SC re-occurred immediately */
+ elapsed_time_us = ktime_us_delta(ktime_get(),
+ lcdb->sc_module_enable_time);
+ if (elapsed_time_us > LCDB_SC_RESET_CNT_DLY_US) {
+ lcdb->sc_count = 0;
+ } else if (lcdb->sc_count > LCDB_SC_CNT_MAX) {
+ pr_err("SC trigged %d times, disabling LCDB forever!\n",
+ lcdb->sc_count);
+ lcdb->lcdb_sc_disable = true;
+ goto unlock_mutex;
+ }
+ lcdb->sc_count++;
+ lcdb->sc_module_enable_time = ktime_get();
+
+ /* delay for SC to clear */
+ usleep_range(10000, 10100);
+
+ rc = qpnp_lcdb_enable(lcdb);
+ if (rc < 0)
+ pr_err("Failed to enable lcdb rc=%d\n", rc);
+
+unlock_mutex:
+ mutex_unlock(&lcdb->lcdb_mutex);
+ return rc;
+}
+
+static irqreturn_t qpnp_lcdb_sc_irq_handler(int irq, void *data)
+{
+ struct qpnp_lcdb *lcdb = data;
+ int rc;
+ u8 val, val2[2] = {0};
+
+ rc = qpnp_lcdb_read(lcdb, lcdb->base + INT_RT_STATUS_REG, &val, 1);
+ if (rc < 0)
+ goto irq_handled;
+
+ if (val & SC_ERROR_RT_STS_BIT) {
+ rc = qpnp_lcdb_read(lcdb,
+ lcdb->base + LCDB_MISC_CTL_REG, &val, 1);
+ if (rc < 0)
+ goto irq_handled;
+
+ if (val & EN_TOUCH_WAKE_BIT) {
+ /* blanking time */
+ usleep_range(300, 310);
+ /*
+ * The status registers need to written with any value
+ * before reading
+ */
+ rc = qpnp_lcdb_write(lcdb,
+ lcdb->base + LCDB_STS3_REG, val2, 2);
+ if (rc < 0)
+ goto irq_handled;
+
+ rc = qpnp_lcdb_read(lcdb,
+ lcdb->base + LCDB_STS3_REG, val2, 2);
+ if (rc < 0)
+ goto irq_handled;
+
+ if (!(val2[0] & LDO_VREG_OK_BIT) ||
+ !(val2[1] & NCP_VREG_OK_BIT)) {
+ rc = qpnp_lcdb_handle_sc_event(lcdb);
+ if (rc < 0) {
+ pr_err("Failed to handle SC rc=%d\n",
+ rc);
+ goto irq_handled;
+ }
+ }
+ } else {
+ /* blanking time */
+ usleep_range(2000, 2100);
+ /* Read the SC status again to confirm true SC */
+ rc = qpnp_lcdb_read(lcdb,
+ lcdb->base + INT_RT_STATUS_REG, &val, 1);
+ if (rc < 0)
+ goto irq_handled;
+
+ if (val & SC_ERROR_RT_STS_BIT) {
+ rc = qpnp_lcdb_handle_sc_event(lcdb);
+ if (rc < 0) {
+ pr_err("Failed to handle SC rc=%d\n",
+ rc);
+ goto irq_handled;
+ }
+ }
+ }
+ }
+irq_handled:
+ return IRQ_HANDLED;
+}
+
#define MIN_BST_VOLTAGE_MV 4700
#define MAX_BST_VOLTAGE_MV 6250
#define MIN_VOLTAGE_MV 4000
@@ -1554,6 +1674,18 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
return rc;
}
+ if (lcdb->sc_irq >= 0) {
+ lcdb->sc_count = 0;
+ rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
+ NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
+ "qpnp_lcdb_sc_irq", lcdb);
+ if (rc < 0) {
+ pr_err("Unable to request sc(%d) irq rc=%d\n",
+ lcdb->sc_irq, rc);
+ return rc;
+ }
+ }
+
if (!is_lcdb_enabled(lcdb)) {
rc = qpnp_lcdb_read(lcdb, lcdb->base +
LCDB_MODULE_RDY_REG, &val, 1);
@@ -1622,6 +1754,10 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
lcdb->ttw_enable = true;
}
+ lcdb->sc_irq = platform_get_irq_byname(lcdb->pdev, "sc-irq");
+ if (lcdb->sc_irq < 0)
+ pr_debug("sc irq is not defined\n");
+
return rc;
}
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 09c50a81a943..cc809cbdd839 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -4187,7 +4187,6 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
if (ctx->local_open_state == GLINK_CHANNEL_OPENED ||
ctx->local_open_state == GLINK_CHANNEL_OPENING) {
ctx->transport_ptr = dummy_xprt_ctx;
- rwref_write_put(&ctx->ch_state_lhb2);
glink_core_move_ch_node(xprt_ptr, dummy_xprt_ctx, ctx);
} else {
/* local state is in either CLOSED or CLOSING */
@@ -4197,9 +4196,9 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
/* Channel should be fully closed now. Delete here */
if (ch_is_fully_closed(ctx))
glink_delete_ch_from_list(ctx, false);
- rwref_write_put(&ctx->ch_state_lhb2);
}
rwref_put(&ctx->ch_state_lhb2);
+ rwref_write_put(&ctx->ch_state_lhb2);
ctx = get_first_ch_ctx(xprt_ptr);
}
spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 4e541773c805..2fcd1a4c636c 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -110,13 +110,7 @@ module_param(qmi_timeout, ulong, 0600);
} \
} while (0)
#else
-#define ICNSS_ASSERT(_condition) do { \
- if (!(_condition)) { \
- icnss_pr_err("ASSERT at line %d\n", \
- __LINE__); \
- WARN_ON(1); \
- } \
- } while (0)
+#define ICNSS_ASSERT(_condition) do { } while (0)
#endif
enum icnss_debug_quirks {
@@ -213,7 +207,7 @@ struct icnss_clk_info {
};
static struct icnss_vreg_info icnss_vreg_info[] = {
- {NULL, "vdd-0.8-cx-mx", 800000, 800000, 0, 0, true},
+ {NULL, "vdd-0.8-cx-mx", 800000, 800000, 0, 0, false},
{NULL, "vdd-1.8-xo", 1800000, 1800000, 0, 0, false},
{NULL, "vdd-1.3-rfa", 1304000, 1304000, 0, 0, false},
{NULL, "vdd-3.3-ch0", 3312000, 3312000, 0, 0, false},
diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c
index 10f71b85a15b..fe5458974406 100644
--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c
+++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c
@@ -368,6 +368,9 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf,
struct voice_svc_prvt *prtd;
struct voice_svc_write_msg *data = NULL;
uint32_t cmd;
+ struct voice_svc_register *register_data = NULL;
+ struct voice_svc_cmd_request *request_data = NULL;
+ uint32_t request_payload_size;
pr_debug("%s\n", __func__);
@@ -416,12 +419,19 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf,
*/
if (count == (sizeof(struct voice_svc_write_msg) +
sizeof(struct voice_svc_register))) {
- ret = process_reg_cmd(
- (struct voice_svc_register *)data->payload, prtd);
+ register_data =
+ (struct voice_svc_register *)data->payload;
+ if (register_data == NULL) {
+ pr_err("%s: register data is NULL", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ ret = process_reg_cmd(register_data, prtd);
if (!ret)
ret = count;
} else {
- pr_err("%s: invalid payload size\n", __func__);
+ pr_err("%s: invalid data payload size for register command\n",
+ __func__);
ret = -EINVAL;
goto done;
}
@@ -430,19 +440,40 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf,
/*
* Check that count reflects the expected size to ensure
* sufficient memory was allocated. Since voice_svc_cmd_request
- * has a variable size, check the minimum value count must be.
+ * has a variable size, check the minimum value count must be to
+ * parse the message request then check the minimum size to hold
+ * the payload of the message request.
*/
if (count >= (sizeof(struct voice_svc_write_msg) +
sizeof(struct voice_svc_cmd_request))) {
- ret = voice_svc_send_req(
- (struct voice_svc_cmd_request *)data->payload, prtd);
- if (!ret)
- ret = count;
- } else {
- pr_err("%s: invalid payload size\n", __func__);
- ret = -EINVAL;
- goto done;
- }
+ request_data =
+ (struct voice_svc_cmd_request *)data->payload;
+ if (request_data == NULL) {
+ pr_err("%s: request data is NULL", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ request_payload_size = request_data->payload_size;
+
+ if (count >= (sizeof(struct voice_svc_write_msg) +
+ sizeof(struct voice_svc_cmd_request) +
+ request_payload_size)) {
+ ret = voice_svc_send_req(request_data, prtd);
+ if (!ret)
+ ret = count;
+ } else {
+ pr_err("%s: invalid request payload size\n",
+ __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ } else {
+ pr_err("%s: invalid data payload size for request command\n",
+ __func__);
+ ret = -EINVAL;
+ goto done;
+ }
break;
default:
pr_debug("%s: Invalid command: %u\n", __func__, cmd);
diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c
index cf0b7ff25201..c7059d60d786 100644
--- a/drivers/soc/qcom/qpnp-haptic.c
+++ b/drivers/soc/qcom/qpnp-haptic.c
@@ -25,6 +25,7 @@
#include <linux/qpnp/pwm.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/qpnp/qpnp-revid.h>
#include <linux/qpnp/qpnp-haptic.h>
#include "../../staging/android/timed_output.h"
@@ -37,6 +38,7 @@
#define QPNP_HAP_LRA_AUTO_RES_HI(b) (b + 0x0C)
#define QPNP_HAP_EN_CTL_REG(b) (b + 0x46)
#define QPNP_HAP_EN_CTL2_REG(b) (b + 0x48)
+#define QPNP_HAP_AUTO_RES_CTRL(b) (b + 0x4B)
#define QPNP_HAP_ACT_TYPE_REG(b) (b + 0x4C)
#define QPNP_HAP_WAV_SHAPE_REG(b) (b + 0x4D)
#define QPNP_HAP_PLAY_MODE_REG(b) (b + 0x4E)
@@ -62,13 +64,25 @@
#define QPNP_HAP_ACT_TYPE_MASK 0xFE
#define QPNP_HAP_LRA 0x0
#define QPNP_HAP_ERM 0x1
-#define QPNP_HAP_AUTO_RES_MODE_MASK 0x8F
+#define QPNP_HAP_AUTO_RES_MODE_MASK GENMASK(6, 4)
#define QPNP_HAP_AUTO_RES_MODE_SHIFT 4
-#define QPNP_HAP_LRA_HIGH_Z_MASK 0xF3
+#define QPNP_HAP_PM660_AUTO_RES_MODE_BIT BIT(7)
+#define QPNP_HAP_PM660_AUTO_RES_MODE_SHIFT 7
+#define QPNP_HAP_PM660_CALIBRATE_DURATION_MASK GENMASK(6, 5)
+#define QPNP_HAP_PM660_CALIBRATE_DURATION_SHIFT 5
+#define QPNP_HAP_PM660_QWD_DRIVE_DURATION_BIT BIT(4)
+#define QPNP_HAP_PM660_QWD_DRIVE_DURATION_SHIFT 4
+#define QPNP_HAP_PM660_CALIBRATE_AT_EOP_BIT BIT(3)
+#define QPNP_HAP_PM660_CALIBRATE_AT_EOP_SHIFT 3
+#define QPNP_HAP_PM660_LRA_ZXD_CAL_PERIOD_BIT GENMASK(2, 0)
+#define QPNP_HAP_LRA_HIGH_Z_MASK GENMASK(3, 2)
#define QPNP_HAP_LRA_HIGH_Z_SHIFT 2
-#define QPNP_HAP_LRA_RES_CAL_PER_MASK 0xFC
+#define QPNP_HAP_LRA_RES_CAL_PER_MASK GENMASK(1, 0)
+#define QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK GENMASK(2, 0)
#define QPNP_HAP_RES_CAL_PERIOD_MIN 4
#define QPNP_HAP_RES_CAL_PERIOD_MAX 32
+#define QPNP_HAP_PM660_RES_CAL_PERIOD_MIN 4
+#define QPNP_HAP_PM660_RES_CAL_PERIOD_MAX 256
#define QPNP_HAP_PLAY_MODE_MASK 0xCF
#define QPNP_HAP_PLAY_MODE_SHFT 4
#define QPNP_HAP_VMAX_MASK 0xC1
@@ -130,7 +144,6 @@
#define QPNP_HAP_TEST2_AUTO_RES_MASK 0x7F
#define QPNP_HAP_SEC_UNLOCK 0xA5
#define AUTO_RES_ENABLE 0x80
-#define AUTO_RES_DISABLE 0x00
#define AUTO_RES_ERR_BIT 0x10
#define SC_FOUND_BIT 0x08
#define SC_MAX_DURATION 5
@@ -148,7 +161,7 @@
#define MISC_SEC_UNLOCK 0xA5
#define PMI8950_MISC_SID 2
-#define POLL_TIME_AUTO_RES_ERR_NS (5 * NSEC_PER_MSEC)
+#define POLL_TIME_AUTO_RES_ERR_NS (20 * NSEC_PER_MSEC)
#define MAX_POSITIVE_VARIATION_LRA_FREQ 30
#define MAX_NEGATIVE_VARIATION_LRA_FREQ -30
@@ -222,9 +235,14 @@ enum qpnp_hap_auto_res_mode {
QPNP_HAP_AUTO_RES_ZXD_EOP,
};
+enum qpnp_hap_pm660_auto_res_mode {
+ QPNP_HAP_PM660_AUTO_RES_ZXD,
+ QPNP_HAP_PM660_AUTO_RES_QWD,
+};
+
/* high Z option lines */
enum qpnp_hap_high_z {
- QPNP_HAP_LRA_HIGH_Z_NONE,
+ QPNP_HAP_LRA_HIGH_Z_NONE, /* opt0 for PM660 */
QPNP_HAP_LRA_HIGH_Z_OPT1,
QPNP_HAP_LRA_HIGH_Z_OPT2,
QPNP_HAP_LRA_HIGH_Z_OPT3,
@@ -238,6 +256,11 @@ enum qpnp_hap_mode {
QPNP_HAP_PWM,
};
+/* status flags */
+enum qpnp_hap_status {
+ AUTO_RESONANCE_ENABLED = BIT(0),
+};
+
/* pwm channel info */
struct qpnp_pwm_info {
struct pwm_device *pwm_dev;
@@ -253,7 +276,6 @@ struct qpnp_pwm_info {
* @ auto_res_err_poll_timer - hrtimer for auto-resonance error
* @ timed_dev - timed output device
* @ work - worker
- * @ auto_res_err_work - correct auto resonance error
* @ sc_work - worker to handle short circuit condition
* @ pwm_info - pwm info
* @ lock - mutex lock
@@ -267,6 +289,7 @@ struct qpnp_pwm_info {
percentage variation on the higher side.
* @ drive_period_code_min_limit - calculated drive period code with
percentage variation on the lower side
+ * @ lra_res_cal_period - LRA resonance calibration period
* @ play_mode - play mode
* @ auto_res_mode - auto resonace mode
* @ lra_high_z - high z option line
@@ -283,6 +306,7 @@ struct qpnp_pwm_info {
* @ wave_s_rep_cnt - waveform sample repeat count
* @ play_irq - irq for play
* @ sc_irq - irq for short circuit
+ * @ status_flags - status
* @ base - base address
* @ act_type - actuator type
* @ wave_shape - waveform shape
@@ -314,7 +338,6 @@ struct qpnp_hap {
struct hrtimer auto_res_err_poll_timer;
struct timed_output_dev timed_dev;
struct work_struct work;
- struct work_struct auto_res_err_work;
struct delayed_work sc_work;
struct hrtimer hap_test_timer;
struct work_struct test_work;
@@ -323,8 +346,9 @@ struct qpnp_hap {
struct mutex wf_lock;
struct completion completion;
enum qpnp_hap_mode play_mode;
- enum qpnp_hap_auto_res_mode auto_res_mode;
enum qpnp_hap_high_z lra_high_z;
+ int lra_qwd_drive_duration;
+ int calibrate_at_eop;
u32 init_drive_period_code;
u32 timeout_ms;
u32 time_required_to_generate_back_emf_us;
@@ -338,9 +362,11 @@ struct qpnp_hap {
u32 wave_s_rep_cnt;
u32 play_irq;
u32 sc_irq;
+ u32 status_flags;
u16 base;
u16 drive_period_code_max_limit;
u16 drive_period_code_min_limit;
+ u16 lra_res_cal_period;
u8 drive_period_code_max_limit_percent_variation;
u8 drive_period_code_min_limit_percent_variation;
u8 act_type;
@@ -350,9 +376,10 @@ struct qpnp_hap {
u8 brake_pat[QPNP_HAP_BRAKE_PAT_LEN];
u8 reg_en_ctl;
u8 reg_play;
- u8 lra_res_cal_period;
u8 sc_duration;
u8 ext_pwm_dtest_line;
+ u8 pmic_subtype;
+ u8 auto_res_mode;
bool vcc_pon_enabled;
bool state;
bool use_play_irq;
@@ -398,6 +425,21 @@ static int qpnp_hap_write_reg(struct qpnp_hap *hap, u8 *data, u16 addr)
return rc;
}
+static int
+qpnp_hap_masked_write_reg(struct qpnp_hap *hap, u8 val, u16 addr, u8 mask)
+{
+ int rc;
+
+ rc = regmap_update_bits(hap->regmap, addr, mask, val);
+ if (rc < 0)
+ pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
+ rc);
+ else
+ pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
+
+ return rc;
+}
+
/* helper to access secure registers */
static int qpnp_hap_sec_access(struct qpnp_hap *hap)
{
@@ -1408,34 +1450,40 @@ static int calculate_lra_code(struct qpnp_hap *hap)
static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
{
int rc = 0;
- u8 val;
+ u8 val = 0;
+ u16 addr;
- rc = qpnp_hap_read_reg(hap, &val, QPNP_HAP_TEST2_REG(hap->base));
- if (rc < 0)
- return rc;
- val &= QPNP_HAP_TEST2_AUTO_RES_MASK;
+
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ addr = QPNP_HAP_AUTO_RES_CTRL(hap->base);
+ } else {
+ addr = QPNP_HAP_TEST2_REG(hap->base);
+ /* TEST2 is a secure access register */
+ rc = qpnp_hap_sec_access(hap);
+ if (rc)
+ return rc;
+ }
if (enable)
val |= AUTO_RES_ENABLE;
- else
- val |= AUTO_RES_DISABLE;
- /* TEST2 is a secure access register */
- rc = qpnp_hap_sec_access(hap);
+ rc = qpnp_hap_masked_write_reg(hap, val, addr, AUTO_RES_ENABLE);
if (rc)
return rc;
- rc = qpnp_hap_write_reg(hap, &val, QPNP_HAP_TEST2_REG(hap->base));
- if (rc)
- return rc;
+ if (enable)
+ hap->status_flags |= AUTO_RESONANCE_ENABLED;
+ else
+ hap->status_flags &= ~AUTO_RESONANCE_ENABLED;
return 0;
}
static void update_lra_frequency(struct qpnp_hap *hap)
{
- u8 lra_auto_res_lo = 0, lra_auto_res_hi = 0;
+ u8 lra_auto_res_lo = 0, lra_auto_res_hi = 0, val;
u32 play_rate_code;
+ int rc;
qpnp_hap_read_reg(hap, &lra_auto_res_lo,
QPNP_HAP_LRA_AUTO_RES_LO(hap->base));
@@ -1449,16 +1497,29 @@ static void update_lra_frequency(struct qpnp_hap *hap)
"lra_auto_res_lo = 0x%x lra_auto_res_hi = 0x%x play_rate_code = 0x%x\n",
lra_auto_res_lo, lra_auto_res_hi, play_rate_code);
+ rc = qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base));
+ if (rc < 0)
+ return;
+
/*
- * If the drive period code read from AUTO RES_LO and AUTO_RES_HI
- * registers is more than the max limit percent variation read from
- * DT or less than the min limit percent variation read from DT, then
- * RATE_CFG registers are not uptdated.
+ * If the drive period code read from AUTO_RES_LO and AUTO_RES_HI
+ * registers is more than the max limit percent variation or less
+ * than the min limit percent variation specified through DT, then
+ * auto-resonance is disabled.
*/
- if ((play_rate_code <= hap->drive_period_code_min_limit) ||
- (play_rate_code >= hap->drive_period_code_max_limit))
+ if ((val & AUTO_RES_ERR_BIT) ||
+ ((play_rate_code <= hap->drive_period_code_min_limit) ||
+ (play_rate_code >= hap->drive_period_code_max_limit))) {
+ dev_dbg(&hap->pdev->dev,
+ "Auto-resonance error, out of 25%%, [min: 0x%x, max: 0x%x]\n",
+ hap->drive_period_code_min_limit,
+ hap->drive_period_code_max_limit);
+ rc = qpnp_hap_auto_res_enable(hap, 0);
+ if (rc < 0)
+ dev_dbg(&hap->pdev->dev, "Auto-resonance write failed\n");
return;
+ }
qpnp_hap_write_reg(hap, &lra_auto_res_lo,
QPNP_HAP_RATE_CFG1_REG(hap->base));
@@ -1472,15 +1533,11 @@ static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer)
{
struct qpnp_hap *hap = container_of(timer, struct qpnp_hap,
auto_res_err_poll_timer);
- u8 val;
ktime_t currtime;
- qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base));
- if (val & AUTO_RES_ERR_BIT) {
- schedule_work(&hap->auto_res_err_work);
+ if (!(hap->status_flags & AUTO_RESONANCE_ENABLED))
return HRTIMER_NORESTART;
- }
update_lra_frequency(hap);
currtime = ktime_get();
@@ -1489,56 +1546,11 @@ static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer)
return HRTIMER_RESTART;
}
-static void correct_auto_res_error(struct work_struct *auto_res_err_work)
-{
- struct qpnp_hap *hap = container_of(auto_res_err_work,
- struct qpnp_hap, auto_res_err_work);
-
- u8 lra_code_lo, lra_code_hi, disable_hap = 0x00;
- static u8 lra_freq_index;
- ktime_t currtime = ktime_set(0, 0), remaining_time = ktime_set(0, 0);
-
- if (hrtimer_active(&hap->hap_timer))
- remaining_time = hrtimer_get_remaining(&hap->hap_timer);
-
- qpnp_hap_play(hap, 0);
- qpnp_hap_write_reg(hap, &disable_hap,
- QPNP_HAP_EN_CTL_REG(hap->base));
-
- if (hap->perform_lra_auto_resonance_search) {
- lra_code_lo =
- adjusted_lra_play_rate_code[lra_freq_index]
- & QPNP_HAP_RATE_CFG1_MASK;
-
- qpnp_hap_write_reg(hap, &lra_code_lo,
- QPNP_HAP_RATE_CFG1_REG(hap->base));
-
- lra_code_hi = adjusted_lra_play_rate_code[lra_freq_index]
- >> QPNP_HAP_RATE_CFG2_SHFT;
-
- qpnp_hap_write_reg(hap, &lra_code_hi,
- QPNP_HAP_RATE_CFG2_REG(hap->base));
-
- lra_freq_index = (lra_freq_index+1) %
- ADJUSTED_LRA_PLAY_RATE_CODE_ARRSIZE;
- }
-
- dev_dbg(&hap->pdev->dev, "Remaining time is %lld\n",
- ktime_to_us(remaining_time));
-
- if ((ktime_to_us(remaining_time)) > 0) {
- currtime = ktime_get();
- hap->state = 1;
- hrtimer_forward(&hap->hap_timer, currtime, remaining_time);
- schedule_work(&hap->work);
- }
-}
-
/* set api for haptics */
static int qpnp_hap_set(struct qpnp_hap *hap, int on)
{
+ u8 auto_res_mode_qwd;
int rc = 0;
- u8 val = 0;
unsigned long timeout_ns = POLL_TIME_AUTO_RES_ERR_NS;
u32 back_emf_delay_us = hap->time_required_to_generate_back_emf_us;
@@ -1562,9 +1574,16 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
* and enable it after the sleep of
* 'time_required_to_generate_back_emf_us' is completed.
*/
+ if (hap->pmic_subtype == PM660_SUBTYPE)
+ auto_res_mode_qwd = (hap->auto_res_mode ==
+ QPNP_HAP_PM660_AUTO_RES_QWD);
+ else
+ auto_res_mode_qwd = (hap->auto_res_mode ==
+ QPNP_HAP_AUTO_RES_QWD);
+
if ((hap->act_type == QPNP_HAP_LRA) &&
(hap->correct_lra_drive_freq ||
- hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD))
+ auto_res_mode_qwd))
qpnp_hap_auto_res_enable(hap, 0);
rc = qpnp_hap_mod_enable(hap, on);
@@ -1575,7 +1594,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
if ((hap->act_type == QPNP_HAP_LRA) &&
(hap->correct_lra_drive_freq ||
- hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD)) {
+ auto_res_mode_qwd)) {
usleep_range(back_emf_delay_us,
(back_emf_delay_us + 1));
@@ -1601,11 +1620,9 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
return rc;
if (hap->act_type == QPNP_HAP_LRA &&
- hap->correct_lra_drive_freq) {
- rc = qpnp_hap_read_reg(hap, &val,
- QPNP_HAP_STATUS(hap->base));
- if (!(val & AUTO_RES_ERR_BIT))
- update_lra_frequency(hap);
+ hap->correct_lra_drive_freq &&
+ (hap->status_flags & AUTO_RESONANCE_ENABLED)) {
+ update_lra_frequency(hap);
}
rc = qpnp_hap_mod_enable(hap, on);
@@ -1810,7 +1827,7 @@ static SIMPLE_DEV_PM_OPS(qpnp_haptic_pm_ops, qpnp_haptic_suspend, NULL);
/* Configuration api for haptics registers */
static int qpnp_hap_config(struct qpnp_hap *hap)
{
- u8 reg = 0, unlock_val;
+ u8 reg = 0, unlock_val, mask;
u32 temp;
int rc, i;
uint error_code = 0;
@@ -1832,24 +1849,66 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
/* Configure auto resonance parameters */
if (hap->act_type == QPNP_HAP_LRA) {
- if (hap->lra_res_cal_period < QPNP_HAP_RES_CAL_PERIOD_MIN)
- hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MIN;
- else if (hap->lra_res_cal_period > QPNP_HAP_RES_CAL_PERIOD_MAX)
- hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ if (hap->lra_res_cal_period <
+ QPNP_HAP_PM660_RES_CAL_PERIOD_MIN)
+ hap->lra_res_cal_period =
+ QPNP_HAP_PM660_RES_CAL_PERIOD_MIN;
+ else if (hap->lra_res_cal_period >
+ QPNP_HAP_PM660_RES_CAL_PERIOD_MAX)
+ hap->lra_res_cal_period =
+ QPNP_HAP_PM660_RES_CAL_PERIOD_MAX;
+ } else if (hap->pmic_subtype != PM660_SUBTYPE) {
+ if (hap->lra_res_cal_period <
+ QPNP_HAP_RES_CAL_PERIOD_MIN)
+ hap->lra_res_cal_period =
+ QPNP_HAP_RES_CAL_PERIOD_MIN;
+ else if (hap->lra_res_cal_period >
+ QPNP_HAP_RES_CAL_PERIOD_MAX)
+ hap->lra_res_cal_period =
+ QPNP_HAP_RES_CAL_PERIOD_MAX;
+ }
+ if (hap->pmic_subtype == PM660_SUBTYPE &&
+ hap->auto_res_mode == QPNP_HAP_PM660_AUTO_RES_QWD) {
+ hap->lra_res_cal_period = 0;
+ }
- rc = qpnp_hap_read_reg(hap, &reg,
- QPNP_HAP_LRA_AUTO_RES_REG(hap->base));
- if (rc < 0)
- return rc;
- reg &= QPNP_HAP_AUTO_RES_MODE_MASK;
- reg |= (hap->auto_res_mode << QPNP_HAP_AUTO_RES_MODE_SHIFT);
- reg &= QPNP_HAP_LRA_HIGH_Z_MASK;
- reg |= (hap->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
- reg &= QPNP_HAP_LRA_RES_CAL_PER_MASK;
- temp = fls(hap->lra_res_cal_period) - 1;
- reg |= (temp - 2);
- rc = qpnp_hap_write_reg(hap, &reg,
- QPNP_HAP_LRA_AUTO_RES_REG(hap->base));
+ reg = mask = 0;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ reg |= hap->auto_res_mode <<
+ QPNP_HAP_PM660_AUTO_RES_MODE_SHIFT;
+ mask = QPNP_HAP_PM660_AUTO_RES_MODE_BIT;
+ reg |= hap->lra_high_z <<
+ QPNP_HAP_PM660_CALIBRATE_DURATION_SHIFT;
+ mask |= QPNP_HAP_PM660_CALIBRATE_DURATION_MASK;
+ if (hap->lra_qwd_drive_duration != -EINVAL) {
+ reg |= hap->lra_qwd_drive_duration <<
+ QPNP_HAP_PM660_QWD_DRIVE_DURATION_SHIFT;
+ mask |= QPNP_HAP_PM660_QWD_DRIVE_DURATION_BIT;
+ }
+ if (hap->calibrate_at_eop != -EINVAL) {
+ reg |= hap->calibrate_at_eop <<
+ QPNP_HAP_PM660_CALIBRATE_AT_EOP_SHIFT;
+ mask |= QPNP_HAP_PM660_CALIBRATE_AT_EOP_BIT;
+ }
+ if (hap->lra_res_cal_period) {
+ temp = fls(hap->lra_res_cal_period) - 1;
+ reg |= (temp - 1);
+ }
+ mask |= QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK;
+ } else {
+ reg |= (hap->auto_res_mode <<
+ QPNP_HAP_AUTO_RES_MODE_SHIFT);
+ mask = QPNP_HAP_AUTO_RES_MODE_MASK;
+ reg |= (hap->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
+ mask |= QPNP_HAP_LRA_HIGH_Z_MASK;
+ temp = fls(hap->lra_res_cal_period) - 1;
+ reg |= (temp - 2);
+ mask |= QPNP_HAP_LRA_RES_CAL_PER_MASK;
+ }
+ rc = qpnp_hap_masked_write_reg(hap, reg,
+ QPNP_HAP_LRA_AUTO_RES_REG(hap->base),
+ mask);
if (rc)
return rc;
} else {
@@ -1895,8 +1954,13 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
/* Configure the INTERNAL_PWM register */
if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_253_KHZ) {
- hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_253_KHZ;
- temp = 0;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
+ temp = 1;
+ } else {
+ hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_253_KHZ;
+ temp = 0;
+ }
} else if (hap->int_pwm_freq_khz <= QPNP_HAP_INT_PWM_FREQ_505_KHZ) {
hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
temp = 1;
@@ -2023,11 +2087,13 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) {
hap->drive_period_code_max_limit =
- (hap->init_drive_period_code * 100) /
- (100 - hap->drive_period_code_max_limit_percent_variation);
+ (hap->init_drive_period_code * (100 +
+ hap->drive_period_code_max_limit_percent_variation))
+ / 100;
hap->drive_period_code_min_limit =
- (hap->init_drive_period_code * 100) /
- (100 + hap->drive_period_code_min_limit_percent_variation);
+ (hap->init_drive_period_code * (100 -
+ hap->drive_period_code_min_limit_percent_variation))
+ / 100;
dev_dbg(&hap->pdev->dev, "Drive period code max limit %x\n"
"Drive period code min limit %x\n",
hap->drive_period_code_max_limit,
@@ -2134,20 +2200,36 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
}
if (hap->act_type == QPNP_HAP_LRA) {
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
rc = of_property_read_string(pdev->dev.of_node,
"qcom,lra-auto-res-mode", &temp_str);
if (!rc) {
- if (strcmp(temp_str, "none") == 0)
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_NONE;
- else if (strcmp(temp_str, "zxd") == 0)
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD;
- else if (strcmp(temp_str, "qwd") == 0)
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_QWD;
- else if (strcmp(temp_str, "max-qwd") == 0)
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_MAX_QWD;
- else
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ hap->auto_res_mode =
+ QPNP_HAP_PM660_AUTO_RES_QWD;
+ if (strcmp(temp_str, "zxd") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_PM660_AUTO_RES_ZXD;
+ else if (strcmp(temp_str, "qwd") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_PM660_AUTO_RES_QWD;
+ } else {
hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
+ if (strcmp(temp_str, "none") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_AUTO_RES_NONE;
+ else if (strcmp(temp_str, "zxd") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_AUTO_RES_ZXD;
+ else if (strcmp(temp_str, "qwd") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_AUTO_RES_QWD;
+ else if (strcmp(temp_str, "max-qwd") == 0)
+ hap->auto_res_mode =
+ QPNP_HAP_AUTO_RES_MAX_QWD;
+ else
+ hap->auto_res_mode =
+ QPNP_HAP_AUTO_RES_ZXD_EOP;
+ }
} else if (rc != -EINVAL) {
dev_err(&pdev->dev, "Unable to read auto res mode\n");
return rc;
@@ -2159,6 +2241,11 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
if (!rc) {
if (strcmp(temp_str, "none") == 0)
hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_NONE;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ if (strcmp(temp_str, "opt0") == 0)
+ hap->lra_high_z =
+ QPNP_HAP_LRA_HIGH_Z_NONE;
+ }
else if (strcmp(temp_str, "opt1") == 0)
hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT1;
else if (strcmp(temp_str, "opt2") == 0)
@@ -2170,6 +2257,15 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return rc;
}
+ hap->lra_qwd_drive_duration = -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,lra-qwd-drive-duration",
+ &hap->lra_qwd_drive_duration);
+
+ hap->calibrate_at_eop = -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,lra-calibrate-at-eop", &hap->calibrate_at_eop);
+
hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,lra-res-cal-period", &temp);
@@ -2347,6 +2443,34 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return 0;
}
+static int qpnp_hap_get_pmic_revid(struct qpnp_hap *hap)
+{
+ struct pmic_revid_data *pmic_rev_id;
+ struct device_node *revid_dev_node;
+
+ revid_dev_node = of_parse_phandle(hap->pdev->dev.of_node,
+ "qcom,pmic-revid", 0);
+ if (!revid_dev_node) {
+ pr_err("Missing qcom,pmic-revid property - driver failed\n");
+ return -EINVAL;
+ }
+ pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR_OR_NULL(pmic_rev_id)) {
+ pr_err("Unable to get pmic_revid rc=%ld\n",
+ PTR_ERR(pmic_rev_id));
+ /*
+ * the revid peripheral must be registered, any failure
+ * here only indicates that the rev-id module has not
+ * probed yet.
+ */
+ return -EPROBE_DEFER;
+ }
+
+ hap->pmic_subtype = pmic_rev_id->pmic_subtype;
+
+ return 0;
+}
+
static int qpnp_haptic_probe(struct platform_device *pdev)
{
struct qpnp_hap *hap;
@@ -2376,6 +2500,12 @@ static int qpnp_haptic_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, hap);
+ rc = qpnp_hap_get_pmic_revid(hap);
+ if (rc) {
+ pr_err("Unable to check PMIC version rc=%d\n", rc);
+ return rc;
+ }
+
rc = qpnp_hap_parse_dt(hap);
if (rc) {
dev_err(&pdev->dev, "DT parsing failed\n");
@@ -2405,7 +2535,6 @@ static int qpnp_haptic_probe(struct platform_device *pdev)
hap->timed_dev.enable = qpnp_hap_td_enable;
if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq) {
- INIT_WORK(&hap->auto_res_err_work, correct_auto_res_error);
hrtimer_init(&hap->auto_res_err_poll_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
hap->auto_res_err_poll_timer.function = detect_auto_res_error;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index c1c65cd25558..ebea5b7726e4 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -99,6 +99,7 @@ struct ind_req_resp {
*/
struct qmi_client_info {
int instance_id;
+ int subsys_state;
struct work_struct svc_arrive;
struct work_struct svc_exit;
struct work_struct svc_rcv_msg;
@@ -436,7 +437,7 @@ static void root_service_exit_work(struct work_struct *work)
{
struct qmi_client_info *data = container_of(work,
struct qmi_client_info, svc_exit);
- root_service_service_exit(data, ROOT_PD_DOWN);
+ root_service_service_exit(data, data->subsys_state);
}
static int service_event_notify(struct notifier_block *this,
@@ -453,6 +454,7 @@ static int service_event_notify(struct notifier_block *this,
break;
case QMI_SERVER_EXIT:
pr_debug("Root PD service DOWN\n");
+ data->subsys_state = ROOT_PD_DOWN;
queue_work(data->svc_event_wq, &data->svc_exit);
break;
default:
@@ -468,7 +470,6 @@ static int ssr_event_notify(struct notifier_block *this,
struct qmi_client_info *info = container_of(this,
struct qmi_client_info, ssr_notifier);
struct notif_data *notif = data;
- enum pd_subsys_state state;
switch (code) {
case SUBSYS_BEFORE_SHUTDOWN:
@@ -476,16 +477,16 @@ static int ssr_event_notify(struct notifier_block *this,
notif->crashed);
switch (notif->crashed) {
case CRASH_STATUS_ERR_FATAL:
- state = ROOT_PD_ERR_FATAL;
+ info->subsys_state = ROOT_PD_ERR_FATAL;
break;
case CRASH_STATUS_WDOG_BITE:
- state = ROOT_PD_WDOG_BITE;
+ info->subsys_state = ROOT_PD_WDOG_BITE;
break;
default:
- state = ROOT_PD_SHUTDOWN;
+ info->subsys_state = ROOT_PD_SHUTDOWN;
break;
}
- root_service_service_exit(info, state);
+ queue_work(info->svc_event_wq, &info->svc_exit);
break;
default:
break;
diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c
index 4ebfc713cb28..cff5b6e3fc63 100644
--- a/drivers/thermal/msm_lmh_dcvs.c
+++ b/drivers/thermal/msm_lmh_dcvs.c
@@ -78,6 +78,7 @@ enum lmh_hw_trips {
};
struct msm_lmh_dcvs_hw {
+ char sensor_name[THERMAL_NAME_LENGTH];
uint32_t affinity;
uint32_t temp_limits[LIMITS_TRIP_MAX];
struct sensor_threshold default_lo, default_hi;
@@ -381,7 +382,6 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
int ret;
int affinity = -1;
struct msm_lmh_dcvs_hw *hw;
- char sensor_name[] = "limits_sensor-00";
struct thermal_zone_device *tzdev;
struct thermal_cooling_device *cdev;
struct device_node *dn = pdev->dev.of_node;
@@ -450,9 +450,9 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
* Let's register with thermal framework, so we have the ability
* to set low/high thresholds.
*/
- snprintf(sensor_name, sizeof(sensor_name), "limits_sensor-%02d",
+ snprintf(hw->sensor_name, sizeof(hw->sensor_name), "limits_sensor-%02d",
affinity);
- tzdev = thermal_zone_device_register(sensor_name, LIMITS_TRIP_MAX,
+ tzdev = thermal_zone_device_register(hw->sensor_name, LIMITS_TRIP_MAX,
(1 << LIMITS_TRIP_MAX) - 1, hw, &limits_sensor_ops,
NULL, 0, 0);
if (IS_ERR_OR_NULL(tzdev))
@@ -467,7 +467,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
* Since we make a check for hi > lo value, set the hi threshold
* before the low threshold
*/
- id = sensor_get_id(sensor_name);
+ id = sensor_get_id(hw->sensor_name);
if (id < 0)
return id;
@@ -525,7 +525,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
set_bit(1, hw->is_irq_enabled);
ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL,
lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT
- | IRQF_NO_SUSPEND, sensor_name, hw);
+ | IRQF_NO_SUSPEND, hw->sensor_name, hw);
if (ret) {
pr_err("Error registering for irq. err:%d\n", ret);
return ret;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 9622514e3df9..9d795489c285 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2470,6 +2470,7 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev)
}
spin_unlock_irqrestore(&cdev->lock, flags);
WARN(cdev, "%s: Unexpected call\n", __func__);
+ return;
} else if (--cdev->delayed_status == 0) {
DBG(cdev, "%s: Completing delayed status\n", __func__);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index ab44bd316217..31d3022b6ce7 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1879,8 +1879,8 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
ffs->epfiles = epfiles;
- ffs_log("exit: epfile name %s state %d setup_state %d flag %lu",
- epfile->name, ffs->state, ffs->setup_state, ffs->flags);
+ ffs_log("exit: eps_count %u state %d setup_state %d flag %lu",
+ count, ffs->state, ffs->setup_state, ffs->flags);
return 0;
}
@@ -1891,7 +1891,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
- ffs_log("enter: epfilename %s", epfile->name);
+ ffs_log("enter: count %u", count);
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) ||
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index e46edc83430c..be532503954f 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -148,15 +148,10 @@ int gsi_wakeup_host(struct f_gsi *gsi)
struct usb_function *func;
func = &gsi->function;
- gadget = gsi->function.config->cdev->gadget;
+ gadget = gsi->gadget;
log_event_dbg("Entering %s", __func__);
- if (!gadget) {
- log_event_err("FAILED: d_port->cdev->gadget == NULL");
- return -ENODEV;
- }
-
/*
* In Super-Speed mode, remote wakeup is not allowed for suspended
* functions which have been disallowed by the host to issue Function
@@ -276,7 +271,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
&d_port->ipa_out_channel_params;
struct ipa_usb_xdci_connect_params *conn_params =
&d_port->ipa_conn_pms;
- struct usb_composite_dev *cdev = gsi->function.config->cdev;
+ struct usb_gadget *gadget = gsi->gadget;
struct gsi_channel_info gsi_channel_info;
struct ipa_req_chan_out_params ipa_in_channel_out_params;
struct ipa_req_chan_out_params ipa_out_channel_out_params;
@@ -366,7 +361,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
/* Populate connection params */
conn_params->max_pkt_size =
- (cdev->gadget->speed == USB_SPEED_SUPER) ?
+ (gadget->speed == USB_SPEED_SUPER) ?
IPA_USB_SUPER_SPEED_1024B : IPA_USB_HIGH_SPEED_512B;
conn_params->ipa_to_usb_xferrscidx =
d_port->in_xfer_rsc_index;
@@ -392,7 +387,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
conn_params->teth_prot_params.max_packet_number_to_dev =
DEFAULT_MAX_PKT_PER_XFER;
conn_params->max_supported_bandwidth_mbps =
- (cdev->gadget->speed == USB_SPEED_SUPER) ? 3600 : 400;
+ (gadget->speed == USB_SPEED_SUPER) ? 3600 : 400;
memset(&ipa_in_channel_out_params, 0x0,
sizeof(ipa_in_channel_out_params));
@@ -604,12 +599,12 @@ static void ipa_work_handler(struct work_struct *w)
{
struct gsi_data_port *d_port = container_of(w, struct gsi_data_port,
usb_ipa_w);
+ struct f_gsi *gsi = d_port_to_gsi(d_port);
u8 event;
int ret = 0;
- struct usb_gadget *gadget = d_port->gadget;
+ struct usb_gadget *gadget = gsi->gadget;
struct device *dev;
struct device *gad_dev;
- struct f_gsi *gsi;
event = read_event(d_port);
@@ -636,7 +631,7 @@ static void ipa_work_handler(struct work_struct *w)
break;
case STATE_INITIALIZED:
if (event == EVT_CONNECT_IN_PROGRESS) {
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
/* allocate buffers used with each TRB */
@@ -661,7 +656,7 @@ static void ipa_work_handler(struct work_struct *w)
* EVT_HOST_READY is posted to the state machine
* in the handler for this msg.
*/
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
/* allocate buffers used with each TRB */
@@ -716,7 +711,7 @@ static void ipa_work_handler(struct work_struct *w)
read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUS_DIS",
__func__);
log_event_dbg("%s: put_async1 = %d", __func__,
@@ -726,7 +721,7 @@ static void ipa_work_handler(struct work_struct *w)
}
ret = ipa_suspend_work_handler(d_port);
if (!ret) {
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUS",
__func__);
log_event_dbg("%s: put_async2 = %d", __func__,
@@ -736,7 +731,7 @@ static void ipa_work_handler(struct work_struct *w)
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_DIS",
__func__);
log_event_dbg("%s: put_async3 = %d",
@@ -760,7 +755,7 @@ static void ipa_work_handler(struct work_struct *w)
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_DIS", __func__);
log_event_dbg("%s: put_async4 = %d",
__func__, atomic_read(
@@ -770,7 +765,7 @@ static void ipa_work_handler(struct work_struct *w)
read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_SUS_DIS",
__func__);
log_event_dbg("%s: put_async5 = %d",
@@ -780,7 +775,7 @@ static void ipa_work_handler(struct work_struct *w)
}
ret = ipa_suspend_work_handler(d_port);
if (!ret) {
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_SUS",
__func__);
log_event_dbg("%s: put_async6 = %d",
@@ -805,7 +800,7 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPEND_IN_PROGRESS:
if (event == EVT_IPA_SUSPEND) {
d_port->sm_state = STATE_SUSPENDED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_IPA_SUS",
__func__);
log_event_dbg("%s: put_async6 = %d",
@@ -820,7 +815,7 @@ static void ipa_work_handler(struct work_struct *w)
* after IPA disconnect is done in disconnect work
* (due to cable disconnect) or in suspended state.
*/
- usb_gadget_autopm_get_noresume(d_port->gadget);
+ usb_gadget_autopm_get_noresume(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_RES", __func__);
log_event_dbg("%s: get_nores1 = %d", __func__,
atomic_read(
@@ -828,7 +823,7 @@ static void ipa_work_handler(struct work_struct *w)
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_DIS", __func__);
log_event_dbg("%s: put_async7 = %d", __func__,
atomic_read(
@@ -838,7 +833,7 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPENDED:
if (event == EVT_RESUMED) {
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
@@ -1425,7 +1420,6 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
__le32 *data;
struct usb_cdc_notification *event;
struct usb_request *req = gsi->c_port.notify_req;
- struct usb_composite_dev *cdev = gsi->function.config->cdev;
struct gsi_ctrl_pkt *cpkt;
unsigned long flags;
bool del_free_cpkt = false;
@@ -1472,11 +1466,11 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
/* SPEED_CHANGE data is up/down speeds in bits/sec */
data = req->buf + sizeof(*event);
- data[0] = cpu_to_le32(gsi_xfer_bitrate(cdev->gadget));
+ data[0] = cpu_to_le32(gsi_xfer_bitrate(gsi->gadget));
data[1] = data[0];
log_event_dbg("notify speed %d",
- gsi_xfer_bitrate(cdev->gadget));
+ gsi_xfer_bitrate(gsi->gadget));
break;
case GSI_CTRL_NOTIFY_OFFLINE:
del_free_cpkt = true;
@@ -1868,10 +1862,10 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
len_in = gsi->d_port.in_request.buf_len *
gsi->d_port.in_request.num_bufs;
gsi->d_port.in_request.buf_base_addr =
- dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ dma_zalloc_coherent(gsi->gadget->dev.parent,
len_in, &gsi->d_port.in_request.dma, GFP_KERNEL);
if (!gsi->d_port.in_request.buf_base_addr) {
- dev_err(&gsi->d_port.gadget->dev,
+ dev_err(&gsi->gadget->dev,
"IN buf_base_addr allocate failed %s\n",
gsi->function.name);
ret = -ENOMEM;
@@ -1887,10 +1881,10 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
len_out = gsi->d_port.out_request.buf_len *
gsi->d_port.out_request.num_bufs;
gsi->d_port.out_request.buf_base_addr =
- dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ dma_zalloc_coherent(gsi->gadget->dev.parent,
len_out, &gsi->d_port.out_request.dma, GFP_KERNEL);
if (!gsi->d_port.out_request.buf_base_addr) {
- dev_err(&gsi->d_port.gadget->dev,
+ dev_err(&gsi->gadget->dev,
"OUT buf_base_addr allocate failed %s\n",
gsi->function.name);
ret = -ENOMEM;
@@ -1903,7 +1897,7 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
fail:
if (len_in && gsi->d_port.in_request.buf_base_addr) {
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len_in,
+ dma_free_coherent(gsi->gadget->dev.parent, len_in,
gsi->d_port.in_request.buf_base_addr,
gsi->d_port.in_request.dma);
gsi->d_port.in_request.buf_base_addr = NULL;
@@ -1922,7 +1916,7 @@ static void gsi_free_trb_buffer(struct f_gsi *gsi)
gsi->d_port.out_request.buf_base_addr) {
len = gsi->d_port.out_request.buf_len *
gsi->d_port.out_request.num_bufs;
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ dma_free_coherent(gsi->gadget->dev.parent, len,
gsi->d_port.out_request.buf_base_addr,
gsi->d_port.out_request.dma);
gsi->d_port.out_request.buf_base_addr = NULL;
@@ -1932,7 +1926,7 @@ static void gsi_free_trb_buffer(struct f_gsi *gsi)
gsi->d_port.in_request.buf_base_addr) {
len = gsi->d_port.in_request.buf_len *
gsi->d_port.in_request.num_bufs;
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ dma_free_coherent(gsi->gadget->dev.parent, len,
gsi->d_port.in_request.buf_base_addr,
gsi->d_port.in_request.dma);
gsi->d_port.in_request.buf_base_addr = NULL;
@@ -2035,7 +2029,7 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
GSI_EP_OP_CONFIG);
}
- gsi->d_port.gadget = cdev->gadget;
+ gsi->gadget = cdev->gadget;
if (gsi->prot_id == IPA_USB_RNDIS) {
gsi_rndis_open(gsi);
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 3baf65572afc..262a60e8a450 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, 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
@@ -192,7 +192,6 @@ struct gsi_data_port {
struct usb_ep *out_ep;
struct usb_gsi_request in_request;
struct usb_gsi_request out_request;
- struct usb_gadget *gadget;
int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *driver_data);
struct ipa_usb_teth_params ipa_init_params;
int in_channel_handle;
@@ -228,6 +227,7 @@ struct gsi_data_port {
struct f_gsi {
struct usb_function function;
+ struct usb_gadget *gadget;
enum ipa_usb_teth_prot prot_id;
int ctrl_id;
int data_id;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 098df6ced1c3..8e5ab373dce9 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1476,6 +1476,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
}
break;
case USB_SPEED_FULL:
+ if (usb_endpoint_xfer_bulk(&ep->desc) && max_packet < 8)
+ max_packet = 8;
case USB_SPEED_LOW:
break;
default:
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index bd8e710870f7..153c733fdf43 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -54,6 +54,8 @@ struct mdss_dp_attention_node {
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
+static int mdss_dp_host_init(struct mdss_panel_data *pdata);
+static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp);
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv);
static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata);
static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp,
@@ -64,6 +66,8 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
enum notification_status status);
static int mdss_dp_process_phy_test_pattern_request(
struct mdss_dp_drv_pdata *dp);
+static int mdss_dp_send_audio_notification(
+ struct mdss_dp_drv_pdata *dp, int val);
static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
{
@@ -474,6 +478,12 @@ static int mdss_dp_clk_ctrl(struct mdss_dp_drv_pdata *dp_drv,
else
dp_drv->link_clks_on = enable;
+ pr_debug("%s clocks for %s\n",
+ enable ? "enable" : "disable",
+ __mdss_dp_pm_name(pm_type));
+ pr_debug("link_clks:%s core_clks:%s\n",
+ dp_drv->link_clks_on ? "on" : "off",
+ dp_drv->core_clks_on ? "on" : "off");
error:
return ret;
}
@@ -961,6 +971,14 @@ static int mdss_dp_wait4video_ready(struct mdss_dp_drv_pdata *dp_drv)
ret = -EINVAL;
} else {
ret = 0;
+ /*
+ * The audio subsystem should only be notified once the DP
+ * controller is in SEND_VIDEO state. This will ensure that
+ * the DP audio engine is able to acknowledge the audio unmute
+ * request, which will result in the AFE port being configured
+ * correctly.
+ */
+ mdss_dp_send_audio_notification(dp_drv, true);
}
pr_debug("End--\n");
@@ -1038,6 +1056,22 @@ static int dp_get_audio_edid_blk(struct platform_device *pdev,
return rc;
} /* dp_get_audio_edid_blk */
+static void dp_audio_teardown_done(struct platform_device *pdev)
+{
+ struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ mdss_dp_audio_enable(&dp->ctrl_io, false);
+ /* Make sure the DP audio engine is disabled */
+ wmb();
+
+ pr_debug("audio engine disabled\n");
+} /* dp_audio_teardown_done */
+
static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
@@ -1059,6 +1093,8 @@ static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
dp_get_audio_edid_blk;
dp->ext_audio_data.codec_ops.cable_status =
dp_get_cable_status;
+ dp->ext_audio_data.codec_ops.teardown_done =
+ dp_audio_teardown_done;
if (!dp->pdev->dev.of_node) {
pr_err("%s cannot find dp dev.of_node\n", __func__);
@@ -1284,6 +1320,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp)
if (dp->pixel_clk_rcg && dp->pixel_parent)
clk_set_parent(dp->pixel_clk_rcg, dp->pixel_parent);
+ if (dp->link_clks_on) {
+ pr_debug("link clocks already on\n");
+ return ret;
+ }
+
mdss_dp_set_clock_rate(dp, "ctrl_link_clk",
(dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ);
@@ -1308,6 +1349,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp)
*/
static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv)
{
+ if (!dp_drv->link_clks_on) {
+ pr_debug("link clocks already off\n");
+ return;
+ }
+
mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false);
}
@@ -1347,7 +1393,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train)
{
int ret = 0;
- int ready = 0;
+ bool mainlink_ready = false;
pr_debug("enter\n");
mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
@@ -1380,8 +1426,8 @@ send_video:
mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
mdss_dp_wait4video_ready(dp);
- ready = mdss_dp_mainlink_ready(dp, BIT(0));
- pr_debug("main link %s\n", ready ? "READY" : "NOT READY");
+ mainlink_ready = mdss_dp_mainlink_ready(dp);
+ pr_debug("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
end:
return ret;
@@ -1543,6 +1589,16 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
return 0;
}
+ /*
+ * During device suspend, host_deinit() is called
+ * to release DP resources. PM_RESUME can be
+ * called for any module wake-up. To avoid multiple host
+ * init/deinit during unrelated resume/suspend events,
+ * add host initialization call before DP power-on.
+ */
+ if (!dp_drv->dp_initialized)
+ mdss_dp_host_init(pdata);
+
return mdss_dp_on_hpd(dp_drv);
}
@@ -1590,25 +1646,7 @@ static int mdss_dp_off_hpd(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_audio_enable(&dp_drv->ctrl_io, false);
- mdss_dp_irq_disable(dp_drv);
-
- mdss_dp_config_gpios(dp_drv, false);
- mdss_dp_pinctrl_set_state(dp_drv, false);
-
- /*
- * The global reset will need DP link ralated clocks to be
- * running. Add the global reset just before disabling the
- * link clocks and core clocks.
- */
- mdss_dp_ctrl_reset(&dp_drv->ctrl_io);
-
- /* Make sure DP is disabled before clk disable */
- wmb();
- mdss_dp_disable_mainlink_clocks(dp_drv);
- mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
-
- mdss_dp_regulator_ctrl(dp_drv, false);
- dp_drv->dp_initialized = false;
+ mdss_dp_host_deinit(dp_drv);
dp_drv->power_on = false;
dp_drv->sink_info_read = false;
@@ -1639,26 +1677,46 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return mdss_dp_off_hpd(dp);
}
-static int mdss_dp_send_cable_notification(
+static int mdss_dp_send_audio_notification(
struct mdss_dp_drv_pdata *dp, int val)
{
int ret = 0;
u32 flags = 0;
if (!dp) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
ret = -EINVAL;
goto end;
}
- flags |= MSM_EXT_DISP_HPD_VIDEO;
-
if (!mdss_dp_is_dvi_mode(dp) || dp->audio_test_req) {
dp->audio_test_req = false;
flags |= MSM_EXT_DISP_HPD_AUDIO;
+
+ if (dp->ext_audio_data.intf_ops.hpd)
+ ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
+ dp->ext_audio_data.type, val, flags);
}
+end:
+ return ret;
+}
+
+static int mdss_dp_send_video_notification(
+ struct mdss_dp_drv_pdata *dp, int val)
+{
+ int ret = 0;
+ u32 flags = 0;
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ flags |= MSM_EXT_DISP_HPD_VIDEO;
+
if (dp->ext_audio_data.intf_ops.hpd)
ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
dp->ext_audio_data.type, val, flags);
@@ -1673,6 +1731,19 @@ static void mdss_dp_set_default_resolution(struct mdss_dp_drv_pdata *dp)
DEFAULT_VIDEO_RESOLUTION, true);
}
+static void mdss_dp_set_default_link_parameters(struct mdss_dp_drv_pdata *dp)
+{
+ const int default_max_link_rate = 0x6;
+ const int default_max_lane_count = 1;
+
+ dp->dpcd.max_lane_count = default_max_lane_count;
+ dp->dpcd.max_link_rate = default_max_link_rate;
+
+ pr_debug("max_link_rate = 0x%x, max_lane_count= 0x%x\n",
+ dp->dpcd.max_link_rate,
+ dp->dpcd.max_lane_count);
+}
+
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
@@ -1776,6 +1847,49 @@ vreg_error:
}
/**
+ * mdss_dp_host_deinit() - Uninitialize DP controller
+ * @dp: Display Port Driver data
+ *
+ * Perform required steps to uninitialize DP controller
+ * and its resources.
+ */
+static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp)
+{
+ if (!dp) {
+ pr_err("Invalid input data\n");
+ return -EINVAL;
+ }
+
+ if (!dp->dp_initialized) {
+ pr_debug("%s: host deinit done already\n", __func__);
+ return 0;
+ }
+
+ mdss_dp_irq_disable(dp);
+
+ mdss_dp_config_gpios(dp, false);
+ mdss_dp_pinctrl_set_state(dp, false);
+
+ /*
+ * The global reset will need DP link ralated clocks to be
+ * running. Add the global reset just before disabling the
+ * link clocks and core clocks.
+ */
+ mdss_dp_ctrl_reset(&dp->ctrl_io);
+
+ /* Make sure DP is disabled before clk disable */
+ wmb();
+ mdss_dp_disable_mainlink_clocks(dp);
+ mdss_dp_clk_ctrl(dp, DP_CORE_PM, false);
+
+ mdss_dp_regulator_ctrl(dp, false);
+ dp->dp_initialized = false;
+ pr_debug("Host deinitialized successfully\n");
+
+ return 0;
+}
+
+/**
* mdss_dp_notify_clients() - notifies DP clients of cable connection
* @dp: Display Port Driver data
* @status: HPD notification status requested
@@ -1804,7 +1918,7 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
goto invalid_request;
/* Follow the same programming as for NOTIFY_CONNECT */
mdss_dp_host_init(&dp->panel_data);
- mdss_dp_send_cable_notification(dp, true);
+ mdss_dp_send_video_notification(dp, true);
break;
case NOTIFY_CONNECT:
if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) ||
@@ -1812,16 +1926,18 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
NOTIFY_DISCONNECT_IRQ_HPD))
goto invalid_request;
mdss_dp_host_init(&dp->panel_data);
- mdss_dp_send_cable_notification(dp, true);
+ mdss_dp_send_video_notification(dp, true);
break;
case NOTIFY_DISCONNECT:
- mdss_dp_send_cable_notification(dp, false);
+ mdss_dp_send_audio_notification(dp, false);
+ mdss_dp_send_video_notification(dp, false);
break;
case NOTIFY_DISCONNECT_IRQ_HPD:
if (dp->hpd_notification_status == NOTIFY_DISCONNECT)
goto invalid_request;
- mdss_dp_send_cable_notification(dp, false);
+ mdss_dp_send_audio_notification(dp, false);
+ mdss_dp_send_video_notification(dp, false);
if (!IS_ERR_VALUE(ret) && ret) {
reinit_completion(&dp->irq_comp);
ret = wait_for_completion_timeout(&dp->irq_comp,
@@ -1878,12 +1994,16 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
pr_debug("edid read error, setting default resolution\n");
mdss_dp_set_default_resolution(dp);
+ mdss_dp_set_default_link_parameters(dp);
goto notify;
}
ret = hdmi_edid_parser(dp->panel_data.panel_info.edid_data);
if (ret) {
- pr_err("edid parse failed\n");
+ pr_err("edid parse failed, setting default resolution\n");
+
+ mdss_dp_set_default_resolution(dp);
+ mdss_dp_set_default_link_parameters(dp);
goto notify;
}
@@ -2307,7 +2427,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
} else {
dp_send_events(dp, EV_USBPD_DISCOVER_MODES);
}
- } else if (!dp->hpd && dp->power_on) {
+ } else if (!dp->hpd) {
mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
}
end:
@@ -2686,6 +2806,22 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
}
}
+/**
+ * mdss_dp_reset_panel_info() - reset the panel_info data
+ * @dp: Display Port Driver data
+ *
+ * This function will reset the panel resolution to
+ * HDMI_VFRMT_UNKNOWN if the sink device is not connected. This will help
+ * to reconfigure the panel resolution during cable connect event.
+ */
+static void mdss_dp_reset_panel_info(struct mdss_dp_drv_pdata *dp)
+{
+ if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN) {
+ dp->suspend_vic = HDMI_VFRMT_UNKNOWN;
+ dp_init_panel_info(dp, dp->suspend_vic);
+ }
+}
+
static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -2705,11 +2841,10 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
switch (event) {
case MDSS_EVENT_UNBLANK:
+ mdss_dp_ack_state(dp, true);
rc = mdss_dp_on(pdata);
break;
case MDSS_EVENT_PANEL_ON:
- mdss_dp_ack_state(dp, true);
-
mdss_dp_update_hdcp_info(dp);
if (dp_is_hdcp_enabled(dp)) {
@@ -2754,6 +2889,31 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
case MDSS_EVENT_CHECK_PARAMS:
rc = mdss_dp_check_params(dp, arg);
break;
+ case MDSS_EVENT_SUSPEND:
+ /*
+ * Make sure DP host_deinit is called
+ * when DP host is initialized but not
+ * powered ON.
+ * For example, this scenerio happens
+ * when you connect DP sink while the
+ * device is in suspend state.
+ */
+ if ((!dp->power_on) && (dp->dp_initialized))
+ rc = mdss_dp_host_deinit(dp);
+
+ /*
+ * For DP suspend/resume use case, CHECK_PARAMS is
+ * not called if the cable status is not changed.
+ * Store the sink resolution in suspend and configure
+ * the resolution during DP resume path.
+ */
+ if (dp->power_on)
+ dp->suspend_vic = dp->vic;
+ break;
+ case MDSS_EVENT_RESUME:
+ if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN)
+ dp_init_panel_info(dp, dp->suspend_vic);
+ break;
default:
pr_debug("unhandled event=%d\n", event);
break;
@@ -2889,8 +3049,6 @@ static int mdss_dp_event_thread(void *data)
return -EINVAL;
ev_data = (struct mdss_dp_event_data *)data;
- init_waitqueue_head(&ev_data->event_q);
- spin_lock_init(&ev_data->event_lock);
while (!kthread_should_stop()) {
wait_event(ev_data->event_q,
@@ -3049,6 +3207,9 @@ static void mdss_dp_event_cleanup(struct mdss_dp_drv_pdata *dp)
static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp)
{
+ init_waitqueue_head(&dp->dp_event.event_q);
+ spin_lock_init(&dp->dp_event.event_lock);
+
dp->ev_thread = kthread_run(mdss_dp_event_thread,
(void *)&dp->dp_event, "mdss_dp_event");
if (IS_ERR(dp->ev_thread)) {
@@ -3108,6 +3269,27 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
} else {
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
}
+
+ /*
+ * If cable is disconnected during device suspend,
+ * reset the panel resolution to HDMI_VFRMT_UNKNOWN
+ * so that new resolution is configured during
+ * cable connect event
+ */
+ if ((!dp_drv->power_on) && (!dp_drv->dp_initialized))
+ mdss_dp_reset_panel_info(dp_drv);
+
+ /*
+ * If a cable/dongle is connected to the TX device but
+ * no sink device is connected, we call host
+ * initialization where orientation settings are
+ * configured. When the cable/dongle is disconnect,
+ * call host de-initialization to make sure
+ * we re-configure the orientation settings during
+ * the next connect event.
+ */
+ if ((!dp_drv->power_on) && (dp_drv->dp_initialized))
+ mdss_dp_host_deinit(dp_drv);
}
static int mdss_dp_validate_callback(u8 cmd,
@@ -3604,6 +3786,16 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
pr_debug("Attention: Notified clients\n");
+ /*
+ * When a DP adaptor is connected and if sink is
+ * disconnected during device suspend,
+ * reset the panel resolution to HDMI_VFRMT_UNKNOWN
+ * so that new resolution is configured during
+ * connect event.
+ */
+ if ((!dp_drv->power_on) && (!dp_drv->dp_initialized))
+ mdss_dp_reset_panel_info(dp_drv);
+
/**
* Manually turn off the DP controller if we are in PHY
* testing mode.
@@ -3826,6 +4018,7 @@ static int mdss_dp_probe(struct platform_device *pdev)
dp_drv->hpd_irq_on = false;
mdss_dp_reset_test_data(dp_drv);
init_completion(&dp_drv->irq_comp);
+ dp_drv->suspend_vic = HDMI_VFRMT_UNKNOWN;
pr_debug("done\n");
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index d6f5d160aef2..34b652d843aa 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -450,6 +450,7 @@ struct mdss_dp_drv_pdata {
bool link_clks_on;
bool power_on;
bool sink_info_read;
+ u32 suspend_vic;
bool hpd;
bool psm_enabled;
bool audio_test_req;
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index ca07e80d6613..479c367fdc92 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -2247,12 +2247,8 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
else
pattern = 0x02;
- dp_write(ep->base + DP_STATE_CTRL, 0x0);
- /* Make sure to clear the current pattern before starting a new one */
- wmb();
-
- dp_host_train_set(ep, pattern);
mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
+ dp_host_train_set(ep, pattern);
dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
do {
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index 3b9242448198..ea492f54054c 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -177,23 +177,22 @@ void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable)
writel_relaxed(mainlink_ctrl, ctrl_io->base + DP_MAINLINK_CTRL);
}
-int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which)
+bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp)
{
u32 data;
int cnt = 10;
+ int const mainlink_ready_bit = BIT(0);
while (--cnt) {
/* DP_MAINLINK_READY */
data = readl_relaxed(dp->base + DP_MAINLINK_READY);
- if (data & which) {
- pr_debug("which=%x ready\n", which);
- return 1;
- }
+ if (data & mainlink_ready_bit)
+ return true;
udelay(1000);
}
- pr_err("which=%x NOT ready\n", which);
+ pr_err("mainlink not ready\n");
- return 0;
+ return false;
}
/* DP Configuration controller*/
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index b3b15a3579fa..8f19e7cdf3cf 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -291,7 +291,7 @@ void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map);
-int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which);
+bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp);
void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io,
struct mdss_panel_info *pinfo);
void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data);
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 4aa14422899f..5f1dde279732 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2550,8 +2550,6 @@ static void mdss_dsi_timing_db_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_ON);
MIPI_OUTP((ctrl->ctrl_base + 0x1e8), enable);
wmb(); /* ensure timing db is disabled */
- MIPI_OUTP((ctrl->ctrl_base + 0x1e4), enable);
- wmb(); /* ensure timing flush is disabled */
mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_OFF);
}
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.c b/drivers/video/fbdev/msm/mdss_hdmi_cec.c
index a424d987bb63..a4ed01210e04 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_cec.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, 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
@@ -196,7 +196,7 @@ static void hdmi_cec_msg_recv(struct work_struct *work)
msg.sender_id, msg.recvr_id,
msg.frame_size);
- if (msg.frame_size < 1) {
+ if (msg.frame_size < 1 || msg.frame_size > MAX_CEC_FRAME_SIZE) {
DEV_ERR("%s: invalid message (frame length = %d)\n",
__func__, msg.frame_size);
return;
@@ -216,7 +216,7 @@ static void hdmi_cec_msg_recv(struct work_struct *work)
msg.operand[i] = data & 0xFF;
}
- for (; i < 14; i++)
+ for (; i < MAX_OPERAND_SIZE; i++)
msg.operand[i] = 0;
DEV_DBG("%s: opcode 0x%x, wakup_en %d, device_suspend %d\n", __func__,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 7b0207de101a..e33e174780e7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -73,8 +73,18 @@ static void __mdss_mdp_mixer_write_cfg(struct mdss_mdp_mixer *mixer,
static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
{
- u64 result = (val * (u64)numer);
- do_div(result, denom);
+ u64 result = val;
+
+ if (val) {
+ u64 temp = -1UL;
+
+ do_div(temp, val);
+ if (temp > numer) {
+ /* no overflow, so we can do the operation*/
+ result = (val * (u64)numer);
+ do_div(result, denom);
+ }
+ }
return result;
}
@@ -2263,8 +2273,8 @@ static bool __mdss_mdp_compare_bw(
__calc_bus_ib_quota(mdata, new_perf, is_nrt, new_perf->bw_ctl);
u64 old_ib =
__calc_bus_ib_quota(mdata, old_perf, is_nrt, old_perf->bw_ctl);
- u64 max_new_bw = max(new_perf->bw_ctl, new_ib);
- u64 max_old_bw = max(old_perf->bw_ctl, old_ib);
+ u64 new_ab = new_perf->bw_ctl;
+ u64 old_ab = old_perf->bw_ctl;
bool update_bw = false;
/*
@@ -2276,16 +2286,18 @@ static bool __mdss_mdp_compare_bw(
* 3. end of writeback/rotator session - last chance to
* non-realtime remove vote.
*/
- if ((params_changed && ((max_new_bw > max_old_bw) || /* ab and ib bw */
+ if ((params_changed &&
+ (((new_ib > old_ib) || (new_ab > old_ab)) ||
(new_perf->bw_writeback > old_perf->bw_writeback))) ||
- (!params_changed && ((max_new_bw < max_old_bw) ||
+ (!params_changed &&
+ (((new_ib < old_ib) || (new_ab < old_ab)) ||
(new_perf->bw_writeback < old_perf->bw_writeback))) ||
(stop_req && is_nrt))
update_bw = true;
trace_mdp_compare_bw(new_perf->bw_ctl, new_ib, new_perf->bw_writeback,
- max_new_bw, old_perf->bw_ctl, old_ib, old_perf->bw_writeback,
- max_old_bw, params_changed, update_bw);
+ old_perf->bw_ctl, old_ib, old_perf->bw_writeback,
+ params_changed, update_bw);
return update_bw;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 97be2fd728c8..533239c99345 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -1416,6 +1416,8 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps)
}
}
+ /* add HW recommended delay to handle panel_vsync */
+ udelay(2000);
mutex_lock(&ctl->offlock);
pdata = ctl->panel_data;
if (pdata == NULL) {
@@ -1545,7 +1547,8 @@ exit_dfps:
if (rc < 0)
pr_err("Error in dfps_wait: %d\n", rc);
}
-
+ /* add HW recommended delay to handle panel_vsync */
+ udelay(2000);
/* Disable interface timing double buffer */
rc = mdss_mdp_ctl_intf_event(ctl,
MDSS_EVENT_DSI_TIMING_DB_CTRL,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_trace.h b/drivers/video/fbdev/msm/mdss_mdp_trace.h
index b79b4c70f5dc..db2f85cb0361 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_trace.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_trace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, 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
@@ -297,22 +297,20 @@ TRACE_EVENT(mdp_perf_update_bus,
TRACE_EVENT(mdp_compare_bw,
TP_PROTO(unsigned long long new_ab, unsigned long long new_ib,
- unsigned long long new_wb, unsigned long long new_max,
+ unsigned long long new_wb,
unsigned long long old_ab, unsigned long long old_ib,
- unsigned long long old_wb, unsigned long long old_max,
+ unsigned long long old_wb,
u32 params_changed, bool update_bw),
- TP_ARGS(new_ab, new_ib, new_wb, new_max,
- old_ab, old_ib, old_wb, old_max,
+ TP_ARGS(new_ab, new_ib, new_wb,
+ old_ab, old_ib, old_wb,
params_changed, update_bw),
TP_STRUCT__entry(
__field(u64, new_ab)
__field(u64, new_ib)
__field(u64, new_wb)
- __field(u64, new_max)
__field(u64, old_ab)
__field(u64, old_ib)
__field(u64, old_wb)
- __field(u64, old_max)
__field(u32, params_changed)
__field(bool, update_bw)
),
@@ -320,18 +318,16 @@ TRACE_EVENT(mdp_compare_bw,
__entry->new_ab = new_ab;
__entry->new_ib = new_ib;
__entry->new_wb = new_wb;
- __entry->new_max = new_max;
__entry->old_ab = old_ab;
__entry->old_ib = old_ib;
__entry->old_wb = old_wb;
- __entry->old_max = old_max;
__entry->params_changed = params_changed;
__entry->update_bw = update_bw;
),
- TP_printk("[ab,ib,wb,max] new[%llu, %llu, %llu, %llu] old[%llu, %llu, %llu, %llu] parm:%d ret:%d",
+ TP_printk("[ab,ib,wb]new[%llu,%llu,%llu]old[%llu,%llu,%llu]chgd:%d %d",
__entry->new_ab, __entry->new_ib, __entry->new_wb,
- __entry->new_max, __entry->old_ab, __entry->old_ib,
- __entry->old_wb, __entry->old_max, __entry->params_changed,
+ __entry->old_ab, __entry->old_ib,
+ __entry->old_wb, __entry->params_changed,
__entry->update_bw)
);
diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h
index 0f0c6300642c..cb5329bc9ba8 100644
--- a/include/dt-bindings/clock/qcom,rpmcc.h
+++ b/include/dt-bindings/clock/qcom,rpmcc.h
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Linaro Limited
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -129,5 +129,9 @@
#define CXO_PIL_CDSP_CLK 84
#define CNOC_PERIPH_KEEPALIVE_A_CLK 85
#define MMSSNOC_A_CLK_CPU_VOTE 86
+#define AGGR2_NOC_MSMBUS_CLK 87
+#define AGGR2_NOC_MSMBUS_A_CLK 88
+#define AGGR2_NOC_SMMU_CLK 89
+#define AGGR2_NOC_USB_CLK 90
#endif
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 7784b597e959..39c7de8c3048 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -186,6 +186,7 @@ extern void clocksource_suspend(void);
extern void clocksource_resume(void);
extern struct clocksource * __init clocksource_default_clock(void);
extern void clocksource_mark_unstable(struct clocksource *cs);
+extern void clocksource_select_force(void);
extern u64
clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cycles);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 5374bd6c4cbe..055b879dfa6b 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -534,6 +534,8 @@ struct mmc_host {
struct dentry *debugfs_root;
+ bool err_occurred;
+
struct mmc_async_req *areq; /* active async req */
struct mmc_context_info context_info; /* async synchronization info */
diff --git a/include/linux/qpnp-misc.h b/include/linux/qpnp-misc.h
index ab3302f6ea78..7d95bf24a425 100644
--- a/include/linux/qpnp-misc.h
+++ b/include/linux/qpnp-misc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2017, 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
@@ -29,8 +29,26 @@
*/
int qpnp_misc_irqs_available(struct device *consumer_dev);
+
+/**
+ * qpnp_misc_read_reg - read register from misc device
+ *
+ * @node: device node pointer
+ * @address: address offset in misc peripheral to be read
+ * @val: data read from register
+ *
+ * This function returns zero if reading the MISC register succeeds.
+ *
+ */
+
+int qpnp_misc_read_reg(struct device_node *node, u16 addr, u8 *val);
#else
-static int qpnp_misc_irqs_available(struct device *consumer_dev)
+static inline int qpnp_misc_irqs_available(struct device *consumer_dev)
+{
+ return 0;
+}
+static inline int qpnp_misc_read_reg(struct device_node *node, u16 addr,
+ u8 *val)
{
return 0;
}
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index ddc21d0c1bbb..06c273252484 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -933,7 +933,6 @@ struct adm_cmd_connect_afe_port_v5 {
#define SLIMBUS_3_TX 0x4007
#define SLIMBUS_4_RX 0x4008
#define SLIMBUS_4_TX 0x4009
-#define SLIMBUS_TX_VI 0x4f09
#define SLIMBUS_5_RX 0x400a
#define SLIMBUS_5_TX 0x400b
#define SLIMBUS_6_RX 0x400c
@@ -10224,12 +10223,108 @@ struct asm_session_cmd_set_mtmx_strstr_params_v2 {
*/
};
+/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the
+ * audio client choose the rendering decision that the audio DSP should use.
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD 0x00012F0D
+
+/* Indicates that rendering decision will be based on default rate
+ * (session clock based rendering, device driven).
+ * 1. The default session clock based rendering is inherently driven
+ * by the timing of the device.
+ * 2. After the initial decision is made (first buffer after a run
+ * command), subsequent data rendering decisions are made with
+ * respect to the rate at which the device is rendering, thus deriving
+ * its timing from the device.
+ * 3. While this decision making is simple, it has some inherent limitations
+ * (mentioned in the next section).
+ * 4. If this API is not set, the session clock based rendering will be assumed
+ * and this will ensure that the DSP is backward compatible.
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT 0
+
+/* Indicates that rendering decision will be based on local clock rate.
+ * 1. In the DSP loopback/client loopback use cases (frame based
+ * inputs), the incoming data into audio DSP is time-stamped at the
+ * local clock rate (STC).
+ * 2. This TS rate may match the incoming data rate or maybe different
+ * from the incoming data rate.
+ * 3. Regardless, the data will be time-stamped with local STC and
+ * therefore, the client is recommended to set this mode for these
+ * use cases. This method is inherently more robust to sequencing
+ * (AFE Start/Stop) and device switches, among other benefits.
+ * 4. This API will inform the DSP to compare every incoming buffer TS
+ * against local STC.
+ * 5. DSP will continue to honor render windows APIs, as before.
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC 1
+
+/* Structure for rendering decision parameter */
+struct asm_session_mtmx_strtr_param_render_mode_t {
+ /* Specifies the type of rendering decision the audio DSP should use.
+ *
+ * @values
+ * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT
+ * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC
+ */
+ u32 flags;
+} __packed;
+
+/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the
+ * audio client to specify the clock recovery mechanism that the audio DSP
+ * should use.
+ */
+
+#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD 0x00012F0E
+
+/* Indicates that default clock recovery will be used (no clock recovery).
+ * If the client wishes that no clock recovery be done, the client can
+ * choose this. This means that no attempt will made by the DSP to try and
+ * match the rates of the input and output audio.
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE 0
+
+/* Indicates that independent clock recovery needs to be used.
+ * 1. In the DSP loopback/client loopback use cases (frame based inputs),
+ * the client should choose the independent clock recovery option.
+ * 2. This basically de-couples the audio and video from knowing each others
+ * clock sources and lets the audio DSP independently rate match the input
+ * and output rates.
+ * 3. After drift detection, the drift correction is achieved by either pulling
+ * the PLLs (if applicable) or by stream to device rate matching
+ * (for PCM use cases) by comparing drift with respect to STC.
+ * 4. For passthrough use cases, since the PLL pulling is the only option,
+ * a best effort will be made.
+ * If PLL pulling is not possible / available, the rendering will be
+ * done without rate matching.
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO 1
+
+/* Payload of the #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC parameter.
+ */
+struct asm_session_mtmx_strtr_param_clk_rec_t {
+ /* Specifies the type of clock recovery that the audio DSP should
+ * use for rate matching.
+ */
+
+ /* @values
+ * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_DEFAULT
+ * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_INDEPENDENT
+ */
+ u32 flags;
+} __packed;
+
+union asm_session_mtmx_strtr_param_config {
+ struct asm_session_mtmx_strtr_param_window_v2_t window_param;
+ struct asm_session_mtmx_strtr_param_render_mode_t render_param;
+ struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
+} __packed;
+
struct asm_mtmx_strtr_params {
struct apr_hdr hdr;
struct asm_session_cmd_set_mtmx_strstr_params_v2 param;
struct asm_stream_param_data_v2 data;
- u32 window_lsw;
- u32 window_msw;
+ union asm_session_mtmx_strtr_param_config config;
} __packed;
#define ASM_SESSION_CMD_GET_MTMX_STRTR_PARAMS_V2 0x00010DCF
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 76bb795119c2..4947c30287a3 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -642,6 +642,14 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
struct asm_session_mtmx_strtr_param_window_v2_t *window_param,
uint32_t param_id);
+/* Configure DSP render mode */
+int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
+ uint32_t render_mode);
+
+/* Configure DSP clock recovery mode */
+int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
+ uint32_t clk_rec_mode);
+
/* Retrieve the current DSP path delay */
int q6asm_get_path_delay(struct audio_client *ac);
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index 71fdf6d6e9e5..843e02711aa7 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -318,6 +318,7 @@ enum kgsl_timestamp_type {
#define KGSL_PROP_HIGHEST_BANK_BIT 0x17
#define KGSL_PROP_DEVICE_BITNESS 0x18
#define KGSL_PROP_DEVICE_QDSS_STM 0x19
+#define KGSL_PROP_DEVICE_QTIMER 0x20
struct kgsl_shadowprop {
unsigned long gpuaddr;
@@ -330,6 +331,11 @@ struct kgsl_qdss_stm_prop {
uint64_t size;
};
+struct kgsl_qtimer_prop {
+ uint64_t gpuaddr;
+ uint64_t size;
+};
+
struct kgsl_version {
unsigned int drv_major;
unsigned int drv_minor;
diff --git a/include/uapi/linux/qseecom.h b/include/uapi/linux/qseecom.h
index 5c5761d690dd..40c96eef3059 100644
--- a/include/uapi/linux/qseecom.h
+++ b/include/uapi/linux/qseecom.h
@@ -92,7 +92,7 @@ struct qseecom_load_img_req {
int32_t ifd_data_fd; /* in */
char img_name[MAX_APP_NAME_SIZE]; /* in */
uint32_t app_arch; /* in */
- int app_id; /* out*/
+ uint32_t app_id; /* out*/
};
struct qseecom_set_sb_mem_param_req {
@@ -116,7 +116,7 @@ struct qseecom_qseos_version_req {
*/
struct qseecom_qseos_app_load_query {
char app_name[MAX_APP_NAME_SIZE]; /* in */
- int app_id; /* out */
+ uint32_t app_id; /* out */
uint32_t app_arch;
};
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index c8653a9f0e9e..336d318c5187 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -927,9 +927,9 @@ enum v4l2_mpeg_vidc_video_mvc_layout {
V4L2_MPEG_VIDC_VIDEO_MVC_SEQUENTIAL = 0,
V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM = 1
};
-
#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 44)
#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 45)
+
#define V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR \
(V4L2_CID_MPEG_MSM_VIDC_BASE + 46)
@@ -969,13 +969,13 @@ enum vl42_mpeg_vidc_video_enable_initial_qp {
V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_BFRAME = 0x4,
};
-#define V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP \
+#define V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_I_FRAME_QP \
(V4L2_CID_MPEG_MSM_VIDC_BASE + 54)
-#define V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP \
+#define V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_P_FRAME_QP \
(V4L2_CID_MPEG_MSM_VIDC_BASE + 55)
-#define V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP \
+#define V4L2_CID_MPEG_VIDC_VIDEO_INITIAL_B_FRAME_QP \
(V4L2_CID_MPEG_MSM_VIDC_BASE + 56)
#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE \
@@ -1211,6 +1211,14 @@ enum v4l2_mpeg_vidc_video_venc_iframesize_type {
V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED,
};
+#define V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 99)
+#define V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 100)
+#define V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 101)
+
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
diff --git a/include/uapi/media/msm_media_info.h b/include/uapi/media/msm_media_info.h
index 746eee61ad0e..f59f034a72b9 100644
--- a/include/uapi/media/msm_media_info.h
+++ b/include/uapi/media/msm_media_info.h
@@ -222,7 +222,7 @@ enum color_fmts {
* Y_Stride = align(Width, 128)
* UV_Stride = align(Width, 128)
* Y_Scanlines = align(Height, 32)
- * UV_Scanlines = align(Height/2, 16)
+ * UV_Scanlines = align((Height + 96)/2, 16)
* Y_UBWC_Plane_size = align(Y_Stride * Y_Scanlines, 4096)
* UV_UBWC_Plane_size = align(UV_Stride * UV_Scanlines, 4096)
* Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64)
@@ -231,11 +231,11 @@ enum color_fmts {
* UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64)
* UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16)
* UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096)
- * Extradata = 8k
+ * Extradata = 16k
*
* Total size = align( Y_UBWC_Plane_size + UV_UBWC_Plane_size +
* Y_Meta_Plane_size + UV_Meta_Plane_size
- * + max(Extradata, Y_Stride * 48), 4096)
+ * + Extradata), 4096)
*/
COLOR_FMT_NV12_UBWC,
/* Venus NV12 10-bit UBWC:
@@ -311,7 +311,7 @@ enum color_fmts {
* Y_Stride = align(Width * 4/3, 128)
* UV_Stride = align(Width * 4/3, 128)
* Y_Scanlines = align(Height, 32)
- * UV_Scanlines = align(Height/2, 16)
+ * UV_Scanlines = align((Height + 96)/2, 16)
* Y_UBWC_Plane_Size = align(Y_Stride * Y_Scanlines, 4096)
* UV_UBWC_Plane_Size = align(UV_Stride * UV_Scanlines, 4096)
* Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64)
@@ -320,11 +320,11 @@ enum color_fmts {
* UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64)
* UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16)
* UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096)
- * Extradata = 8k
+ * Extradata = 16k
*
* Total size = align(Y_UBWC_Plane_size + UV_UBWC_Plane_size +
* Y_Meta_Plane_size + UV_Meta_Plane_size
- * + max(Extradata, Y_Stride * 48), 4096)
+ * + Extradata), 4096)
*/
COLOR_FMT_NV12_BPP10_UBWC,
/* Venus RGBA8888 format:
@@ -970,6 +970,7 @@ static inline unsigned int VENUS_BUFFER_SIZE(
break;
case COLOR_FMT_NV12_UBWC:
case COLOR_FMT_NV12_BPP10_UBWC:
+ uv_sclines = VENUS_UV_SCANLINES(color_fmt, height + 96);
y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
@@ -982,8 +983,7 @@ static inline unsigned int VENUS_BUFFER_SIZE(
uv_meta_scanlines, 4096);
size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
- uv_meta_plane +
- MSM_MEDIA_MAX(extra_size + 8192, 48 * y_stride);
+ uv_meta_plane + extra_size;
size = MSM_MEDIA_ALIGN(size, 4096);
break;
case COLOR_FMT_P010_UBWC:
diff --git a/include/uapi/media/msmb_pproc.h b/include/uapi/media/msmb_pproc.h
index b65669b87a21..8f454571e69d 100644
--- a/include/uapi/media/msmb_pproc.h
+++ b/include/uapi/media/msmb_pproc.h
@@ -16,6 +16,7 @@
#define MSM_CPP_MAX_FRAME_LENGTH 4096
#define MSM_CPP_MAX_FW_NAME_LEN 32
#define MAX_FREQ_TBL 10
+#define MSM_OUTPUT_BUF_CNT 8
enum msm_cpp_frame_type {
MSM_CPP_OFFLINE_FRAME,
@@ -76,7 +77,7 @@ struct msm_cpp_frame_info_t {
uint32_t feature_mask;
uint8_t we_disable;
struct msm_cpp_buffer_info_t input_buffer_info;
- struct msm_cpp_buffer_info_t output_buffer_info[8];
+ struct msm_cpp_buffer_info_t output_buffer_info[MSM_OUTPUT_BUF_CNT];
struct msm_cpp_buffer_info_t duplicate_buffer_info;
struct msm_cpp_buffer_info_t tnr_scratch_buffer_info[2];
uint32_t reserved;
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
index e050bc758b3b..30481056cce1 100644
--- a/include/uapi/sound/compress_offload.h
+++ b/include/uapi/sound/compress_offload.h
@@ -132,20 +132,42 @@ struct snd_compr_audio_info {
__u32 reserved[15];
} __attribute__((packed, aligned(4)));
+#define SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER 0
+#define SNDRV_COMPRESS_RENDER_MODE_STC_MASTER 1
+
+#define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0
+#define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1
+
/**
* enum sndrv_compress_encoder
* @SNDRV_COMPRESS_ENCODER_PADDING: no of samples appended by the encoder at the
* end of the track
* @SNDRV_COMPRESS_ENCODER_DELAY: no of samples inserted by the encoder at the
* beginning of the track
+ * @SNDRV_COMPRESS_PATH_DELAY: dsp path delay in microseconds
+ * @SNDRV_COMPRESS_RENDER_MODE: dsp render mode (audio master or stc)
+ * @SNDRV_COMPRESS_CLK_REC_MODE: clock recovery mode ( none or auto)
+ * @SNDRV_COMPRESS_RENDER_WINDOW: render window
+ * @SNDRV_COMPRESS_START_DELAY: start delay
*/
enum sndrv_compress_encoder {
SNDRV_COMPRESS_ENCODER_PADDING = 1,
SNDRV_COMPRESS_ENCODER_DELAY = 2,
SNDRV_COMPRESS_MIN_BLK_SIZE = 3,
SNDRV_COMPRESS_MAX_BLK_SIZE = 4,
+ SNDRV_COMPRESS_PATH_DELAY = 5,
+ SNDRV_COMPRESS_RENDER_MODE = 6,
+ SNDRV_COMPRESS_CLK_REC_MODE = 7,
+ SNDRV_COMPRESS_RENDER_WINDOW = 8,
+ SNDRV_COMPRESS_START_DELAY = 9,
};
+#define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY
+#define SNDRV_COMPRESS_RENDER_MODE SNDRV_COMPRESS_RENDER_MODE
+#define SNDRV_COMPRESS_CLK_REC_MODE SNDRV_COMPRESS_CLK_REC_MODE
+#define SNDRV_COMPRESS_RENDER_WINDOW SNDRV_COMPRESS_RENDER_WINDOW
+#define SNDRV_COMPRESS_START_DELAY SNDRV_COMPRESS_START_DELAY
+
/**
* struct snd_compr_metadata - compressed stream metadata
* @key: key id
diff --git a/include/uapi/video/msm_hdmi_modes.h b/include/uapi/video/msm_hdmi_modes.h
index 43ca6bab4c62..5b4b2b492be4 100644
--- a/include/uapi/video/msm_hdmi_modes.h
+++ b/include/uapi/video/msm_hdmi_modes.h
@@ -271,7 +271,7 @@ struct msm_hdmi_mode_timing_info {
720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0}
#define HDMI_VFRMT_1920x1080i60_16_9_TIMING \
{HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \
- 540, 2, 5, 5, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0}
+ 540, 2, 5, 5, false, 74250, 60000, true, true, HDMI_RES_AR_16_9, 0}
#define HDMI_VFRMT_1440x480i60_4_3_TIMING \
{HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \
240, 4, 3, 15, true, 27000, 60000, true, true, HDMI_RES_AR_4_3, 0}
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index b98810d2f3b4..89cc82a38e4d 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -108,7 +108,7 @@ static int finished_booting;
#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
static void clocksource_watchdog_work(struct work_struct *work);
-static void clocksource_select(void);
+static void clocksource_select(bool force);
static LIST_HEAD(watchdog_list);
static struct clocksource *watchdog;
@@ -415,7 +415,7 @@ static int clocksource_watchdog_kthread(void *data)
{
mutex_lock(&clocksource_mutex);
if (__clocksource_watchdog_kthread())
- clocksource_select();
+ clocksource_select(false);
mutex_unlock(&clocksource_mutex);
return 0;
}
@@ -555,11 +555,12 @@ static inline void clocksource_update_max_deferment(struct clocksource *cs)
#ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
-static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur)
+static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur,
+ bool force)
{
struct clocksource *cs;
- if (!finished_booting || list_empty(&clocksource_list))
+ if ((!finished_booting && !force) || list_empty(&clocksource_list))
return NULL;
/*
@@ -577,13 +578,13 @@ static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur)
return NULL;
}
-static void __clocksource_select(bool skipcur)
+static void __clocksource_select(bool skipcur, bool force)
{
bool oneshot = tick_oneshot_mode_active();
struct clocksource *best, *cs;
/* Find the best suitable clocksource */
- best = clocksource_find_best(oneshot, skipcur);
+ best = clocksource_find_best(oneshot, skipcur, force);
if (!best)
return;
@@ -623,22 +624,40 @@ static void __clocksource_select(bool skipcur)
* Select the clocksource with the best rating, or the clocksource,
* which is selected by userspace override.
*/
-static void clocksource_select(void)
+static void clocksource_select(bool force)
{
- __clocksource_select(false);
+ return __clocksource_select(false, force);
}
static void clocksource_select_fallback(void)
{
- __clocksource_select(true);
+ __clocksource_select(true, false);
}
#else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */
-static inline void clocksource_select(void) { }
+
+static inline void clocksource_select(bool force) { }
static inline void clocksource_select_fallback(void) { }
#endif
+/**
+ * clocksource_select_force - Force re-selection of the best clocksource
+ * among registered clocksources
+ *
+ * clocksource_select() can't select the best clocksource before
+ * calling clocksource_done_booting() and since clocksource_select()
+ * should be called with clocksource_mutex held, provide a new API
+ * can be called from other files to select best clockrouce irrespective
+ * of finished_booting flag.
+ */
+void clocksource_select_force(void)
+{
+ mutex_lock(&clocksource_mutex);
+ clocksource_select(true);
+ mutex_unlock(&clocksource_mutex);
+}
+
/*
* clocksource_done_booting - Called near the end of core bootup
*
@@ -655,7 +674,7 @@ static int __init clocksource_done_booting(void)
* Run the watchdog first to eliminate unstable clock sources
*/
__clocksource_watchdog_kthread();
- clocksource_select();
+ clocksource_select(false);
mutex_unlock(&clocksource_mutex);
return 0;
}
@@ -744,6 +763,7 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
}
EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale);
+
/**
* __clocksource_register_scale - Used to install new clocksources
* @cs: clocksource to be registered
@@ -765,7 +785,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
mutex_lock(&clocksource_mutex);
clocksource_enqueue(cs);
clocksource_enqueue_watchdog(cs);
- clocksource_select();
+ clocksource_select(false);
clocksource_select_watchdog(false);
mutex_unlock(&clocksource_mutex);
return 0;
@@ -788,7 +808,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating)
{
mutex_lock(&clocksource_mutex);
__clocksource_change_rating(cs, rating);
- clocksource_select();
+ clocksource_select(false);
clocksource_select_watchdog(false);
mutex_unlock(&clocksource_mutex);
}
@@ -892,7 +912,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev,
ret = sysfs_get_uname(buf, override_name, count);
if (ret >= 0)
- clocksource_select();
+ clocksource_select(false);
mutex_unlock(&clocksource_mutex);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9b15d6eb1622..66d9e907aa07 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3991,6 +3991,7 @@ static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
{
kfree(s->saved_cmdlines);
kfree(s->map_cmdline_to_pid);
+ kfree(s->saved_tgids);
kfree(s);
}
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index f2813e137b23..91fa701b4a24 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -27,6 +27,7 @@
#include <linux/kvm_para.h>
#include <linux/perf_event.h>
#include <linux/kthread.h>
+#include <soc/qcom/watchdog.h>
/*
* The run state of the lockup detectors is controlled by the content of the
@@ -366,8 +367,11 @@ static void watchdog_check_hardlockup_other_cpu(void)
if (per_cpu(hard_watchdog_warn, next_cpu) == true)
return;
- if (hardlockup_panic)
- panic("Watchdog detected hard LOCKUP on cpu %u", next_cpu);
+ if (hardlockup_panic) {
+ pr_err("Watchdog detected hard LOCKUP on cpu %u",
+ next_cpu);
+ msm_trigger_wdog_bite();
+ }
else
WARN(1, "Watchdog detected hard LOCKUP on cpu %u", next_cpu);
@@ -430,6 +434,9 @@ static void watchdog_overflow_callback(struct perf_event *event,
return;
pr_emerg("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+ if (hardlockup_panic)
+ msm_trigger_wdog_bite();
+
print_modules();
print_irqtrace_events(current);
if (regs)
@@ -552,6 +559,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
smp_processor_id(), duration,
current->comm, task_pid_nr(current));
+
+ if (softlockup_panic)
+ msm_trigger_wdog_bite();
__this_cpu_write(softlockup_task_ptr_saved, current);
print_modules();
print_irqtrace_events(current);
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
index 5ecd7870bb3b..e18a756b0eda 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -48,18 +48,11 @@
#define BUS_DOWN 1
/*
- *50 Milliseconds sufficient for DSP bring up in the modem
+ * 50 Milliseconds sufficient for DSP bring up in the lpass
* after Sub System Restart
*/
#define ADSP_STATE_READY_TIMEOUT_MS 50
-enum {
- BOOST_SWITCH = 0,
- BOOST_ALWAYS,
- BYPASS_ALWAYS,
- BOOST_ON_FOREVER,
-};
-
#define EAR_PMD 0
#define EAR_PMU 1
#define SPK_PMD 2
@@ -81,12 +74,10 @@ enum {
((value - min_value)/step_size)
enum {
- RX_MIX1_INP_SEL_ZERO = 0,
- RX_MIX1_INP_SEL_IIR1,
- RX_MIX1_INP_SEL_IIR2,
- RX_MIX1_INP_SEL_RX1,
- RX_MIX1_INP_SEL_RX2,
- RX_MIX1_INP_SEL_RX3,
+ BOOST_SWITCH = 0,
+ BOOST_ALWAYS,
+ BYPASS_ALWAYS,
+ BOOST_ON_FOREVER,
};
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -874,11 +865,12 @@ static int msm_anlg_cdc_dig_register_notifier(void *handle,
struct notifier_block *nblock,
bool enable)
{
- struct sdm660_cdc *handle_cdc = handle;
+ struct sdm660_cdc_priv *handle_cdc = handle;
if (enable)
return blocking_notifier_chain_register(&handle_cdc->notifier,
nblock);
+
return blocking_notifier_chain_unregister(&handle_cdc->notifier,
nblock);
}
@@ -893,10 +885,10 @@ static int msm_anlg_cdc_mbhc_register_notifier(struct wcd_mbhc *wcd_mbhc,
if (enable)
return blocking_notifier_chain_register(
- &sdm660_cdc->notifier,
+ &sdm660_cdc->notifier_mbhc,
nblock);
- return blocking_notifier_chain_unregister(&sdm660_cdc->notifier,
+ return blocking_notifier_chain_unregister(&sdm660_cdc->notifier_mbhc,
nblock);
}
@@ -944,7 +936,7 @@ static const uint32_t wcd_imped_val[] = {4, 8, 12, 13, 16,
static void msm_anlg_cdc_dig_notifier_call(struct snd_soc_codec *codec,
const enum dig_cdc_notify_event event)
{
- struct sdm660_cdc *sdm660_cdc = codec->control_data;
+ struct sdm660_cdc_priv *sdm660_cdc = snd_soc_codec_get_drvdata(codec);
pr_debug("%s: notifier call event %d\n", __func__, event);
blocking_notifier_call_chain(&sdm660_cdc->notifier,
@@ -958,7 +950,7 @@ static void msm_anlg_cdc_notifier_call(struct snd_soc_codec *codec,
snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s: notifier call event %d\n", __func__, event);
- blocking_notifier_call_chain(&sdm660_cdc->notifier, event,
+ blocking_notifier_call_chain(&sdm660_cdc->notifier_mbhc, event,
&sdm660_cdc->mbhc);
}
@@ -2045,12 +2037,6 @@ static const char * const wsa_spk_text[] = {
"ZERO", "WSA"
};
-
-
-static const char * const iir_inp1_text[] = {
- "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
-};
-
static const struct soc_enum adc2_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
@@ -2598,7 +2584,7 @@ static int msm_anlg_cdc_codec_enable_micbias(struct snd_soc_dapm_widget *w,
static void update_clkdiv(void *handle, int val)
{
- struct sdm660_cdc *handle_cdc = handle;
+ struct sdm660_cdc_priv *handle_cdc = handle;
struct snd_soc_codec *codec = handle_cdc->codec;
snd_soc_update_bits(codec,
@@ -2608,10 +2594,7 @@ static void update_clkdiv(void *handle, int val)
static int get_cdc_version(void *handle)
{
- struct sdm660_cdc *handle_cdc = handle;
- struct snd_soc_codec *codec = handle_cdc->codec;
- struct sdm660_cdc_priv *sdm660_cdc =
- snd_soc_codec_get_drvdata(codec);
+ struct sdm660_cdc_priv *sdm660_cdc = handle;
return get_codec_version(sdm660_cdc);
}
@@ -3680,11 +3663,12 @@ static int msm_anlg_cdc_bringup(struct snd_soc_codec *codec)
MSM89XX_PMIC_ANALOG_SEC_ACCESS,
0xA5);
snd_soc_write(codec, MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x00);
+
return 0;
}
static struct regulator *msm_anlg_cdc_find_regulator(
- const struct sdm660_cdc *sdm660_cdc,
+ const struct sdm660_cdc_priv *sdm660_cdc,
const char *name)
{
int i;
@@ -3779,6 +3763,7 @@ static int msm_anlg_cdc_device_down(struct snd_soc_codec *codec)
msm_anlg_cdc_dig_notifier_call(codec, DIG_CDC_EVENT_SSR_DOWN);
set_bit(BUS_DOWN, &sdm660_cdc_priv->status_mask);
snd_soc_card_change_online_state(codec->component.card, 0);
+
return 0;
}
@@ -3906,7 +3891,7 @@ EXPORT_SYMBOL(msm_anlg_cdc_update_int_spk_boost);
static void msm_anlg_cdc_set_micb_v(struct snd_soc_codec *codec)
{
- struct sdm660_cdc *sdm660_cdc = codec->control_data;
+ struct sdm660_cdc_priv *sdm660_cdc = snd_soc_codec_get_drvdata(codec);
struct sdm660_cdc_pdata *pdata = sdm660_cdc->dev->platform_data;
u8 reg_val;
@@ -4060,63 +4045,53 @@ EXPORT_SYMBOL(msm_anlg_codec_info_create_codec_entry);
static int msm_anlg_cdc_soc_probe(struct snd_soc_codec *codec)
{
- struct sdm660_cdc_priv *sdm660_cdc_priv;
- struct sdm660_cdc *handle_cdc;
+ struct sdm660_cdc_priv *sdm660_cdc;
int ret;
- sdm660_cdc_priv = devm_kzalloc(codec->dev,
- sizeof(struct sdm660_cdc_priv),
- GFP_KERNEL);
- if (!sdm660_cdc_priv)
- return -ENOMEM;
-
- codec->control_data = dev_get_drvdata(codec->dev);
- snd_soc_codec_set_drvdata(codec, sdm660_cdc_priv);
- sdm660_cdc_priv->codec = codec;
- handle_cdc = codec->control_data;
- handle_cdc->codec = codec;
+ sdm660_cdc = dev_get_drvdata(codec->dev);
+ sdm660_cdc->codec = codec;
/* codec resmgr module init */
- sdm660_cdc_priv->spkdrv_reg =
- msm_anlg_cdc_find_regulator(codec->control_data,
+ sdm660_cdc->spkdrv_reg =
+ msm_anlg_cdc_find_regulator(sdm660_cdc,
MSM89XX_VDD_SPKDRV_NAME);
- sdm660_cdc_priv->pmic_rev =
+ sdm660_cdc->pmic_rev =
snd_soc_read(codec,
MSM89XX_PMIC_DIGITAL_REVISION1);
- sdm660_cdc_priv->codec_version =
+ sdm660_cdc->codec_version =
snd_soc_read(codec,
MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE);
- sdm660_cdc_priv->analog_major_rev =
+ sdm660_cdc->analog_major_rev =
snd_soc_read(codec,
MSM89XX_PMIC_ANALOG_REVISION4);
- if (sdm660_cdc_priv->codec_version == CONGA) {
+ if (sdm660_cdc->codec_version == CONGA) {
dev_dbg(codec->dev, "%s :Conga REV: %d\n", __func__,
- sdm660_cdc_priv->codec_version);
- sdm660_cdc_priv->ext_spk_boost_set = true;
+ sdm660_cdc->codec_version);
+ sdm660_cdc->ext_spk_boost_set = true;
} else {
dev_dbg(codec->dev, "%s :PMIC REV: %d\n", __func__,
- sdm660_cdc_priv->pmic_rev);
- if (sdm660_cdc_priv->pmic_rev == TOMBAK_1_0 &&
- sdm660_cdc_priv->codec_version == CAJON_2_0) {
- if (sdm660_cdc_priv->analog_major_rev == 0x02) {
- sdm660_cdc_priv->codec_version = DRAX_CDC;
+ sdm660_cdc->pmic_rev);
+ if (sdm660_cdc->pmic_rev == TOMBAK_1_0 &&
+ sdm660_cdc->codec_version == CAJON_2_0) {
+ if (sdm660_cdc->analog_major_rev == 0x02) {
+ sdm660_cdc->codec_version = DRAX_CDC;
dev_dbg(codec->dev,
"%s : Drax codec detected\n", __func__);
} else {
- sdm660_cdc_priv->codec_version = DIANGU;
+ sdm660_cdc->codec_version = DIANGU;
dev_dbg(codec->dev, "%s : Diangu detected\n",
__func__);
}
- } else if (sdm660_cdc_priv->pmic_rev == TOMBAK_1_0 &&
+ } else if (sdm660_cdc->pmic_rev == TOMBAK_1_0 &&
(snd_soc_read(codec, MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
& 0x80)) {
- sdm660_cdc_priv->codec_version = CAJON;
+ sdm660_cdc->codec_version = CAJON;
dev_dbg(codec->dev, "%s : Cajon detected\n", __func__);
- } else if (sdm660_cdc_priv->pmic_rev == TOMBAK_2_0 &&
+ } else if (sdm660_cdc->pmic_rev == TOMBAK_2_0 &&
(snd_soc_read(codec, MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
& 0x80)) {
- sdm660_cdc_priv->codec_version = CAJON_2_0;
+ sdm660_cdc->codec_version = CAJON_2_0;
dev_dbg(codec->dev, "%s : Cajon 2.0 detected\n",
__func__);
}
@@ -4125,8 +4100,8 @@ static int msm_anlg_cdc_soc_probe(struct snd_soc_codec *codec)
* set to default boost option BOOST_SWITCH, user mixer path can change
* it to BOOST_ALWAYS or BOOST_BYPASS based on solution chosen.
*/
- sdm660_cdc_priv->boost_option = BOOST_SWITCH;
- sdm660_cdc_priv->hph_mode = NORMAL_MODE;
+ sdm660_cdc->boost_option = BOOST_SWITCH;
+ sdm660_cdc->hph_mode = NORMAL_MODE;
msm_anlg_cdc_dt_parse_boost_info(codec);
msm_anlg_cdc_set_boost_v(codec);
@@ -4143,50 +4118,49 @@ static int msm_anlg_cdc_soc_probe(struct snd_soc_codec *codec)
wcd9xxx_spmi_set_codec(codec);
- sdm660_cdc_priv->on_demand_list[ON_DEMAND_MICBIAS].supply =
+ sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].supply =
msm_anlg_cdc_find_regulator(
- codec->control_data,
+ sdm660_cdc,
on_demand_supply_name[ON_DEMAND_MICBIAS]);
- atomic_set(&sdm660_cdc_priv->on_demand_list[ON_DEMAND_MICBIAS].ref,
+ atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].ref,
0);
- BLOCKING_INIT_NOTIFIER_HEAD(&sdm660_cdc_priv->notifier);
-
- sdm660_cdc_priv->fw_data = devm_kzalloc(codec->dev,
- sizeof(*(sdm660_cdc_priv->fw_data)),
+ sdm660_cdc->fw_data = devm_kzalloc(codec->dev,
+ sizeof(*(sdm660_cdc->fw_data)),
GFP_KERNEL);
- if (!sdm660_cdc_priv->fw_data)
+ if (!sdm660_cdc->fw_data)
return -ENOMEM;
- set_bit(WCD9XXX_MBHC_CAL, sdm660_cdc_priv->fw_data->cal_bit);
- ret = wcd_cal_create_hwdep(sdm660_cdc_priv->fw_data,
+ set_bit(WCD9XXX_MBHC_CAL, sdm660_cdc->fw_data->cal_bit);
+ ret = wcd_cal_create_hwdep(sdm660_cdc->fw_data,
WCD9XXX_CODEC_HWDEP_NODE, codec);
if (ret < 0) {
dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
return ret;
}
- wcd_mbhc_init(&sdm660_cdc_priv->mbhc, codec, &mbhc_cb, &intr_ids,
+ wcd_mbhc_init(&sdm660_cdc->mbhc, codec, &mbhc_cb, &intr_ids,
wcd_mbhc_registers, true);
- sdm660_cdc_priv->int_mclk0_enabled = false;
+ sdm660_cdc->int_mclk0_enabled = false;
/*Update speaker boost configuration*/
- sdm660_cdc_priv->spk_boost_set = spkr_boost_en;
+ sdm660_cdc->spk_boost_set = spkr_boost_en;
pr_debug("%s: speaker boost configured = %d\n",
- __func__, sdm660_cdc_priv->spk_boost_set);
+ __func__, sdm660_cdc->spk_boost_set);
/* Set initial MICBIAS voltage level */
msm_anlg_cdc_set_micb_v(codec);
/* Set initial cap mode */
msm_anlg_cdc_configure_cap(codec, false, false);
+
return 0;
}
static int msm_anlg_cdc_soc_remove(struct snd_soc_codec *codec)
{
struct sdm660_cdc_priv *sdm660_cdc_priv =
- snd_soc_codec_get_drvdata(codec);
+ dev_get_drvdata(codec->dev);
sdm660_cdc_priv->spkdrv_reg = NULL;
sdm660_cdc_priv->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
@@ -4198,7 +4172,7 @@ static int msm_anlg_cdc_soc_remove(struct snd_soc_codec *codec)
}
static int msm_anlg_cdc_enable_static_supplies_to_optimum(
- struct sdm660_cdc *sdm660_cdc,
+ struct sdm660_cdc_priv *sdm660_cdc,
struct sdm660_cdc_pdata *pdata)
{
int i;
@@ -4231,7 +4205,7 @@ static int msm_anlg_cdc_enable_static_supplies_to_optimum(
}
static int msm_anlg_cdc_disable_static_supplies_to_optimum(
- struct sdm660_cdc *sdm660_cdc,
+ struct sdm660_cdc_priv *sdm660_cdc,
struct sdm660_cdc_pdata *pdata)
{
int i;
@@ -4256,7 +4230,7 @@ static int msm_anlg_cdc_disable_static_supplies_to_optimum(
static int msm_anlg_cdc_suspend(struct snd_soc_codec *codec)
{
struct msm_asoc_mach_data *pdata = NULL;
- struct sdm660_cdc *sdm660_cdc = codec->control_data;
+ struct sdm660_cdc_priv *sdm660_cdc = snd_soc_codec_get_drvdata(codec);
struct sdm660_cdc_pdata *sdm660_cdc_pdata =
sdm660_cdc->dev->platform_data;
@@ -4281,7 +4255,7 @@ static int msm_anlg_cdc_suspend(struct snd_soc_codec *codec)
static int msm_anlg_cdc_resume(struct snd_soc_codec *codec)
{
struct msm_asoc_mach_data *pdata = NULL;
- struct sdm660_cdc *sdm660_cdc = codec->control_data;
+ struct sdm660_cdc_priv *sdm660_cdc = snd_soc_codec_get_drvdata(codec);
struct sdm660_cdc_pdata *sdm660_cdc_pdata =
sdm660_cdc->dev->platform_data;
@@ -4311,7 +4285,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sdm660_cdc = {
.get_regmap = msm_anlg_get_regmap,
};
-static int msm_anlg_cdc_init_supplies(struct sdm660_cdc *sdm660_cdc,
+static int msm_anlg_cdc_init_supplies(struct sdm660_cdc_priv *sdm660_cdc,
struct sdm660_cdc_pdata *pdata)
{
int ret;
@@ -4386,7 +4360,7 @@ err:
}
static int msm_anlg_cdc_enable_static_supplies(
- struct sdm660_cdc *sdm660_cdc,
+ struct sdm660_cdc_priv *sdm660_cdc,
struct sdm660_cdc_pdata *pdata)
{
int i;
@@ -4411,7 +4385,7 @@ static int msm_anlg_cdc_enable_static_supplies(
return ret;
}
-static void msm_anlg_cdc_disable_supplies(struct sdm660_cdc *sdm660_cdc,
+static void msm_anlg_cdc_disable_supplies(struct sdm660_cdc_priv *sdm660_cdc,
struct sdm660_cdc_pdata *pdata)
{
int i;
@@ -4438,7 +4412,7 @@ static const struct of_device_id sdm660_codec_of_match[] = {
static void msm_anlg_add_child_devices(struct work_struct *work)
{
- struct sdm660_cdc *pdata;
+ struct sdm660_cdc_priv *pdata;
struct platform_device *pdev;
struct device_node *node;
struct msm_dig_ctrl_data *dig_ctrl_data = NULL, *temp;
@@ -4446,7 +4420,7 @@ static void msm_anlg_add_child_devices(struct work_struct *work)
struct msm_dig_ctrl_platform_data *platdata;
char plat_dev_name[MSM_DIG_CDC_STRING_LEN];
- pdata = container_of(work, struct sdm660_cdc,
+ pdata = container_of(work, struct sdm660_cdc_priv,
msm_anlg_add_child_devices_work);
if (!pdata) {
pr_err("%s: Memory for pdata does not exist\n",
@@ -4527,7 +4501,7 @@ err:
static int msm_anlg_cdc_probe(struct platform_device *pdev)
{
int ret = 0;
- struct sdm660_cdc *sdm660_cdc = NULL;
+ struct sdm660_cdc_priv *sdm660_cdc = NULL;
struct sdm660_cdc_pdata *pdata;
int adsp_state;
@@ -4554,7 +4528,7 @@ static int msm_anlg_cdc_probe(struct platform_device *pdev)
__func__);
goto rtn;
}
- sdm660_cdc = devm_kzalloc(&pdev->dev, sizeof(struct sdm660_cdc),
+ sdm660_cdc = devm_kzalloc(&pdev->dev, sizeof(struct sdm660_cdc_priv),
GFP_KERNEL);
if (sdm660_cdc == NULL) {
ret = -ENOMEM;
@@ -4578,7 +4552,6 @@ static int msm_anlg_cdc_probe(struct platform_device *pdev)
/* Allow supplies to be ready */
usleep_range(5, 6);
- dev_set_drvdata(&pdev->dev, sdm660_cdc);
wcd9xxx_spmi_set_dev(pdev, 0);
wcd9xxx_spmi_set_dev(pdev, 1);
if (wcd9xxx_spmi_irq_init()) {
@@ -4588,6 +4561,7 @@ static int msm_anlg_cdc_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev,
"%s: irq initialization passed\n", __func__);
}
+ dev_set_drvdata(&pdev->dev, sdm660_cdc);
ret = snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_sdm660_cdc,
@@ -4599,6 +4573,9 @@ static int msm_anlg_cdc_probe(struct platform_device *pdev)
__func__, ret);
goto err_supplies;
}
+ BLOCKING_INIT_NOTIFIER_HEAD(&sdm660_cdc->notifier);
+ BLOCKING_INIT_NOTIFIER_HEAD(&sdm660_cdc->notifier_mbhc);
+
sdm660_cdc->dig_plat_data.handle = (void *) sdm660_cdc;
sdm660_cdc->dig_plat_data.update_clkdiv = update_clkdiv;
sdm660_cdc->dig_plat_data.get_cdc_version = get_cdc_version;
@@ -4617,7 +4594,7 @@ rtn:
static int msm_anlg_cdc_remove(struct platform_device *pdev)
{
- struct sdm660_cdc *sdm660_cdc = dev_get_drvdata(&pdev->dev);
+ struct sdm660_cdc_priv *sdm660_cdc = dev_get_drvdata(&pdev->dev);
struct sdm660_cdc_pdata *pdata = sdm660_cdc->dev->platform_data;
snd_soc_unregister_codec(&pdev->dev);
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
index e0626d3be971..0c9e9a6aeb6a 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 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
@@ -172,7 +172,7 @@ struct msm_dig_ctrl_platform_data {
bool enable);
};
-struct sdm660_cdc {
+struct sdm660_cdc_priv {
struct device *dev;
u32 num_of_supplies;
struct regulator_bulk_data *supplies;
@@ -182,15 +182,6 @@ struct sdm660_cdc {
/* digital codec data structure */
struct msm_dig_ctrl_data *dig_ctrl_data;
struct blocking_notifier_head notifier;
-};
-
-struct sdm660_cdc_pdata {
- struct wcd_micbias_setting micbias;
- struct sdm660_cdc_regulator regulator[MAX_REGULATOR];
-};
-
-struct sdm660_cdc_priv {
- struct snd_soc_codec *codec;
u16 pmic_rev;
u16 codec_version;
u16 analog_major_rev;
@@ -207,7 +198,7 @@ struct sdm660_cdc_priv {
bool ext_spk_boost_set;
struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
struct regulator *spkdrv_reg;
- struct blocking_notifier_head notifier;
+ struct blocking_notifier_head notifier_mbhc;
/* mbhc module */
struct wcd_mbhc mbhc;
/* cal info for codec */
@@ -222,6 +213,12 @@ struct sdm660_cdc_priv {
struct snd_info_entry *version_entry;
};
+struct sdm660_cdc_pdata {
+ struct wcd_micbias_setting micbias;
+ struct sdm660_cdc_regulator regulator[MAX_REGULATOR];
+};
+
+
extern int msm_anlg_cdc_mclk_enable(struct snd_soc_codec *codec,
int mclk_enable, bool dapm);
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
index f1c3b4050323..d8828a1e36b7 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -285,7 +285,7 @@ static int msm_dig_cdc_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
- struct msm_dig *msm_dig_cdc = dev_get_drvdata(codec->dev);
+ struct msm_dig_priv *msm_dig_cdc = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
@@ -542,14 +542,14 @@ static void tx_hpf_corner_freq_callback(struct work_struct *work)
struct delayed_work *hpf_delayed_work;
struct hpf_work *hpf_work;
struct snd_soc_codec *codec;
- struct msm_dig *msm_dig_cdc;
+ struct msm_dig_priv *msm_dig_cdc;
u16 tx_mux_ctl_reg;
u8 hpf_cut_of_freq;
hpf_delayed_work = to_delayed_work(work);
hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
codec = hpf_work->dig_cdc->codec;
- msm_dig_cdc = codec->control_data;
+ msm_dig_cdc = hpf_work->dig_cdc;
hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
@@ -826,8 +826,7 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct msm_asoc_mach_data *pdata = NULL;
unsigned int decimator;
- struct msm_dig_priv *dig_cdc = snd_soc_codec_get_drvdata(codec);
- struct msm_dig *msm_dig_cdc = codec->control_data;
+ struct msm_dig_priv *msm_dig_cdc = snd_soc_codec_get_drvdata(codec);
char *dec_name = NULL;
char *widget_name = NULL;
char *temp;
@@ -897,7 +896,7 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
for (i = 0; i < NUM_DECIMATORS; i++) {
if (decimator == i + 1)
- dig_cdc->dec_active[i] = true;
+ msm_dig_cdc->dec_active[i] = true;
}
dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
@@ -957,7 +956,7 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
for (i = 0; i < NUM_DECIMATORS; i++) {
if (decimator == i + 1)
- dig_cdc->dec_active[i] = false;
+ msm_dig_cdc->dec_active[i] = false;
}
break;
}
@@ -972,7 +971,7 @@ static int msm_dig_cdc_event_notify(struct notifier_block *block,
{
enum dig_cdc_notify_event event = (enum dig_cdc_notify_event)val;
struct snd_soc_codec *codec = registered_digcodec;
- struct msm_dig *msm_dig_cdc = codec->control_data;
+ struct msm_dig_priv *msm_dig_cdc = snd_soc_codec_get_drvdata(codec);
struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
@@ -1155,36 +1154,34 @@ int msm_dig_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
return -ENOMEM;
}
msm_dig->version_entry = version_entry;
+ if (msm_dig->get_cdc_version)
+ msm_dig->version = msm_dig->get_cdc_version(msm_dig->handle);
+ else
+ msm_dig->version = DRAX_CDC;
+
return 0;
}
EXPORT_SYMBOL(msm_dig_codec_info_create_codec_entry);
static int msm_dig_cdc_soc_probe(struct snd_soc_codec *codec)
{
- struct msm_dig_priv *dig_cdc = NULL;
- struct msm_dig *msm_dig_cdc = dev_get_drvdata(codec->dev);
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(codec->dev);
int i, ret;
- dig_cdc = devm_kzalloc(codec->dev, sizeof(struct msm_dig_priv),
- GFP_KERNEL);
- if (!dig_cdc)
- return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, dig_cdc);
- dig_cdc->codec = codec;
- codec->control_data = msm_dig_cdc;
+ msm_dig_cdc->codec = codec;
snd_soc_add_codec_controls(codec, compander_kcontrols,
ARRAY_SIZE(compander_kcontrols));
for (i = 0; i < NUM_DECIMATORS; i++) {
- tx_hpf_work[i].dig_cdc = dig_cdc;
+ tx_hpf_work[i].dig_cdc = msm_dig_cdc;
tx_hpf_work[i].decimator = i + 1;
INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
tx_hpf_corner_freq_callback);
}
for (i = 0; i < MSM89XX_RX_MAX; i++)
- dig_cdc->comp_enabled[i] = COMPANDER_NONE;
+ msm_dig_cdc->comp_enabled[i] = COMPANDER_NONE;
/* Register event notifier */
msm_dig_cdc->nblock.notifier_call = msm_dig_cdc_event_notify;
@@ -1198,15 +1195,14 @@ static int msm_dig_cdc_soc_probe(struct snd_soc_codec *codec)
return ret;
}
}
- /* Assign to DRAX_CDC for initial version */
- dig_cdc->version = DRAX_CDC;
registered_digcodec = codec;
+
return 0;
}
static int msm_dig_cdc_soc_remove(struct snd_soc_codec *codec)
{
- struct msm_dig *msm_dig_cdc = dev_get_drvdata(codec->dev);
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(codec->dev);
if (msm_dig_cdc->register_notifier)
msm_dig_cdc->register_notifier(msm_dig_cdc->handle,
@@ -1968,7 +1964,7 @@ static struct snd_soc_dai_driver msm_codec_dais[] = {
static struct regmap *msm_digital_get_regmap(struct device *dev)
{
- struct msm_dig *msm_dig_cdc = dev_get_drvdata(dev);
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(dev);
return msm_dig_cdc->regmap;
}
@@ -2005,10 +2001,10 @@ static int msm_dig_cdc_probe(struct platform_device *pdev)
{
int ret;
u32 dig_cdc_addr;
- struct msm_dig *msm_dig_cdc;
+ struct msm_dig_priv *msm_dig_cdc;
struct dig_ctrl_platform_data *pdata;
- msm_dig_cdc = devm_kzalloc(&pdev->dev, sizeof(struct msm_dig),
+ msm_dig_cdc = devm_kzalloc(&pdev->dev, sizeof(struct msm_dig_priv),
GFP_KERNEL);
if (!msm_dig_cdc)
return -ENOMEM;
@@ -2019,7 +2015,6 @@ static int msm_dig_cdc_probe(struct platform_device *pdev)
ret = -EINVAL;
goto rtn;
}
- dev_set_drvdata(&pdev->dev, msm_dig_cdc);
ret = of_property_read_u32(pdev->dev.of_node, "reg",
&dig_cdc_addr);
@@ -2044,6 +2039,7 @@ static int msm_dig_cdc_probe(struct platform_device *pdev)
msm_dig_cdc->handle = pdata->handle;
msm_dig_cdc->register_notifier = pdata->register_notifier;
+ dev_set_drvdata(&pdev->dev, msm_dig_cdc);
snd_soc_register_codec(&pdev->dev, &soc_msm_dig_codec,
msm_codec_dais, ARRAY_SIZE(msm_codec_dais));
dev_dbg(&pdev->dev, "%s: registered DIG CODEC 0x%x\n",
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h
index 4cb82cd421b0..b401a4082cbb 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -43,9 +43,6 @@ struct msm_dig_priv {
/* Entry for version info */
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
-};
-
-struct msm_dig {
char __iomem *dig_base;
struct regmap *regmap;
struct notifier_block nblock;
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 4fe9e2d50f7a..192d9291a8f3 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -9319,6 +9319,7 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback");
snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture");
snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF4 MAD TX");
snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
snd_soc_dapm_sync(dapm);
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 6324e81759de..041a91e28988 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -2906,7 +2906,6 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
break;
case MSM_BACKEND_DAI_SLIMBUS_4_TX:
- case MSM_BACKEND_DAI_SLIMBUS_TX_VI:
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_FORMAT_S32_LE);
rate->min = rate->max = SAMPLING_RATE_8KHZ;
@@ -3699,8 +3698,7 @@ static int msm_snd_hw_params(struct snd_pcm_substream *substream,
/* For <codec>_tx3 case */
else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
user_set_tx_ch = slim_tx_cfg[1].channels;
- else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX ||
- dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_TX_VI)
+ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
user_set_tx_ch = msm_vi_feed_tx_ch;
else
user_set_tx_ch = tx_ch_cnt;
@@ -5728,12 +5726,12 @@ static struct snd_soc_dai_link msm_tasha_be_dai_links[] = {
/* Slimbus VI Recording */
{
.name = LPASS_BE_SLIMBUS_TX_VI,
- .stream_name = "Slimbus VI Capture",
- .cpu_dai_name = "msm-dai-q6-dev.20233",
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_vifeedback",
- .be_id = MSM_BACKEND_DAI_SLIMBUS_TX_VI,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.ignore_suspend = 1,
@@ -5913,16 +5911,15 @@ static struct snd_soc_dai_link msm_tavil_be_dai_links[] = {
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
-
/* Slimbus VI Recording */
{
.name = LPASS_BE_SLIMBUS_TX_VI,
- .stream_name = "Slimbus VI Capture",
- .cpu_dai_name = "msm-dai-q6-dev.20233",
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
.platform_name = "msm-pcm-routing",
.codec_name = "tavil_codec",
.codec_dai_name = "tavil_vifeedback",
- .be_id = MSM_BACKEND_DAI_SLIMBUS_TX_VI,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.ignore_suspend = 1,
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 7f032dcceabd..4fa80c679b46 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -160,6 +160,10 @@ struct msm_compr_audio {
uint32_t stream_available;
uint32_t next_stream;
+ uint32_t run_mode;
+ uint32_t start_delay_lsw;
+ uint32_t start_delay_msw;
+
uint64_t marker_timestamp;
struct msm_compr_gapless_state gapless_state;
@@ -215,6 +219,99 @@ static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
struct msm_compr_dec_params *dec_params,
int stream_id);
+static int msm_compr_set_render_mode(struct msm_compr_audio *prtd,
+ uint32_t render_mode) {
+ int ret = -EINVAL;
+ struct audio_client *ac = prtd->audio_client;
+
+ pr_debug("%s, got render mode %u\n", __func__, render_mode);
+
+ if (render_mode == SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER) {
+ render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT;
+ } else if (render_mode == SNDRV_COMPRESS_RENDER_MODE_STC_MASTER) {
+ render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC;
+ prtd->run_mode = ASM_SESSION_CMD_RUN_STARTIME_RUN_WITH_DELAY;
+ } else {
+ pr_err("%s, Invalid render mode %u\n", __func__,
+ render_mode);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode);
+ if (ret) {
+ pr_err("%s, Render mode can't be set error %d\n", __func__,
+ ret);
+ }
+exit:
+ return ret;
+}
+
+static int msm_compr_set_clk_rec_mode(struct audio_client *ac,
+ uint32_t clk_rec_mode) {
+ int ret = -EINVAL;
+
+ pr_debug("%s, got clk rec mode %u\n", __func__, clk_rec_mode);
+
+ if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_NONE) {
+ clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE;
+ } else if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_AUTO) {
+ clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO;
+ } else {
+ pr_err("%s, Invalid clk rec_mode mode %u\n", __func__,
+ clk_rec_mode);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = q6asm_send_mtmx_strtr_clk_rec_mode(ac, clk_rec_mode);
+ if (ret) {
+ pr_err("%s, clk rec mode can't be set, error %d\n", __func__,
+ ret);
+ }
+
+exit:
+ return ret;
+}
+
+static int msm_compr_set_render_window(struct audio_client *ac,
+ uint32_t ws_lsw, uint32_t ws_msw,
+ uint32_t we_lsw, uint32_t we_msw)
+{
+ int ret = -EINVAL;
+ struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window;
+ uint32_t param_id;
+
+ pr_debug("%s, ws_lsw 0x%x ws_msw 0x%x we_lsw 0x%x we_ms 0x%x\n",
+ __func__, ws_lsw, ws_msw, we_lsw, we_msw);
+
+ memset(&asm_mtmx_strtr_window, 0,
+ sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
+ asm_mtmx_strtr_window.window_lsw = ws_lsw;
+ asm_mtmx_strtr_window.window_msw = ws_msw;
+ param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_START_V2;
+ ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
+ param_id);
+ if (ret) {
+ pr_err("%s, start window can't be set error %d\n", __func__,
+ ret);
+ goto exit;
+ }
+
+ asm_mtmx_strtr_window.window_lsw = we_lsw;
+ asm_mtmx_strtr_window.window_msw = we_msw;
+ param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2;
+ ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window,
+ param_id);
+ if (ret) {
+ pr_err("%s, end window can't be set error %d\n", __func__,
+ ret);
+ }
+
+exit:
+ return ret;
+}
+
static int msm_compr_set_volume(struct snd_compr_stream *cstream,
uint32_t volume_l, uint32_t volume_r)
{
@@ -1586,6 +1683,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
pdata->dec_params[soc_prtd->dai_link->be_id] = NULL;
kfree(prtd);
+ runtime->private_data = NULL;
return 0;
}
@@ -1645,6 +1743,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream)
q6asm_audio_client_free(ac);
kfree(prtd);
+ runtime->private_data = NULL;
return 0;
}
@@ -1963,7 +2062,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
msm_compr_read_buffer(prtd);
}
/* issue RUN command for the stream */
- q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
+ prtd->start_delay_msw, prtd->start_delay_lsw);
break;
case SNDRV_PCM_TRIGGER_STOP:
spin_lock_irqsave(&prtd->lock, flags);
@@ -2047,7 +2147,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
prtd->gapless_state.gapless_transition);
if (!prtd->gapless_state.gapless_transition) {
atomic_set(&prtd->start, 1);
- q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ q6asm_run_nowait(prtd->audio_client, prtd->run_mode,
+ 0, 0);
}
break;
case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
@@ -2717,11 +2818,14 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
return -EINVAL;
}
- if (prtd->compr_passthr != LEGACY_PCM) {
+ if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) ||
+ (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) &&
+ (prtd->compr_passthr != LEGACY_PCM)) {
pr_debug("%s: No trailing silence for compress_type[%d]\n",
__func__, prtd->compr_passthr);
return 0;
}
+
ac = prtd->audio_client;
if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
pr_debug("%s, got encoder padding %u", __func__, metadata->value[0]);
@@ -2729,11 +2833,63 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
} else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
pr_debug("%s, got encoder delay %u", __func__, metadata->value[0]);
prtd->gapless_state.initial_samples_drop = metadata->value[0];
+ } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
+ return msm_compr_set_render_mode(prtd, metadata->value[0]);
+ } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
+ return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
+ } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
+ return msm_compr_set_render_window(
+ ac,
+ metadata->value[0],
+ metadata->value[1],
+ metadata->value[2],
+ metadata->value[3]);
+ } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
+ prtd->start_delay_lsw = metadata->value[0];
+ prtd->start_delay_msw = metadata->value[1];
}
return 0;
}
+static int msm_compr_get_metadata(struct snd_compr_stream *cstream,
+ struct snd_compr_metadata *metadata)
+{
+ struct msm_compr_audio *prtd;
+ struct audio_client *ac;
+ int ret = -EINVAL;
+
+ pr_debug("%s\n", __func__);
+
+ if (!metadata || !cstream || !cstream->runtime)
+ return ret;
+
+ if (metadata->key != SNDRV_COMPRESS_PATH_DELAY) {
+ pr_err("%s, unsupported key %d\n", __func__, metadata->key);
+ return ret;
+ }
+
+ prtd = cstream->runtime->private_data;
+ if (!prtd || !prtd->audio_client) {
+ pr_err("%s: prtd or audio client is NULL\n", __func__);
+ return ret;
+ }
+
+ ac = prtd->audio_client;
+ ret = q6asm_get_path_delay(prtd->audio_client);
+ if (ret) {
+ pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pr_debug("%s, path delay(in us) %u\n", __func__, ac->path_delay);
+
+ metadata->value[0] = ac->path_delay;
+
+ return ret;
+}
+
+
static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
union snd_codec_options *codec_options)
{
@@ -3889,6 +4045,7 @@ static struct snd_compr_ops msm_compr_ops = {
.pointer = msm_compr_pointer,
.set_params = msm_compr_set_params,
.set_metadata = msm_compr_set_metadata,
+ .get_metadata = msm_compr_get_metadata,
.set_next_track_param = msm_compr_set_next_track_param,
.ack = msm_compr_ack,
.copy = msm_compr_copy,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 19e2fad2920d..d7efefdb3a04 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -1773,7 +1773,6 @@ static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
case SLIMBUS_2_TX:
case SLIMBUS_3_TX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_TX:
case SLIMBUS_6_TX:
case SLIMBUS_7_TX:
@@ -1928,7 +1927,6 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
case SLIMBUS_2_TX:
case SLIMBUS_3_TX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_TX:
case SLIMBUS_6_TX:
case SLIMBUS_7_TX:
@@ -2348,9 +2346,6 @@ static const struct snd_kcontrol_new sb_config_controls[] = {
msm_dai_q6_cal_info_put),
SOC_ENUM_EXT("SLIM_2_RX Format", sb_config_enum[0],
msm_dai_q6_sb_format_get,
- msm_dai_q6_sb_format_put),
- SOC_ENUM_EXT("SLIM_TX_VI Format", sb_config_enum[0],
- msm_dai_q6_sb_format_get,
msm_dai_q6_sb_format_put)
};
@@ -2409,11 +2404,6 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
snd_ctl_new1(&sb_config_controls[0],
dai_data));
break;
- case SLIMBUS_TX_VI:
- rc = snd_ctl_add(dai->component->card->snd_card,
- snd_ctl_new1(&sb_config_controls[3],
- dai_data));
- break;
case SLIMBUS_2_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&sb_config_controls[1],
@@ -3302,25 +3292,6 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai[] = {
},
{
.capture = {
- .stream_name = "Slimbus VI Capture",
- .aif_name = "SLIMBUS_TX_VI",
- .rates = SNDRV_PCM_RATE_8000_96000 |
- SNDRV_PCM_RATE_192000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .channels_min = 1,
- .channels_max = 4,
- .rate_min = 8000,
- .rate_max = 192000,
- },
- .ops = &msm_dai_q6_ops,
- .id = SLIMBUS_TX_VI,
- .probe = msm_dai_q6_dai_probe,
- .remove = msm_dai_q6_dai_remove,
- },
- {
- .capture = {
.stream_name = "Slimbus5 Capture",
.aif_name = "SLIMBUS_5_TX",
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -4677,9 +4648,6 @@ register_slim_playback:
case SLIMBUS_4_TX:
strlcpy(stream_name, "Slimbus4 Capture", 80);
goto register_slim_capture;
- case SLIMBUS_TX_VI:
- strlcpy(stream_name, "Slimbus VI Capture", 80);
- goto register_slim_capture;
case SLIMBUS_5_TX:
strlcpy(stream_name, "Slimbus5 Capture", 80);
goto register_slim_capture;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index d65108e04e0b..b1a1ea54a73e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -684,6 +684,7 @@ done:
mutex_unlock(&prtd->lock);
prtd->prepared--;
kfree(prtd);
+ runtime->private_data = NULL;
return 0;
}
static int msm_afe_prepare(struct snd_pcm_substream *substream)
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 33c5b6486cca..c0ca9b24f544 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -570,6 +570,8 @@ static int msm_pcm_close(struct snd_pcm_substream *substream)
SNDRV_PCM_STREAM_PLAYBACK :
SNDRV_PCM_STREAM_CAPTURE);
kfree(prtd);
+ runtime->private_data = NULL;
+
return 0;
}
@@ -834,6 +836,182 @@ static int msm_pcm_add_fe_topology_control(struct snd_soc_pcm_runtime *rtd)
return ret;
}
+static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_RX;
+ int be_id = ucontrol->value.integer.value[3];
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+
+ ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
+ be_id, app_type,
+ acdb_dev_id, sample_rate);
+ if (ret < 0)
+ pr_err("%s: msm_pcm_playback_app_type_cfg_ctl_put failed, err %d\n",
+ __func__, ret);
+
+ pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
+ __func__, fe_id, session_type, be_id,
+ app_type, acdb_dev_id, sample_rate);
+ return ret;
+}
+
+static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_RX;
+ int be_id = ucontrol->value.integer.value[3];
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
+ be_id, &app_type,
+ &acdb_dev_id,
+ &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_playback_app_type_cfg_ctl_get failed, err: %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+
+ pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, session_type, be_id,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_TX;
+ int be_id = ucontrol->value.integer.value[3];
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+
+ ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
+ be_id, app_type,
+ acdb_dev_id, sample_rate);
+ if (ret < 0)
+ pr_err("%s: msm_pcm_capture_app_type_cfg_ctl_put failed, err: %d\n",
+ __func__, ret);
+
+ pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
+ __func__, fe_id, session_type, be_id,
+ app_type, acdb_dev_id, sample_rate);
+
+ return ret;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_TX;
+ int be_id = ucontrol->value.integer.value[3];
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
+ be_id, &app_type,
+ &acdb_dev_id,
+ &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_capture_app_type_cfg_ctl_get failed, err: %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+ pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, session_type, be_id,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
+static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_pcm *pcm = rtd->pcm;
+ struct snd_pcm_usr *app_type_info;
+ struct snd_kcontrol *kctl;
+ const char *playback_mixer_ctl_name = "Audio Stream";
+ const char *capture_mixer_ctl_name = "Audio Stream Capture";
+ const char *deviceNo = "NN";
+ const char *suffix = "App Type Cfg";
+ int ctl_len, ret = 0;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ctl_len = strlen(playback_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 +
+ strlen(suffix) + 1;
+ pr_debug("%s: Playback app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0) {
+ pr_err("%s: playback app type cntrl add failed, err: %d\n",
+ __func__, ret);
+ return ret;
+ }
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ playback_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_playback_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_playback_app_type_cfg_ctl_get;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ctl_len = strlen(capture_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ pr_debug("%s: Capture app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0) {
+ pr_err("%s: capture app type cntrl add failed, err: %d\n",
+ __func__, ret);
+ return ret;
+ }
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ capture_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_capture_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_capture_app_type_cfg_ctl_get;
+ }
+
+ return 0;
+}
+
+
static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
@@ -860,6 +1038,13 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add pcm topology control %d\n",
__func__, ret);
}
+
+ ret = msm_pcm_add_app_type_controls(rtd);
+ if (ret) {
+ pr_err("%s: Could not add app type controls failed %d\n",
+ __func__, ret);
+ }
+
pcm->nonatomic = true;
exit:
return ret;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index e14f410bd310..7928c3791f96 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -804,6 +804,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
kfree(prtd);
+ runtime->private_data = NULL;
+
return 0;
}
@@ -909,6 +911,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_CAPTURE);
kfree(prtd);
+ runtime->private_data = NULL;
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 3677a06c65ae..e8bf562acc4f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -96,7 +96,6 @@ enum {
#define SLIMBUS_2_TX_TEXT "SLIMBUS_2_TX"
#define SLIMBUS_3_TX_TEXT "SLIMBUS_3_TX"
#define SLIMBUS_4_TX_TEXT "SLIMBUS_4_TX"
-#define SLIMBUS_TX_VI_TEXT "SLIMBUS_TX_VI"
#define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX"
#define TERT_MI2S_TX_TEXT "TERT_MI2S_TX"
#define QUAT_MI2S_TX_TEXT "QUAT_MI2S_TX"
@@ -109,7 +108,7 @@ static const char * const lsm_port_text[] = {
SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT,
SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT,
TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT,
- INT3_MI2S_TX_TEXT, SLIMBUS_TX_VI_TEXT
+ INT3_MI2S_TX_TEXT
};
struct msm_pcm_route_bdai_pp_params {
@@ -538,7 +537,6 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
LPASS_BE_INT6_MI2S_RX},
{ AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0,
LPASS_BE_INT6_MI2S_TX},
- { SLIMBUS_TX_VI, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI},
};
/* Track ASM playback & capture sessions of DAI
@@ -2760,14 +2758,9 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget_list *wlist =
dapm_kcontrol_get_wlist(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
- int mux = ucontrol->value.enumerated.item[0];
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct snd_soc_dapm_update *update = NULL;
- if (mux >= e->items) {
- pr_err("%s: Invalid mux value %d\n", __func__, mux);
- return -EINVAL;
- }
mutex_lock(&routing_lock);
switch (ucontrol->value.integer.value[0]) {
@@ -2870,7 +2863,8 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
pr_debug("%s: msm_route_ec_ref_rx = %d\n",
__func__, msm_route_ec_ref_rx);
mutex_unlock(&routing_lock);
- snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update);
+ snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+ msm_route_ec_ref_rx, e, update);
return 0;
}
@@ -5681,9 +5675,6 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
SOC_SINGLE_EXT("SLIM_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
- SOC_SINGLE_EXT("SLIM_TX_VI", MSM_BACKEND_DAI_SLIMBUS_TX_VI,
- MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
- msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -10994,8 +10985,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture",
0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("SLIMBUS_TX_VI", "Slimbus VI Capture",
- 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SENARY_TX", "Senary_mi2s Capture",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("INT5_MI2S_TX", "INT5 MI2S Capture",
@@ -11759,7 +11748,6 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
{"MultiMedia8 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
- {"MultiMedia1 Mixer", "SLIM_TX_VI", "SLIMBUS_TX_VI"},
{"MultiMedia1 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
{"MultiMedia1 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
{"MultiMedia1 Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
@@ -13921,7 +13909,6 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SLIMBUS_1_TX", NULL, "BE_IN" },
{"SLIMBUS_3_TX", NULL, "BE_IN" },
{"SLIMBUS_4_TX", NULL, "BE_IN" },
- {"SLIMBUS_TX_VI", NULL, "BE_IN" },
{"SLIMBUS_5_TX", NULL, "BE_IN" },
{"SLIMBUS_6_TX", NULL, "BE_IN" },
{"SLIMBUS_7_TX", NULL, "BE_IN" },
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 94c79f00afec..fcd155e71317 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -70,8 +70,8 @@
#define LPASS_BE_SLIMBUS_3_TX "SLIMBUS_3_TX"
#define LPASS_BE_SLIMBUS_4_RX "SLIMBUS_4_RX"
#define LPASS_BE_SLIMBUS_4_TX "SLIMBUS_4_TX"
-#define LPASS_BE_SLIMBUS_5_RX "SLIMBUS_5_RX"
#define LPASS_BE_SLIMBUS_TX_VI "SLIMBUS_TX_VI"
+#define LPASS_BE_SLIMBUS_5_RX "SLIMBUS_5_RX"
#define LPASS_BE_SLIMBUS_5_TX "SLIMBUS_5_TX"
#define LPASS_BE_SLIMBUS_6_RX "SLIMBUS_6_RX"
#define LPASS_BE_SLIMBUS_6_TX "SLIMBUS_6_TX"
@@ -362,7 +362,6 @@ enum {
MSM_BACKEND_DAI_INT5_MI2S_TX,
MSM_BACKEND_DAI_INT6_MI2S_RX,
MSM_BACKEND_DAI_INT6_MI2S_TX,
- MSM_BACKEND_DAI_SLIMBUS_TX_VI,
MSM_BACKEND_DAI_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 4a4f02c7b9b6..2da7e6dc11e7 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -2463,6 +2463,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
pr_err("%s: DTS_EAGLE mmap did not work!",
__func__);
}
+ memset(&open, 0, sizeof(struct adm_cmd_device_open_v5));
open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
APR_PKT_VER);
@@ -2506,6 +2507,8 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
(open.endpoint_id_2 != 0xFFFF)) {
+ memset(&open_v6, 0,
+ sizeof(struct adm_cmd_device_open_v6));
memcpy(&open_v6, &open,
sizeof(struct adm_cmd_device_open_v5));
open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index fcff383b9c3b..80729b3052b7 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -547,7 +547,6 @@ int afe_get_port_type(u16 port_id)
case SLIMBUS_2_TX:
case SLIMBUS_3_TX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_TX:
case SLIMBUS_6_TX:
case SLIMBUS_7_TX:
@@ -652,7 +651,6 @@ int afe_sizeof_cfg_cmd(u16 port_id)
case SLIMBUS_3_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_RX:
case SLIMBUS_5_TX:
case SLIMBUS_6_RX:
@@ -2939,13 +2937,6 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
return ret;
}
- /*
- * Virtual SLIMBUS_TX_VI shares afe port with SLIMBUS_4_TX.
- * port_id changes to physical port of SLIMBUS_4_TX.
- */
- if (port_id == SLIMBUS_TX_VI)
- port_id = SLIMBUS_4_TX;
-
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX)) {
pr_debug("%s: before incrementing pcm_afe_instance %d"\
@@ -3132,7 +3123,6 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
case SLIMBUS_3_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_RX:
case SLIMBUS_5_TX:
case SLIMBUS_6_RX:
@@ -3325,7 +3315,6 @@ int afe_get_port_index(u16 port_id)
case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
- case SLIMBUS_TX_VI: return IDX_SLIMBUS_4_TX;
case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
@@ -5494,14 +5483,6 @@ int afe_close(int port_id)
goto fail_cmd;
}
pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
-
- /*
- * Virtual SLIMBUS_TX_VI shares afe port with SLIMBUS_4_TX.
- * port_id changes to physical port of SLIMBUS_4_TX.
- */
- if (port_id == SLIMBUS_TX_VI)
- port_id = SLIMBUS_4_TX;
-
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX)) {
pr_debug("%s: before decrementing pcm_afe_instance %d\n",
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index d55c28fab652..c3a4719542ef 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -7934,16 +7934,18 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
matrix.param.data_payload_addr_lsw = 0;
matrix.param.data_payload_addr_msw = 0;
matrix.param.mem_map_handle = 0;
- matrix.param.data_payload_size = sizeof(matrix) -
- sizeof(matrix.hdr) - sizeof(matrix.param);
+ matrix.param.data_payload_size =
+ sizeof(struct asm_stream_param_data_v2) +
+ sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
matrix.param.direction = 0; /* RX */
matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
matrix.data.param_id = param_id;
- matrix.data.param_size = matrix.param.data_payload_size -
- sizeof(matrix.data);
+ matrix.data.param_size =
+ sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
matrix.data.reserved = 0;
- matrix.window_lsw = window_param->window_lsw;
- matrix.window_msw = window_param->window_msw;
+ memcpy(&(matrix.config.window_param),
+ window_param,
+ sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));
rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
if (rc < 0) {
@@ -7973,7 +7975,177 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
rc = 0;
fail_cmd:
return rc;
-};
+}
+
+int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
+ uint32_t render_mode)
+{
+ struct asm_mtmx_strtr_params matrix;
+ struct asm_session_mtmx_strtr_param_render_mode_t render_param;
+ int sz = 0;
+ int rc = 0;
+
+ pr_debug("%s: render mode is %d\n", __func__, render_mode);
+
+ if (!ac) {
+ pr_err("%s: audio client handle is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if ((render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT) &&
+ (render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC)) {
+ pr_err("%s: Invalid render mode %d\n", __func__, render_mode);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ memset(&render_param, 0,
+ sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
+ render_param.flags = render_mode;
+
+ memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
+ sz = sizeof(struct asm_mtmx_strtr_params);
+ q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
+
+ matrix.param.data_payload_addr_lsw = 0;
+ matrix.param.data_payload_addr_msw = 0;
+ matrix.param.mem_map_handle = 0;
+ matrix.param.data_payload_size =
+ sizeof(struct asm_stream_param_data_v2) +
+ sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
+ matrix.param.direction = 0; /* RX */
+ matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
+ matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD;
+ matrix.data.param_size =
+ sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
+ matrix.data.reserved = 0;
+ memcpy(&(matrix.config.render_param),
+ &render_param,
+ sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
+ if (rc < 0) {
+ pr_err("%s: Render mode send failed paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout, Render mode send paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -ETIMEDOUT;
+ goto exit;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto exit;
+ }
+ rc = 0;
+exit:
+ return rc;
+}
+
+int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
+ uint32_t clk_rec_mode)
+{
+ struct asm_mtmx_strtr_params matrix;
+ struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
+ int sz = 0;
+ int rc = 0;
+
+ pr_debug("%s: clk rec mode is %d\n", __func__, clk_rec_mode);
+
+ if (!ac) {
+ pr_err("%s: audio client handle is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if ((clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE) &&
+ (clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO)) {
+ pr_err("%s: Invalid clk rec mode %d\n", __func__, clk_rec_mode);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ memset(&clk_rec_param, 0,
+ sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
+ clk_rec_param.flags = clk_rec_mode;
+
+ memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
+ sz = sizeof(struct asm_mtmx_strtr_params);
+ q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
+
+ matrix.param.data_payload_addr_lsw = 0;
+ matrix.param.data_payload_addr_msw = 0;
+ matrix.param.mem_map_handle = 0;
+ matrix.param.data_payload_size =
+ sizeof(struct asm_stream_param_data_v2) +
+ sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
+ matrix.param.direction = 0; /* RX */
+ matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
+ matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD;
+ matrix.data.param_size =
+ sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
+ matrix.data.reserved = 0;
+ memcpy(&(matrix.config.clk_rec_param),
+ &clk_rec_param,
+ sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
+ if (rc < 0) {
+ pr_err("%s: clk rec mode send failed paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout, clk rec mode send paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -ETIMEDOUT;
+ goto exit;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto exit;
+ }
+ rc = 0;
+exit:
+ return rc;
+}
static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
{
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index a4951dc77378..3b745c24f90e 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,7 +64,6 @@ int q6audio_get_port_index(u16 port_id)
case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
- case SLIMBUS_TX_VI: return IDX_SLIMBUS_4_TX;
case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX;
case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX;
@@ -312,7 +311,6 @@ int q6audio_get_port_id(u16 port_id)
case SLIMBUS_3_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX;
case SLIMBUS_4_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX;
case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
- case SLIMBUS_TX_VI: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
case SLIMBUS_5_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX;
case SLIMBUS_5_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX;
case SLIMBUS_6_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX;
@@ -690,7 +688,6 @@ int q6audio_validate_port(u16 port_id)
case SLIMBUS_3_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
- case SLIMBUS_TX_VI:
case SLIMBUS_5_RX:
case SLIMBUS_5_TX:
case SLIMBUS_6_RX:
diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c
index 37b34b231b72..228e84ae8e1d 100644
--- a/sound/soc/msm/sdm660-internal.c
+++ b/sound/soc/msm/sdm660-internal.c
@@ -1255,7 +1255,6 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *ana_cdc = rtd->codec_dais[ANA_CDC]->codec;
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(ana_cdc);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
struct snd_card *card;
int ret = -ENOMEM;
@@ -1299,17 +1298,6 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_sync(dapm);
- /*
- * Send speaker configuration only for WSA8810.
- * Defalut configuration is for WSA8815.
- */
- if (rtd_aux && rtd_aux->component)
- if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
- !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
- msm_sdw_set_spkr_mode(rtd->codec, SPKR_MODE_1);
- msm_sdw_set_spkr_gain_offset(rtd->codec,
- RX_GAIN_OFFSET_M1P5_DB);
- }
msm_anlg_cdc_spk_ext_pa_cb(enable_spk_ext_pa, ana_cdc);
msm_dig_cdc_hph_comp_cb(msm_config_hph_compander_gpio, dig_cdc);
@@ -1344,6 +1332,7 @@ static int msm_sdw_audrx_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm =
snd_soc_codec_get_dapm(codec);
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
struct snd_card *card;
snd_soc_add_codec_controls(codec, msm_sdw_controls,
@@ -1357,6 +1346,18 @@ static int msm_sdw_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_SDW");
snd_soc_dapm_sync(dapm);
+
+ /*
+ * Send speaker configuration only for WSA8810.
+ * Default configuration is for WSA8815.
+ */
+ if (rtd_aux && rtd_aux->component)
+ if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
+ !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ msm_sdw_set_spkr_mode(rtd->codec, SPKR_MODE_1);
+ msm_sdw_set_spkr_gain_offset(rtd->codec,
+ RX_GAIN_OFFSET_M1P5_DB);
+ }
card = rtd->card->snd_card;
if (!codec_root)
codec_root = snd_register_module_info(card->module, "codecs",
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index eb894d073c07..736b9c45e59a 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -527,6 +527,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
cstream, &async_domain);
} else {
be_list[j++] = be;
+ if (j == DPCM_MAX_BE_USERS) {
+ dev_dbg(fe->dev,
+ "ASoC: MAX backend users!\n");
+ break;
+ }
}
}
for (i = 0; i < j; i++) {
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 13649f96b370..0ba9dfb854b3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2403,6 +2403,10 @@ void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream,
dpcm, domain);
} else {
dpcm_async[i++] = dpcm;
+ if (i == DPCM_MAX_BE_USERS) {
+ dev_dbg(fe->dev, "ASoC: MAX backend users!\n");
+ break;
+ }
}
}