summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DMA-attributes.txt9
-rw-r--r--Documentation/DocBook/80211.tmpl1
-rw-r--r--Documentation/devicetree/bindings/cnss/icnss.txt12
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt5
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt3
-rw-r--r--Documentation/devicetree/bindings/misc/qpnp-misc.txt24
-rw-r--r--Documentation/devicetree/bindings/platform/msm/msm_rmnet_mhi.txt25
-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/apq8998-v2.1-mediabox.dts4
-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.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi5
-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-pm.dtsi6
-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/msm8998.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi35
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi44
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi54
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi39
-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.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-common.dtsi12
-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.dtsi12
-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_defconfig4
-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/kernel/perf_trace_counters.h18
-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/leds/leds-qpnp-wled.c85
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c15
-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/card/block.c13
-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.c97
-rw-r--r--drivers/mmc/host/cmdq_hci.h5
-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/ethernet/msm/msm_rmnet_mhi.c714
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c190
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h325
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c18
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c295
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h92
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c2
-rw-r--r--drivers/net/wireless/cnss_prealloc/cnss_prealloc.c1
-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.c20
-rw-r--r--drivers/power/supply/qcom/smb-lib.c127
-rw-r--r--drivers/power/supply/qcom/smb-lib.h3
-rw-r--r--drivers/power/supply/qcom/smb138x-charger.c13
-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.c8
-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_dsi_host.c58
-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.h3
-rw-r--r--include/linux/qpnp-misc.h22
-rw-r--r--include/net/cfg80211.h59
-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/nl80211.h28
-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/rcu/tree.c12
-rw-r--r--kernel/time/clocksource.c48
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--kernel/watchdog.c14
-rw-r--r--lib/Kconfig.debug11
-rw-r--r--net/wireless/core.h8
-rw-r--r--net/wireless/mlme.c3
-rw-r--r--net/wireless/nl80211.c12
-rw-r--r--net/wireless/nl80211.h4
-rw-r--r--net/wireless/sme.c43
-rw-r--r--net/wireless/util.c2
-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
196 files changed, 4936 insertions, 1796 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/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 02431aeca15f..eaadf60f4692 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -137,6 +137,7 @@
!Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_connect_bss
+!Finclude/net/cfg80211.h cfg80211_connect_timeout
!Finclude/net/cfg80211.h cfg80211_roamed
!Finclude/net/cfg80211.h cfg80211_disconnected
!Finclude/net/cfg80211.h cfg80211_ready_on_channel
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/leds/leds-qpnp-wled.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
index a77a291a99da..1e6aac56c44e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
@@ -75,6 +75,9 @@ Optional properties for WLED:
- qcom,lcd-auto-pfm-thresh : Specify the auto-pfm threshold, if the headroom voltage level
falls below this threshold and auto PFM is enabled, boost
controller will enter into PFM mode automatically.
+- qcom,lcd-psm-ctrl : A boolean property to specify if PSM needs to be
+ controlled dynamically when WLED module is enabled
+ or disabled.
Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
- qcom,loop-comp-res-kohm : control to select the compensation resistor in kohm. default is 320.
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/platform/msm/msm_rmnet_mhi.txt b/Documentation/devicetree/bindings/platform/msm/msm_rmnet_mhi.txt
new file mode 100644
index 000000000000..5ec2fb51833e
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/msm_rmnet_mhi.txt
@@ -0,0 +1,25 @@
+MSM MHI RMNET interface device
+
+MHI RMNET provides a network interface over PCIe
+to transfer IP packets between modem and apps.
+
+Required properties:
+- compatible : "qcom,mhi-rmnet"
+- At least one of MHI channel
+ - qcom,mhi-rx-channel : MHI channel number for incoming data
+ - qcom,mhi-tx-channel : MHI channel number for outgoing data
+- Default MRU for interface
+ - qcom,mhi-mru
+- Alias id to identify interface instance
+
+Example:
+ aliases {
+ mhi_rmnet0 = &mhi_rmnet_0;
+ };
+ mhi_rmnet_0: qcom,mhi-rmnet@0 {
+ compatible = "qcom,mhi-rmnet";
+ qcom,mhi-rx-channel = <101>;
+ qcom,mhi-tx-channel = <100>;
+ qcom,mhi-mru = <8000>;
+ status = "okay";
+ };
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/apq8998-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
index 00e3d0e42427..2f4037497764 100644
--- a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
+++ b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
@@ -21,6 +21,10 @@
qcom,board-id = <8 1>;
};
+&spi_10 {
+ status = "disabled";
+};
+
&msm_ath10k_wlan {
status = "ok";
};
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 f39cc96ea9a6..bcdbc4ed7c55 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -250,8 +250,8 @@
<0xd900 0x100>;
reg-names = "qpnp-wled-ctrl-base",
"qpnp-wled-sink-base";
- interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_BOTH>,
- <0x3 0xd8 0x2 IRQ_TYPE_EDGE_BOTH>;
+ interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "ovp-irq", "sc-irq";
linux,name = "wled";
linux,default-trigger = "bkl-trigger";
@@ -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 c21c136907d4..111d0b51b6c2 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -600,8 +600,8 @@
<0xd900 0x100>;
reg-names = "qpnp-wled-ctrl-base",
"qpnp-wled-sink-base";
- interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_BOTH>,
- <0x3 0xd8 0x2 IRQ_TYPE_EDGE_BOTH>;
+ interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "ovp-irq", "sc-irq";
linux,name = "wled";
linux,default-trigger = "bkl-trigger";
@@ -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-pm.dtsi b/arch/arm/boot/dts/qcom/msm8998-pm.dtsi
index 8fd75c369c53..bb478794e832 100644
--- a/arch/arm/boot/dts/qcom/msm8998-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-pm.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
@@ -302,7 +302,7 @@
qcom,rpm-master-stats@778150 {
compatible = "qcom,rpm-master-stats";
reg = <0x778150 0x5000>;
- qcom,masters = "APSS", "MPSS", "ADSP", "SLPI";
+ qcom,masters = "APSS", "MPSS", "ADSP", "SLPI", "TZ", "SPSS";
qcom,master-stats-version = <2>;
qcom,master-offset = <4096>;
};
@@ -322,7 +322,7 @@
compatible = "qcom,system-stats";
qcom,rpm-msg-ram = <&rpm_msg_ram>;
qcom,rpm-code-ram = <&rpm_code_ram>;
- qcom,masters = "APSS", "MPSS", "ADSP", "SLPI";
+ qcom,masters = "APSS", "MPSS", "ADSP", "SLPI", "TZ", "SPSS";
};
qcom,mpm@7781b8 {
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/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index 0e014a171156..66ca39ee6ebc 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -286,16 +286,22 @@
reg = <0 0x85800000 0 0x3700000>;
};
- pil_ipa_gpu_mem: pil_ipa_gpu_region@95000000 {
+ pil_ipa_gpu_mem: pil_ipa_gpu_region@95200000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x95000000 0 0x100000>;
+ reg = <0 0x95200000 0 0x100000>;
};
- pil_slpi_mem: pil_slpi_region@94100000 {
+ pil_slpi_mem: pil_slpi_region@94300000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x94100000 0 0xf00000>;
+ reg = <0 0x94300000 0 0xf00000>;
+ };
+
+ pil_mba_mem: pil_mba_region@94100000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x94100000 0 0x200000>;
};
pil_video_mem: pil_video_region@93c00000 {
@@ -2109,6 +2115,10 @@
/* GPIO output to mss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ qcom,mba-mem@0 {
+ compatible = "qcom,pil-mba-mem";
+ memory-region = <&pil_mba_mem>;
+ };
};
tsens0: tsens@10aa000 {
diff --git a/arch/arm/boot/dts/qcom/sdm630-camera.dtsi b/arch/arm/boot/dts/qcom/sdm630-camera.dtsi
index 56210dc6892b..72f606168691 100644
--- a/arch/arm/boot/dts/qcom/sdm630-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-camera.dtsi
@@ -501,8 +501,9 @@
cell-index = <0>;
compatible = "qcom,vfe48";
reg = <0xca10000 0x4000>,
- <0xca40000 0x3000>;
- reg-names = "vfe", "vfe_vbif";
+ <0xca40000 0x3000>,
+ <0x007801a4 0x8>;
+ reg-names = "vfe", "vfe_vbif", "vfe_fuse";
interrupts = <0 314 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe0>;
@@ -581,8 +582,9 @@
cell-index = <1>;
compatible = "qcom,vfe48";
reg = <0xca14000 0x4000>,
- <0xca40000 0x3000>;
- reg-names = "vfe", "vfe_vbif";
+ <0xca40000 0x3000>,
+ <0x007801a4 0x8>;
+ reg-names = "vfe", "vfe_vbif", "vfe_fuse";
interrupts = <0 315 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe1>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index a5e33514976f..55e6943bf327 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -154,6 +154,15 @@
qcom,platform-te-gpio = <&tlmm 59 0>;
};
+&mdss_dp_ctrl {
+ pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+ pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>;
+ pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>;
+ qcom,aux-en-gpio = <&tlmm 55 0>;
+ qcom,aux-sel-gpio = <&tlmm 56 0>;
+ qcom,usbplug-cc-gpio = <&tlmm 58 0>;
+};
+
&pm660l_wled {
qcom,led-strings-list = [01 02];
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
index 82acdec92431..42eac0ab223a 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
@@ -44,4 +44,39 @@
};
};
};
+
+ mdss_dp_pll: qcom,mdss_dp_pll@c011000 {
+ compatible = "qcom,mdss_dp_pll_sdm630";
+ status = "ok";
+ label = "MDSS DP PLL";
+ cell-index = <0>;
+ #clock-cells = <1>;
+
+ reg = <0xc011c00 0x190>,
+ <0xc011000 0x910>,
+ <0x0c8c2300 0x8>;
+ reg-names = "pll_base", "phy_base", "gdsc_base";
+
+ gdsc-supply = <&gdsc_mdss>;
+
+ clocks = <&clock_mmss MMSS_MDSS_AHB_CLK>,
+ <&clock_rpmcc RPM_LN_BB_CLK1>,
+ <&clock_gcc GCC_USB3_CLKREF_CLK>;
+ clock-names = "iface_clk", "ref_clk_src", "ref_clk";
+ clock-rate = <0>;
+
+ qcom,platform-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,platform-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "gdsc";
+ qcom,supply-min-voltage = <0>;
+ qcom,supply-max-voltage = <0>;
+ qcom,supply-enable-load = <0>;
+ qcom,supply-disable-load = <0>;
+ };
+ };
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index 3fb6993d71d6..9c34a60e7aaa 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
@@ -244,6 +244,9 @@
mdss_fb0: qcom,mdss_fb_primary {
cell-index = <0>;
compatible = "qcom,mdss-fb";
+ qcom,cont-splash-memory {
+ linux,contiguous-region = <&cont_splash_mem>;
+ };
};
mdss_fb1: qcom,mdss_fb_wfd {
@@ -382,7 +385,7 @@
};
msm_ext_disp: qcom,msm_ext_disp {
- status = "disabled";
+ status = "ok";
compatible = "qcom,msm-ext-disp";
ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
@@ -392,13 +395,13 @@
};
mdss_dp_ctrl: qcom,dp_ctrl@c990000 {
- status = "disabled";
+ status = "ok";
cell-index = <0>;
compatible = "qcom,mdss-dp";
qcom,mdss-fb-map = <&mdss_fb2>;
gdsc-supply = <&gdsc_mdss>;
- vdda-1p2-supply = <&pm660_l1>;
+ vdda-1p8-supply = <&pm660_l10>;
vdda-0p9-supply = <&pm660l_l1>;
reg = <0xc990000 0xa84>,
@@ -410,8 +413,37 @@
reg-names = "dp_ctrl", "dp_phy", "tcsr_regs", "dp_mmss_cc",
"qfprom_physical","hdcp_physical";
+ clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_MDSS_AHB_CLK>,
+ <&clock_mmss MMSS_MDSS_AXI_CLK>,
+ <&clock_mmss MMSS_MDSS_MDP_CLK>,
+ <&clock_mmss MMSS_MDSS_HDMI_DP_AHB_CLK>,
+ <&clock_mmss MMSS_MDSS_DP_AUX_CLK>,
+ <&clock_rpmcc RPM_LN_BB_CLK1>,
+ <&clock_gcc GCC_USB3_CLKREF_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&clock_mmss MMSS_MDSS_DP_LINK_CLK>,
+ <&clock_mmss MMSS_MDSS_DP_LINK_INTF_CLK>,
+ <&clock_mmss MMSS_MDSS_DP_CRYPTO_CLK>,
+ <&clock_mmss MMSS_MDSS_DP_PIXEL_CLK>,
+ <&clock_mmss DP_PIXEL_CLK_SRC>,
+ <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>;
+ clock-names = "core_mnoc_clk", "core_iface_clk", "core_bus_clk",
+ "core_mdp_core_clk", "core_alt_iface_clk",
+ "core_aux_clk", "core_ref_clk_src", "core_ref_clk",
+ "core_ahb_phy_clk", "ctrl_link_clk",
+ "ctrl_link_iface_clk", "ctrl_crypto_clk",
+ "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent";
+
+ qcom,dp-usbpd-detection = <&pm660_pdphy>;
+
qcom,msm_ext_disp = <&msm_ext_disp>;
+ qcom,aux-cfg-settings = [00 13 00 00 0a 28 0a 03 b7 03];
+ qcom,logical2physical-lane-map = [00 01 02 03];
+ qcom,phy-register-offset = <0x4>;
+ qcom,max-pclk-frequency-khz = <150000>;
+
qcom,core-supply-entries {
#address-cells = <1>;
#size-cells = <0>;
@@ -432,9 +464,9 @@
qcom,ctrl-supply-entry@0 {
reg = <0>;
- qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1200000>;
- qcom,supply-max-voltage = <1250000>;
+ qcom,supply-name = "vdda-1p8";
+ qcom,supply-min-voltage = <1780000>;
+ qcom,supply-max-voltage = <1950000>;
qcom,supply-enable-load = <12560>;
qcom,supply-disable-load = <4>;
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index be36f1b8a6cb..0619d62526b1 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -164,6 +164,15 @@
qcom,platform-te-gpio = <&tlmm 59 0>;
};
+&mdss_dp_ctrl {
+ pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+ pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>;
+ pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>;
+ qcom,aux-en-gpio = <&tlmm 55 0>;
+ qcom,aux-sel-gpio = <&tlmm 56 0>;
+ qcom,usbplug-cc-gpio = <&tlmm 58 0>;
+};
+
&pm660l_wled {
qcom,led-strings-list = [01 02];
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index 8763f57f5ae8..cb083c0a8aa0 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -285,7 +285,43 @@
};
};
+&tlmm {
+ pmx_ts_rst_active {
+ ts_rst_active: ts_rst_active {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ pmx_ts_rst_suspend {
+ ts_rst_suspend: ts_rst_suspend {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+};
+
&soc {
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
+
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
@@ -310,4 +346,22 @@
};
};
+
+ hbtp {
+ compatible = "qcom,hbtp-input";
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+ pinctrl-0 = <&ts_rst_active>;
+ pinctrl-1 = <&ts_rst_suspend>;
+ vcc_ana-supply = <&pm660l_l3>;
+ vcc_dig-supply = <&pm660_l13>;
+ qcom,afe-load = <20000>;
+ qcom,afe-vtg-min = <3008000>;
+ qcom,afe-vtg-max = <3008000>;
+ qcom,dig-load = <40000>;
+ qcom,dig-vtg-min = <1808000>;
+ qcom,dig-vtg-max = <1808000>;
+ qcom,fb-resume-delay-us = <10000>;
+ qcom,afe-power-on-delay-us = <1000>;
+ qcom,afe-power-off-delay-us = <6>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index cd895a067f65..b3175fed4dcc 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 {
@@ -364,13 +376,17 @@
linux,cma-default;
};
+ cont_splash_mem: splash_region@9d400000 {
+ reg = <0x0 0x9d400000 0x0 0x02400000>;
+ label = "cont_splash_mem";
+ };
};
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";
@@ -722,7 +738,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 +1757,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 +1801,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 +2240,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 10afca1c56ed..14b009656890 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -392,10 +392,12 @@
<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
480000000 540000000 576000000>;
+ qcom,micro-reset;
qcom,cpp-fw-payload-info {
qcom,stripe-base = <790>;
qcom,plane-base = <715>;
@@ -576,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 {
@@ -656,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-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
index a9de658a064d..6ea151667abc 100644
--- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
@@ -170,7 +170,7 @@
clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
<&clock_gcc GCC_CFG_NOC_USB3_AXI_CLK>,
<&clock_gcc GCC_AGGRE2_USB3_AXI_CLK>,
- <&clock_rpmcc RPM_AGGR2_NOC_CLK>,
+ <&clock_rpmcc AGGR2_NOC_USB_CLK>,
<&clock_gcc GCC_USB30_MOCK_UTMI_CLK>,
<&clock_gcc GCC_USB30_SLEEP_CLK>,
<&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
@@ -467,10 +467,10 @@
qcom,devfreq,freq-table = <50000000 200000000>;
qcom,pm-qos-irq-type = "affine_irq";
- qcom,pm-qos-irq-latency = <43 377>;
+ qcom,pm-qos-irq-latency = <43 518>;
qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
- qcom,pm-qos-cmdq-latency-us = <43 377>, <40 325>;
- qcom,pm-qos-legacy-latency-us = <43 377>, <40 325>;
+ qcom,pm-qos-cmdq-latency-us = <43 518>, <40 518>;
+ qcom,pm-qos-legacy-latency-us = <43 518>, <40 518>;
qcom,msm-bus,name = "sdhc1";
qcom,msm-bus,num-cases = <9>;
@@ -565,9 +565,9 @@
qcom,devfreq,freq-table = <50000000 200000000>;
qcom,pm-qos-irq-type = "affine_irq";
- qcom,pm-qos-irq-latency = <43 377>;
+ qcom,pm-qos-irq-latency = <43 518>;
qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
- qcom,pm-qos-legacy-latency-us = <43 377>, <40 325>;
+ qcom,pm-qos-legacy-latency-us = <43 518>, <40 518>;
clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
<&clock_gcc GCC_SDCC2_APPS_CLK>;
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 65741e0df3ba..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>;
@@ -245,10 +252,13 @@
qcom,parallel-charger;
qcom,float-voltage-mv = <4400>;
qcom,recharge-mv = <100>;
- qcom,parallel-en-pin-polarity = <0>;
+ qcom,parallel-en-pin-polarity = <1>;
};
};
+/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..d3b7ec7c4f2b 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
@@ -655,6 +658,7 @@ CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LIST=y
+CONFIG_RCU_STALL_WATCHDOG_BITE=y
CONFIG_FAULT_INJECTION=y
CONFIG_FAIL_PAGE_ALLOC=y
CONFIG_UFS_FAULT_INJECTION=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/kernel/perf_trace_counters.h b/arch/arm64/kernel/perf_trace_counters.h
index d686e928e5df..ff3bd371791d 100644
--- a/arch/arm64/kernel/perf_trace_counters.h
+++ b/arch/arm64/kernel/perf_trace_counters.h
@@ -22,8 +22,10 @@
#define C1 0x2
#define C2 0x4
#define C3 0x8
-#define C_ALL (CC | C0 | C1 | C2 | C3)
-#define NUM_L1_CTRS 4
+#define C4 0x10
+#define C5 0x20
+#define C_ALL (CC | C0 | C1 | C2 | C3 | C4 | C5)
+#define NUM_L1_CTRS 6
#include <linux/sched.h>
#include <linux/cpumask.h>
@@ -46,8 +48,8 @@ TRACE_EVENT(sched_switch_with_ctrs,
__field(u32, ctr1)
__field(u32, ctr2)
__field(u32, ctr3)
- __field(u32, lctr0)
- __field(u32, lctr1)
+ __field(u32, ctr4)
+ __field(u32, ctr5)
),
TP_fast_assign(
@@ -91,15 +93,15 @@ TRACE_EVENT(sched_switch_with_ctrs,
__entry->ctr1 = delta_l1_cnts[1];
__entry->ctr2 = delta_l1_cnts[2];
__entry->ctr3 = delta_l1_cnts[3];
- __entry->lctr0 = 0;
- __entry->lctr1 = 0;
+ __entry->ctr4 = delta_l1_cnts[4];
+ __entry->ctr5 = delta_l1_cnts[5];
),
- TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u, CTR1: %u, CTR2: %u, CTR3: %u, L2CTR0: %u, L2CTR1: %u",
+ TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u, CTR1: %u, CTR2: %u, CTR3: %u, CTR4: %u, CTR5: %u",
__entry->old_pid, __entry->new_pid,
__entry->cctr, __entry->ctr0, __entry->ctr1,
__entry->ctr2, __entry->ctr3,
- __entry->lctr0, __entry->lctr1)
+ __entry->ctr4, __entry->ctr5)
);
#endif
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/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index 1e24c79c3f0a..950244f1e4e8 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -33,6 +33,7 @@
/* ctrl registers */
#define QPNP_WLED_FAULT_STATUS(b) (b + 0x08)
+#define QPNP_WLED_INT_RT_STS(b) (b + 0x10)
#define QPNP_WLED_EN_REG(b) (b + 0x46)
#define QPNP_WLED_FDBK_OP_REG(b) (b + 0x48)
#define QPNP_WLED_VREF_REG(b) (b + 0x49)
@@ -44,6 +45,7 @@
#define QPNP_WLED_SOFTSTART_RAMP_DLY(b) (b + 0x53)
#define QPNP_WLED_VLOOP_COMP_RES_REG(b) (b + 0x55)
#define QPNP_WLED_VLOOP_COMP_GM_REG(b) (b + 0x56)
+#define QPNP_WLED_EN_PSM_REG(b) (b + 0x5A)
#define QPNP_WLED_PSM_CTRL_REG(b) (b + 0x5B)
#define QPNP_WLED_LCD_AUTO_PFM_REG(b) (b + 0x5C)
#define QPNP_WLED_SC_PRO_REG(b) (b + 0x5E)
@@ -82,12 +84,13 @@
#define QPNP_WLED_VREF_PSM_MIN_MV 400
#define QPNP_WLED_VREF_PSM_MAX_MV 750
#define QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV 450
-#define QPNP_WLED_PSM_CTRL_OVERWRITE 0x80
+#define QPNP_WLED_PSM_OVERWRITE_BIT BIT(7)
#define QPNP_WLED_LCD_AUTO_PFM_DFLT_THRESH 1
#define QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX 0xF
#define QPNP_WLED_LCD_AUTO_PFM_EN_SHIFT 7
#define QPNP_WLED_LCD_AUTO_PFM_EN_BIT BIT(7)
#define QPNP_WLED_LCD_AUTO_PFM_THRESH_MASK GENMASK(3, 0)
+#define QPNP_WLED_EN_PSM_BIT BIT(7)
#define QPNP_WLED_ILIM_MASK GENMASK(2, 0)
#define QPNP_WLED_ILIM_OVERWRITE BIT(7)
@@ -117,6 +120,9 @@
QPNP_WLED_TEST4_EN_CLAMP_BIT | \
QPNP_WLED_TEST4_EN_SOFT_START_BIT)
#define QPNP_WLED_TEST4_EN_IIND_UP 0x1
+#define QPNP_WLED_ILIM_FAULT_BIT BIT(0)
+#define QPNP_WLED_OVP_FAULT_BIT BIT(1)
+#define QPNP_WLED_SC_FAULT_BIT BIT(2)
/* sink registers */
#define QPNP_WLED_CURR_SINK_REG(b) (b + 0x46)
@@ -335,6 +341,7 @@ static struct wled_vref_setting vref_setting_pmi8998 = {
* @ lcd_auto_pfm_thresh - the threshold for lcd auto pfm mode
* @ loop_auto_gm_en - select if auto gm is enabled
* @ lcd_auto_pfm_en - select if auto pfm is enabled in lcd mode
+ * @ lcd_psm_ctrl - select if psm needs to be controlled in lcd mode
* @ avdd_mode_spmi - enable avdd programming via spmi
* @ en_9b_dim_res - enable or disable 9bit dimming
* @ en_phase_stag - enable or disable phase staggering
@@ -380,6 +387,7 @@ struct qpnp_wled {
u8 lcd_auto_pfm_thresh;
bool loop_auto_gm_en;
bool lcd_auto_pfm_en;
+ bool lcd_psm_ctrl;
bool avdd_mode_spmi;
bool en_9b_dim_res;
bool en_phase_stag;
@@ -549,6 +557,30 @@ static int qpnp_wled_set_level(struct qpnp_wled *wled, int level)
return 0;
}
+static int qpnp_wled_psm_config(struct qpnp_wled *wled, bool enable)
+{
+ int rc;
+
+ if (!wled->lcd_psm_ctrl)
+ return 0;
+
+ rc = qpnp_wled_masked_write_reg(wled,
+ QPNP_WLED_EN_PSM_REG(wled->ctrl_base),
+ QPNP_WLED_EN_PSM_BIT,
+ enable ? QPNP_WLED_EN_PSM_BIT : 0);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_wled_masked_write_reg(wled,
+ QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base),
+ QPNP_WLED_PSM_OVERWRITE_BIT,
+ enable ? QPNP_WLED_PSM_OVERWRITE_BIT : 0);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
static int qpnp_wled_module_en(struct qpnp_wled *wled,
u16 base_addr, bool state)
{
@@ -561,21 +593,31 @@ static int qpnp_wled_module_en(struct qpnp_wled *wled,
if (rc < 0)
return rc;
- if (wled->ovp_irq > 0) {
- if (state && wled->ovp_irq_disabled) {
- /*
- * Wait for at least 10ms before enabling OVP fault
- * interrupt after enabling the module so that soft
- * start is completed. Keep OVP interrupt disabled
- * when the module is disabled.
- */
- usleep_range(10000, 11000);
+ /*
+ * Wait for at least 10ms before enabling OVP fault interrupt after
+ * enabling the module so that soft start is completed. Also, this
+ * delay can be used to control PSM during enable when required. Keep
+ * OVP interrupt disabled when the module is disabled.
+ */
+ if (state) {
+ usleep_range(10000, 11000);
+ rc = qpnp_wled_psm_config(wled, false);
+ if (rc < 0)
+ return rc;
+
+ if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
enable_irq(wled->ovp_irq);
wled->ovp_irq_disabled = false;
- } else if (!state && !wled->ovp_irq_disabled) {
+ }
+ } else {
+ if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
disable_irq(wled->ovp_irq);
wled->ovp_irq_disabled = true;
}
+
+ rc = qpnp_wled_psm_config(wled, true);
+ if (rc < 0)
+ return rc;
}
return 0;
@@ -990,7 +1032,7 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
reg &= QPNP_WLED_VREF_PSM_MASK;
reg |= ((wled->vref_psm_mv - QPNP_WLED_VREF_PSM_MIN_MV)/
QPNP_WLED_VREF_PSM_STEP_MV);
- reg |= QPNP_WLED_PSM_CTRL_OVERWRITE;
+ reg |= QPNP_WLED_PSM_OVERWRITE_BIT;
rc = qpnp_wled_write_reg(wled,
QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base), reg);
if (rc)
@@ -1053,16 +1095,25 @@ static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
{
struct qpnp_wled *wled = _wled;
int rc;
- u8 val;
+ u8 fault_sts, int_sts;
rc = qpnp_wled_read_reg(wled,
- QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &val);
+ QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
+ if (rc < 0) {
+ pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_wled_read_reg(wled,
+ QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_sts);
if (rc < 0) {
pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
return IRQ_HANDLED;
}
- pr_err("WLED OVP fault detected, fault_status= %x\n", val);
+ if (fault_sts & (QPNP_WLED_OVP_FAULT_BIT | QPNP_WLED_ILIM_FAULT_BIT))
+ pr_err("WLED OVP fault detected, int_sts=%x fault_sts= %x\n",
+ int_sts, fault_sts);
return IRQ_HANDLED;
}
@@ -1677,6 +1728,8 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
wled->ovp_irq, rc);
return rc;
}
+ disable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = true;
}
if (wled->sc_irq >= 0) {
@@ -2063,6 +2116,8 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
wled->en_ext_pfet_sc_pro = of_property_read_bool(pdev->dev.of_node,
"qcom,en-ext-pfet-sc-pro");
+ wled->lcd_psm_ctrl = of_property_read_bool(pdev->dev.of_node,
+ "qcom,lcd-psm-ctrl");
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index dfa544df5c7c..5dbed80f5b85 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -1282,6 +1282,7 @@ static int msm_isp_deinit_isp_buf_mgr(
int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
unsigned int cmd, void *arg)
{
+ int rc = -EINVAL;
switch (cmd) {
case VIDIOC_MSM_ISP_REQUEST_BUF: {
struct msm_isp_buf_request *buf_req = arg;
@@ -1290,7 +1291,7 @@ int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
memcpy(&buf_req_ver2, buf_req,
sizeof(struct msm_isp_buf_request));
buf_req_ver2.security_mode = NON_SECURE_MODE;
- buf_mgr->ops->request_buf(buf_mgr, &buf_req_ver2);
+ rc = buf_mgr->ops->request_buf(buf_mgr, &buf_req_ver2);
memcpy(buf_req, &buf_req_ver2,
sizeof(struct msm_isp_buf_request));
break;
@@ -1298,35 +1299,35 @@ int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
case VIDIOC_MSM_ISP_REQUEST_BUF_VER2: {
struct msm_isp_buf_request_ver2 *buf_req_ver2 = arg;
- buf_mgr->ops->request_buf(buf_mgr, buf_req_ver2);
+ rc = buf_mgr->ops->request_buf(buf_mgr, buf_req_ver2);
break;
}
case VIDIOC_MSM_ISP_ENQUEUE_BUF: {
struct msm_isp_qbuf_info *qbuf_info = arg;
- buf_mgr->ops->enqueue_buf(buf_mgr, qbuf_info);
+ rc = buf_mgr->ops->enqueue_buf(buf_mgr, qbuf_info);
break;
}
case VIDIOC_MSM_ISP_DEQUEUE_BUF: {
struct msm_isp_qbuf_info *qbuf_info = arg;
- buf_mgr->ops->dequeue_buf(buf_mgr, qbuf_info);
+ rc = buf_mgr->ops->dequeue_buf(buf_mgr, qbuf_info);
break;
}
case VIDIOC_MSM_ISP_RELEASE_BUF: {
struct msm_isp_buf_request *buf_req = arg;
- buf_mgr->ops->release_buf(buf_mgr, buf_req->handle);
+ rc = buf_mgr->ops->release_buf(buf_mgr, buf_req->handle);
break;
}
case VIDIOC_MSM_ISP_UNMAP_BUF: {
struct msm_isp_unmap_buf_req *unmap_req = arg;
- buf_mgr->ops->unmap_buf(buf_mgr, unmap_req->fd);
+ rc = buf_mgr->ops->unmap_buf(buf_mgr, unmap_req->fd);
break;
}
}
- return 0;
+ return rc;
}
static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
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/card/block.c b/drivers/mmc/card/block.c
index fb5ffde61e8b..ce0ecd1e9b7a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3544,7 +3544,7 @@ void mmc_blk_cmdq_complete_rq(struct request *rq)
else if (mrq->data && mrq->data->error)
err = mrq->data->error;
- if (err || cmdq_req->resp_err) {
+ if ((err || cmdq_req->resp_err) && !cmdq_req->skip_err_handling) {
pr_err("%s: %s: txfr error(%d)/resp_err(%d)\n",
mmc_hostname(mrq->host), __func__, err,
cmdq_req->resp_err);
@@ -3581,6 +3581,17 @@ void mmc_blk_cmdq_complete_rq(struct request *rq)
blk_end_request_all(rq, err);
goto out;
}
+ /*
+ * In case of error, cmdq_req->data.bytes_xfered is set to 0.
+ * If we call blk_end_request() with nr_bytes as 0 then the request
+ * never gets completed. So in case of error, to complete a request
+ * with error we should use blk_end_request_all().
+ */
+ if (err && cmdq_req->skip_err_handling) {
+ cmdq_req->skip_err_handling = false;
+ blk_end_request_all(rq, err);
+ goto out;
+ }
blk_end_request(rq, err, cmdq_req->data.bytes_xfered);
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 96d4fbf1a823..a83960fd474f 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -145,6 +145,29 @@ static void cmdq_clear_set_irqs(struct cmdq_host *cq_host, u32 clear, u32 set)
mb();
}
+static int cmdq_clear_task_poll(struct cmdq_host *cq_host, unsigned int tag)
+{
+ int retries = 100;
+
+ cmdq_clear_set_irqs(cq_host, CQIS_TCL, 0);
+ cmdq_writel(cq_host, 1<<tag, CQTCLR);
+ while (retries) {
+ /*
+ * Task Clear register and doorbell,
+ * both should indicate that task is cleared
+ */
+ if ((cmdq_readl(cq_host, CQTCLR) & 1<<tag) ||
+ (cmdq_readl(cq_host, CQTDBR) & 1<<tag)) {
+ udelay(5);
+ retries--;
+ continue;
+ } else
+ break;
+ }
+
+ cmdq_clear_set_irqs(cq_host, 0, CQIS_TCL);
+ return retries ? 0 : -ETIMEDOUT;
+}
#define DRV_NAME "cmdq-host"
@@ -829,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;
@@ -842,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);
@@ -857,6 +889,8 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
struct mmc_request *mrq;
int ret;
u32 dbr_set = 0;
+ u32 dev_pend_set = 0;
+ int stat_err = 0;
status = cmdq_readl(cq_host, CQIS);
@@ -865,7 +899,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n",
__func__, status, err);
- if (err || (status & CQIS_RED)) {
+ stat_err = status & (CQIS_RED | CQIS_GCE | CQIS_ICCE);
+
+ if (err || stat_err) {
err_info = cmdq_readl(cq_host, CQTERRI);
pr_err("%s: err: %d status: 0x%08x task-err-info (0x%08lx)\n",
mmc_hostname(mmc), err, status, err_info);
@@ -968,7 +1004,7 @@ skip_cqterri:
* CQE detected a reponse error from device
* In most cases, this would require a reset.
*/
- if (status & CQIS_RED) {
+ if (stat_err & CQIS_RED) {
/*
* will check if the RED error is due to a bkops
* exception once the queue is empty
@@ -987,6 +1023,62 @@ skip_cqterri:
mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA);
}
+ /*
+ * Generic Crypto error detected by CQE.
+ * Its a fatal, would require cmdq reset.
+ */
+ if (stat_err & CQIS_GCE) {
+ if (mrq->data)
+ mrq->data->error = -EIO;
+ pr_err("%s: Crypto generic error while processing task %lu!",
+ mmc_hostname(mmc), tag);
+ MMC_TRACE(mmc, "%s: GCE error detected with tag %lu\n",
+ __func__, tag);
+ }
+ /*
+ * Invalid crypto config error detected by CQE, clear the task.
+ * Task can be cleared only when CQE is halt state.
+ */
+ if (stat_err & CQIS_ICCE) {
+ /*
+ * Invalid Crypto Config Error is detected at the
+ * beginning of the transfer before the actual execution
+ * started. So just clear the task in CQE. No need to
+ * clear in device. Only the task which caused ICCE has
+ * to be cleared. Other tasks can be continue processing
+ * The first task which is about to be prepared would
+ * cause ICCE Error.
+ */
+ dbr_set = cmdq_readl(cq_host, CQTDBR);
+ dev_pend_set = cmdq_readl(cq_host, CQDPT);
+ if (dbr_set ^ dev_pend_set)
+ tag = ffs(dbr_set ^ dev_pend_set) - 1;
+ mrq = get_req_by_tag(cq_host, tag);
+ pr_err("%s: Crypto config error while processing task %lu!",
+ mmc_hostname(mmc), tag);
+ MMC_TRACE(mmc, "%s: ICCE error with tag %lu\n",
+ __func__, tag);
+ if (mrq->data)
+ mrq->data->error = -EIO;
+ else if (mrq->cmd)
+ mrq->cmd->error = -EIO;
+ /*
+ * If CQE is halted and tag is valid then clear the task
+ * then un-halt CQE and set flag to skip error recovery.
+ * If any of the condtions is not met thene it will
+ * enter into default error recovery path.
+ */
+ if (!ret && (dbr_set ^ dev_pend_set)) {
+ ret = cmdq_clear_task_poll(cq_host, tag);
+ if (ret) {
+ pr_err("%s: %s: task[%lu] clear failed ret=%d\n",
+ mmc_hostname(mmc),
+ __func__, tag, ret);
+ } else if (!cmdq_halt_poll(mmc, false)) {
+ mrq->cmdq_req->skip_err_handling = true;
+ }
+ }
+ }
cmdq_finish_data(mmc, tag);
} else {
cmdq_writel(cq_host, status, CQIS);
@@ -1052,6 +1144,7 @@ static int cmdq_halt_poll(struct mmc_host *mmc, bool halt)
cq_host->ops->clear_set_irqs(mmc, true);
cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT,
CQCTL);
+ mmc_host_clr_halt(mmc);
return 0;
}
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index 6c10ab3859d1..ee5e6549fa4a 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -37,6 +37,8 @@
#define CQIS_TCC (1 << 1)
#define CQIS_RED (1 << 2)
#define CQIS_TCL (1 << 3)
+#define CQIS_GCE (1 << 4)
+#define CQIS_ICCE (1 << 5)
/* interrupt status enable */
#define CQISTE 0x14
@@ -112,7 +114,7 @@
/* command response argument */
#define CQCRA 0x5C
-#define CQ_INT_ALL 0xF
+#define CQ_INT_ALL 0x3F
#define CQIC_DEFAULT_ICCTH 31
#define CQIC_DEFAULT_ICTOVAL 1
@@ -221,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/ethernet/msm/msm_rmnet_mhi.c b/drivers/net/ethernet/msm/msm_rmnet_mhi.c
index 4285a8d8a65f..9117ea7d08c0 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_mhi.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_mhi.c
@@ -26,18 +26,16 @@
#include <linux/ipc_logging.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/of_device.h>
#define RMNET_MHI_DRIVER_NAME "rmnet_mhi"
#define RMNET_MHI_DEV_NAME "rmnet_mhi%d"
#define MHI_DEFAULT_MTU 8000
-#define MHI_DEFAULT_MRU 8000
#define MHI_MAX_MRU 0xFFFF
#define MHI_NAPI_WEIGHT_VALUE 12
#define MHI_RX_HEADROOM 64
#define WATCHDOG_TIMEOUT (30 * HZ)
-#define MHI_RMNET_DEVICE_COUNT 1
#define RMNET_IPC_LOG_PAGES (100)
-#define IS_INBOUND(_chan) (((u32)(_chan)) % 2)
enum DBG_LVL {
MSG_VERBOSE = 0x1,
@@ -49,88 +47,38 @@ enum DBG_LVL {
MSG_reserved = 0x80000000
};
+struct debug_params {
+ enum DBG_LVL rmnet_msg_lvl;
+ enum DBG_LVL rmnet_ipc_log_lvl;
+ u64 tx_interrupts_count;
+ u64 rx_interrupts_count;
+ u64 tx_ring_full_count;
+ u64 tx_queued_packets_count;
+ u64 rx_interrupts_in_masked_irq;
+ u64 rx_napi_skb_burst_min;
+ u64 rx_napi_skb_burst_max;
+ u64 tx_cb_skb_free_burst_min;
+ u64 tx_cb_skb_free_burst_max;
+ u64 rx_napi_budget_overflow;
+ u64 rx_fragmentation;
+};
+
struct __packed mhi_skb_priv {
dma_addr_t dma_addr;
size_t dma_size;
};
-enum DBG_LVL rmnet_msg_lvl = MSG_CRITICAL;
-
-#ifdef CONFIG_MSM_MHI_DEBUG
-enum DBG_LVL rmnet_ipc_log_lvl = MSG_VERBOSE;
-#else
-enum DBG_LVL rmnet_ipc_log_lvl = MSG_ERROR;
-#endif
-
-module_param(rmnet_msg_lvl , uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rmnet_msg_lvl, "dbg lvl");
-module_param(rmnet_ipc_log_lvl, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rmnet_ipc_log_lvl, "dbg lvl");
-
-unsigned int mru = MHI_DEFAULT_MRU;
-module_param(mru, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(mru, "MRU interface setting");
-
-void *rmnet_ipc_log;
-
-#define rmnet_log(_msg_lvl, _msg, ...) do { \
- if ((_msg_lvl) >= rmnet_msg_lvl) \
+#define rmnet_log(rmnet_mhi_ptr, _msg_lvl, _msg, ...) do { \
+ if ((_msg_lvl) >= rmnet_mhi_ptr->debug.rmnet_msg_lvl) \
pr_alert("[%s] " _msg, __func__, ##__VA_ARGS__);\
- if (rmnet_ipc_log && ((_msg_lvl) >= rmnet_ipc_log_lvl)) \
- ipc_log_string(rmnet_ipc_log, \
+ if (rmnet_mhi_ptr->rmnet_ipc_log && \
+ ((_msg_lvl) >= rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl)) \
+ ipc_log_string(rmnet_mhi_ptr->rmnet_ipc_log, \
"[%s] " _msg, __func__, ##__VA_ARGS__); \
} while (0)
-unsigned long tx_interrupts_count[MHI_RMNET_DEVICE_COUNT];
-module_param_array(tx_interrupts_count, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(tx_interrupts_count, "Tx interrupts");
-
-unsigned long rx_interrupts_count[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_interrupts_count, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_interrupts_count, "RX interrupts");
-
-unsigned long tx_ring_full_count[MHI_RMNET_DEVICE_COUNT];
-module_param_array(tx_ring_full_count, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(tx_ring_full_count, "RING FULL errors from MHI Core");
-
-
-unsigned long tx_queued_packets_count[MHI_RMNET_DEVICE_COUNT];
-module_param_array(tx_queued_packets_count, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(tx_queued_packets_count, "TX packets queued in MHI core");
-
-unsigned long rx_interrupts_in_masked_irq[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_interrupts_in_masked_irq, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_interrupts_in_masked_irq,
- "RX interrupts while IRQs are masked");
-
-unsigned long rx_napi_skb_burst_min[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_napi_skb_burst_min, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_napi_skb_burst_min, "MIN SKBs sent to NS during NAPI");
-
-unsigned long rx_napi_skb_burst_max[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_napi_skb_burst_max, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_napi_skb_burst_max, "MAX SKBs sent to NS during NAPI");
-
-unsigned long tx_cb_skb_free_burst_min[MHI_RMNET_DEVICE_COUNT];
-module_param_array(tx_cb_skb_free_burst_min, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(tx_cb_skb_free_burst_min, "MIN SKBs freed during TX CB");
-
-unsigned long tx_cb_skb_free_burst_max[MHI_RMNET_DEVICE_COUNT];
-module_param_array(tx_cb_skb_free_burst_max, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(tx_cb_skb_free_burst_max, "MAX SKBs freed during TX CB");
-
-unsigned long rx_napi_budget_overflow[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_napi_budget_overflow, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_napi_budget_overflow,
- "Budget hit with more items to read counter");
-
-unsigned long rx_fragmentation[MHI_RMNET_DEVICE_COUNT];
-module_param_array(rx_fragmentation, ulong, 0, S_IRUGO);
-MODULE_PARM_DESC(rx_fragmentation,
- "Number of fragmented packets received");
-
struct rmnet_mhi_private {
- int dev_index;
+ struct list_head node;
struct mhi_client_handle *tx_client_handle;
struct mhi_client_handle *rx_client_handle;
enum MHI_CLIENT_CHANNEL tx_channel;
@@ -138,7 +86,7 @@ struct rmnet_mhi_private {
struct sk_buff_head tx_buffers;
struct sk_buff_head rx_buffers;
atomic_t rx_pool_len;
- uint32_t mru;
+ u32 mru;
struct napi_struct napi;
gfp_t allocation_flags;
uint32_t tx_buffers_max;
@@ -147,6 +95,7 @@ struct rmnet_mhi_private {
u32 tx_enabled;
u32 rx_enabled;
u32 mhi_enabled;
+ struct platform_device *pdev;
struct net_device *dev;
atomic_t irq_masked_cntr;
spinlock_t out_chan_full_lock; /* tx queue lock */
@@ -155,9 +104,12 @@ struct rmnet_mhi_private {
struct work_struct alloc_work;
/* lock to queue hardware and internal queue */
spinlock_t alloc_lock;
+ void *rmnet_ipc_log;
+ struct debug_params debug;
+ struct dentry *dentry;
};
-static struct rmnet_mhi_private rmnet_mhi_ctxt_list[MHI_RMNET_DEVICE_COUNT];
+static LIST_HEAD(rmnet_mhi_ctxt_list);
static int rmnet_mhi_process_fragment(struct rmnet_mhi_private *rmnet_mhi_ptr,
struct sk_buff *skb, int frag)
@@ -189,7 +141,7 @@ static int rmnet_mhi_process_fragment(struct rmnet_mhi_private *rmnet_mhi_ptr,
if (frag) {
/* This is the first fragment */
rmnet_mhi_ptr->frag_skb = skb;
- rx_fragmentation[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.rx_fragmentation++;
} else {
netif_receive_skb(skb);
}
@@ -201,8 +153,10 @@ static void rmnet_mhi_internal_clean_unmap_buffers(struct net_device *dev,
enum dma_data_direction dir)
{
struct mhi_skb_priv *skb_priv;
+ struct rmnet_mhi_private *rmnet_mhi_ptr =
+ *(struct rmnet_mhi_private **)netdev_priv(dev);
- rmnet_log(MSG_INFO, "Entered\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n");
while (!skb_queue_empty(queue)) {
struct sk_buff *skb = skb_dequeue(queue);
skb_priv = (struct mhi_skb_priv *)(skb->cb);
@@ -210,7 +164,7 @@ static void rmnet_mhi_internal_clean_unmap_buffers(struct net_device *dev,
kfree_skb(skb);
}
}
- rmnet_log(MSG_INFO, "Exited\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited\n");
}
static __be16 rmnet_mhi_ip_type_trans(struct sk_buff *skb)
@@ -246,7 +200,8 @@ static int rmnet_alloc_rx(struct rmnet_mhi_private *rmnet_mhi_ptr,
rmnet_mhi_ptr->rx_buffers_max) {
skb = alloc_skb(cur_mru, alloc_flags);
if (!skb) {
- rmnet_log(MSG_INFO,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
"SKB Alloc failed with flags:0x%x\n",
alloc_flags);
return -ENOMEM;
@@ -278,7 +233,8 @@ static int rmnet_alloc_rx(struct rmnet_mhi_private *rmnet_mhi_ptr,
skb_priv->dma_size,
MHI_EOT);
if (unlikely(ret != 0)) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
"mhi_queue_xfer failed, error %d", ret);
spin_unlock_irqrestore(&rmnet_mhi_ptr->alloc_lock,
flags);
@@ -300,11 +256,12 @@ static void rmnet_mhi_alloc_work(struct work_struct *work)
alloc_work);
int ret;
- rmnet_log(MSG_INFO, "Entered\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n");
ret = rmnet_alloc_rx(rmnet_mhi_ptr,
rmnet_mhi_ptr->allocation_flags);
+
WARN_ON(ret == -ENOMEM);
- rmnet_log(MSG_INFO, "Exit\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exit\n");
}
static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
@@ -319,18 +276,20 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
struct mhi_skb_priv *skb_priv;
int r;
- rmnet_log(MSG_VERBOSE, "Entered\n");
- rmnet_mhi_ptr->mru = mru;
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n");
+
while (received_packets < budget) {
struct mhi_result *result =
mhi_poll(rmnet_mhi_ptr->rx_client_handle);
if (result->transaction_status == -ENOTCONN) {
- rmnet_log(MSG_INFO,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
"Transaction status not ready, continuing\n");
break;
} else if (result->transaction_status != 0 &&
result->transaction_status != -EOVERFLOW) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
"mhi_poll failed, error %d\n",
result->transaction_status);
break;
@@ -345,7 +304,8 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
atomic_dec(&rmnet_mhi_ptr->rx_pool_len);
skb = skb_dequeue(&(rmnet_mhi_ptr->rx_buffers));
if (unlikely(!skb)) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
"No RX buffers to match");
break;
}
@@ -363,7 +323,7 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
else
r = rmnet_mhi_process_fragment(rmnet_mhi_ptr, skb, 0);
if (r) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr, MSG_CRITICAL,
"Failed to process fragmented packet ret %d",
r);
BUG();
@@ -379,7 +339,9 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
/* Queue new buffers */
res = rmnet_alloc_rx(rmnet_mhi_ptr, GFP_ATOMIC);
if (res == -ENOMEM) {
- rmnet_log(MSG_INFO, "out of mem, queuing bg worker\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "out of mem, queuing bg worker\n");
rmnet_mhi_ptr->alloc_fail++;
schedule_work(&rmnet_mhi_ptr->alloc_work);
}
@@ -391,22 +353,24 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget)
if (atomic_read(&rmnet_mhi_ptr->irq_masked_cntr)) {
atomic_dec(&rmnet_mhi_ptr->irq_masked_cntr);
mhi_unmask_irq(rmnet_mhi_ptr->rx_client_handle);
+ mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, true);
}
} else {
if (received_packets == budget)
- rx_napi_budget_overflow[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.rx_napi_budget_overflow++;
napi_reschedule(napi);
}
- rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index] =
- min((unsigned long)received_packets,
- rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index]);
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_min =
+ min((u64)received_packets,
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_min);
- rx_napi_skb_burst_max[rmnet_mhi_ptr->dev_index] =
- max((unsigned long)received_packets,
- rx_napi_skb_burst_max[rmnet_mhi_ptr->dev_index]);
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_max =
+ max((u64)received_packets,
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_max);
- rmnet_log(MSG_VERBOSE, "Exited, polled %d pkts\n", received_packets);
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE,
+ "Exited, polled %d pkts\n", received_packets);
return received_packets;
}
@@ -414,7 +378,8 @@ void rmnet_mhi_clean_buffers(struct net_device *dev)
{
struct rmnet_mhi_private *rmnet_mhi_ptr =
*(struct rmnet_mhi_private **)netdev_priv(dev);
- rmnet_log(MSG_INFO, "Entered\n");
+
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n");
/* Clean TX buffers */
rmnet_mhi_internal_clean_unmap_buffers(dev,
&rmnet_mhi_ptr->tx_buffers,
@@ -424,16 +389,16 @@ void rmnet_mhi_clean_buffers(struct net_device *dev)
rmnet_mhi_internal_clean_unmap_buffers(dev,
&rmnet_mhi_ptr->rx_buffers,
DMA_FROM_DEVICE);
- rmnet_log(MSG_INFO, "Exited\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited\n");
}
static int rmnet_mhi_disable_channels(struct rmnet_mhi_private *rmnet_mhi_ptr)
{
- rmnet_log(MSG_INFO, "Closing MHI TX channel\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Closing MHI TX channel\n");
mhi_close_channel(rmnet_mhi_ptr->tx_client_handle);
- rmnet_log(MSG_INFO, "Closing MHI RX channel\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Closing MHI RX channel\n");
mhi_close_channel(rmnet_mhi_ptr->rx_client_handle);
- rmnet_log(MSG_INFO, "Clearing Pending TX buffers.\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Clearing Pending TX buffers.\n");
rmnet_mhi_clean_buffers(rmnet_mhi_ptr->dev);
rmnet_mhi_ptr->tx_client_handle = NULL;
rmnet_mhi_ptr->rx_client_handle = NULL;
@@ -445,7 +410,7 @@ static int rmnet_mhi_init_inbound(struct rmnet_mhi_private *rmnet_mhi_ptr)
{
int res;
- rmnet_log(MSG_INFO, "Entered\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n");
rmnet_mhi_ptr->tx_buffers_max = mhi_get_max_desc(
rmnet_mhi_ptr->tx_client_handle);
rmnet_mhi_ptr->rx_buffers_max = mhi_get_max_desc(
@@ -454,7 +419,7 @@ static int rmnet_mhi_init_inbound(struct rmnet_mhi_private *rmnet_mhi_ptr)
res = rmnet_alloc_rx(rmnet_mhi_ptr,
rmnet_mhi_ptr->allocation_flags);
- rmnet_log(MSG_INFO, "Exited with %d\n", res);
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited with %d\n", res);
return res;
}
@@ -467,9 +432,9 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result)
rmnet_mhi_ptr = result->user_data;
dev = rmnet_mhi_ptr->dev;
- tx_interrupts_count[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.tx_interrupts_count++;
- rmnet_log(MSG_VERBOSE, "Entered\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n");
if (!result->buf_addr || !result->bytes_xferd)
return;
/* Free the buffers which are TX'd up to the provided address */
@@ -477,7 +442,8 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result)
struct sk_buff *skb =
skb_dequeue(&(rmnet_mhi_ptr->tx_buffers));
if (!skb) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
"NULL buffer returned, error");
break;
} else {
@@ -498,20 +464,21 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result)
*/
}
} /* While TX queue is not empty */
- tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index] =
- min(burst_counter,
- tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index]);
- tx_cb_skb_free_burst_max[rmnet_mhi_ptr->dev_index] =
- max(burst_counter,
- tx_cb_skb_free_burst_max[rmnet_mhi_ptr->dev_index]);
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min =
+ min((u64)burst_counter,
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min);
+
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max =
+ max((u64)burst_counter,
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max);
/* In case we couldn't write again, now we can! */
spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, flags);
- rmnet_log(MSG_VERBOSE, "Waking up queue\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Waking up queue\n");
netif_wake_queue(dev);
spin_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags);
- rmnet_log(MSG_VERBOSE, "Exited\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n");
}
static void rmnet_mhi_rx_cb(struct mhi_result *result)
@@ -521,17 +488,18 @@ static void rmnet_mhi_rx_cb(struct mhi_result *result)
rmnet_mhi_ptr = result->user_data;
dev = rmnet_mhi_ptr->dev;
- rmnet_log(MSG_VERBOSE, "Entered\n");
- rx_interrupts_count[rmnet_mhi_ptr->dev_index]++;
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n");
+ rmnet_mhi_ptr->debug.rx_interrupts_count++;
if (napi_schedule_prep(&(rmnet_mhi_ptr->napi))) {
mhi_mask_irq(rmnet_mhi_ptr->rx_client_handle);
atomic_inc(&rmnet_mhi_ptr->irq_masked_cntr);
+ mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, false);
__napi_schedule(&(rmnet_mhi_ptr->napi));
} else {
- rx_interrupts_in_masked_irq[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq++;
}
- rmnet_log(MSG_VERBOSE, "Exited\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n");
}
static int rmnet_mhi_open(struct net_device *dev)
@@ -539,11 +507,19 @@ static int rmnet_mhi_open(struct net_device *dev)
struct rmnet_mhi_private *rmnet_mhi_ptr =
*(struct rmnet_mhi_private **)netdev_priv(dev);
- rmnet_log(MSG_INFO,
- "Opened net dev interface for MHI chans %d and %d\n",
- rmnet_mhi_ptr->tx_channel,
- rmnet_mhi_ptr->rx_channel);
- netif_start_queue(dev);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "Opened net dev interface for MHI chans %d and %d\n",
+ rmnet_mhi_ptr->tx_channel,
+ rmnet_mhi_ptr->rx_channel);
+
+ /* tx queue may not necessarily be stopped already
+ * so stop the queue if tx path is not enabled
+ */
+ if (!rmnet_mhi_ptr->tx_client_handle)
+ netif_stop_queue(dev);
+ else
+ netif_start_queue(dev);
/* Poll to check if any buffers are accumulated in the
* transport buffers
@@ -551,9 +527,10 @@ static int rmnet_mhi_open(struct net_device *dev)
if (napi_schedule_prep(&(rmnet_mhi_ptr->napi))) {
mhi_mask_irq(rmnet_mhi_ptr->rx_client_handle);
atomic_inc(&rmnet_mhi_ptr->irq_masked_cntr);
+ mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, false);
__napi_schedule(&(rmnet_mhi_ptr->napi));
} else {
- rx_interrupts_in_masked_irq[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq++;
}
return 0;
@@ -591,14 +568,17 @@ static int rmnet_mhi_stop(struct net_device *dev)
{
struct rmnet_mhi_private *rmnet_mhi_ptr =
*(struct rmnet_mhi_private **)netdev_priv(dev);
+
netif_stop_queue(dev);
- rmnet_log(MSG_VERBOSE, "Entered\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n");
if (atomic_read(&rmnet_mhi_ptr->irq_masked_cntr)) {
mhi_unmask_irq(rmnet_mhi_ptr->rx_client_handle);
atomic_dec(&rmnet_mhi_ptr->irq_masked_cntr);
- rmnet_log(MSG_ERROR, "IRQ was masked, unmasking...\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_ERROR,
+ "IRQ was masked, unmasking...\n");
}
- rmnet_log(MSG_VERBOSE, "Exited\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n");
return 0;
}
@@ -619,17 +599,22 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
struct mhi_skb_priv *tx_priv;
- rmnet_log(MSG_VERBOSE, "Entered chan %d\n", rmnet_mhi_ptr->tx_channel);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_VERBOSE,
+ "Entered chan %d\n",
+ rmnet_mhi_ptr->tx_channel);
tx_priv = (struct mhi_skb_priv *)(skb->cb);
tx_priv->dma_size = skb->len;
tx_priv->dma_addr = 0;
if (mhi_get_free_desc(rmnet_mhi_ptr->tx_client_handle) <= 0) {
- rmnet_log(MSG_VERBOSE, "Stopping Queue\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_VERBOSE,
+ "Stopping Queue\n");
spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock,
flags);
- tx_ring_full_count[rmnet_mhi_ptr->dev_index]++;
+ rmnet_mhi_ptr->debug.tx_ring_full_count++;
netif_stop_queue(dev);
spin_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock,
flags);
@@ -641,7 +626,9 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev)
MHI_EOT);
if (res != 0) {
- rmnet_log(MSG_CRITICAL, "Failed to queue with reason:%d\n",
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Failed to queue with reason:%d\n",
res);
spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock,
flags);
@@ -652,12 +639,10 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev)
}
skb_queue_tail(&(rmnet_mhi_ptr->tx_buffers), skb);
-
dev->trans_start = jiffies;
+ rmnet_mhi_ptr->debug.tx_queued_packets_count++;
- tx_queued_packets_count[rmnet_mhi_ptr->dev_index]++;
- rmnet_log(MSG_VERBOSE, "Exited\n");
-
+ rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n");
return NETDEV_TX_OK;
}
@@ -673,24 +658,27 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
sizeof(struct rmnet_ioctl_extended_s));
if (rc) {
- rmnet_log(MSG_CRITICAL,
- "copy_from_user failed ,error %d", rc);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "copy_from_user failed ,error %d",
+ rc);
return rc;
}
switch (ext_cmd.extended_ioctl) {
case RMNET_IOCTL_SET_MRU:
- if ((0 > ext_cmd.u.data) || (ext_cmd.u.data > MHI_MAX_MRU)) {
- rmnet_log(MSG_CRITICAL,
- "Can't set MRU, value %u is invalid\n",
- ext_cmd.u.data);
+ if (!ext_cmd.u.data || ext_cmd.u.data > MHI_MAX_MRU) {
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Can't set MRU, value %u is invalid\n",
+ ext_cmd.u.data);
return -EINVAL;
}
- rmnet_log(MSG_INFO,
- "MRU change request to 0x%x\n",
- ext_cmd.u.data);
- mru = ext_cmd.u.data;
- rmnet_mhi_ptr->mru = mru;
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "MRU change request to 0x%x\n",
+ ext_cmd.u.data);
+ rmnet_mhi_ptr->mru = ext_cmd.u.data;
break;
case RMNET_IOCTL_GET_EPID:
ext_cmd.u.data =
@@ -709,7 +697,8 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
mhi_set_lpm(rmnet_mhi_ptr->tx_client_handle,
ext_cmd.u.data);
} else {
- rmnet_log(MSG_ERROR,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_ERROR,
"Cannot set LPM value, MHI is not up.\n");
return -ENODEV;
}
@@ -723,9 +712,10 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
sizeof(struct rmnet_ioctl_extended_s));
if (rc)
- rmnet_log(MSG_CRITICAL,
- "copy_to_user failed, error %d\n",
- rc);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "copy_to_user failed, error %d\n",
+ rc);
return rc;
}
@@ -804,50 +794,49 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
struct rmnet_mhi_private **rmnet_mhi_ctxt = NULL;
int r = 0;
- memset(tx_interrupts_count, 0, sizeof(tx_interrupts_count));
- memset(rx_interrupts_count, 0, sizeof(rx_interrupts_count));
- memset(rx_interrupts_in_masked_irq, 0,
- sizeof(rx_interrupts_in_masked_irq));
- memset(rx_napi_skb_burst_min, 0, sizeof(rx_napi_skb_burst_min));
- memset(rx_napi_skb_burst_max, 0, sizeof(rx_napi_skb_burst_max));
- memset(tx_cb_skb_free_burst_min, 0, sizeof(tx_cb_skb_free_burst_min));
- memset(tx_cb_skb_free_burst_max, 0, sizeof(tx_cb_skb_free_burst_max));
- memset(tx_ring_full_count, 0, sizeof(tx_ring_full_count));
- memset(tx_queued_packets_count, 0, sizeof(tx_queued_packets_count));
- memset(rx_napi_budget_overflow, 0, sizeof(rx_napi_budget_overflow));
-
- rmnet_log(MSG_INFO, "Entered.\n");
-
- if (rmnet_mhi_ptr == NULL) {
- rmnet_log(MSG_CRITICAL, "Bad input args.\n");
- return -EINVAL;
- }
-
- rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index] = UINT_MAX;
- tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index] = UINT_MAX;
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered.\n");
+
+ rmnet_mhi_ptr->debug.tx_interrupts_count = 0;
+ rmnet_mhi_ptr->debug.rx_interrupts_count = 0;
+ rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq = 0;
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_min = 0;
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_max = 0;
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min = 0;
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max = 0;
+ rmnet_mhi_ptr->debug.tx_ring_full_count = 0;
+ rmnet_mhi_ptr->debug.tx_queued_packets_count = 0;
+ rmnet_mhi_ptr->debug.rx_napi_budget_overflow = 0;
+ rmnet_mhi_ptr->debug.rx_napi_skb_burst_min = UINT_MAX;
+ rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min = UINT_MAX;
skb_queue_head_init(&(rmnet_mhi_ptr->tx_buffers));
skb_queue_head_init(&(rmnet_mhi_ptr->rx_buffers));
if (rmnet_mhi_ptr->tx_client_handle != NULL) {
- rmnet_log(MSG_INFO,
- "Opening TX channel\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "Opening TX channel\n");
r = mhi_open_channel(rmnet_mhi_ptr->tx_client_handle);
if (r != 0) {
- rmnet_log(MSG_CRITICAL,
- "Failed to start TX chan ret %d\n", r);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Failed to start TX chan ret %d\n",
+ r);
goto mhi_tx_chan_start_fail;
} else {
rmnet_mhi_ptr->tx_enabled = 1;
}
}
if (rmnet_mhi_ptr->rx_client_handle != NULL) {
- rmnet_log(MSG_INFO,
- "Opening RX channel\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "Opening RX channel\n");
r = mhi_open_channel(rmnet_mhi_ptr->rx_client_handle);
if (r != 0) {
- rmnet_log(MSG_CRITICAL,
- "Failed to start RX chan ret %d\n", r);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Failed to start RX chan ret %d\n",
+ r);
goto mhi_rx_chan_start_fail;
} else {
rmnet_mhi_ptr->rx_enabled = 1;
@@ -858,11 +847,13 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
RMNET_MHI_DEV_NAME,
NET_NAME_PREDICTABLE, rmnet_mhi_setup);
if (!rmnet_mhi_ptr->dev) {
- rmnet_log(MSG_CRITICAL, "Network device allocation failed\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Network device allocation failed\n");
ret = -ENOMEM;
goto net_dev_alloc_fail;
}
-
+ SET_NETDEV_DEV(rmnet_mhi_ptr->dev, &rmnet_mhi_ptr->pdev->dev);
rmnet_mhi_ctxt = netdev_priv(rmnet_mhi_ptr->dev);
*rmnet_mhi_ctxt = rmnet_mhi_ptr;
@@ -875,8 +866,10 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
r = rmnet_mhi_init_inbound(rmnet_mhi_ptr);
if (r) {
- rmnet_log(MSG_CRITICAL,
- "Failed to init inbound ret %d\n", r);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Failed to init inbound ret %d\n",
+ r);
}
netif_napi_add(rmnet_mhi_ptr->dev, &(rmnet_mhi_ptr->napi),
@@ -885,13 +878,14 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
rmnet_mhi_ptr->mhi_enabled = 1;
ret = register_netdev(rmnet_mhi_ptr->dev);
if (ret) {
- rmnet_log(MSG_CRITICAL,
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
"Network device registration failed\n");
goto net_dev_reg_fail;
}
napi_enable(&(rmnet_mhi_ptr->napi));
- rmnet_log(MSG_INFO, "Exited.\n");
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited.\n");
return 0;
@@ -904,7 +898,7 @@ net_dev_alloc_fail:
mhi_rx_chan_start_fail:
mhi_close_channel(rmnet_mhi_ptr->tx_client_handle);
mhi_tx_chan_start_fail:
- rmnet_log(MSG_INFO, "Exited ret %d.\n", ret);
+ rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited ret %d.\n", ret);
return ret;
}
@@ -914,52 +908,60 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info)
struct mhi_result *result;
int r = 0;
- if (NULL != cb_info && NULL != cb_info->result) {
- result = cb_info->result;
- rmnet_mhi_ptr = result->user_data;
- } else {
- rmnet_log(MSG_CRITICAL,
- "Invalid data in MHI callback, quitting\n");
+ if (!cb_info || !cb_info->result) {
+ pr_err("%s: Invalid data in MHI callback\n", __func__);
return;
}
+ result = cb_info->result;
+ rmnet_mhi_ptr = result->user_data;
+
switch (cb_info->cb_reason) {
case MHI_CB_MHI_DISABLED:
- rmnet_log(MSG_CRITICAL,
- "Got MHI_DISABLED notification. Stopping stack\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Got MHI_DISABLED notification. Stopping stack\n");
if (rmnet_mhi_ptr->mhi_enabled) {
rmnet_mhi_ptr->mhi_enabled = 0;
/* Ensure MHI is disabled before other mem ops */
wmb();
while (atomic_read(&rmnet_mhi_ptr->pending_data)) {
- rmnet_log(MSG_CRITICAL,
- "Waiting for channels to stop.\n");
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Waiting for channels to stop.\n");
msleep(25);
}
rmnet_mhi_disable(rmnet_mhi_ptr);
}
break;
case MHI_CB_MHI_ENABLED:
- rmnet_log(MSG_CRITICAL,
- "Got MHI_ENABLED notification. Starting stack\n");
- if (IS_INBOUND(cb_info->chan))
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Got MHI_ENABLED notification. Starting stack\n");
+ if (cb_info->chan == rmnet_mhi_ptr->rx_channel)
rmnet_mhi_ptr->rx_enabled = 1;
else
rmnet_mhi_ptr->tx_enabled = 1;
- if (rmnet_mhi_ptr->tx_enabled &&
- rmnet_mhi_ptr->rx_enabled) {
- rmnet_log(MSG_INFO,
- "Both RX/TX are enabled, enabling iface.\n");
+ if ((rmnet_mhi_ptr->tx_enabled && rmnet_mhi_ptr->rx_enabled) ||
+ (rmnet_mhi_ptr->tx_enabled &&
+ !rmnet_mhi_ptr->rx_client_handle) ||
+ (rmnet_mhi_ptr->rx_enabled &&
+ !rmnet_mhi_ptr->tx_client_handle)) {
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "enabling iface.\n");
r = rmnet_mhi_enable_iface(rmnet_mhi_ptr);
if (r)
- rmnet_log(MSG_CRITICAL,
- "Failed to enable iface for chan %d\n",
- cb_info->chan);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "Failed to enable iface for chan %d\n",
+ cb_info->chan);
else
- rmnet_log(MSG_INFO,
- "Enabled iface for chan %d\n",
- cb_info->chan);
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_INFO,
+ "Enabled iface for chan %d\n",
+ cb_info->chan);
}
break;
case MHI_CB_XFER:
@@ -967,7 +969,7 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info)
/* Flush pending data is set before any other mem operations */
wmb();
if (rmnet_mhi_ptr->mhi_enabled) {
- if (IS_INBOUND(cb_info->chan))
+ if (cb_info->chan == rmnet_mhi_ptr->rx_channel)
rmnet_mhi_rx_cb(cb_info->result);
else
rmnet_mhi_tx_cb(cb_info->result);
@@ -981,67 +983,261 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info)
static struct mhi_client_info_t rmnet_mhi_info = {rmnet_mhi_cb};
-static int __init rmnet_mhi_init(void)
+#ifdef CONFIG_DEBUG_FS
+struct dentry *dentry;
+
+static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr)
{
+ char node_name[15];
int i;
- int res = 0;
- struct rmnet_mhi_private *rmnet_mhi_ptr = 0;
- rmnet_ipc_log = ipc_log_context_create(RMNET_IPC_LOG_PAGES,
- "mhi_rmnet", 0);
-
- for (i = 0; i < MHI_RMNET_DEVICE_COUNT; i++) {
- rmnet_mhi_ptr = &rmnet_mhi_ctxt_list[i];
-
- rmnet_mhi_ptr->tx_channel = MHI_CLIENT_IP_HW_0_OUT +
- (enum MHI_CLIENT_CHANNEL)(i * 2);
- rmnet_mhi_ptr->rx_channel = MHI_CLIENT_IP_HW_0_IN +
- (enum MHI_CLIENT_CHANNEL)((i * 2));
-
- rmnet_mhi_ptr->tx_client_handle = 0;
- rmnet_mhi_ptr->rx_client_handle = 0;
- spin_lock_init(&rmnet_mhi_ptr->out_chan_full_lock);
-
- rmnet_mhi_ptr->mru = MHI_DEFAULT_MRU;
- rmnet_mhi_ptr->dev_index = i;
-
- res = mhi_register_channel(
- &(rmnet_mhi_ptr->tx_client_handle),
- rmnet_mhi_ptr->tx_channel, 0,
- &rmnet_mhi_info, rmnet_mhi_ptr);
-
- if (0 != res) {
- rmnet_mhi_ptr->tx_client_handle = 0;
- rmnet_log(MSG_CRITICAL,
- "mhi_register_channel failed chan %d ret %d\n",
- rmnet_mhi_ptr->tx_channel, res);
+ const umode_t mode = (S_IRUSR | S_IWUSR);
+ struct dentry *file;
+
+ const struct {
+ char *name;
+ u64 *ptr;
+ } debugfs_table[] = {
+ {
+ "tx_interrupts_count",
+ &rmnet_mhi_ptr->debug.tx_interrupts_count
+ },
+ {
+ "rx_interrupts_count",
+ &rmnet_mhi_ptr->debug.rx_interrupts_count
+ },
+ {
+ "tx_ring_full_count",
+ &rmnet_mhi_ptr->debug.tx_ring_full_count
+ },
+ {
+ "tx_queued_packets_count",
+ &rmnet_mhi_ptr->debug.tx_queued_packets_count
+ },
+ {
+ "rx_interrupts_in_masked_irq",
+ &rmnet_mhi_ptr->
+ debug.rx_interrupts_in_masked_irq
+ },
+ {
+ "rx_napi_skb_burst_min",
+ &rmnet_mhi_ptr->debug.rx_napi_skb_burst_min
+ },
+ {
+ "rx_napi_skb_burst_max",
+ &rmnet_mhi_ptr->debug.rx_napi_skb_burst_max
+ },
+ {
+ "tx_cb_skb_free_burst_min",
+ &rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min
+ },
+ {
+ "tx_cb_skb_free_burst_max",
+ &rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max
+ },
+ {
+ "rx_napi_budget_overflow",
+ &rmnet_mhi_ptr->debug.rx_napi_budget_overflow
+ },
+ {
+ "rx_fragmentation",
+ &rmnet_mhi_ptr->debug.rx_fragmentation
+ },
+ {
+ NULL, NULL
+ },
+ };
+
+ snprintf(node_name, sizeof(node_name), "%s%d",
+ RMNET_MHI_DRIVER_NAME, rmnet_mhi_ptr->pdev->id);
+
+ if (IS_ERR_OR_NULL(dentry))
+ return;
+
+ rmnet_mhi_ptr->dentry = debugfs_create_dir(node_name, dentry);
+ if (IS_ERR_OR_NULL(rmnet_mhi_ptr->dentry))
+ return;
+
+ file = debugfs_create_u32("msg_lvl",
+ mode,
+ rmnet_mhi_ptr->dentry,
+ (u32 *)&rmnet_mhi_ptr->debug.rmnet_msg_lvl);
+ if (IS_ERR_OR_NULL(file))
+ return;
+
+ file = debugfs_create_u32("ipc_log_lvl",
+ mode,
+ rmnet_mhi_ptr->dentry,
+ (u32 *)&rmnet_mhi_ptr->
+ debug.rmnet_ipc_log_lvl);
+ if (IS_ERR_OR_NULL(file))
+ return;
+
+ file = debugfs_create_u32("mru",
+ mode,
+ rmnet_mhi_ptr->dentry,
+ &rmnet_mhi_ptr->mru);
+ if (IS_ERR_OR_NULL(file))
+ return;
+
+ /* Add debug stats table */
+ for (i = 0; debugfs_table[i].name; i++) {
+ file = debugfs_create_u64(debugfs_table[i].name,
+ mode,
+ rmnet_mhi_ptr->dentry,
+ debugfs_table[i].ptr);
+ if (IS_ERR_OR_NULL(file))
+ return;
+ }
+}
+
+static void rmnet_mhi_create_debugfs_dir(void)
+{
+ dentry = debugfs_create_dir(RMNET_MHI_DRIVER_NAME, 0);
+}
+#else
+static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr)
+{
+}
+
+static void rmnet_mhi_create_debugfs_dir(void)
+{
+}
+#endif
+
+static int rmnet_mhi_probe(struct platform_device *pdev)
+{
+ int rc;
+ u32 channel;
+ struct rmnet_mhi_private *rmnet_mhi_ptr;
+ char node_name[15];
+
+ if (unlikely(!pdev->dev.of_node))
+ return -ENODEV;
+
+ pdev->id = of_alias_get_id(pdev->dev.of_node, "mhi_rmnet");
+ if (unlikely(pdev->id < 0))
+ return -ENODEV;
+
+ rmnet_mhi_ptr = kzalloc(sizeof(*rmnet_mhi_ptr), GFP_KERNEL);
+ if (unlikely(!rmnet_mhi_ptr))
+ return -ENOMEM;
+ rmnet_mhi_ptr->pdev = pdev;
+ spin_lock_init(&rmnet_mhi_ptr->out_chan_full_lock);
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mhi-mru",
+ &rmnet_mhi_ptr->mru);
+ if (unlikely(rc)) {
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "failed to get valid mru\n");
+ goto probe_fail;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mhi-tx-channel",
+ &channel);
+ if (rc == 0) {
+ rmnet_mhi_ptr->tx_channel = channel;
+ rc = mhi_register_channel(&rmnet_mhi_ptr->tx_client_handle,
+ rmnet_mhi_ptr->tx_channel,
+ 0,
+ &rmnet_mhi_info,
+ rmnet_mhi_ptr);
+ if (unlikely(rc)) {
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "mhi_register_channel failed chan %d ret %d\n",
+ rmnet_mhi_ptr->tx_channel,
+ rc);
+ goto probe_fail;
}
- res = mhi_register_channel(
- &(rmnet_mhi_ptr->rx_client_handle),
- rmnet_mhi_ptr->rx_channel, 0,
- &rmnet_mhi_info, rmnet_mhi_ptr);
-
- if (0 != res) {
- rmnet_mhi_ptr->rx_client_handle = 0;
- rmnet_log(MSG_CRITICAL,
- "mhi_register_channel failed chan %d, ret %d\n",
- rmnet_mhi_ptr->rx_channel, res);
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mhi-rx-channel",
+ &channel);
+ if (rc == 0) {
+ rmnet_mhi_ptr->rx_channel = channel;
+ rc = mhi_register_channel(&rmnet_mhi_ptr->rx_client_handle,
+ rmnet_mhi_ptr->rx_channel,
+ 0,
+ &rmnet_mhi_info,
+ rmnet_mhi_ptr);
+ if (unlikely(rc)) {
+ rmnet_log(rmnet_mhi_ptr,
+ MSG_CRITICAL,
+ "mhi_register_channel failed chan %d ret %d\n",
+ rmnet_mhi_ptr->rx_channel,
+ rc);
+ goto probe_fail;
}
INIT_WORK(&rmnet_mhi_ptr->alloc_work, rmnet_mhi_alloc_work);
spin_lock_init(&rmnet_mhi_ptr->alloc_lock);
}
+
+ /* We must've have @ least one valid channel */
+ if (!rmnet_mhi_ptr->rx_client_handle &&
+ !rmnet_mhi_ptr->tx_client_handle) {
+ rmnet_log(rmnet_mhi_ptr, MSG_CRITICAL,
+ "No registered channels\n");
+ rc = -ENODEV;
+ goto probe_fail;
+ }
+
+ snprintf(node_name, sizeof(node_name), "%s%d",
+ RMNET_MHI_DRIVER_NAME, pdev->id);
+ rmnet_mhi_ptr->rmnet_ipc_log =
+ ipc_log_context_create(RMNET_IPC_LOG_PAGES,
+ node_name, 0);
+ rmnet_mhi_ptr->debug.rmnet_msg_lvl = MSG_CRITICAL;
+
+#ifdef CONFIG_MSM_MHI_DEBUG
+ rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl = MSG_VERBOSE;
+#else
+ rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl = MSG_ERROR;
+#endif
+
+ rmnet_mhi_create_debugfs(rmnet_mhi_ptr);
+ list_add_tail(&rmnet_mhi_ptr->node, &rmnet_mhi_ctxt_list);
return 0;
+
+probe_fail:
+ kfree(rmnet_mhi_ptr);
+ return rc;
+}
+
+static const struct of_device_id msm_mhi_match_table[] = {
+ {.compatible = "qcom,mhi-rmnet"},
+ {},
+};
+
+static struct platform_driver rmnet_mhi_driver = {
+ .probe = rmnet_mhi_probe,
+ .driver = {
+ .name = RMNET_MHI_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_mhi_match_table,
+ },
+};
+
+static int __init rmnet_mhi_init(void)
+{
+ rmnet_mhi_create_debugfs_dir();
+
+ return platform_driver_register(&rmnet_mhi_driver);
}
static void __exit rmnet_mhi_exit(void)
{
struct rmnet_mhi_private *rmnet_mhi_ptr = 0;
- int index = 0;
- for (index = 0; index < MHI_RMNET_DEVICE_COUNT; index++) {
- rmnet_mhi_ptr = &rmnet_mhi_ctxt_list[index];
- mhi_deregister_channel(rmnet_mhi_ptr->tx_client_handle);
- mhi_deregister_channel(rmnet_mhi_ptr->rx_client_handle);
+ list_for_each_entry(rmnet_mhi_ptr, &rmnet_mhi_ctxt_list, node) {
+ if (rmnet_mhi_ptr->tx_client_handle)
+ mhi_deregister_channel(rmnet_mhi_ptr->tx_client_handle);
+ if (rmnet_mhi_ptr->rx_client_handle)
+ mhi_deregister_channel(rmnet_mhi_ptr->rx_client_handle);
}
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index b8ef3780c2ac..b8a3a1ecabaa 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -64,7 +64,8 @@ static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->dst_wr_index_addr, n);
}
static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
@@ -72,8 +73,8 @@ static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- return ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- DST_WR_INDEX_ADDRESS);
+ return ar_opaque->bus_ops->read32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->dst_wr_index_addr);
}
static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
@@ -82,7 +83,8 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr, n);
}
static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
@@ -90,8 +92,8 @@ static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- return ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- SR_WR_INDEX_ADDRESS);
+ return ar_opaque->bus_ops->read32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr);
}
static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
@@ -99,8 +101,8 @@ static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- return ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- CURRENT_SRRI_ADDRESS);
+ return ar_opaque->bus_ops->read32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->current_srri_addr);
}
static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar,
@@ -130,7 +132,8 @@ static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->sr_base_addr, addr);
}
static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
@@ -139,7 +142,8 @@ static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->sr_size_addr, n);
}
static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
@@ -147,12 +151,14 @@ static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+
u32 ctrl1_addr = ar_opaque->bus_ops->read32((ar),
- (ce_ctrl_addr) + CE_CTRL1_ADDRESS);
+ (ce_ctrl_addr) + ctrl_regs->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) |
- CE_CTRL1_DMAX_LENGTH_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dmax->mask)) |
+ ctrl_regs->dmax->set(n, ctrl_regs->dmax));
}
static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
@@ -160,12 +166,14 @@ static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+
u32 ctrl1_addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- CE_CTRL1_ADDRESS);
+ ctrl_regs->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) |
+ ctrl_regs->src_ring->set(n, ctrl_regs->src_ring));
}
static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
@@ -173,12 +181,14 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+
u32 ctrl1_addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- CE_CTRL1_ADDRESS);
+ ctrl_regs->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) |
+ ctrl_regs->dst_ring->set(n, ctrl_regs->dst_ring));
}
static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
@@ -186,8 +196,8 @@ static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- return ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- CURRENT_DRRI_ADDRESS);
+ return ar_opaque->bus_ops->read32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->current_drri_addr);
}
static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
@@ -196,7 +206,8 @@ static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->dr_base_addr, addr);
}
static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
@@ -205,7 +216,8 @@ static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->dr_size_addr, n);
}
static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
@@ -213,13 +225,12 @@ static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + srcr_wm->addr);
- u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- SRC_WATERMARK_ADDRESS);
-
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_HIGH_MASK) |
- SRC_WATERMARK_HIGH_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_high->mask)) |
+ (srcr_wm->wm_high->set(n, srcr_wm->wm_high)));
}
static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
@@ -227,12 +238,12 @@ static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- SRC_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + srcr_wm->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_LOW_MASK) |
- SRC_WATERMARK_LOW_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_low->mask)) |
+ (srcr_wm->wm_low->set(n, srcr_wm->wm_low)));
}
static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
@@ -240,12 +251,12 @@ static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_HIGH_MASK) |
- DST_WATERMARK_HIGH_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_high->mask)) |
+ (dstr_wm->wm_high->set(n, dstr_wm->wm_high)));
}
static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
@@ -253,67 +264,82 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
unsigned int n)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr +
- DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_LOW_MASK) |
- DST_WATERMARK_LOW_SET(n));
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_low->mask)) |
+ (dstr_wm->wm_low->set(n, dstr_wm->wm_low)));
}
static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+
u32 host_ie_addr = ar_opaque->bus_ops->read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr | HOST_IE_COPY_COMPLETE_MASK);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr | host_ie->copy_complete->mask);
}
static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+
u32 host_ie_addr = ar_opaque->bus_ops->read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(host_ie->copy_complete->mask));
}
static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
+
u32 host_ie_addr = ar_opaque->bus_ops->read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~CE_WATERMARK_MASK);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(wm_regs->wm_mask));
}
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+
u32 misc_ie_addr = ar_opaque->bus_ops->read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr | CE_ERROR_MASK);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr | misc_regs->err_mask);
}
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+
u32 misc_ie_addr = ar_opaque->bus_ops->read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr);
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr & ~CE_ERROR_MASK);
+ ar_opaque->bus_ops->write32(ar,
+ ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr & ~(misc_regs->err_mask));
}
static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
@@ -321,8 +347,9 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
unsigned int mask)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
- ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
+ ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
}
u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr)
@@ -391,6 +418,21 @@ u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr)
return addr;
}
+static inline void ath10k_ce_snoc_addr_config(struct ce_desc *sdesc,
+ dma_addr_t buffer,
+ unsigned int flags)
+{
+ __le32 *addr = (__le32 *)&sdesc->addr;
+
+ flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK;
+ addr[0] = __cpu_to_le32(buffer);
+ addr[1] = flags;
+ if (flags & CE_SEND_FLAG_GATHER)
+ addr[1] |= CE_WCN3990_DESC_FLAGS_GATHER;
+ else
+ addr[1] &= ~CE_WCN3990_DESC_FLAGS_GATHER;
+}
+
/*
* Guts of ath10k_ce_send, used by both ath10k_ce_send and
* ath10k_ce_sendlist_send.
@@ -434,17 +476,10 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
if (flags & CE_SEND_FLAG_BYTE_SWAP)
desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
- if (QCA_REV_WCN3990(ar)) {
- flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK;
- sdesc.addr_lo = __cpu_to_le32(buffer);
- sdesc.addr_hi = flags;
- if (flags & CE_SEND_FLAG_GATHER)
- sdesc.addr_hi |= CE_WCN3990_DESC_FLAGS_GATHER;
- else
- sdesc.addr_hi &= ~CE_WCN3990_DESC_FLAGS_GATHER;
- } else {
+ if (QCA_REV_WCN3990(ar))
+ ath10k_ce_snoc_addr_config(&sdesc, buffer, flags);
+ else
sdesc.addr = __cpu_to_le32(buffer);
- }
sdesc.nbytes = __cpu_to_le16(nbytes);
sdesc.flags = __cpu_to_le16(desc_flags);
@@ -866,13 +901,14 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id];
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 ctrl_addr = ce_state->ctrl_addr;
spin_lock_bh(&ar_opaque->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */
ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
- HOST_IS_COPY_COMPLETE_MASK);
+ wm_regs->cc_mask);
spin_unlock_bh(&ar_opaque->ce_lock);
@@ -888,7 +924,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
* Misc CE interrupts are not being handled, but still need
* to be cleared.
*/
- ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
+ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
spin_unlock_bh(&ar_opaque->ce_lock);
}
@@ -983,7 +1019,7 @@ void ath10k_ce_enable_per_ce_interrupts(struct ath10k *ar, unsigned int ce_id)
u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- offset = HOST_IE_ADDRESS + ctrl_addr;
+ offset = ar->hw_ce_regs->host_ie_addr + ctrl_addr;
ar_opaque->bus_ops->write32(ar, offset, 1);
ar_opaque->bus_ops->read32(ar, offset);
}
@@ -994,7 +1030,7 @@ void ath10k_ce_disable_per_ce_interrupts(struct ath10k *ar, unsigned int ce_id)
u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
struct bus_opaque *ar_opaque = ath10k_bus_priv(ar);
- offset = HOST_IE_ADDRESS + ctrl_addr;
+ offset = ar->hw_ce_regs->host_ie_addr + ctrl_addr;
ar_opaque->bus_ops->write32(ar, offset, 0);
ar_opaque->bus_ops->read32(ar, offset);
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index f4fa86b93082..936f0698c0f0 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -58,13 +58,7 @@ struct ce_desc {
};
#else
struct ce_desc {
- union {
- __le64 addr;
- struct {
- __le32 addr_lo;
- __le32 addr_hi;
- };
- };
+ __le64 addr;
u16 nbytes; /* length in register map */
u16 flags; /* fw_metadata_high */
u32 toeplitz_hash_result;
@@ -362,311 +356,6 @@ struct ce_attr {
void (*recv_cb)(struct ath10k_ce_pipe *);
};
-#ifndef CONFIG_ATH10K_SNOC
-#define SR_BA_ADDRESS 0x0000
-#define SR_SIZE_ADDRESS 0x0004
-#define DR_BA_ADDRESS 0x0008
-#define DR_SIZE_ADDRESS 0x000c
-#define CE_CMD_ADDRESS 0x0018
-
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
- (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_DMAX_LENGTH_MSB 15
-#define CE_CTRL1_DMAX_LENGTH_LSB 0
-#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff
-#define CE_CTRL1_DMAX_LENGTH_GET(x) \
- (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
-#define CE_CTRL1_DMAX_LENGTH_SET(x) \
- (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
-
-#define CE_CTRL1_ADDRESS 0x0010
-#define CE_CTRL1_HW_MASK 0x0007ffff
-#define CE_CTRL1_SW_MASK 0x0007ffff
-#define CE_CTRL1_HW_WRITE_MASK 0x00000000
-#define CE_CTRL1_SW_WRITE_MASK 0x0007ffff
-#define CE_CTRL1_RSTMASK 0xffffffff
-#define CE_CTRL1_RESET 0x00000080
-
-#define CE_CMD_HALT_STATUS_MSB 3
-#define CE_CMD_HALT_STATUS_LSB 3
-#define CE_CMD_HALT_STATUS_MASK 0x00000008
-#define CE_CMD_HALT_STATUS_GET(x) \
- (((x) & CE_CMD_HALT_STATUS_MASK) >> CE_CMD_HALT_STATUS_LSB)
-#define CE_CMD_HALT_STATUS_SET(x) \
- (((0 | (x)) << CE_CMD_HALT_STATUS_LSB) & CE_CMD_HALT_STATUS_MASK)
-#define CE_CMD_HALT_STATUS_RESET 0
-#define CE_CMD_HALT_MSB 0
-#define CE_CMD_HALT_MASK 0x00000001
-
-#define HOST_IE_COPY_COMPLETE_MSB 0
-#define HOST_IE_COPY_COMPLETE_LSB 0
-#define HOST_IE_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IE_COPY_COMPLETE_GET(x) \
- (((x) & HOST_IE_COPY_COMPLETE_MASK) >> HOST_IE_COPY_COMPLETE_LSB)
-#define HOST_IE_COPY_COMPLETE_SET(x) \
- (((0 | (x)) << HOST_IE_COPY_COMPLETE_LSB) & HOST_IE_COPY_COMPLETE_MASK)
-#define HOST_IE_COPY_COMPLETE_RESET 0
-#define HOST_IE_ADDRESS 0x002c
-
-#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
-#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
-#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
-#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
-#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IS_ADDRESS 0x0030
-
-#define MISC_IE_ADDRESS 0x0034
-
-#define MISC_IS_AXI_ERR_MASK 0x00000400
-
-#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
-#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
-#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
-#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
-#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
-
-#define MISC_IS_ADDRESS 0x0038
-
-#define SR_WR_INDEX_ADDRESS 0x003c
-
-#define DST_WR_INDEX_ADDRESS 0x0040
-
-#define CURRENT_SRRI_ADDRESS 0x0044
-
-#define CURRENT_DRRI_ADDRESS 0x0048
-
-#define SRC_WATERMARK_LOW_MSB 31
-#define SRC_WATERMARK_LOW_LSB 16
-#define SRC_WATERMARK_LOW_MASK 0xffff0000
-#define SRC_WATERMARK_LOW_GET(x) \
- (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
-#define SRC_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
-#define SRC_WATERMARK_LOW_RESET 0
-#define SRC_WATERMARK_HIGH_MSB 15
-#define SRC_WATERMARK_HIGH_LSB 0
-#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
-#define SRC_WATERMARK_HIGH_GET(x) \
- (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
-#define SRC_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
-#define SRC_WATERMARK_HIGH_RESET 0
-#define SRC_WATERMARK_ADDRESS 0x004c
-
-#define DST_WATERMARK_LOW_LSB 16
-#define DST_WATERMARK_LOW_MASK 0xffff0000
-#define DST_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
-#define DST_WATERMARK_LOW_RESET 0
-#define DST_WATERMARK_HIGH_MSB 15
-#define DST_WATERMARK_HIGH_LSB 0
-#define DST_WATERMARK_HIGH_MASK 0x0000ffff
-#define DST_WATERMARK_HIGH_GET(x) \
- (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
-#define DST_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
-#define DST_WATERMARK_HIGH_RESET 0
-#define DST_WATERMARK_ADDRESS 0x0050
-
-#else
-#define WCN3990_CE0_SR_BA_LOW (0x00240000)
-#define WCN3990_CE1_SR_BA_LOW (0x00241000)
-#define WCN3990_CE2_SR_BA_LOW (0x00242000)
-#define WCN3990_CE3_SR_BA_LOW (0x00243000)
-#define WCN3990_CE4_SR_BA_LOW (0x00244000)
-#define WCN3990_CE5_SR_BA_LOW (0x00245000)
-#define WCN3990_CE6_SR_BA_LOW (0x00246000)
-#define WCN3990_CE7_SR_BA_LOW (0x00247000)
-#define WCN3990_CE8_SR_BA_LOW (0x00248000)
-#define WCN3990_CE9_SR_BA_LOW (0x00249000)
-#define WCN3990_CE10_SR_BA_LOW (0x0024A000)
-#define WCN3990_CE11_SR_BA_LOW (0x0024B000)
-#define WCN3990_CE0_DR_BA_LOW (0x0024000C)
-#define WNC3990_CE0_DR_SIZE (0x00240014)
-#define WCN3990_CE0_CE_CTRL1 (0x00240018)
-#define WCN3990_CE0_HOST_IE (0x0024002C)
-#define WCN3990_CE0_HOST_IS (0x00240030)
-#define WCN3990_CE0_MISC_IE (0x00240034)
-#define WCN3990_CE0_MISC_IS (0x00240038)
-#define WCN3990_CE0_SRC_WR_INDEX (0x0024003C)
-#define WCN3990_CE0_CURRENT_SRRI (0x00240044)
-#define WCN3990_CE0_CURRENT_DRRI (0x00240048)
-#define WCN3990_CE0_SRC_WATERMARK (0x0024004C)
-#define WCN3990_CE0_DST_WATERMARK (0x00240050)
-#define WCN3990_CE0_SR_SIZE (0x00240008)
-#define HOST_IE_COPY_COMPLETE_MASK (0x00000001)
-#define WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY 0x0024C000
-#define WCN3990_CE_WRAPPER_INDEX_BASE_LOW 0x0024C004
-#define WCN3990_CE_WRAPPER_INDEX_BASE_HIGH 0x0024C008
-#define CE_CTRL1_IDX_UPD_EN 0x00080000
-
-#define WCN3990_CE_WRAPPER_BASE_ADDRESS \
- WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY
-#define WCN3990_CE0_BASE_ADDRESS \
- WCN3990_CE0_SR_BA_LOW
-#define WCN3990_CE1_BASE_ADDRESS \
- WCN3990_CE1_SR_BA_LOW
-#define WCN3990_CE2_BASE_ADDRESS \
- WCN3990_CE2_SR_BA_LOW
-#define WCN3990_CE3_BASE_ADDRESS \
- WCN3990_CE3_SR_BA_LOW
-#define WCN3990_CE4_BASE_ADDRESS \
- WCN3990_CE4_SR_BA_LOW
-#define WCN3990_CE5_BASE_ADDRESS \
- WCN3990_CE5_SR_BA_LOW
-#define WCN3990_CE6_BASE_ADDRESS \
- WCN3990_CE6_SR_BA_LOW
-#define WCN3990_CE7_BASE_ADDRESS \
- WCN3990_CE7_SR_BA_LOW
-#define WCN3990_CE8_BASE_ADDRESS \
- WCN3990_CE8_SR_BA_LOW
-#define WCN3990_CE9_BASE_ADDRESS \
- WCN3990_CE9_SR_BA_LOW
-#define WCN3990_CE10_BASE_ADDRESS \
- WCN3990_CE10_SR_BA_LOW
-#define WCN3990_CE11_BASE_ADDRESS \
- WCN3990_CE11_SR_BA_LOW
-
-#define SR_BA_ADDRESS (WCN3990_CE0_SR_BA_LOW\
- - WCN3990_CE0_BASE_ADDRESS)
-#define SR_SIZE_ADDRESS (WCN3990_CE0_SR_SIZE \
- - WCN3990_CE0_BASE_ADDRESS)
-#define DR_BA_ADDRESS (WCN3990_CE0_DR_BA_LOW\
- - WCN3990_CE0_BASE_ADDRESS)
-#define DR_SIZE_ADDRESS (WNC3990_CE0_DR_SIZE\
- - WCN3990_CE0_BASE_ADDRESS)
-#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW \
- (WCN3990_CE_WRAPPER_INDEX_BASE_LOW - WCN3990_CE_WRAPPER_BASE_ADDRESS)
-
-#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH \
- (WCN3990_CE_WRAPPER_INDEX_BASE_HIGH - WCN3990_CE_WRAPPER_BASE_ADDRESS)
-
-#define CE_RRI_LOW (WCN3990_CE_WRAPPER_BASE_ADDRESS \
- + WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW)
-
-#define CE_RRI_HIGH (WCN3990_CE_WRAPPER_BASE_ADDRESS \
- + WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH)
-
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 18
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 18
-
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00040000
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
-
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00020000
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
- (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_DMAX_LENGTH_MSB 0
-#define CE_CTRL1_DMAX_LENGTH_LSB 0
-
-#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000FFFF
-#define CE_CTRL1_DMAX_LENGTH_GET(x) \
- (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
-#define CE_CTRL1_DMAX_LENGTH_SET(x) \
- (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
-
-#define CE_CTRL1_ADDRESS (WCN3990_CE0_CE_CTRL1 \
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define HOST_IE_ADDRESS (WCN3990_CE0_HOST_IE\
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
-#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
-#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
-#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
-#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IS_ADDRESS (WCN3990_CE0_HOST_IS \
- - WCN3990_CE0_BASE_ADDRESS)
-#define MISC_IE_ADDRESS (WCN3990_CE0_MISC_IE \
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define MISC_IS_AXI_ERR_MASK 0x00000100
-#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
-#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
-#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
-#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
-#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
-#define MISC_IS_ADDRESS (WCN3990_CE0_MISC_IS \
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define SR_WR_INDEX_ADDRESS 0x3C
-#define DST_WR_INDEX_ADDRESS 0x40
-
-#define CURRENT_SRRI_ADDRESS (WCN3990_CE0_CURRENT_SRRI\
- - WCN3990_CE0_BASE_ADDRESS)
-#define CURRENT_DRRI_ADDRESS (WCN3990_CE0_CURRENT_DRRI\
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define SRC_WATERMARK_LOW_MSB 0
-#define SRC_WATERMARK_LOW_LSB 16
-
-#define SRC_WATERMARK_LOW_MASK 0xffff0000
-#define SRC_WATERMARK_LOW_GET(x) \
- (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
-#define SRC_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
-
-#define SRC_WATERMARK_LOW_RESET 0
-#define SRC_WATERMARK_HIGH_MSB 15
-#define SRC_WATERMARK_HIGH_LSB 0
-#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
-#define SRC_WATERMARK_HIGH_GET(x) \
- (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
-#define SRC_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
-
-#define SRC_WATERMARK_HIGH_RESET 0
-#define SRC_WATERMARK_ADDRESS (WCN3990_CE0_SRC_WATERMARK\
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define DST_WATERMARK_LOW_LSB 16
-#define DST_WATERMARK_LOW_MASK 0xffff0000
-#define DST_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
-#define DST_WATERMARK_LOW_RESET 0
-#define DST_WATERMARK_HIGH_MSB 15
-#define DST_WATERMARK_HIGH_LSB 0
-#define DST_WATERMARK_HIGH_MASK 0x0000ffff
-#define DST_WATERMARK_HIGH_GET(x) \
- (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
-#define DST_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
-#define DST_WATERMARK_HIGH_RESET 0
-#define DST_WATERMARK_ADDRESS (WCN3990_CE0_DST_WATERMARK \
- - WCN3990_CE0_BASE_ADDRESS)
-
-#define BITS0_TO_31(val) ((uint32_t)((uint64_t)(val)\
- & (uint64_t)(0xFFFFFFFF)))
-#define BITS32_TO_35(val) ((uint32_t)(((uint64_t)(val)\
- & (uint64_t)(0xF00000000)) >> 32))
-#endif
-
#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \
- CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS))
@@ -675,18 +364,6 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
}
-#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \
- HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \
- HOST_IS_DST_RING_LOW_WATERMARK_MASK | \
- HOST_IS_DST_RING_HIGH_WATERMARK_MASK)
-
-#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \
- MISC_IS_DST_ADDR_ERR_MASK | \
- MISC_IS_SRC_LEN_ERR_MASK | \
- MISC_IS_DST_MAX_LEN_VIO_MASK | \
- MISC_IS_DST_RING_OVERFLOW_MASK | \
- MISC_IS_SRC_RING_OVERFLOW_MASK)
-
#define CE_SRC_RING_TO_DESC(baddr, idx) \
(&(((struct ce_desc *)baddr)[idx]))
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 052ebd7dd26b..d37ed66d767b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2324,28 +2324,34 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA9887:
ar->regs = &qca988x_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca988x_values;
break;
case ATH10K_HW_QCA6174:
case ATH10K_HW_QCA9377:
ar->regs = &qca6174_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca6174_values;
break;
case ATH10K_HW_QCA99X0:
case ATH10K_HW_QCA9984:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca99x0_values;
break;
case ATH10K_HW_QCA9888:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca9888_values;
break;
case ATH10K_HW_QCA4019:
ar->regs = &qca4019_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca4019_values;
break;
case ATH10K_HW_WCN3990:
ar->regs = &wcn3990_regs;
+ ar->hw_ce_regs = &wcn3990_ce_regs;
ar->hw_values = &wcn3990_values;
/* WCN3990 chip set is non bmi based */
ar->is_bmi = false;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index dc4cefb1177f..21c63d5d3ead 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -740,6 +740,7 @@ struct ath10k {
struct completion target_suspend;
const struct ath10k_hw_regs *regs;
+ const struct ath10k_hw_ce_regs *hw_ce_regs;
const struct ath10k_hw_values *hw_values;
struct ath10k_shadow_reg_value *shadow_reg_value;
struct ath10k_shadow_reg_address *shadow_reg_address;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 82a4c67f3672..c36c2481856b 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1909,7 +1909,7 @@ int ath10k_debug_start(struct ath10k *ar)
ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
}
- if (ar->debug.nf_cal_period) {
+ if (ar->debug.nf_cal_period && !QCA_REV_WCN3990(ar)) {
ret = ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->cal_period,
ar->debug.nf_cal_period);
@@ -1926,7 +1926,8 @@ void ath10k_debug_stop(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
- ath10k_debug_cal_data_fetch(ar);
+ if (!QCA_REV_WCN3990(ar))
+ ath10k_debug_cal_data_fetch(ar);
/* Must not use _sync to avoid deadlock, we do that in
* ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
@@ -2419,15 +2420,18 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
- debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
- ar, &fops_cal_data);
+ if (!QCA_REV_WCN3990(ar)) {
+ debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
+ ar, &fops_cal_data);
+
+ debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_phy, ar,
+ &fops_nf_cal_period);
+ }
debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_ani_enable);
- debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
- ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
-
if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index b2678984f2de..6dd396430f19 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -541,6 +541,7 @@ struct htt_rx_indication_hdr {
#define HTT_RX_INDICATION_INFO2_SERVICE_LSB 24
#define HTT_WCN3990_PADDR_MASK 0x1F
+#define HTT_WCN3990_ARCH_PADDR_MASK 0x1FFFFFFFFF
enum htt_rx_legacy_rate {
HTT_RX_OFDM_48 = 0,
@@ -865,8 +866,7 @@ struct htt_rx_offload_ind {
struct htt_rx_in_ord_msdu_desc {
#ifdef CONFIG_ATH10K_SNOC
- __le32 msdu_paddr_lo;
- __le32 msdu_paddr_hi;
+ __le64 msdu_paddr;
#else
__le32 msdu_paddr;
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index cbb61267eb10..ddf097e3a143 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -429,9 +429,8 @@ static int ath10k_htt_rx_pop_paddr_list(struct ath10k_htt *htt,
while (msdu_count--) {
#ifdef CONFIG_ATH10K_SNOC
- paddr = __le32_to_cpu(msdu_desc->msdu_paddr_lo);
- paddr |= ((u64)(msdu_desc->msdu_paddr_hi &
- HTT_WCN3990_PADDR_MASK) << 32);
+ paddr = __le64_to_cpu(msdu_desc->msdu_paddr);
+ paddr &= HTT_WCN3990_ARCH_PADDR_MASK;
#else
paddr = __le32_to_cpu(msdu_desc->msdu_paddr);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 1a8f3a388ce2..1d37b2c8426b 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -164,6 +164,301 @@ const struct ath10k_hw_regs wcn3990_regs = {
.pcie_intr_fw_mask = 0x00100000,
};
+static unsigned int
+ath10k_set_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return (((0 | (offset)) << addr_map->lsb) & addr_map->mask);
+}
+
+static unsigned int
+ath10k_get_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return (((offset) & addr_map->mask) >> (addr_map->lsb));
+}
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = {
+ .msb = 0x00000010,
+ .lsb = 0x00000010,
+ .mask = 0x00020000,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = {
+ .msb = 0x00000012,
+ .lsb = 0x00000012,
+ .mask = 0x00040000,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = {
+ .msb = 0x00000000,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = {
+ .addr = 0x00000018,
+ .src_ring = &wcn3990_src_ring,
+ .dst_ring = &wcn3990_dst_ring,
+ .dmax = &wcn3990_dmax,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = {
+ .mask = 0x00000001,
+};
+
+struct ath10k_hw_ce_host_ie wcn3990_host_ie = {
+ .copy_complete = &wcn3990_host_ie_cc,
+};
+
+struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = {
+ .dstr_lmask = 0x00000010,
+ .dstr_hmask = 0x00000008,
+ .srcr_lmask = 0x00000004,
+ .srcr_hmask = 0x00000002,
+ .cc_mask = 0x00000001,
+ .wm_mask = 0x0000001E,
+ .addr = 0x00000030,
+};
+
+struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = {
+ .axi_err = 0x00000100,
+ .dstr_add_err = 0x00000200,
+ .srcr_len_err = 0x00000100,
+ .dstr_mlen_vio = 0x00000080,
+ .dstr_overflow = 0x00000040,
+ .srcr_overflow = 0x00000020,
+ .err_mask = 0x000003E0,
+ .addr = 0x00000038,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = {
+ .msb = 0x00000000,
+ .lsb = 0x00000010,
+ .mask = 0xffff0000,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = {
+ .addr = 0x0000004c,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &wcn3990_src_wm_low,
+ .wm_high = &wcn3990_src_wm_high,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = {
+ .lsb = 0x00000010,
+ .mask = 0xffff0000,
+ .set = &ath10k_set_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = {
+ .addr = 0x00000050,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &wcn3990_dst_wm_low,
+ .wm_high = &wcn3990_dst_wm_high,
+};
+
+struct ath10k_hw_ce_regs wcn3990_ce_regs = {
+ .sr_base_addr = 0x00000000,
+ .sr_size_addr = 0x00000008,
+ .dr_base_addr = 0x0000000c,
+ .dr_size_addr = 0x00000014,
+ .misc_ie_addr = 0x00000034,
+ .sr_wr_index_addr = 0x0000003c,
+ .dst_wr_index_addr = 0x00000040,
+ .current_srri_addr = 0x00000044,
+ .current_drri_addr = 0x00000048,
+ .ddr_addr_for_rri_low = 0x00000004,
+ .ddr_addr_for_rri_high = 0x00000008,
+ .ce_rri_low = 0x0024C004,
+ .ce_rri_high = 0x0024C008,
+ .host_ie_addr = 0x0000002c,
+ .ctrl1_regs = &wcn3990_ctrl1,
+ .host_ie = &wcn3990_host_ie,
+ .wm_regs = &wcn3990_wm_reg,
+ .misc_regs = &wcn3990_misc_reg,
+ .wm_srcr = &wcn3990_wm_src_ring,
+ .wm_dstr = &wcn3990_wm_dst_ring,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
+ .msb = 0x00000010,
+ .lsb = 0x00000010,
+ .mask = 0x00010000,
+ .set = &ath10k_set_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
+ .msb = 0x00000011,
+ .lsb = 0x00000011,
+ .mask = 0x00020000,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
+ .addr = 0x00000010,
+ .hw_mask = 0x0007ffff,
+ .sw_mask = 0x0007ffff,
+ .hw_wr_mask = 0x00000000,
+ .sw_wr_mask = 0x0007ffff,
+ .reset_mask = 0xffffffff,
+ .reset = 0x00000080,
+ .src_ring = &qcax_src_ring,
+ .dst_ring = &qcax_dst_ring,
+ .dmax = &qcax_dmax,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
+ .msb = 0x00000003,
+ .lsb = 0x00000003,
+ .mask = 0x00000008,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
+ .msb = 0x00000000,
+ .mask = 0x00000001,
+ .status_reset = 0x00000000,
+ .status = &qcax_cmd_halt_status,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
+ .msb = 0x00000000,
+ .lsb = 0x00000000,
+ .mask = 0x00000001,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_host_ie qcax_host_ie = {
+ .copy_complete_reset = 0x00000000,
+ .copy_complete = &qcax_host_ie_cc,
+};
+
+struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
+ .dstr_lmask = 0x00000010,
+ .dstr_hmask = 0x00000008,
+ .srcr_lmask = 0x00000004,
+ .srcr_hmask = 0x00000002,
+ .cc_mask = 0x00000001,
+ .wm_mask = 0x0000001E,
+ .addr = 0x00000030,
+};
+
+struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
+ .axi_err = 0x00000400,
+ .dstr_add_err = 0x00000200,
+ .srcr_len_err = 0x00000100,
+ .dstr_mlen_vio = 0x00000080,
+ .dstr_overflow = 0x00000040,
+ .srcr_overflow = 0x00000020,
+ .err_mask = 0x000007E0,
+ .addr = 0x00000038,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
+ .msb = 0x0000001f,
+ .lsb = 0x00000010,
+ .mask = 0xffff0000,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
+ .addr = 0x0000004c,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_src_wm_low,
+ .wm_high = &qcax_src_wm_high,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
+ .lsb = 0x00000010,
+ .mask = 0xffff0000,
+ .set = &ath10k_set_ring_byte,
+};
+
+struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = 0x0000ffff,
+ .set = &ath10k_set_ring_byte,
+ .get = &ath10k_get_ring_byte,
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
+ .addr = 0x00000050,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_dst_wm_low,
+ .wm_high = &qcax_dst_wm_high,
+};
+
+struct ath10k_hw_ce_regs qcax_ce_regs = {
+ .sr_base_addr = 0x00000000,
+ .sr_size_addr = 0x00000004,
+ .dr_base_addr = 0x00000008,
+ .dr_size_addr = 0x0000000c,
+ .ce_cmd_addr = 0x00000018,
+ .misc_ie_addr = 0x00000034,
+ .sr_wr_index_addr = 0x0000003c,
+ .dst_wr_index_addr = 0x00000040,
+ .current_srri_addr = 0x00000044,
+ .current_drri_addr = 0x00000048,
+ .host_ie_addr = 0x0000002c,
+ .ctrl1_regs = &qcax_ctrl1,
+ .cmd_halt = &qcax_cmd_halt,
+ .host_ie = &qcax_host_ie,
+ .wm_regs = &qcax_wm_reg,
+ .misc_regs = &qcax_misc_reg,
+ .wm_srcr = &qcax_wm_src_ring,
+ .wm_dstr = &qcax_wm_dst_ring,
+};
+
const struct ath10k_hw_values qca988x_values = {
.rtc_state_val_on = 3,
.ce_count = 8,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index ce87f8112928..0f2422480c4e 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -268,6 +268,98 @@ extern const struct ath10k_hw_regs qca99x0_regs;
extern const struct ath10k_hw_regs qca4019_regs;
extern const struct ath10k_hw_regs wcn3990_regs;
+struct ath10k_hw_ce_regs_addr_map {
+ u32 msb;
+ u32 lsb;
+ u32 mask;
+ unsigned int (*set)(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map);
+ unsigned int (*get)(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map);
+};
+
+struct ath10k_hw_ce_ctrl1 {
+ u32 addr;
+ u32 hw_mask;
+ u32 sw_mask;
+ u32 hw_wr_mask;
+ u32 sw_wr_mask;
+ u32 reset_mask;
+ u32 reset;
+ struct ath10k_hw_ce_regs_addr_map *src_ring;
+ struct ath10k_hw_ce_regs_addr_map *dst_ring;
+ struct ath10k_hw_ce_regs_addr_map *dmax;
+};
+
+struct ath10k_hw_ce_cmd_halt {
+ u32 status_reset;
+ u32 msb;
+ u32 mask;
+ struct ath10k_hw_ce_regs_addr_map *status;
+};
+
+struct ath10k_hw_ce_host_ie {
+ u32 copy_complete_reset;
+ struct ath10k_hw_ce_regs_addr_map *copy_complete;
+};
+
+struct ath10k_hw_ce_host_wm_regs {
+ u32 dstr_lmask;
+ u32 dstr_hmask;
+ u32 srcr_lmask;
+ u32 srcr_hmask;
+ u32 cc_mask;
+ u32 wm_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_misc_regs {
+ u32 axi_err;
+ u32 dstr_add_err;
+ u32 srcr_len_err;
+ u32 dstr_mlen_vio;
+ u32 dstr_overflow;
+ u32 srcr_overflow;
+ u32 err_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs {
+ u32 addr;
+ u32 low_rst;
+ u32 high_rst;
+ struct ath10k_hw_ce_regs_addr_map *wm_low;
+ struct ath10k_hw_ce_regs_addr_map *wm_high;
+};
+
+struct ath10k_hw_ce_regs {
+ u32 sr_base_addr;
+ u32 sr_size_addr;
+ u32 dr_base_addr;
+ u32 dr_size_addr;
+ u32 ce_cmd_addr;
+ u32 misc_ie_addr;
+ u32 sr_wr_index_addr;
+ u32 dst_wr_index_addr;
+ u32 current_srri_addr;
+ u32 current_drri_addr;
+ u32 ddr_addr_for_rri_low;
+ u32 ddr_addr_for_rri_high;
+ u32 ce_rri_low;
+ u32 ce_rri_high;
+ u32 host_ie_addr;
+ struct ath10k_hw_ce_host_wm_regs *wm_regs;
+ struct ath10k_hw_ce_misc_regs *misc_regs;
+ struct ath10k_hw_ce_ctrl1 *ctrl1_regs;
+ struct ath10k_hw_ce_cmd_halt *cmd_halt;
+ struct ath10k_hw_ce_host_ie *host_ie;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr;
+};
+
+extern struct ath10k_hw_ce_regs wcn3990_ce_regs;
+extern struct ath10k_hw_ce_regs qcax_ce_regs;
+
extern struct fw_flag wcn3990_fw_flags;
struct ath10k_hw_values {
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/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
index 16f64e9fb8d3..913f756f9520 100644
--- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
+++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
@@ -98,6 +98,7 @@ static struct wcnss_prealloc wcnss_allocs[] = {
{0, 64 * 1024, NULL},
{0, 64 * 1024, NULL},
{0, 64 * 1024, NULL},
+ {0, 64 * 1024, NULL},
{0, 128 * 1024, NULL},
{0, 128 * 1024, NULL},
};
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..771d1cd32714 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);
@@ -858,6 +857,7 @@ static int smb2_batt_get_prop(struct power_supply *psy,
{
struct smb_charger *chg = power_supply_get_drvdata(psy);
int rc = 0;
+ union power_supply_propval pval = {0, };
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
@@ -882,7 +882,14 @@ static int smb2_batt_get_prop(struct power_supply *psy,
rc = smblib_get_prop_system_temp_level(chg, val);
break;
case POWER_SUPPLY_PROP_CHARGER_TEMP:
- rc = smblib_get_prop_charger_temp(chg, val);
+ /* do not query RRADC if charger is not present */
+ rc = smblib_get_prop_usb_present(chg, &pval);
+ if (rc < 0)
+ pr_err("Couldn't get usb present rc=%d\n", rc);
+
+ rc = -ENODATA;
+ if (pval.intval)
+ rc = smblib_get_prop_charger_temp(chg, val);
break;
case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
rc = smblib_get_prop_charger_temp_max(chg, val);
@@ -1386,7 +1393,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 +1657,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..22ef78fd9641 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,11 +306,13 @@ struct smb_charger {
int otg_attempts;
int vconn_attempts;
int default_icl_ua;
+ int otg_cl_ua;
/* workaround flag */
u32 wa_flags;
enum cc2_sink_type cc2_sink_detach_flag;
int boost_current_ua;
+ int temp_speed_reading_count;
/* extcon for VBUS / ID notification to USB for uUSB */
struct extcon_dev *extcon;
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 1c7c1e78699f..739d80cd8801 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -45,6 +45,7 @@
#define STACKED_DIODE_EN_BIT BIT(2)
#define TDIE_AVG_COUNT 10
+#define MAX_SPEED_READING_TIMES 5
enum {
OOB_COMP_WA_BIT = BIT(0),
@@ -126,8 +127,16 @@ static int smb138x_get_prop_charger_temp(struct smb138x *chip,
union power_supply_propval pval;
int rc = 0, avg = 0, i;
struct smb_charger *chg = &chip->chg;
+ int die_avg_count;
- for (i = 0; i < TDIE_AVG_COUNT; i++) {
+ if (chg->temp_speed_reading_count < MAX_SPEED_READING_TIMES) {
+ chg->temp_speed_reading_count++;
+ die_avg_count = 1;
+ } else {
+ die_avg_count = TDIE_AVG_COUNT;
+ }
+
+ for (i = 0; i < die_avg_count; i++) {
pval.intval = 0;
rc = smblib_get_prop_charger_temp(chg, &pval);
if (rc < 0) {
@@ -137,7 +146,7 @@ static int smb138x_get_prop_charger_temp(struct smb138x *chip,
}
avg += pval.intval;
}
- val->intval = avg / TDIE_AVG_COUNT;
+ val->intval = avg / die_avg_count;
return rc;
}
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 018f539054fe..9d795489c285 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1942,7 +1942,9 @@ unknown:
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
- composite_setup_complete(gadget->ep0, req);
+ if (value != -ESHUTDOWN)
+ composite_setup_complete(gadget->ep0,
+ req);
}
return value;
}
@@ -2031,7 +2033,8 @@ try_fun_setup:
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
- composite_setup_complete(gadget->ep0, req);
+ if (value != -ESHUTDOWN)
+ composite_setup_complete(gadget->ep0, req);
}
} else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
WARN(cdev,
@@ -2467,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_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index d57558a1b52d..734d3bee8fd0 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -41,6 +41,8 @@
#define LANE_SWAP_CTRL 0x0B0
#define LOGICAL_LANE_SWAP_CTRL 0x310
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+
struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
struct mdss_hw mdss_dsi0_hw = {
@@ -1423,6 +1425,35 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl)
mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata);
}
+static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int ret = 0;
+ u32 v_total = 0, v_blank = 0, sleep_ms = 0, fps = 0;
+ struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
+
+ if (ctrl->panel_mode == DSI_CMD_MODE)
+ return ret;
+
+ if (ctrl->ctrl_state & CTRL_STATE_MDP_ACTIVE) {
+ mdss_dsi_wait4video_done(ctrl);
+ v_total = mdss_panel_get_vtotal(pinfo);
+ v_blank = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_front_porch +
+ pinfo->lcdc.v_pulse_width;
+ if (pinfo->dynamic_fps && pinfo->current_fps)
+ fps = pinfo->current_fps;
+ else
+ fps = pinfo->mipi.frame_rate;
+
+ sleep_ms = CEIL((v_blank * 1000), (v_total * fps)) + 1;
+ /* delay sleep_ms to skip BLLP */
+ if (sleep_ms)
+ udelay(sleep_ms * 1000);
+ ret = 1;
+ }
+
+ return ret;
+}
+
/**
* mdss_dsi_bta_status_check() - Check dsi panel status through bta check
* @ctrl_pdata: pointer to the dsi controller structure
@@ -1463,6 +1494,7 @@ int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
reinit_completion(&ctrl_pdata->bta_comp);
mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM);
spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag);
+ mdss_dsi_wait4video_eng_busy(ctrl_pdata);
/* mask out overflow errors */
if (ignore_underflow)
mdss_dsi_set_reg(ctrl_pdata, 0x10c, 0x0f0000, 0x0f0000);
@@ -2348,15 +2380,20 @@ void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
/* DSI_INTL_CTRL */
data = MIPI_INP((ctrl->ctrl_base) + 0x0110);
data &= DSI_INTR_TOTAL_MASK;
- data |= DSI_INTR_VIDEO_DONE_MASK;
- MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
+ /* clear previous VIDEO_DONE interrupt */
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0110, (data | DSI_INTR_VIDEO_DONE));
+ wmb(); /* ensure interrupt is cleared */
spin_lock_irqsave(&ctrl->mdp_lock, flag);
reinit_completion(&ctrl->video_comp);
mdss_dsi_enable_irq(ctrl, DSI_VIDEO_TERM);
spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
+ data |= DSI_INTR_VIDEO_DONE_MASK;
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
+ wmb(); /* ensure interrupt is enabled */
+
wait_for_completion_timeout(&ctrl->video_comp,
msecs_to_jiffies(VSYNC_PERIOD * 4));
@@ -2366,23 +2403,6 @@ void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
}
-static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
-{
- int ret = 0;
-
- if (ctrl->panel_mode == DSI_CMD_MODE)
- return ret;
-
- if (ctrl->ctrl_state & CTRL_STATE_MDP_ACTIVE) {
- mdss_dsi_wait4video_done(ctrl);
- /* delay 4 ms to skip BLLP */
- usleep_range(4000, 4000);
- ret = 1;
- }
-
- return ret;
-}
-
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl)
{
unsigned long flag;
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 804d89a825fc..055b879dfa6b 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -208,6 +208,7 @@ struct mmc_cmdq_req {
unsigned int resp_arg;
unsigned int dev_pend_tasks;
bool resp_err;
+ bool skip_err_handling;
int tag; /* used for command queuing */
u8 ctx_id;
};
@@ -533,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/net/cfg80211.h b/include/net/cfg80211.h
index 1ce3ea1fd917..9e88da2764d7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -71,6 +71,8 @@ struct wiphy;
#define CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT 1
#define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1
#define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1
+#define CFG80211_CONNECT_TIMEOUT 1
+#define CFG80211_CONNECT_TIMEOUT_REASON_CODE 1
/*
* wireless hardware capability structures
@@ -2437,9 +2439,23 @@ struct cfg80211_qos_map {
* (invoked with the wireless_dev mutex held)
*
* @connect: Connect to the ESS with the specified parameters. When connected,
- * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
- * If the connection fails for some reason, call cfg80211_connect_result()
- * with the status from the AP.
+ * call cfg80211_connect_result()/cfg80211_connect_bss() with status code
+ * %WLAN_STATUS_SUCCESS. If the connection fails for some reason, call
+ * cfg80211_connect_result()/cfg80211_connect_bss() with the status code
+ * from the AP or cfg80211_connect_timeout() if no frame with status code
+ * was received.
+ * The driver is allowed to roam to other BSSes within the ESS when the
+ * other BSS matches the connect parameters. When such roaming is initiated
+ * by the driver, the driver is expected to verify that the target matches
+ * the configured security parameters and to use Reassociation Request
+ * frame instead of Association Request frame.
+ * The connect function can also be used to request the driver to perform a
+ * specific roam when connected to an ESS. In that case, the prev_bssid
+ * parameter is set to the BSSID of the currently associated BSS as an
+ * indication of requesting reassociation.
+ * In both the driver-initiated and new connect() call initiated roaming
+ * cases, the result of roaming is indicated with a call to
+ * cfg80211_roamed() or cfg80211_roamed_bss().
* (invoked with the wireless_dev mutex held)
* @update_connect_params: Update the connect parameters while connected to a
* BSS. The updated parameters can be used by driver/firmware for
@@ -4804,6 +4820,12 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
* %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
* the real status code for failures.
* @gfp: allocation flags
+ * @timeout_reason: reason for connection timeout. This is used when the
+ * connection fails due to a timeout instead of an explicit rejection from
+ * the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is
+ * not known. This value is used only if @status < 0 to indicate that the
+ * failure is due to a timeout and not due to explicit rejection by the AP.
+ * This value is ignored in other cases (@status >= 0).
*
* It should be called by the underlying driver whenever connect() has
* succeeded. This is similar to cfg80211_connect_result(), but with the
@@ -4813,7 +4835,8 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
- size_t resp_ie_len, u16 status, gfp_t gfp);
+ size_t resp_ie_len, int status, gfp_t gfp,
+ enum nl80211_timeout_reason timeout_reason);
/**
* cfg80211_connect_result - notify cfg80211 of connection result
@@ -4839,7 +4862,33 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
u16 status, gfp_t gfp)
{
cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie,
- resp_ie_len, status, gfp);
+ resp_ie_len, status, gfp,
+ NL80211_TIMEOUT_UNSPECIFIED);
+}
+
+/**
+ * cfg80211_connect_timeout - notify cfg80211 of connection timeout
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @gfp: allocation flags
+ * @timeout_reason: reason for connection timeout.
+ *
+ * It should be called by the underlying driver whenever connect() has failed
+ * in a sequence where no explicit authentication/association rejection was
+ * received from the AP. This could happen, e.g., due to not being able to send
+ * out the Authentication or Association Request frame or timing out while
+ * waiting for the response.
+ */
+static inline void
+cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len, gfp_t gfp,
+ enum nl80211_timeout_reason timeout_reason)
+{
+ cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1,
+ gfp, timeout_reason);
}
/**
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/nl80211.h b/include/uapi/linux/nl80211.h
index 0505b1f9872b..8a5c59a9ff0e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -486,7 +486,12 @@
* This attribute is ignored if driver does not support roam scan.
* It is also sent as an event, with the BSSID and response IEs when the
* connection is established or failed to be established. This can be
- * determined by the STATUS_CODE attribute.
+ * determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success,
+ * non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the
+ * event, the connection attempt failed due to not being able to initiate
+ * authentication/association or not receiving a response from the AP.
+ * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
+ * well to remain backwards compatible.
* @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
* sent as an event when the card/driver roamed by itself.
* @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
@@ -1948,6 +1953,10 @@ enum nl80211_commands {
* better BSSs. The attribute value is a packed structure
* value as specified by &struct nl80211_bss_select_rssi_adjust.
*
+ * @NL80211_ATTR_TIMEOUT_REASON: The reason for which an operation timed out.
+ * u32 attribute with an &enum nl80211_timeout_reason value. This is used,
+ * e.g., with %NL80211_CMD_CONNECT event.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2357,6 +2366,8 @@ enum nl80211_attrs {
NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+ NL80211_ATTR_TIMEOUT_REASON,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4695,6 +4706,21 @@ enum nl80211_connect_failed_reason {
};
/**
+ * enum nl80211_timeout_reason - timeout reasons
+ *
+ * @NL80211_TIMEOUT_UNSPECIFIED: Timeout reason unspecified.
+ * @NL80211_TIMEOUT_SCAN: Scan (AP discovery) timed out.
+ * @NL80211_TIMEOUT_AUTH: Authentication timed out.
+ * @NL80211_TIMEOUT_ASSOC: Association timed out.
+ */
+enum nl80211_timeout_reason {
+ NL80211_TIMEOUT_UNSPECIFIED,
+ NL80211_TIMEOUT_SCAN,
+ NL80211_TIMEOUT_AUTH,
+ NL80211_TIMEOUT_ASSOC,
+};
+
+/**
* enum nl80211_scan_flags - scan request control flags
*
* Scan request control flags are used to control the handling
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/rcu/tree.c b/kernel/rcu/tree.c
index f07343b54fe5..2cb46d51d715 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,8 @@
#include <linux/trace_events.h>
#include <linux/suspend.h>
+#include <soc/qcom/watchdog.h>
+
#include "tree.h"
#include "rcu.h"
@@ -1298,6 +1300,11 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
rcu_check_gp_kthread_starvation(rsp);
+#ifdef CONFIG_RCU_STALL_WATCHDOG_BITE
+ /* Induce watchdog bite */
+ msm_trigger_wdog_bite();
+#endif
+
force_quiescent_state(rsp); /* Kick them all. */
}
@@ -1333,6 +1340,11 @@ static void print_cpu_stall(struct rcu_state *rsp)
jiffies + 3 * rcu_jiffies_till_stall_check() + 3);
raw_spin_unlock_irqrestore(&rnp->lock, flags);
+#ifdef CONFIG_RCU_STALL_WATCHDOG_BITE
+ /* Induce non secure watchdog bite to collect context */
+ msm_trigger_wdog_bite();
+#endif
+
/*
* Attempt to revive the RCU machinery by forcing a context switch.
*
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/lib/Kconfig.debug b/lib/Kconfig.debug
index 902657d4cac5..3cd6011f209d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1455,6 +1455,17 @@ config RCU_CPU_STALL_TIMEOUT
RCU grace period persists, additional CPU stall warnings are
printed at more widely spaced intervals.
+config RCU_STALL_WATCHDOG_BITE
+ bool "RCU stall induce watchdog bite"
+ depends on RCU_STALL_COMMON && QCOM_WATCHDOG_V2
+ help
+ Induce watchdog bite if RCU grace period extends more than
+ specified no of seconds instead of just warning messages.
+ This helps to collect ram dumps and cpu context for
+ postmortem analysis. Generally if a given RCU grace period
+ extends more than the specified number of seconds,
+ a CPU stall warning is printed.
+
config RCU_TRACE
bool "Enable tracing for RCU"
depends on DEBUG_KERNEL
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 46495dd821c8..2ec028ea7775 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -215,7 +215,8 @@ struct cfg80211_event {
size_t req_ie_len;
size_t resp_ie_len;
struct cfg80211_bss *bss;
- u16 status;
+ int status; /* -1 = failed; 0..65535 = status code */
+ enum nl80211_timeout_reason timeout_reason;
} cr;
struct {
const u8 *req_ie;
@@ -375,8 +376,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
- u16 status, bool wextev,
- struct cfg80211_bss *bss);
+ int status, bool wextev,
+ struct cfg80211_bss *bss,
+ enum nl80211_timeout_reason timeout_reason);
void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
size_t ie_len, u16 reason, bool from_ap);
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 594eeea9533b..36baa8d22108 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -48,7 +48,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
/* update current_bss etc., consumes the bss reference */
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
status_code,
- status_code == WLAN_STATUS_SUCCESS, bss);
+ status_code == WLAN_STATUS_SUCCESS, bss,
+ NL80211_TIMEOUT_UNSPECIFIED);
}
EXPORT_SYMBOL(cfg80211_rx_assoc_resp);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index dcae8ae9bfad..08bd3f3d27e3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -408,6 +408,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
.len = sizeof(struct nl80211_bss_select_rssi_adjust)
},
+ [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
};
/* policy for the key attributes */
@@ -12264,7 +12265,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
- u16 status, gfp_t gfp)
+ int status,
+ enum nl80211_timeout_reason timeout_reason,
+ gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
@@ -12282,7 +12285,12 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
(bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
- nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) ||
+ nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
+ status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
+ status) ||
+ (status < 0 &&
+ (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
+ nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON, timeout_reason))) ||
(req_ie &&
nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
(resp_ie &&
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 84d4edf1d545..a749c9be2836 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -55,7 +55,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
- u16 status, gfp_t gfp);
+ int status,
+ enum nl80211_timeout_reason timeout_reason,
+ gfp_t gfp);
void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index e5b962d2ffe7..9c7f0ce35a06 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -34,10 +34,11 @@ struct cfg80211_conn {
CFG80211_CONN_SCAN_AGAIN,
CFG80211_CONN_AUTHENTICATE_NEXT,
CFG80211_CONN_AUTHENTICATING,
- CFG80211_CONN_AUTH_FAILED,
+ CFG80211_CONN_AUTH_FAILED_TIMEOUT,
CFG80211_CONN_ASSOCIATE_NEXT,
CFG80211_CONN_ASSOCIATING,
CFG80211_CONN_ASSOC_FAILED,
+ CFG80211_CONN_ASSOC_FAILED_TIMEOUT,
CFG80211_CONN_DEAUTH,
CFG80211_CONN_CONNECTED,
} state;
@@ -162,7 +163,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
return err;
}
-static int cfg80211_conn_do_work(struct wireless_dev *wdev)
+static int cfg80211_conn_do_work(struct wireless_dev *wdev,
+ enum nl80211_timeout_reason *treason)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_connect_params *params;
@@ -193,7 +195,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
NULL, 0,
params->key, params->key_len,
params->key_idx, NULL, 0);
- case CFG80211_CONN_AUTH_FAILED:
+ case CFG80211_CONN_AUTH_FAILED_TIMEOUT:
+ *treason = NL80211_TIMEOUT_AUTH;
return -ENOTCONN;
case CFG80211_CONN_ASSOCIATE_NEXT:
if (WARN_ON(!rdev->ops->assoc))
@@ -220,6 +223,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
WLAN_REASON_DEAUTH_LEAVING,
false);
return err;
+ case CFG80211_CONN_ASSOC_FAILED_TIMEOUT:
+ *treason = NL80211_TIMEOUT_ASSOC;
+ /* fall through */
case CFG80211_CONN_ASSOC_FAILED:
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
@@ -243,6 +249,7 @@ void cfg80211_conn_work(struct work_struct *work)
container_of(work, struct cfg80211_registered_device, conn_work);
struct wireless_dev *wdev;
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
+ enum nl80211_timeout_reason treason;
rtnl_lock();
@@ -264,12 +271,12 @@ void cfg80211_conn_work(struct work_struct *work)
memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
bssid = bssid_buf;
}
- if (cfg80211_conn_do_work(wdev)) {
+ treason = NL80211_TIMEOUT_UNSPECIFIED;
+ if (cfg80211_conn_do_work(wdev, &treason)) {
__cfg80211_connect_result(
wdev->netdev, bssid,
- NULL, 0, NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- false, NULL);
+ NULL, 0, NULL, 0, -1, false, NULL,
+ treason);
}
wdev_unlock(wdev);
}
@@ -374,7 +381,8 @@ void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len)
} else if (status_code != WLAN_STATUS_SUCCESS) {
__cfg80211_connect_result(wdev->netdev, mgmt->bssid,
NULL, 0, NULL, 0,
- status_code, false, NULL);
+ status_code, false, NULL,
+ NL80211_TIMEOUT_UNSPECIFIED);
} else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
schedule_work(&rdev->conn_work);
@@ -422,7 +430,7 @@ void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
if (!wdev->conn)
return;
- wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
+ wdev->conn->state = CFG80211_CONN_AUTH_FAILED_TIMEOUT;
schedule_work(&rdev->conn_work);
}
@@ -444,7 +452,7 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
if (!wdev->conn)
return;
- wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
+ wdev->conn->state = CFG80211_CONN_ASSOC_FAILED_TIMEOUT;
schedule_work(&rdev->conn_work);
}
@@ -565,7 +573,9 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
/* we're good if we have a matching bss struct */
if (bss) {
- err = cfg80211_conn_do_work(wdev);
+ enum nl80211_timeout_reason treason;
+
+ err = cfg80211_conn_do_work(wdev, &treason);
cfg80211_put_bss(wdev->wiphy, bss);
} else {
/* otherwise we'll need to scan for the AP first */
@@ -662,8 +672,9 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
- u16 status, bool wextev,
- struct cfg80211_bss *bss)
+ int status, bool wextev,
+ struct cfg80211_bss *bss,
+ enum nl80211_timeout_reason timeout_reason)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
const u8 *country_ie;
@@ -682,7 +693,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev,
bssid, req_ie, req_ie_len,
resp_ie, resp_ie_len,
- status, GFP_KERNEL);
+ status, timeout_reason, GFP_KERNEL);
#ifdef CONFIG_CFG80211_WEXT
if (wextev) {
@@ -771,7 +782,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
- size_t resp_ie_len, u16 status, gfp_t gfp)
+ size_t resp_ie_len, int status, gfp_t gfp,
+ enum nl80211_timeout_reason timeout_reason)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -811,6 +823,7 @@ void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
cfg80211_hold_bss(bss_from_pub(bss));
ev->cr.bss = bss;
ev->cr.status = status;
+ ev->cr.timeout_reason = timeout_reason;
spin_lock_irqsave(&wdev->event_lock, flags);
list_add_tail(&ev->list, &wdev->event_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index dfd0766abd6f..305370cfd1e0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -878,7 +878,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
ev->cr.resp_ie, ev->cr.resp_ie_len,
ev->cr.status,
ev->cr.status == WLAN_STATUS_SUCCESS,
- ev->cr.bss);
+ ev->cr.bss, ev->cr.timeout_reason);
break;
case EVENT_ROAMED:
__cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,
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;
+ }
}
}