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/input/touchscreen/gt9xx/gt9xx.txt104
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-cpp.txt8
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-vfe.txt15
-rw-r--r--Documentation/devicetree/bindings/misc/qpnp-misc.txt24
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt10
-rw-r--r--arch/arm/boot/dts/qcom/Makefile1
-rw-r--r--arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts23
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-rm67195-amoled-fhd-cmd.dtsi124
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-660.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-gpu.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi138
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts128
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts28
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-bus.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-common.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-coresight.dtsi160
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-gpu.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi19
-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-pm660a-qrd.dts31
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi23
-rw-r--r--arch/arm/configs/sdm660-perf_defconfig30
-rw-r--r--arch/arm/configs/sdm660_defconfig30
-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_defconfig2
-rw-r--r--arch/arm64/configs/sdm660_defconfig2
-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/firmware/qcom/tz_log.c39
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-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/hid/hid-core.c1
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/gt9xx/Kconfig51
-rw-r--r--drivers/input/touchscreen/gt9xx/Makefile8
-rw-r--r--drivers/input/touchscreen/gt9xx/goodix_tool.c603
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.c2564
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.h220
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx_update.c1530
-rw-r--r--drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c36
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c41
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c78
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c75
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c19
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c64
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h5
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c1
-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.c8
-rw-r--r--drivers/mmc/core/bus.c13
-rw-r--r--drivers/mmc/core/mmc.c36
-rw-r--r--drivers/mmc/host/cmdq_hci.c9
-rw-r--r--drivers/mmc/host/cmdq_hci.h1
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.c31
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.h6
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/mmc/host/sdhci.c35
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c4
-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.c81
-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/core.c3
-rw-r--r--drivers/regulator/qpnp-lcdb-regulator.c138
-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-locator.c11
-rw-r--r--drivers/soc/qcom/service-notifier.c13
-rw-r--r--drivers/thermal/msm_lmh_dcvs.c10
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/function/f_fs.c6
-rw-r--r--drivers/usb/gadget/function/f_gsi.c62
-rw-r--r--drivers/usb/gadget/function/f_gsi.h4
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-plat.c12
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.h7
-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.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c33
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c21
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h5
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_cec.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c57
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c65
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c106
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_trace.h20
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h8
-rw-r--r--include/dt-bindings/clock/qcom,rpmcc.h6
-rw-r--r--include/linux/qpnp-misc.h22
-rw-r--r--include/net/cfg80211.h59
-rw-r--r--include/uapi/drm/msm_drm.h8
-rw-r--r--include/uapi/linux/msm_kgsl.h6
-rw-r--r--include/uapi/linux/msm_mdp_ext.h10
-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_isp.h13
-rw-r--r--include/uapi/media/msmb_pproc.h3
-rw-r--r--include/uapi/video/msm_hdmi_modes.h2
-rw-r--r--kernel/rcu/tree.c12
-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.c181
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h21
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c119
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h6
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c60
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c183
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c8
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c10
-rw-r--r--sound/soc/msm/sdm660-internal.c25
188 files changed, 3731 insertions, 6299 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/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
deleted file mode 100644
index bde115155eba..000000000000
--- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-Goodix GT9xx series touch controller
-
-The Goodix GT9xx series touch controller is connected to the host processor via
-I2C. The controller generates interrupts when the user touches the panel. The
-host controller is expected to read the touch coordinates over I2C and pass
-the coordinates to the rest of the system.
-
-Required properties:
-
- - compatible : Should be "goodix,gt9xx"
- - reg : I2C slave address of the device.
- - interrupt-parent : Parent of interrupt.
- - interrupts : Configuration of touch panel controller interrupt
- GPIO.
- - goodix,product-id : Product identification of the controller.
- - interrupt-gpios : Interrupt gpio which is to provide interrupts to
- host, same as "interrupts" node.
- - reset-gpios : Reset gpio to control the reset of chip.
- - goodix,display-coords : Display coordinates in pixels. It is a four
- tuple consisting of min x, min y, max x and
- max y values.
-
-Optional properties:
-
- - avdd-supply : Power supply needed to power up the device, this is
- for fixed voltage external regulator.
- - vdd-supply : Power supply needed to power up the device, when use
- external regulator, do not add this property.
- - vcc-i2c-supply : Power source required to power up i2c bus.
- GT9xx series can provide 1.8V from internal
- LDO, add this properties base on hardware
- design.
- - goodix,panel-coords : Panel coordinates for the chip in pixels.
- It is a four tuple consisting of min x,
- min y, max x and max y values.
- - goodix,i2c-pull-up : To specify pull up is required.
- - goodix,force-update : To specify force update is allowed.
- - goodix,enable-power-off : Power off touchscreen during suspend.
- - goodix,button-map : Button map of key codes. The number of key codes
- depend on panel.
- - goodix,cfg-data0 : Touch screen controller config data group 0. Ask vendor
- to provide that.
- Driver supports maximum six config groups. If more than one
- groups are defined, driver will select config group depending
- on hardware configuration. If only config group 0 is defined,
- it will be used for all hardware configurations.
- Touch screen controller will use its onchip default config data
- if this property is not present.
- - goodix,cfg-data1 : Touch screen controller config data group 1. Ask vendor
- to provide that.
- - goodix,cfg-data2 : Touch screen controller config data group 2. Ask vendor
- to provide that.
- - goodix,cfg-data3 : Touch screen controller config data group 3. Ask vendor
- to provide that.
- - goodix,cfg-data4 : Touch screen controller config data group 4. Ask vendor
- to provide that.
- - goodix,cfg-data5 : Touch screen controller config data group 5. Ask vendor
- to provide that.
- - goodix,fw-name : Touch screen controller firmware file name.
- - goodix,slide-wakeup : To specify slide-wakeup property is enabled or not.
- - goodix,dbl-clk-wakeup : To specify dbl-clk-wakeup property is enabled or not.
- - goodix,change-x2y : To specify change-x2y property is enabled or not.
- - goodix,driver-send-cfg : To specify driver-send-cfg property is enabled or not.
- - goodix,have-touch-key : To specify have-touch-key property is enabled or not.
- - goodix,with-pen : To specify with-pen property is enabled or not.
-Example:
-i2c@f9927000 {
- goodix@5d {
- compatible = "goodix,gt9xx";
- reg = <0x5d>;
- interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2008>;
- reset-gpios = <&msmgpio 16 0x00>;
- interrupt-gpios = <&msmgpio 17 0x00>;
- avdd-supply = <&tp_power>;
- goodix,panel-coords = <0 0 720 1200>;
- goodix,display-coords = <0 0 720 1080>;
- goodix,button-map= <158 102 139>;
- goodix,product-id = "915";
- goodix,cfg-data0 = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
- 00 01 1B 14 0C 14 00 00 01 00
- 00 00 00 00 00 00 00 00 00 00
- 00 00 02 04 06 08 0A 0C 0E 10
- 12 14 16 18 1A 1C FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF 00 02 04 06 08 0A 0C 0F
- 10 12 13 14 16 18 1C 1D 1E 1F
- 20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
- goodix,fw_name = "gtp_fw.bin";
- goodix,have-touch-key;
- goodix,driver-send-cfg;
- };
-};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cpp.txt b/Documentation/devicetree/bindings/media/video/msm-cpp.txt
index 2bd9fb840830..450e4d6ee8f0 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cpp.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cpp.txt
@@ -70,6 +70,13 @@ Optional properties:
The first entry is register offset and second entry is register value.
- qcom,micro-reset: Boolean flag indicating if micro reset need to be enabled.
This needs to present on platforms that support this feature.
+- qcom,cpp-cx-ipeak: To handle Cx peak current limit.
+ <phandle bit>
+ phandle - phandle of cx ipeak device node
+ bit - bit number of client in relevant register
+ This is used to access Cx ipeak HW module to limit the current drawn by
+ various subsystem blocks on Cx power rail. CPP set their bit in tcsr register
+ if it is going to cross its own threshold.
Example:
@@ -105,6 +112,7 @@ Example:
"micro_iface_clk", "camss_ahb_clk";
"smmu_cpp_axi_clk", "cpp_vbif_ahb_clk";
qcom,clock-rates = <0 0 0 0 465000000 0 0 465000000 0 0 0 0>;
+ qcom,cpp-cx-ipeak = <&cx_ipeak_lm 2>;
qcom,min-clock-rate = <320000000>;
qcom,bus-master = <1>;
qcom,vbif-qos-setting = <0x20 0x10000000>,
diff --git a/Documentation/devicetree/bindings/media/video/msm-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
index dac22f30bf1d..aaf13442fcf1 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vfe.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
@@ -23,6 +23,7 @@ Required properties for child node:
Only needed for child node.
- "vfe" - Required.
- "vfe_vbif" - Optional for "vfe32". Required for "vfe40".
+ - "vfe_fuse" - Optional.
- interrupts : should contain the vfe interrupt.
- interrupt-names : should specify relevant names to each interrupts
property defined.
@@ -52,9 +53,10 @@ Example:
vfe0: qcom,vfe0@fda10000 {
cell-index = <0>;
compatible = "qcom,vfe44";
- reg = <0xfda10000 0x1000>;
- <0xfda40000 0x200>;
- reg-names = "vfe", "vfe_vbif";
+ reg = <0xfda10000 0x1000>,
+ <0xfda40000 0x200>,
+ <0x7801a4 0x8>;
+ reg-names = "vfe", "vfe_vbif", "vfe_fuse";
interrupts = <0 57 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe>;
@@ -105,9 +107,10 @@ vfe0: qcom,vfe0@fda10000 {
vfe1: qcom,vfe1@fda14000 {
cell-index = <1>;
compatible = "qcom,vfe44";
- reg = <0xfda14000 0x1000>;
- <0xfda40000 0x200>;
- reg-names = "vfe", "vfe_vbif";
+ reg = <0xfda14000 0x1000>,
+ <0xfda40000 0x200>,
+ <0x7801a4 0x8>;
+ reg-names = "vfe", "vfe_vbif", "vfe_fuse";
interrupts = <0 58 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe>;
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
index 9de6857a2643..a34cbde456e4 100644
--- a/Documentation/devicetree/bindings/misc/qpnp-misc.txt
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -17,23 +17,9 @@ Optional properties:
"qcom,pwm-sel" property.
Example:
- qcom,spmi@fc4c0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <3>;
-
- qcom,pm8941@0 {
- spmi-slave-container;
- reg = <0x0>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- qcom,misc@900 {
- compatible = "qcom,qpnp-misc";
- reg = <0x900 0x100>;
- qcom,pwm-sel = <2>;
- qcom,enable-gp-driver;
- };
- }
+ qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ qcom,pwm-sel = <2>;
+ qcom,enable-gp-driver;
};
diff --git a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
index a7848153f83c..6574cfe30ce5 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
@@ -10,6 +10,7 @@ pwm(pulse width modulation) and audio.
Required Properties:
- compatible: must be "qcom,qpnp-haptic"
- reg: address of device
+ - qcom,pmic-revid : phandle to fetch PMIC revid
- qcom,actuator-type: must be one of "erm" or "lra"
- qcom,play-mode : must be one of "buffer", "direct", "pwm" or "audio"
@@ -63,7 +64,13 @@ Optional properties when qcom,actuator-type is "lra"
"max-qwd" : Maximum QWD
"zxd-eop" : ZXD + End of pattern (This is the Default)
- qcom,lra-high-z : High Z configuration for auto resonance. Possible string values are
- "none", "opt1", "opt2" and "opt3" (default)
+ "none", "opt1", "opt2" and "opt3" (default). For PM660,
+ "opt0" is valid value for 1 LRA period.
+ - qcom,lra-qwd-drive-duration : Drive duration of LRA in QWD mode for PM660.
+ Possible values are: 0: 1/4 LRA PERIOD and 1: 3/8 LRA PERIOD
+ - qcom,lra-calibrate-at-eop : To calibrate at End of Pattern for PM660.
+ Possible values are: 0 to disable and 1 to enable Calibration
+ at End of Pattern
- qcom,lra-res-cal-period : Auto resonance calibration period. The values range from
4 to 32(default)
- qcom,perform-lra-auto-resonance-search : boolean, define this property if:
@@ -109,6 +116,7 @@ Example:
interrupts = <0x3 0xc0 0x0>,
<0x3 0xc0 0x1>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pm660_revid>;
vcc_pon-supply = <&pon_perph_reg>;
qcom,play-mode = "direct";
qcom,wave-play-rate-us = <5263>;
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index db37dc6f31bb..a2e7311705e3 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -123,6 +123,7 @@ dtb-$(CONFIG_ARCH_MSM8998) += msm8998-sim.dtb \
apq8998-v2-mtp.dtb \
apq8998-v2-cdp.dtb \
apq8998-v2-qrd.dtb \
+ apq8998-v2-qrd-skuk-hdk.dtb \
msm8998-v2.1-mtp.dtb \
msm8998-v2.1-cdp.dtb \
msm8998-v2.1-qrd.dtb \
diff --git a/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts b/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts
new file mode 100644
index 000000000000..6406fe52242d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/apq8998-v2-qrd-skuk-hdk.dts
@@ -0,0 +1,23 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "apq8998-v2.dtsi"
+#include "msm8998-qrd-skuk-hdk.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ 8998 SKUK HDK";
+ compatible = "qcom,msm8998-qrd", "qcom,msm8998", "qcom,qrd";
+ qcom,board-id = <0x06000b 0x10>;
+};
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
index ebd73ceaa8ce..f4829eb7f799 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -82,7 +82,6 @@
15 01 00 00 10 00 02 ff 24
15 01 00 00 10 00 02 fb 01
15 01 00 00 10 00 02 c6 06
- 15 01 00 00 10 00 02 9d 30 /* Enable IMGSWAP */
15 01 00 00 10 00 02 ff 10
05 01 00 00 a0 00 02 11 00
05 01 00 00 a0 00 02 29 00];
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-rm67195-amoled-fhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-rm67195-amoled-fhd-cmd.dtsi
new file mode 100644
index 000000000000..8757dad98b3e
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/dsi-panel-rm67195-amoled-fhd-cmd.dtsi
@@ -0,0 +1,124 @@
+/* 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.
+ */
+
+&mdss_mdp {
+ dsi_rm67195_amoled_fhd_cmd: qcom,mdss_dsi_rm67195_amoled_fhd_cmd{
+ qcom,mdss-dsi-panel-name =
+ "rm67195 amoled fhd cmd mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <32>;
+ qcom,mdss-dsi-h-back-porch = <40>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <16>;
+ qcom,mdss-dsi-v-front-porch = <8>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-on-command = [
+ 15 01 00 00 00 00 02 fe 0d
+ 15 01 00 00 00 00 02 42 00
+ 15 01 00 00 00 00 02 18 08
+ 15 01 00 00 00 00 02 08 41
+ 15 01 00 00 00 00 02 46 02
+ 15 01 00 00 00 00 02 1e 04
+ 15 01 00 00 02 00 02 1e 00
+ 15 01 00 00 00 00 02 fe 0a
+ 15 01 00 00 00 00 02 24 17
+ 15 01 00 00 00 00 02 04 07
+ 15 01 00 00 00 00 02 1a 0c
+ 15 01 00 00 02 00 02 0f 44
+ 15 01 00 00 00 00 02 fe 0b
+ 15 01 00 00 00 00 02 28 40
+ 15 01 00 00 02 00 02 29 4f
+ 15 01 00 00 00 00 02 fe 04
+ 15 01 00 00 00 00 02 4f 1b
+ 15 01 00 00 02 00 02 50 2f
+ 15 01 00 00 00 00 02 fe 09
+ 15 01 00 00 00 00 02 00 08
+ 15 01 00 00 00 00 02 01 08
+ 15 01 00 00 00 00 02 02 00
+ 15 01 00 00 00 00 02 03 00
+ 15 01 00 00 00 00 02 04 10
+ 15 01 00 00 00 00 02 05 00
+ 15 01 00 00 00 00 02 06 08
+ 15 01 00 00 00 00 02 07 08
+ 15 01 00 00 00 00 02 08 00
+ 15 01 00 00 00 00 02 12 24
+ 15 01 00 00 00 00 02 13 49
+ 15 01 00 00 00 00 02 14 92
+ 15 01 00 00 00 00 02 15 49
+ 15 01 00 00 00 00 02 16 92
+ 15 01 00 00 00 00 02 17 24
+ 15 01 00 00 00 00 02 18 24
+ 15 01 00 00 00 00 02 19 49
+ 15 01 00 00 00 00 02 1a 92
+ 15 01 00 00 00 00 02 1b 49
+ 15 01 00 00 00 00 02 1c 92
+ 15 01 00 00 00 00 02 1d 24
+ 15 01 00 00 00 00 02 1e 24
+ 15 01 00 00 00 00 02 1f 49
+ 15 01 00 00 00 00 02 20 92
+ 15 01 00 00 00 00 02 21 49
+ 15 01 00 00 00 00 02 22 92
+ 15 01 00 00 00 00 02 23 24
+ 15 01 00 00 00 00 02 9b 07
+ 15 01 00 00 02 00 02 9c a5
+ 15 01 00 00 00 00 02 fe 00
+ 15 01 00 00 00 00 02 c2 08
+ 15 01 00 00 02 00 02 35 00
+ 39 01 00 00 00 00 03 44 03 e8
+ 05 01 00 00 82 00 02 11 00
+ 05 01 00 00 14 00 02 29 00];
+
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 82 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_pulse";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-wr-mem-start = <0x2c>;
+ qcom,mdss-dsi-wr-mem-continue = <0x3c>;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-lp11-init;
+ 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,mdss-pan-physical-width-dimension = <70>;
+ qcom,mdss-pan-physical-height-dimension = <125>;
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 20>, <1 20>;
+ qcom,mdss-dsi-panel-orientation = "180";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-660.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-660.dtsi
index 874b97a3c965..33bd86654363 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-660.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
@@ -55,7 +55,7 @@
<GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock_rpmcc RPM_AGGR2_NOC_CLK>;
+ clocks = <&clock_rpmcc AGGR2_NOC_SMMU_CLK>;
clock-names = "smmu_aggr2_noc_clk";
#clock-cells = <1>;
};
diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index 9c4890a84a37..463d352f8791 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -607,6 +607,7 @@
interrupts = <0x1 0xc0 0x0 IRQ_TYPE_NONE>,
<0x1 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pm660_revid>;
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
qcom,vmax-mv = <3200>;
@@ -619,9 +620,9 @@
qcom,brake-pattern = [03 03 00 00];
qcom,use-play-irq;
qcom,use-sc-irq;
- qcom,lra-high-z = "opt1";
+ qcom,lra-high-z = "opt0";
qcom,lra-auto-res-mode = "qwd";
- qcom,lra-res-cal-period = <4>;
+ qcom,lra-calibrate-at-eop = <0>;
qcom,correct-lra-drive-freq;
qcom,misc-trim-error-rc19p2-clk-reg-present;
};
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
index 0356942cbe95..bcdbc4ed7c55 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -394,6 +394,9 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <0xec00 0x100>;
+ interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "sc-irq";
+
qcom,force-module-reenable;
lcdb_ldo_vreg: ldo {
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index fba0aed42146..111d0b51b6c2 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -631,6 +631,7 @@
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_NONE>,
<0x3 0xc0 0x1 IRQ_TYPE_NONE>;
interrupt-names = "sc-irq", "play-irq";
+ qcom,pmic-revid = <&pmi8998_revid>;
qcom,actuator-type = "lra";
qcom,play-mode = "direct";
qcom,vmax-mv = <3200>;
diff --git a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
index 3f81da7c3ebc..1396f27159df 100644
--- a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -308,6 +308,32 @@
23 1e 07 08 05 03 04 a0
23 1e 07 08 05 03 04 a0
23 18 07 08 04 03 04 a0];
+
+ qcom,mdss-dsi-on-command = [15 01 00 00 10 00 02 ff 10
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 ba 03
+ 15 01 00 00 10 00 02 e5 01
+ 15 01 00 00 10 00 02 35 00
+ 15 01 00 00 10 00 02 bb 10
+ 15 01 00 00 10 00 02 b0 03
+ 15 01 00 00 10 00 02 ff e0
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 6b 3d
+ 15 01 00 00 10 00 02 6c 3d
+ 15 01 00 00 10 00 02 6d 3d
+ 15 01 00 00 10 00 02 6e 3d
+ 15 01 00 00 10 00 02 6f 3d
+ 15 01 00 00 10 00 02 35 02
+ 15 01 00 00 10 00 02 36 72
+ 15 01 00 00 10 00 02 37 10
+ 15 01 00 00 10 00 02 08 c0
+ 15 01 00 00 10 00 02 ff 24
+ 15 01 00 00 10 00 02 fb 01
+ 15 01 00 00 10 00 02 c6 06
+ 15 01 00 00 10 00 02 9d 30 /* Enable IMGSWAP */
+ 15 01 00 00 10 00 02 ff 10
+ 05 01 00 00 a0 00 02 11 00
+ 05 01 00 00 a0 00 02 29 00];
};
&dsi_nt35597_dsc_video {
diff --git a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
index 144d319d9121..cc20c57a8099 100644
--- a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
@@ -75,6 +75,8 @@
qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
+ qcom,gpu-qtimer = <0x17921000 0x1000>; // base addr, size
+
qcom,tsens-name = "tsens_tz_sensor12";
/* Quirks */
diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi
new file mode 100644
index 000000000000..7ed28e4c8813
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi
@@ -0,0 +1,138 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8998-qrd-skuk.dtsi"
+#include "msm8998-camera-sensor-skuk-hdk.dtsi"
+
+&soc {
+ sound-tavil {
+ qcom,msm-mbhc-hphl-swh = <0>;
+ };
+};
+
+&pmx_mdss {
+ mdss_dsi_active: mdss_dsi_active {
+ mux {
+ pins = "gpio52", "gpio94";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52", "gpio94";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable = <0>; /* no pull */
+ };
+ };
+
+ mdss_dsi_suspend: mdss_dsi_suspend {
+ mux {
+ pins = "gpio52", "gpio94";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52", "gpio94";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "split_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-enable-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
+ qcom,platform-bklight-en-gpio-invert;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-enable-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
+ qcom,platform-bklight-en-gpio-invert;
+};
+
+&pmi8998_wled {
+ qcom,disp-type-amoled;
+};
+
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "amoled";
+ qcom,swire-control;
+};
+
+&pmi8998_gpios {
+ /* GPIO 1 for WLED power enable */
+ gpio@c000 {
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,out-strength = <1>;
+ qcom,src-sel = <0>;
+ qcom,invert = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&dsi_dual_s6e3ha3_amoled_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&i2c_5 {
+ status = "okay";
+ st_fts@49 {
+ compatible = "st,fts";
+ reg = <0x49>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 0x2008>;
+ vdd-supply = <&pm8998_l6>;
+ avdd-supply = <&pm8998_l28>;
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+ pinctrl-0 = <&ts_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ st,irq-gpio = <&tlmm 125 0x2008>;
+ st,reset-gpio = <&tlmm 89 0x00>;
+ st,regulator_dvdd = "vdd";
+ st,regulator_avdd = "avdd";
+ };
+};
+
+&soc {
+ /* HDK835 do not use improveTouch. If do not remove this node,
+ * legacy TOUCH could not work.
+ */
+ /delete-node/hbtp;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
index 73debc374fda..f3ba42e4dfd9 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
+++ b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
@@ -10,139 +10,13 @@
* GNU General Public License for more details.
*/
-
/dts-v1/;
#include "msm8998-v2.dtsi"
-#include "msm8998-qrd-skuk.dtsi"
-#include "msm8998-camera-sensor-skuk-hdk.dtsi"
+#include "msm8998-qrd-skuk-hdk.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM 8998 SKUK HDK";
compatible = "qcom,msm8998-qrd", "qcom,msm8998", "qcom,qrd";
qcom,board-id = <0x06000b 0x10>;
};
-
-&soc {
- sound-tavil {
- qcom,msm-mbhc-hphl-swh = <0>;
- };
-};
-
-&pmx_mdss {
- mdss_dsi_active: mdss_dsi_active {
- mux {
- pins = "gpio52", "gpio94";
- function = "gpio";
- };
-
- config {
- pins = "gpio52", "gpio94";
- drive-strength = <8>; /* 8 mA */
- bias-disable = <0>; /* no pull */
- };
- };
-
- mdss_dsi_suspend: mdss_dsi_suspend {
- mux {
- pins = "gpio52", "gpio94";
- function = "gpio";
- };
-
- config {
- pins = "gpio52", "gpio94";
- drive-strength = <2>; /* 2 mA */
- bias-pull-down; /* pull down */
- };
- };
-};
-
-&mdss_mdp {
- qcom,mdss-pref-prim-intf = "dsi";
-};
-
-&mdss_dsi {
- hw-config = "split_dsi";
-};
-
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 10 0>;
- qcom,platform-enable-gpio = <&tlmm 52 0>;
- qcom,platform-reset-gpio = <&tlmm 94 0>;
- qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
- qcom,platform-bklight-en-gpio-invert;
-};
-
-&mdss_dsi1 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_s6e3ha3_amoled_cmd>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 10 0>;
- qcom,platform-enable-gpio = <&tlmm 52 0>;
- qcom,platform-reset-gpio = <&tlmm 94 0>;
- qcom,platform-bklight-en-gpio = <&pmi8998_gpios 1 0>;
- qcom,platform-bklight-en-gpio-invert;
-};
-
-&pmi8998_wled {
- qcom,disp-type-amoled;
-};
-
-&labibb {
- status = "ok";
- qcom,qpnp-labibb-mode = "amoled";
- qcom,swire-control;
-};
-
-&pmi8998_gpios {
- /* GPIO 1 for WLED power enable */
- gpio@c000 {
- qcom,mode = <1>;
- qcom,output-type = <0>;
- qcom,pull = <5>;
- qcom,vin-sel = <0>;
- qcom,out-strength = <1>;
- qcom,src-sel = <0>;
- qcom,invert = <0>;
- qcom,master-en = <1>;
- status = "okay";
- };
-};
-
-&dsi_dual_s6e3ha3_amoled_cmd {
- qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
- qcom,mdss-dsi-bl-min-level = <1>;
- qcom,mdss-dsi-bl-max-level = <255>;
- qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-};
-
-&i2c_5 {
- status = "okay";
- st_fts@49 {
- compatible = "st,fts";
- reg = <0x49>;
- interrupt-parent = <&tlmm>;
- interrupts = <125 0x2008>;
- vdd-supply = <&pm8998_l6>;
- avdd-supply = <&pm8998_l28>;
- pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
- pinctrl-0 = <&ts_active>;
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- st,irq-gpio = <&tlmm 125 0x2008>;
- st,reset-gpio = <&tlmm 89 0x00>;
- st,regulator_dvdd = "vdd";
- st,regulator_avdd = "avdd";
- };
-};
-
-&soc {
- /* HDK835 do not use improveTouch. If do not remove this node,
- * legacy TOUCH could not work.
- */
- /delete-node/hbtp;
-};
diff --git a/arch/arm/boot/dts/qcom/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-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index 1fdfba6ddf2c..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 {
diff --git a/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts b/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
index d535d62e521c..c2408ba7bf76 100644
--- a/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
+++ b/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
@@ -16,6 +16,7 @@
#include "sdm630.dtsi"
#include "sdm630-qrd.dtsi"
#include "msm-pm660a.dtsi"
+#include "sdm660-internal-codec.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660A QRD";
@@ -23,3 +24,30 @@
qcom,board-id = <0x0002000b 0x00>;
qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
};
+
+&int_codec {
+ qcom,model = "sdm660-snd-card-skush";
+ /delete-property/ qcom,us-euro-gpios;
+ qcom,audio-routing =
+ "RX_BIAS", "INT_MCLK0",
+ "SPK_RX_BIAS", "INT_MCLK0",
+ "INT_LDO_H", "INT_MCLK0",
+ "MIC BIAS External2", "Headset Mic",
+ "AMIC2", "MIC BIAS External2",
+ "MIC BIAS External", "Digital Mic1",
+ "DMIC1", "MIC BIAS External",
+ "MIC BIAS External", "Digital Mic3",
+ "DMIC3", "MIC BIAS External",
+ "MIC BIAS External", "Digital Mic4",
+ "DMIC4", "MIC BIAS External",
+ "SpkrLeft IN", "SPK1 OUT",
+ "PDM_IN_RX1", "PDM_OUT_RX1",
+ "PDM_IN_RX2", "PDM_OUT_RX2",
+ "PDM_IN_RX3", "PDM_OUT_RX3",
+ "ADC1_IN", "ADC1_OUT",
+ "ADC2_IN", "ADC2_OUT",
+ "ADC3_IN", "ADC3_OUT";
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_213_en>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index f21707db590a..cb083c0a8aa0 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -318,6 +318,10 @@
};
&soc {
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
+
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index ce088c372eea..623ca54de94b 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -376,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";
@@ -734,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>;
@@ -1205,7 +1208,7 @@
qcom,wan-rx-ring-size = <192>; /* IPA WAN-rx-ring-size*/
qcom,lan-rx-ring-size = <192>; /* IPA LAN-rx-ring-size*/
clocks = <&clock_rpmcc RPM_IPA_CLK>,
- <&clock_rpmcc RPM_AGGR2_NOC_CLK>;
+ <&clock_rpmcc AGGR2_NOC_SMMU_CLK>;
clock-names = "core_clk", "smmu_clk";
qcom,arm-smmu;
qcom,smmu-disable-htw;
@@ -1798,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>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
index 0524935b9a30..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",
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
index e6bd0c06e444..14b009656890 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -392,6 +392,7 @@
<106 512 0 0>,
<106 512 0 0>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,cpp-cx-ipeak = <&cx_ipeak_lm 2>;
resets = <&clock_mmss CAMSS_MICRO_BCR>;
reset-names = "micro_iface_reset";
qcom,src-clock-rates = <120000000 256000000 384000000
@@ -577,6 +578,7 @@
<29 512 0 0>,
<29 512 100000000 100000000>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,vfe-cx-ipeak = <&cx_ipeak_lm 2>;
};
vfe1: qcom,vfe1@ca14000 {
@@ -657,6 +659,7 @@
<29 512 0 0>,
<29 512 100000000 100000000>;
qcom,msm-bus-vector-dyn-vote;
+ qcom,vfe-cx-ipeak = <&cx_ipeak_lm 2>;
};
qcom,vfe {
diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
index ad30af3376c7..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>,
diff --git a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
index 51903c8b028d..76023a72ed96 100644
--- a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi
@@ -1133,14 +1133,6 @@
<&funnel_qatb_in_tpda>;
};
};
- port@1 {
- reg = <1>;
- tpda_in_funnel_gpu_dl: endpoint {
- slave-mode;
- remote-endpoint =
- <&funnel_gpu_dl_out_tpda>;
- };
- };
port@2 {
reg = <2>;
tpda_in_funnel_dlct: endpoint {
@@ -1200,60 +1192,6 @@
};
};
- funnel_gpu_dl: funnel@7140000 {
- compatible = "arm,primecell";
- arm,primecell-periphid = <0x0003b908>;
-
- reg = <0x7140000 0x1000>;
- reg-names = "funnel-base";
-
- coresight-name = "coresight-funnel-gpu-dl";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- funnel_gpu_dl_out_tpda: endpoint {
- remote-endpoint =
- <&tpda_in_funnel_gpu_dl>;
- };
- };
- port@2 {
- reg = <0>;
- funnel_gpu_dl_in_tpdm_gpu: endpoint {
- slave-mode;
- remote-endpoint =
- <&tpdm_gpu_out_funnel_gpu_dl>;
- };
- };
- };
- };
-
- tpdm_gpu: tpdm@7111000 {
- status = "disabled";
- compatible = "qcom,coresight-tpdm";
- reg = <0x7111000 0x1000>;
- reg-names = "tpdm-base";
-
- coresight-name = "coresight-tpdm-gpu";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
-
- port{
- tpdm_gpu_out_funnel_gpu_dl: endpoint {
- remote-endpoint = <&funnel_gpu_dl_in_tpdm_gpu>;
- };
- };
- };
-
tpdm_vsense: tpdm@7038000 {
compatible = "qcom,coresight-tpdm";
reg = <0x7038000 0x1000>;
@@ -1613,14 +1551,6 @@
<&tpdm_dlct_out_funnel_dlct>;
};
};
- port@3 {
- reg = <3>;
- funnel_dlct_in_funnel_wcss: endpoint {
- slave-mode;
- remote-endpoint =
- <&funnel_wcss_out_funnel_dlct>;
- };
- };
port@4 {
reg = <1>;
funnel_dlct_in_audio_etm0: endpoint {
@@ -1751,94 +1681,4 @@
};
};
};
-
- funnel_wcss: funnel@719e000 {
- compatible = "arm,primecell";
- arm,primecell-periphid = <0x0003b908>;
-
- reg = <0x719e000 0x1000>;
- reg-names = "funnel-base";
-
- coresight-name = "coresight-funnel-wcss";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- funnel_wcss_out_funnel_dlct: endpoint {
- remote-endpoint =
- <&funnel_dlct_in_funnel_wcss>;
- };
- };
- port@1 {
- reg = <1>;
- funnel_wcss_in_tpda_wcss: endpoint {
- slave-mode;
- remote-endpoint =
- <&tpda_wcss_out_funnel_wcss>;
- };
- };
- };
- };
-
- tpda_wcss: tpda@719d000 {
- status = "disabled";
- compatible = "qcom,coresight-tpda";
- reg = <0x719d000 0x1000>;
- reg-names = "tpda-base";
-
- coresight-name = "coresight-tpda-wcss";
-
- qcom,tpda-atid = <70>;
- qcom,dsb-elem-size = <0 32>;
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- tpda_wcss_out_funnel_wcss: endpoint {
- remote-endpoint =
- <&funnel_wcss_in_tpda_wcss>;
- };
- };
- port@1 {
- reg = <0>;
- tpda_wcss_in_tpdm_wcss: endpoint {
- slave-mode;
- remote-endpoint =
- <&tpdm_wcss_out_tpda_wcss>;
- };
- };
- };
- };
-
- tpdm_wcss: tpdm@719c000 {
- status = "disabled";
- compatible = "qcom,coresight-tpdm";
- reg = <0x719c000 0x1000>;
- reg-names = "tpdm-base";
-
- coresight-name = "coresight-tpdm-wcss";
-
- clocks = <&clock_rpmcc RPM_QDSS_CLK>,
- <&clock_rpmcc RPM_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
-
- port{
- tpdm_wcss_out_tpda_wcss: endpoint {
- remote-endpoint = <&tpda_wcss_in_tpdm_wcss>;
- };
- };
- };
};
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..ff51db728d85 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -24,6 +24,7 @@
#include "dsi-panel-nt35695b-truly-fhd-cmd.dtsi"
#include "dsi-panel-truly-1080p-cmd.dtsi"
#include "dsi-panel-truly-1080p-video.dtsi"
+#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -67,7 +68,7 @@
qcom,panel-supply-entry@0 {
reg = <0>;
qcom,supply-name = "wqhd-vddio";
- qcom,supply-min-voltage = <1880000>;
+ qcom,supply-min-voltage = <1800000>;
qcom,supply-max-voltage = <1950000>;
qcom,supply-enable-load = <32000>;
qcom,supply-disable-load = <80>;
@@ -117,7 +118,7 @@
qcom,panel-supply-entry@0 {
reg = <0>;
qcom,supply-name = "wqhd-vddio";
- qcom,supply-min-voltage = <1880000>;
+ qcom,supply-min-voltage = <1800000>;
qcom,supply-max-voltage = <1950000>;
qcom,supply-enable-load = <32000>;
qcom,supply-disable-load = <80>;
@@ -133,6 +134,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 {
@@ -256,3 +261,13 @@
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "bta_check";
};
+
+&dsi_rm67195_amoled_fhd_cmd {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 19 07 08 05 03 04 a0];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+};
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-pm660a-qrd.dts b/arch/arm/boot/dts/qcom/sdm660-pm660a-qrd.dts
index 48e02bbdfbfe..d9d74ea31d3d 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pm660a-qrd.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-pm660a-qrd.dts
@@ -23,3 +23,34 @@
qcom,board-id = <0x0012000b 0>;
qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
};
+
+&pm660a_oledb {
+ status = "okay";
+ qcom,oledb-default-voltage-mv = <6400>;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_rm67195_amoled_fhd_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+ qcom,platform-reset-gpio = <&tlmm 53 0>;
+ qcom,platform-te-gpio = <&tlmm 59 0>;
+};
+
+&dsi_rm67195_amoled_fhd_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_labibb_amoled>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index 417df33047f6..001ae6e4fc04 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -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;
@@ -1430,7 +1435,7 @@
qcom,wan-rx-ring-size = <192>; /* IPA WAN-rx-ring-size*/
qcom,lan-rx-ring-size = <192>; /* IPA LAN-rx-ring-size*/
clocks = <&clock_rpmcc RPM_IPA_CLK>,
- <&clock_rpmcc RPM_AGGR2_NOC_CLK>;
+ <&clock_rpmcc AGGR2_NOC_SMMU_CLK>;
clock-names = "core_clk", "smmu_clk";
qcom,arm-smmu;
qcom,smmu-disable-htw;
@@ -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..21650ead5a34 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
@@ -379,6 +380,32 @@ CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_VIDC_VMEM=y
CONFIG_MSM_VIDC_GOVERNORS=y
@@ -460,8 +487,6 @@ CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SDHCI_MSM_ICE=y
CONFIG_MMC_CQ_HCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_QPNP_FLASH_V2=y
CONFIG_LEDS_QPNP_WLED=y
@@ -560,6 +585,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..02b15745e882 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
@@ -378,6 +379,32 @@ CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_VIDC_VMEM=y
CONFIG_MSM_VIDC_GOVERNORS=y
@@ -460,8 +487,6 @@ CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SDHCI_MSM_ICE=y
CONFIG_MMC_CQ_HCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_QPNP_FLASH_V2=y
CONFIG_LEDS_QPNP_WLED=y
@@ -565,6 +590,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 740584b30c60..cf073304e0b5 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -239,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
@@ -576,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 f6c53a1e1ace..46786b90e067 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_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
@@ -597,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/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c
index bf3a24b3eb01..11bd3aae340b 100644
--- a/drivers/firmware/qcom/tz_log.c
+++ b/drivers/firmware/qcom/tz_log.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -57,6 +57,11 @@
* TZ 3.X version info
*/
#define QSEE_VERSION_TZ_3_X 0x800000
+
+#define TZBSP_AES_256_ENCRYPTED_KEY_SIZE 256
+#define TZBSP_NONCE_LEN 12
+#define TZBSP_TAG_LEN 16
+
/*
* VMID Table
*/
@@ -125,6 +130,14 @@ struct tzdbg_int_t {
uint64_t int_count[TZBSP_MAX_CPU_COUNT]; /* # of times seen per CPU */
};
+/* warm boot reason for cores */
+struct tzbsp_diag_wakeup_info_t {
+ /* Wake source info : APCS_GICC_HPPIR */
+ uint32_t HPPIR;
+ /* Wake source info : APCS_GICC_AHPPIR */
+ uint32_t AHPPIR;
+};
+
/*
* Log ring buffer position
*/
@@ -179,6 +192,10 @@ struct tzdbg_t {
* Ring Buffer Length
*/
uint32_t ring_len;
+
+ /* Offset for Wakeup info */
+ uint32_t wakeup_info_off;
+
/*
* VMID to EE Mapping
*/
@@ -193,6 +210,16 @@ struct tzdbg_t {
struct tzdbg_reset_info_t reset_info[TZBSP_MAX_CPU_COUNT];
uint32_t num_interrupts;
struct tzdbg_int_t int_info[TZBSP_DIAG_INT_NUM];
+
+ /* Wake up info */
+ struct tzbsp_diag_wakeup_info_t wakeup_info[TZBSP_MAX_CPU_COUNT];
+
+ uint8_t key[TZBSP_AES_256_ENCRYPTED_KEY_SIZE];
+
+ uint8_t nonce[TZBSP_NONCE_LEN];
+
+ uint8_t tag[TZBSP_TAG_LEN];
+
/*
* We need at least 2K for the ring buffer
*/
@@ -731,10 +758,16 @@ static ssize_t tzdbgfs_read(struct file *file, char __user *buf,
int len = 0;
int *tz_id = file->private_data;
- memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
+ if (*tz_id == TZDBG_BOOT || *tz_id == TZDBG_RESET ||
+ *tz_id == TZDBG_INTERRUPT || *tz_id == TZDBG_GENERAL ||
+ *tz_id == TZDBG_VMID || *tz_id == TZDBG_LOG)
+ memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
debug_rw_buf_size);
- memcpy_fromio((void *)tzdbg.hyp_diag_buf, tzdbg.hyp_virt_iobase,
+
+ if (*tz_id == TZDBG_HYP_GENERAL || *tz_id == TZDBG_HYP_LOG)
+ memcpy_fromio((void *)tzdbg.hyp_diag_buf, tzdbg.hyp_virt_iobase,
tzdbg.hyp_debug_rw_buf_size);
+
switch (*tz_id) {
case TZDBG_BOOT:
len = _disp_tz_boot_stats();
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index f821a81c53a6..532ff8677259 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1683,7 +1683,7 @@ static struct drm_driver msm_driver = {
.debugfs_cleanup = msm_debugfs_cleanup,
#endif
.ioctls = msm_ioctls,
- .num_ioctls = DRM_MSM_NUM_IOCTLS,
+ .num_ioctls = ARRAY_SIZE(msm_ioctls),
.fops = &fops,
.name = "msm_drm",
.desc = "MSM Snapdragon DRM",
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/hid/hid-core.c b/drivers/hid/hid-core.c
index 577183bea07c..34ea83d067af 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2011,7 +2011,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 99de4002275e..075c18e0e4ae 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1206,18 +1206,6 @@ config TOUCHSCREEN_IT7260_I2C
To compile this driver as a module, choose M here: the
module will be called it7258_ts_i2c.
-config TOUCHSCREEN_GT9XX
- bool "Goodix touchpanel GT9xx series"
- depends on I2C
- help
- Say Y here if you have a Goodix GT9xx touchscreen.
- Gt9xx controllers are multi touch controllers which can
- report 5 touches at a time.
-
- If unsure, say N.
-
-source "drivers/input/touchscreen/gt9xx/Kconfig"
-
config TOUCHSCREEN_ST
bool "STMicroelectronics Touchscreen Driver"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a32132cffe92..2e0161cf95bc 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -98,5 +98,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
-obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/
obj-$(CONFIG_TOUCHSCREEN_ST) += st/
diff --git a/drivers/input/touchscreen/gt9xx/Kconfig b/drivers/input/touchscreen/gt9xx/Kconfig
deleted file mode 100644
index 2e1b5ba567a0..000000000000
--- a/drivers/input/touchscreen/gt9xx/Kconfig
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Goodix GT9xx Touchscreen driver
-#
-
-config GT9XX_TOUCHPANEL_DRIVER
- tristate "Goodix GT9xx touchpanel driver"
- depends on TOUCHSCREEN_GT9XX
- default n
- help
- This is the main file for touchpanel driver for Goodix GT9xx
- touchscreens.
-
- Say Y here if you have a Goodix GT9xx touchscreen connected
- to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called gt9xx.
-
-config GT9XX_TOUCHPANEL_UPDATE
- tristate "Goodix GT9xx touchpanel auto update support"
- depends on GT9XX_TOUCHPANEL_DRIVER
- default n
- help
- This enables support for firmware update for Goodix GT9xx
- touchscreens.
-
- Say Y here if you have a Goodix GT9xx touchscreen connected
- to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called gt9xx_update.
-
-config GT9XX_TOUCHPANEL_DEBUG
- tristate "Goodix GT9xx Tools for debuging"
- depends on GT9XX_TOUCHPANEL_DRIVER
- default n
- help
- This is application debug interface support for Goodix GT9xx
- touchscreens.
-
- Say Y here if you want to have a Android app debug interface
- to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called gt9xx_tool.
diff --git a/drivers/input/touchscreen/gt9xx/Makefile b/drivers/input/touchscreen/gt9xx/Makefile
deleted file mode 100644
index 482d869a2d37..000000000000
--- a/drivers/input/touchscreen/gt9xx/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#gt915 touchpanel driver
-
-
-obj-$(CONFIG_GT9XX_TOUCHPANEL_DRIVER) += gt9xx.o
-#gt915 update file
-obj-$(CONFIG_GT9XX_TOUCHPANEL_UPDATE) += gt9xx_update.o
-#debug tool
-obj-$(CONFIG_GT9XX_TOUCHPANEL_DEBUG) += goodix_tool.o
diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c
deleted file mode 100644
index ded8c88fdac9..000000000000
--- a/drivers/input/touchscreen/gt9xx/goodix_tool.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/* drivers/input/touchscreen/goodix_tool.c
- *
- * 2010 - 2012 Goodix Technology.
- * 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be a reference
- * to you, when you are integrating the GOODiX's CTP IC into your system,
- * 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.
- *
- * Version:1.6
- * V1.0:2012/05/01,create file.
- * V1.2:2012/06/08,modify some warning.
- * V1.4:2012/08/28,modified to support GT9XX
- * V1.6:new proc name
- */
-
-#include "gt9xx.h"
-#include <linux/mutex.h>
-#include <linux/proc_fs.h>
-#include <linux/debugfs.h>
-
-#define DATA_LENGTH_UINT 512
-#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *))
-static char procname[20] = {0};
-
-struct st_cmd_head {
- u8 wr; /* write read flag 0:R 1:W 2:PID 3: */
- u8 flag; /* 0:no need flag/int 1: need flag 2:need int */
- u8 flag_addr[2];/* flag address */
- u8 flag_val; /* flag val */
- u8 flag_relation; /* flag_val:flag 0:not equal 1:equal 2:> 3:< */
- u16 circle; /* polling cycle */
- u8 times; /* plling times */
- u8 retry; /* I2C retry times */
- u16 delay; /* delay before read or after write */
- u16 data_len; /* data length */
- 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 struct i2c_client *gt_client;
-
-static struct proc_dir_entry *goodix_proc_entry;
-
-static struct mutex lock;
-
-static s32 (*tool_i2c_read)(u8 *, u16);
-static s32 (*tool_i2c_write)(u8 *, u16);
-
-s32 data_length;
-s8 ic_type[16] = {0};
-
-static void tool_set_proc_name(char *procname)
-{
- char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May",
- "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- char date[20] = {0};
- char month[4] = {0};
- int i = 0, n_month = 1, n_day = 0, n_year = 0, ret;
-
- ret = sscanf(date, "%s %d %d", month, &n_day, &n_year);
- if (!ret)
- return;
- for (i = 0; i < 12; ++i) {
- if (!memcmp(months[i], month, 3)) {
- n_month = i+1;
- break;
- }
- }
-
- snprintf(procname, 20, "gmnode%04d%02d%02d", n_year, n_month, n_day);
-}
-
-static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
-{
- s32 ret = -1;
- u8 i = 0;
- struct i2c_msg msgs[2] = {
- {
- .flags = !I2C_M_RD,
- .addr = gt_client->addr,
- .len = cmd_head.addr_len,
- .buf = &buf[0],
- },
- {
- .flags = I2C_M_RD,
- .addr = gt_client->addr,
- .len = len,
- .buf = &buf[GTP_ADDR_LENGTH],
- },
- };
-
- for (i = 0; i < cmd_head.retry; i++) {
- ret = i2c_transfer(gt_client->adapter, msgs, 2);
- if (ret > 0)
- break;
- }
-
- if (i == cmd_head.retry) {
- dev_err(&gt_client->dev, "I2C read retry limit over\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
-{
- s32 ret = -1;
- u8 i = 0;
- struct i2c_msg msg = {
- .flags = !I2C_M_RD,
- .addr = gt_client->addr,
- .len = len,
- .buf = buf,
- };
-
- for (i = 0; i < cmd_head.retry; i++) {
- ret = i2c_transfer(gt_client->adapter, &msg, 1);
- if (ret > 0)
- break;
- }
-
- if (i == cmd_head.retry) {
- dev_err(&gt_client->dev, "I2C write retry limit over\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static s32 tool_i2c_read_with_extra(u8 *buf, u16 len)
-{
- s32 ret = -1;
- u8 pre[2] = {0x0f, 0xff};
- u8 end[2] = {0x80, 0x00};
-
- tool_i2c_write_no_extra(pre, 2);
- ret = tool_i2c_read_no_extra(buf, len);
- tool_i2c_write_no_extra(end, 2);
-
- return ret;
-}
-
-static s32 tool_i2c_write_with_extra(u8 *buf, u16 len)
-{
- s32 ret = -1;
- u8 pre[2] = {0x0f, 0xff};
- u8 end[2] = {0x80, 0x00};
-
- tool_i2c_write_no_extra(pre, 2);
- ret = tool_i2c_write_no_extra(buf, len);
- tool_i2c_write_no_extra(end, 2);
-
- return ret;
-}
-
-static void register_i2c_func(void)
-{
- if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105")
- && strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800")
- && strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811")
- && strcmp(ic_type, "GTxxx")) {
- tool_i2c_read = tool_i2c_read_with_extra;
- tool_i2c_write = tool_i2c_write_with_extra;
- pr_debug("I2C function: with pre and end cmd\n");
- } else {
- tool_i2c_read = tool_i2c_read_no_extra;
- tool_i2c_write = tool_i2c_write_no_extra;
- pr_info("I2C function: without pre and end cmd\n");
- }
-}
-
-static void unregister_i2c_func(void)
-{
- tool_i2c_read = NULL;
- tool_i2c_write = NULL;
- pr_info("I2C function: unregister i2c transfer function\n");
-}
-
-void uninit_wr_node(void)
-{
- cmd_head.data = NULL;
- unregister_i2c_func();
- proc_remove(goodix_proc_entry);
-}
-
-static u8 relation(u8 src, u8 dst, u8 rlt)
-{
- u8 ret = 0;
-
- switch (rlt) {
-
- case 0:
- ret = (src != dst) ? true : false;
- break;
-
- case 1:
- ret = (src == dst) ? true : false;
- pr_debug("equal:src:0x%02x dst:0x%02x ret:%d\n",
- src, dst, (s32)ret);
- break;
-
- case 2:
- ret = (src > dst) ? true : false;
- break;
-
- case 3:
- ret = (src < dst) ? true : false;
- break;
-
- case 4:
- ret = (src & dst) ? true : false;
- break;
-
- case 5:
- ret = (!(src | dst)) ? true : false;
- break;
-
- default:
- ret = false;
- break;
- }
-
- return ret;
-}
-
-/*
- * Function:
- * Comfirm function.
- * Input:
- * None.
- * Output:
- * Return write length.
- */
-static u8 comfirm(void)
-{
- s32 i = 0;
- u8 buf[32];
-
- memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
-
- for (i = 0; i < cmd_head.times; i++) {
- if (tool_i2c_read(buf, 1) <= 0) {
- dev_err(&gt_client->dev, "Read flag data failed");
- return FAIL;
- }
- if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val,
- cmd_head.flag_relation)) {
- pr_debug("value at flag addr:0x%02x\n",
- buf[GTP_ADDR_LENGTH]);
- pr_debug("flag value:0x%02x\n", cmd_head.flag_val);
- break;
- }
-
- msleep(cmd_head.circle);
- }
-
- if (i >= cmd_head.times) {
- dev_err(&gt_client->dev, "Didn't get the flag to continue");
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
-static s32 fill_update_info(char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- u8 buf[4];
-
- buf[0] = show_len >> 8;
- buf[1] = show_len & 0xff;
- buf[2] = total_len >> 8;
- buf[3] = total_len & 0xff;
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, sizeof(buf));
-}
-#else
-static s32 fill_update_info(char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- return -ENODEV;
-}
-#endif
-
-/*
- * Function:
- * Goodix tool write function.
- * Input:
- * standard proc write function param.
- * Output:
- * Return write length.
- */
-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);
- if (ret) {
- dev_err(&gt_client->dev, "copy_from_user failed");
- ret = -EFAULT;
- goto exit;
- }
-
- dev_dbg(&gt_client->dev,
- "wr: 0x%02x, flag:0x%02x, flag addr:0x%02x%02x\n", cmd_head.wr,
- cmd_head.flag, cmd_head.flag_addr[0], cmd_head.flag_addr[1]);
- dev_dbg(&gt_client->dev,
- "flag val:0x%02x, flag rel:0x%02x,\n", cmd_head.flag_val,
- cmd_head.flag_relation);
- dev_dbg(&gt_client->dev, "circle:%u, times:%u, retry:%u, delay:%u\n",
- (s32) cmd_head.circle, (s32) cmd_head.times,
- (s32) cmd_head.retry, (s32)cmd_head.delay);
- dev_dbg(&gt_client->dev,
- "data len:%u, addr len:%u, addr:0x%02x%02x, write len: %u\n",
- (s32)cmd_head.data_len, (s32)cmd_head.addr_len,
- cmd_head.addr[0], cmd_head.addr[1], (s32)count);
-
- if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) {
- dev_err(&gt_client->dev, "data len %u > data buff %d, rejected\n",
- cmd_head.data_len, (data_length - GTP_ADDR_LENGTH));
- ret = -EINVAL;
- goto exit;
- }
-
- if (cmd_head.wr == GTP_RW_WRITE) {
- ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
- &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
- if (ret) {
- dev_err(&gt_client->dev, "copy_from_user failed");
- ret = -EFAULT;
- goto exit;
- }
-
- memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
- cmd_head.addr, cmd_head.addr_len);
-
- if (cmd_head.flag == GTP_NEED_FLAG) {
- if (comfirm() == FAIL) {
- dev_err(&gt_client->dev, "Confirm fail");
- ret = -EINVAL;
- goto exit;
- }
- } else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
- /* Need interrupt! */
- }
- if (tool_i2c_write(
- &cmd_head.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;
- goto exit;
- }
-
- if (cmd_head.delay)
- msleep(cmd_head.delay);
-
- 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],
- &userbuf[CMD_HEAD_LENGTH],
- cmd_head.data_len);
- if (ret) {
- dev_err(&gt_client->dev, "copy_from_user failed");
- ret = -EFAULT;
- goto exit;
- }
-
- if (cmd_head.data_len > sizeof(ic_type)) {
- dev_err(&gt_client->dev,
- "data len %u > data buff %zu, rejected\n",
- cmd_head.data_len, sizeof(ic_type));
- ret = -EINVAL;
- goto exit;
- }
- memcpy(ic_type, cmd_head.data, cmd_head.data_len);
-
- register_i2c_func();
-
- ret = cmd_head.data_len + CMD_HEAD_LENGTH;
- goto exit;
- } else if (cmd_head.wr == GTP_RW_NO_WRITE) {
- ret = cmd_head.data_len + CMD_HEAD_LENGTH;
- goto exit;
- } else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */
- gtp_irq_disable(i2c_get_clientdata(gt_client));
-
- #if GTP_ESD_PROTECT
- gtp_esd_switch(gt_client, SWITCH_OFF);
- #endif
- ret = CMD_HEAD_LENGTH;
- goto exit;
- } else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */
- gtp_irq_enable(i2c_get_clientdata(gt_client));
-
- #if GTP_ESD_PROTECT
- gtp_esd_switch(gt_client, SWITCH_ON);
- #endif
- ret = CMD_HEAD_LENGTH;
- goto exit;
- } 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],
- &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]) {
- pr_debug("gtp enter rawdiff\n");
- ts->gtp_rawdiff_mode = true;
- } else {
- ts->gtp_rawdiff_mode = false;
- pr_debug("gtp leave rawdiff\n");
- }
- ret = CMD_HEAD_LENGTH;
- goto exit;
- } else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) {
- /* Enter update mode! */
- if (gup_enter_update_mode(gt_client) == FAIL) {
- ret = -EBUSY;
- goto exit;
- }
- } else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) {
- /* Leave update mode! */
- gup_leave_update_mode(gt_client);
- } else if (cmd_head.wr == GTP_RW_UPDATE_FW) {
- /* Update firmware! */
- show_len = 0;
- total_len = 0;
- if (cmd_head.data_len + 1 > data_length) {
- dev_err(&gt_client->dev, "data len %u > data buff %d, rejected\n",
- cmd_head.data_len + 1, data_length);
- ret = -EINVAL;
- goto exit;
- }
- memset(cmd_head.data, 0, cmd_head.data_len + 1);
- memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH],
- cmd_head.data_len);
-
- if (gup_update_proc((void *)cmd_head.data) == FAIL) {
- ret = -EBUSY;
- goto exit;
- }
- }
- 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;
-}
-
-/*
- * Function:
- * Goodix tool read function.
- * Input:
- * standard proc read function param.
- * Output:
- * Return read length.
- */
-static ssize_t goodix_tool_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- u16 data_len = 0;
- s32 ret;
- u8 buf[32];
-
- mutex_lock(&lock);
- if (cmd_head.wr & 0x1) {
- dev_err(&gt_client->dev, "command head wrong\n");
- ret = -EINVAL;
- goto exit;
- }
-
- switch (cmd_head.wr) {
- case GTP_RW_READ:
- if (cmd_head.flag == GTP_NEED_FLAG) {
- if (comfirm() == FAIL) {
- dev_err(&gt_client->dev, "Confirm fail");
- ret = -EINVAL;
- goto exit;
- }
- } else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
- /* Need interrupt! */
- }
-
- memcpy(cmd_head.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 ADDR] ADDR:0x%02x%02x.\n", cmd_head.addr[0],
- cmd_head.addr[1]);
-
- if (cmd_head.delay)
- msleep(cmd_head.delay);
-
- data_len = cmd_head.data_len;
- if (data_len <= 0 || (data_len > data_length)) {
- dev_err(&gt_client->dev, "Invalid data length %d\n",
- data_len);
- ret = -EINVAL;
- goto exit;
- }
- if (data_len > count)
- data_len = count;
-
- if (tool_i2c_read(cmd_head.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);
- break;
- case GTP_RW_FILL_INFO:
- ret = fill_update_info(user_buf, count, ppos);
- break;
- case GTP_RW_READ_VERSION:
- /* Read driver version */
- data_len = scnprintf(buf, sizeof(buf), "%s\n",
- GTP_DRIVER_VERSION);
- ret = simple_read_from_buffer(user_buf, count, ppos,
- buf, data_len);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
-exit:
- mutex_unlock(&lock);
- return ret;
-}
-
-static const struct file_operations goodix_proc_fops = {
- .write = goodix_tool_write,
- .read = goodix_tool_read,
- .open = simple_open,
- .owner = THIS_MODULE,
-};
-
-s32 init_wr_node(struct i2c_client *client)
-{
- u8 i;
-
- gt_client = client;
- memset(&cmd_head, 0, sizeof(cmd_head));
- cmd_head.data = NULL;
-
- i = GTP_I2C_RETRY_5;
- while ((!cmd_head.data) && i) {
- cmd_head.data = devm_kzalloc(&client->dev,
- i * DATA_LENGTH_UINT, GFP_KERNEL);
- if (cmd_head.data)
- break;
- i--;
- }
- if (i) {
- data_length = i * DATA_LENGTH_UINT;
- dev_dbg(&client->dev, "Applied memory size:%d", data_length);
- }
-
- cmd_head.addr_len = 2;
- cmd_head.retry = GTP_I2C_RETRY_5;
-
- register_i2c_func();
-
- mutex_init(&lock);
- tool_set_proc_name(procname);
- goodix_proc_entry = proc_create(procname,
- S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
- goodix_proc_entry,
- &goodix_proc_fops);
- if (goodix_proc_entry == NULL) {
- dev_err(&client->dev, "Couldn't create proc entry");
- return FAIL;
- }
-
- return SUCCESS;
-}
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
deleted file mode 100644
index ead935120624..000000000000
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ /dev/null
@@ -1,2564 +0,0 @@
-/* drivers/input/touchscreen/gt9xx.c
- *
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
- *
- * 2010 - 2013 Goodix Technology.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be a reference
- * to you, when you are integrating the GOODiX's CTP IC into your system,
- * 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.
- *
- * Version: 1.8
- * Authors: andrew@goodix.com, meta@goodix.com
- * Release Date: 2013/04/25
- * Revision record:
- * V1.0:
- * first Release. By Andrew, 2012/08/31
- * V1.2:
- * modify gtp_reset_guitar,slot report,tracking_id & 0x0F.
- * By Andrew, 2012/10/15
- * V1.4:
- * modify gt9xx_update.c. By Andrew, 2012/12/12
- * V1.6:
- * 1. new heartbeat/esd_protect mechanism(add external watchdog)
- * 2. doze mode, sliding wakeup
- * 3. 3 more cfg_group(GT9 Sensor_ID: 0~5)
- * 3. config length verification
- * 4. names & comments
- * By Meta, 2013/03/11
- * V1.8:
- * 1. pen/stylus identification
- * 2. read double check & fixed config support
- * 2. new esd & slide wakeup optimization
- * By Meta, 2013/06/08
- */
-
-#include <linux/regulator/consumer.h>
-#include "gt9xx.h"
-
-#include <linux/of_gpio.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/input/mt.h>
-#include <linux/debugfs.h>
-#include <linux/interrupt.h>
-
-#define GOODIX_DEV_NAME "Goodix-CTP"
-#define CFG_MAX_TOUCH_POINTS 5
-#define GOODIX_COORDS_ARR_SIZE 4
-#define MAX_BUTTONS 4
-
-#define GOODIX_VTG_MIN_UV 2600000
-#define GOODIX_VTG_MAX_UV 3300000
-#define GOODIX_I2C_VTG_MIN_UV 1800000
-#define GOODIX_I2C_VTG_MAX_UV 1800000
-#define GOODIX_VDD_LOAD_MIN_UA 0
-#define GOODIX_VDD_LOAD_MAX_UA 10000
-#define GOODIX_VIO_LOAD_MIN_UA 0
-#define GOODIX_VIO_LOAD_MAX_UA 10000
-
-#define RESET_DELAY_T3_US 200 /* T3: > 100us */
-#define RESET_DELAY_T4 20 /* T4: > 5ms */
-#define SLEEP_DELAY_US 5000
-#define WAKE_UP_DELAY_US 5000
-
-#define PHY_BUF_SIZE 32
-#define PROP_NAME_SIZE 24
-
-#define GTP_MAX_TOUCH 5
-#define GTP_ESD_CHECK_CIRCLE_MS 2000
-
-static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
-static int gtp_i2c_test(struct i2c_client *client);
-static int goodix_power_off(struct goodix_ts_data *ts);
-static int goodix_power_on(struct goodix_ts_data *ts);
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self,
- unsigned long event, void *data);
-static int goodix_ts_suspend(struct device *dev);
-static int goodix_ts_resume(struct device *dev);
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-static void goodix_ts_early_suspend(struct early_suspend *h);
-static void goodix_ts_late_resume(struct early_suspend *h);
-#endif
-
-#if GTP_ESD_PROTECT
-static struct delayed_work gtp_esd_check_work;
-static struct workqueue_struct *gtp_esd_check_workqueue;
-static void gtp_esd_check_func(struct work_struct *work);
-static int gtp_init_ext_watchdog(struct i2c_client *client);
-#endif
-
-enum doze {
- DOZE_DISABLED = 0,
- DOZE_ENABLED = 1,
- DOZE_WAKEUP = 2,
-};
-static enum doze doze_status = DOZE_DISABLED;
-static s8 gtp_enter_doze(struct goodix_ts_data *ts);
-
-bool init_done;
-static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */
-u8 grp_cfg_version;
-struct i2c_client *i2c_connect_client;
-
-#define GTP_DEBUGFS_DIR "ts_debug"
-#define GTP_DEBUGFS_FILE_SUSPEND "suspend"
-#define GTP_DEBUGFS_FILE_DATA "data"
-#define GTP_DEBUGFS_FILE_ADDR "addr"
-
-/*******************************************************
-Function:
- Read data from the i2c slave device.
-Input:
- client: i2c device.
- buf[0~1]: read start address.
- buf[2~len-1]: read data buffer.
- len: GTP_ADDR_LENGTH + read bytes count
-Output:
- numbers of i2c_msgs to transfer:
- 2: succeed, otherwise: failed
-*********************************************************/
-int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
-{
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
- int ret = -EIO;
- u8 retries;
- struct i2c_msg msgs[2] = {
- {
- .flags = !I2C_M_RD,
- .addr = client->addr,
- .len = GTP_ADDR_LENGTH,
- .buf = &buf[0],
- },
- {
- .flags = I2C_M_RD,
- .addr = client->addr,
- .len = len - GTP_ADDR_LENGTH,
- .buf = &buf[GTP_ADDR_LENGTH],
- },
- };
-
- for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
- ret = i2c_transfer(client->adapter, msgs, 2);
- if (ret == 2)
- break;
- dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
- }
- if (retries == GTP_I2C_RETRY_5) {
- if (ts->pdata->slide_wakeup)
- /* reset chip would quit doze mode */
- if (doze_status == DOZE_ENABLED)
- return ret;
-
- if (init_done)
- gtp_reset_guitar(ts, 10);
- else
- dev_warn(&client->dev,
- "gtp_reset_guitar exit init_done=%d:\n",
- init_done);
- }
- return ret;
-}
-
-/*******************************************************
-Function:
- Write data to the i2c slave device.
-Input:
- client: i2c device.
- buf[0~1]: write start address.
- buf[2~len-1]: data buffer
- len: GTP_ADDR_LENGTH + write bytes count
-Output:
- numbers of i2c_msgs to transfer:
- 1: succeed, otherwise: failed
-*********************************************************/
-int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
-{
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
- int ret = -EIO;
- u8 retries;
- struct i2c_msg msg = {
- .flags = !I2C_M_RD,
- .addr = client->addr,
- .len = len,
- .buf = buf,
- };
-
- for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
- ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret == 1)
- break;
- dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
- }
- if (retries == GTP_I2C_RETRY_5) {
- if (ts->pdata->slide_wakeup)
- if (doze_status == DOZE_ENABLED)
- return ret;
-
- if (init_done)
- gtp_reset_guitar(ts, 10);
- else
- dev_warn(&client->dev,
- "gtp_reset_guitar exit init_done=%d:\n",
- init_done);
- }
- return ret;
-}
-
-/*******************************************************
-Function:
- i2c read twice, compare the results
-Input:
- client: i2c device
- addr: operate address
- rxbuf: read data to store, if compare successful
- len: bytes to read
-Output:
- FAIL: read failed
- SUCCESS: read successful
-*********************************************************/
-int gtp_i2c_read_dbl_check(struct i2c_client *client,
- u16 addr, u8 *rxbuf, int len)
-{
- u8 buf[16] = {0};
- u8 confirm_buf[16] = {0};
- u8 retry = 0;
-
- while (retry++ < GTP_I2C_RETRY_3) {
- memset(buf, 0xAA, 16);
- buf[0] = (u8)(addr >> 8);
- buf[1] = (u8)(addr & 0xFF);
- gtp_i2c_read(client, buf, len + 2);
-
- memset(confirm_buf, 0xAB, 16);
- confirm_buf[0] = (u8)(addr >> 8);
- confirm_buf[1] = (u8)(addr & 0xFF);
- gtp_i2c_read(client, confirm_buf, len + 2);
-
- if (!memcmp(buf, confirm_buf, len + 2))
- break;
- }
- if (retry < GTP_I2C_RETRY_3) {
- memcpy(rxbuf, confirm_buf + 2, len);
- return SUCCESS;
- }
- dev_err(&client->dev,
- "i2c read 0x%04X, %d bytes, double check failed!", addr, len);
- return FAIL;
-}
-
-/*******************************************************
-Function:
- Send config data.
-Input:
- client: i2c device.
-Output:
- result of i2c write operation.
- > 0: succeed, otherwise: failed
-*********************************************************/
-int gtp_send_cfg(struct goodix_ts_data *ts)
-{
- int ret = 0;
- int retry;
-
- if (ts->pdata->driver_send_cfg) {
- if (ts->fixed_cfg) {
- dev_dbg(&ts->client->dev,
- "Ic fixed config, no config sent!");
- ret = 2;
- } else {
- for (retry = 0; retry < GTP_I2C_RETRY_5; retry++) {
- ret = gtp_i2c_write(ts->client,
- ts->config_data,
- GTP_CONFIG_MAX_LENGTH +
- GTP_ADDR_LENGTH);
- if (ret > 0)
- break;
- }
- }
- }
-
- return ret;
-}
-
-/*******************************************************
-Function:
- Disable irq function
-Input:
- ts: goodix i2c_client private data
-Output:
- None.
-*********************************************************/
-void gtp_irq_disable(struct goodix_ts_data *ts)
-{
- unsigned long irqflags;
-
- spin_lock_irqsave(&ts->irq_lock, irqflags);
- if (!ts->irq_is_disabled) {
- ts->irq_is_disabled = true;
- disable_irq_nosync(ts->client->irq);
- }
- spin_unlock_irqrestore(&ts->irq_lock, irqflags);
-}
-
-/*******************************************************
-Function:
- Enable irq function
-Input:
- ts: goodix i2c_client private data
-Output:
- None.
-*********************************************************/
-void gtp_irq_enable(struct goodix_ts_data *ts)
-{
- unsigned long irqflags = 0;
-
- spin_lock_irqsave(&ts->irq_lock, irqflags);
- if (ts->irq_is_disabled) {
- enable_irq(ts->client->irq);
- ts->irq_is_disabled = false;
- }
- spin_unlock_irqrestore(&ts->irq_lock, irqflags);
-}
-
-/*******************************************************
-Function:
- Report touch point event
-Input:
- ts: goodix i2c_client private data
- id: trackId
- x: input x coordinate
- y: input y coordinate
- w: input pressure
-Output:
- None.
-*********************************************************/
-static void gtp_touch_down(struct goodix_ts_data *ts, int id, int x, int y,
- int w)
-{
- if (ts->pdata->change_x2y)
- swap(x, y);
-
- input_mt_slot(ts->input_dev, id);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
-}
-
-/*******************************************************
-Function:
- Report touch release event
-Input:
- ts: goodix i2c_client private data
-Output:
- None.
-*********************************************************/
-static void gtp_touch_up(struct goodix_ts_data *ts, int id)
-{
- input_mt_slot(ts->input_dev, id);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
-}
-
-
-
-/*******************************************************
-Function:
- Goodix touchscreen work function
-Input:
- work: work struct of goodix_workqueue
-Output:
- None.
-*********************************************************/
-static void goodix_ts_work_func(struct work_struct *work)
-{
- u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8,
- GTP_READ_COOR_ADDR & 0xFF, 0};
- u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = {
- GTP_READ_COOR_ADDR >> 8,
- GTP_READ_COOR_ADDR & 0xFF};
- u8 touch_num = 0;
- u8 finger = 0;
- static u16 pre_touch;
- static u8 pre_key;
- static u8 pre_pen;
- u8 key_value = 0;
- u8 *coor_data = NULL;
- s32 input_x = 0;
- s32 input_y = 0;
- s32 input_w = 0;
- s32 id = 0;
- s32 i = 0;
- int ret = -1;
- struct goodix_ts_data *ts = NULL;
- u8 doze_buf[3] = {0x81, 0x4B};
-
- ts = container_of(work, struct goodix_ts_data, work);
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
- if (ts->enter_update)
- return;
-#endif
-
- if (ts->pdata->slide_wakeup) {
- if (doze_status == DOZE_ENABLED) {
- ret = gtp_i2c_read(ts->client, doze_buf, 3);
- if (ret > 0) {
- if (doze_buf[2] == 0xAA) {
- dev_dbg(&ts->client->dev,
- "Slide(0xAA) To Light up the screen!");
- doze_status = DOZE_WAKEUP;
- input_report_key(
- ts->input_dev, KEY_POWER, 1);
- input_sync(ts->input_dev);
- input_report_key(
- ts->input_dev, KEY_POWER, 0);
- input_sync(ts->input_dev);
- /* clear 0x814B */
- doze_buf[2] = 0x00;
- gtp_i2c_write(ts->client, doze_buf, 3);
- } else if (doze_buf[2] == 0xBB) {
- dev_dbg(&ts->client->dev,
- "Slide(0xBB) To Light up the screen!");
- doze_status = DOZE_WAKEUP;
- input_report_key(ts->input_dev,
- KEY_POWER, 1);
- input_sync(ts->input_dev);
- input_report_key(ts->input_dev,
- KEY_POWER, 0);
- input_sync(ts->input_dev);
- /* clear 0x814B*/
- doze_buf[2] = 0x00;
- gtp_i2c_write(ts->client, doze_buf, 3);
- } else if (0xC0 == (doze_buf[2] & 0xC0)) {
- dev_dbg(&ts->client->dev,
- "double click to light up the screen!");
- doze_status = DOZE_WAKEUP;
- input_report_key(ts->input_dev,
- KEY_POWER, 1);
- input_sync(ts->input_dev);
- input_report_key(ts->input_dev,
- KEY_POWER, 0);
- input_sync(ts->input_dev);
- /* clear 0x814B */
- doze_buf[2] = 0x00;
- gtp_i2c_write(ts->client, doze_buf, 3);
- } else {
- gtp_enter_doze(ts);
- }
- }
- if (ts->use_irq)
- gtp_irq_enable(ts);
-
- return;
- }
- }
-
- ret = gtp_i2c_read(ts->client, point_data, 12);
- if (ret < 0) {
- dev_err(&ts->client->dev,
- "I2C transfer error. errno:%d\n ", ret);
- goto exit_work_func;
- }
-
- finger = point_data[GTP_ADDR_LENGTH];
- if ((finger & 0x80) == 0)
- goto exit_work_func;
-
- touch_num = finger & 0x0f;
- if (touch_num > GTP_MAX_TOUCH)
- goto exit_work_func;
-
- if (touch_num > 1) {
- u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8,
- (GTP_READ_COOR_ADDR + 10) & 0xff };
-
- ret = gtp_i2c_read(ts->client, buf,
- 2 + 8 * (touch_num - 1));
- memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
- }
-
-
- key_value = point_data[3 + 8 * touch_num];
-
- if (key_value || pre_key) {
- for (i = 0; i < ts->pdata->num_button; i++) {
- input_report_key(ts->input_dev,
- ts->pdata->button_map[i],
- key_value & (0x01<<i));
- }
- touch_num = 0;
- pre_touch = 0;
- }
-
- pre_key = key_value;
-
- if (ts->pdata->with_pen) {
- if (pre_pen && (touch_num == 0)) {
- dev_dbg(&ts->client->dev, "Pen touch UP(Slot)!");
- input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
- input_mt_slot(ts->input_dev, 5);
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
- pre_pen = 0;
- }
- }
-
- if (pre_touch || touch_num) {
- s32 pos = 0;
- u16 touch_index = 0;
-
- coor_data = &point_data[3];
- if (touch_num) {
- id = coor_data[pos] & 0x0F;
- if (ts->pdata->with_pen) {
- id = coor_data[pos];
- if (id == 128) {
- dev_dbg(&ts->client->dev,
- "Pen touch DOWN(Slot)!");
- input_x = coor_data[pos + 1]
- | (coor_data[pos + 2] << 8);
- input_y = coor_data[pos + 3]
- | (coor_data[pos + 4] << 8);
- input_w = coor_data[pos + 5]
- | (coor_data[pos + 6] << 8);
-
- input_report_key(ts->input_dev,
- BTN_TOOL_PEN, 1);
- input_mt_slot(ts->input_dev, 5);
- input_report_abs(ts->input_dev,
- ABS_MT_TRACKING_ID, 5);
- input_report_abs(ts->input_dev,
- ABS_MT_POSITION_X, input_x);
- input_report_abs(ts->input_dev,
- ABS_MT_POSITION_Y, input_y);
- input_report_abs(ts->input_dev,
- ABS_MT_TOUCH_MAJOR, input_w);
- dev_dbg(&ts->client->dev,
- "Pen/Stylus: (%d, %d)[%d]",
- input_x, input_y, input_w);
- pre_pen = 1;
- pre_touch = 0;
- }
- }
-
- touch_index |= (0x01<<id);
- }
-
- for (i = 0; i < GTP_MAX_TOUCH; i++) {
- if (ts->pdata->with_pen)
- if (pre_pen == 1)
- break;
-
- if (touch_index & (0x01<<i)) {
- input_x = coor_data[pos + 1] |
- coor_data[pos + 2] << 8;
- input_y = coor_data[pos + 3] |
- coor_data[pos + 4] << 8;
- input_w = coor_data[pos + 5] |
- coor_data[pos + 6] << 8;
-
- gtp_touch_down(ts, id,
- input_x, input_y, input_w);
- pre_touch |= 0x01 << i;
-
- pos += 8;
- id = coor_data[pos] & 0x0F;
- touch_index |= (0x01<<id);
- } else {
- gtp_touch_up(ts, i);
- pre_touch &= ~(0x01 << i);
- }
- }
- }
- input_sync(ts->input_dev);
-
-exit_work_func:
- if (!ts->gtp_rawdiff_mode) {
- ret = gtp_i2c_write(ts->client, end_cmd, 3);
- if (ret < 0)
- dev_warn(&ts->client->dev, "I2C write end_cmd error!\n");
-
- }
- if (ts->use_irq)
- gtp_irq_enable(ts);
-
- return;
-}
-
-/*******************************************************
-Function:
- External interrupt service routine for interrupt mode.
-Input:
- irq: interrupt number.
- dev_id: private data pointer
-Output:
- Handle Result.
- IRQ_HANDLED: interrupt handled successfully
-*********************************************************/
-static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
-{
- struct goodix_ts_data *ts = dev_id;
-
- gtp_irq_disable(ts);
-
- queue_work(ts->goodix_wq, &ts->work);
-
- return IRQ_HANDLED;
-}
-/*******************************************************
-Function:
- Synchronization.
-Input:
- ms: synchronization time in millisecond.
-Output:
- None.
-*******************************************************/
-void gtp_int_sync(struct goodix_ts_data *ts, int ms)
-{
- gpio_direction_output(ts->pdata->irq_gpio, 0);
- msleep(ms);
- gpio_direction_input(ts->pdata->irq_gpio);
-}
-
-/*******************************************************
-Function:
- Reset chip.
-Input:
- ms: reset time in millisecond, must >10ms
-Output:
- None.
-*******************************************************/
-void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
-{
- /* This reset sequence will selcet I2C slave address */
- gpio_direction_output(ts->pdata->reset_gpio, 0);
- msleep(ms);
-
- if (ts->client->addr == GTP_I2C_ADDRESS_HIGH)
- gpio_direction_output(ts->pdata->irq_gpio, 1);
- else
- gpio_direction_output(ts->pdata->irq_gpio, 0);
-
- usleep_range(RESET_DELAY_T3_US, RESET_DELAY_T3_US + 1);
- gpio_direction_output(ts->pdata->reset_gpio, 1);
- msleep(RESET_DELAY_T4);
-
- gpio_direction_input(ts->pdata->reset_gpio);
-
- gtp_int_sync(ts, 50);
-
-#if GTP_ESD_PROTECT
- gtp_init_ext_watchdog(ts->client);
-#endif
-}
-
-#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB)
-/*******************************************************
-Function:
- Enter doze mode for sliding wakeup.
-Input:
- ts: goodix tp private data
-Output:
- 1: succeed, otherwise failed
-*******************************************************/
-static s8 gtp_enter_doze(struct goodix_ts_data *ts)
-{
- int ret = -1;
- s8 retry = 0;
- u8 i2c_control_buf[3] = {
- (u8)(GTP_REG_SLEEP >> 8),
- (u8)GTP_REG_SLEEP, 8};
-
- if (ts->pdata->dbl_clk_wakeup)
- i2c_control_buf[2] = 0x09;
-
- gtp_irq_disable(ts);
-
- while (retry++ < GTP_I2C_RETRY_3) {
- i2c_control_buf[0] = 0x80;
- i2c_control_buf[1] = 0x46;
- ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
- if (ret < 0) {
- dev_err(&ts->client->dev,
- "failed to set doze flag into 0x8046, %d",
- retry);
- continue;
- }
- i2c_control_buf[0] = 0x80;
- i2c_control_buf[1] = 0x40;
- ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
- if (ret > 0) {
- doze_status = DOZE_ENABLED;
- dev_dbg(&ts->client->dev,
- "GTP has been working in doze mode!");
- gtp_irq_enable(ts);
- return ret;
- }
- msleep(20);
- }
- dev_err(&ts->client->dev, "GTP send doze cmd failed.\n");
- gtp_irq_enable(ts);
- return ret;
-}
-/**
- * gtp_enter_sleep - Enter sleep mode
- * @ts: driver private data
- *
- * Returns zero on success, else an error.
- */
-static u8 gtp_enter_sleep(struct goodix_ts_data *ts)
-{
- int ret = -1;
- s8 retry = 0;
- u8 i2c_control_buf[3] = {
- (u8)(GTP_REG_SLEEP >> 8),
- (u8)GTP_REG_SLEEP, 5};
-
- ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
- if (ret)
- dev_err(&ts->client->dev,
- "GTP sleep: Cannot reconfig gpio %d.\n",
- ts->pdata->irq_gpio);
- if (ts->pdata->enable_power_off) {
- ret = gpio_direction_output(ts->pdata->reset_gpio, 0);
- if (ret)
- dev_err(&ts->client->dev,
- "GTP sleep: Cannot reconfig gpio %d.\n",
- ts->pdata->reset_gpio);
- ret = goodix_power_off(ts);
- if (ret) {
- dev_err(&ts->client->dev, "GTP power off failed.\n");
- return ret;
- }
- return 0;
- }
- usleep_range(SLEEP_DELAY_US, SLEEP_DELAY_US + 1);
- while (retry++ < GTP_I2C_RETRY_5) {
- ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
- if (ret == 1) {
- dev_dbg(&ts->client->dev, "GTP enter sleep!");
- return 0;
- }
- msleep(20);
- }
- dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n");
- return ret;
-}
-
-/*******************************************************
-Function:
- Wakeup from sleep.
-Input:
- ts: private data.
-Output:
- Executive outcomes.
- >0: succeed, otherwise: failed.
-*******************************************************/
-static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts)
-{
- u8 retry = 0;
- s8 ret = -1;
-
- if (ts->pdata->enable_power_off) {
- ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
- if (ret)
- dev_err(&ts->client->dev,
- "GTP wakeup: Cannot reconfig gpio %d.\n",
- ts->pdata->irq_gpio);
- ret = gpio_direction_output(ts->pdata->reset_gpio, 0);
- if (ret)
- dev_err(&ts->client->dev,
- "GTP wakeup: Cannot reconfig gpio %d.\n",
- ts->pdata->reset_gpio);
- ret = goodix_power_on(ts);
- if (ret) {
- dev_err(&ts->client->dev, "GTP power on failed.\n");
- return 0;
- }
-
- gtp_reset_guitar(ts, 20);
-
- ret = gtp_send_cfg(ts);
- if (ret <= 0) {
- dev_err(&ts->client->dev,
- "GTP wakeup sleep failed.\n");
- return ret;
- }
-
- dev_dbg(&ts->client->dev,
- "Wakeup sleep send config success.");
- } else {
-err_retry:
- if (ts->pdata->slide_wakeup) { /* wakeup not by slide */
- if (doze_status != DOZE_WAKEUP)
- gtp_reset_guitar(ts, 10);
- else
- /* wakeup by slide */
- doze_status = DOZE_DISABLED;
- } else {
- if (chip_gt9xxs == 1) {
- gtp_reset_guitar(ts, 10);
- } else {
- ret = gpio_direction_output(
- ts->pdata->irq_gpio, 1);
- usleep_range(WAKE_UP_DELAY_US,
- WAKE_UP_DELAY_US + 1);
- }
- }
- ret = gtp_i2c_test(ts->client);
- if (ret == 2) {
- dev_dbg(&ts->client->dev, "GTP wakeup sleep.");
- if (!ts->pdata->slide_wakeup) {
- if (chip_gt9xxs == 0) {
- gtp_int_sync(ts, 25);
- msleep(20);
-#if GTP_ESD_PROTECT
- gtp_init_ext_watchdog(ts->client);
-#endif
- }
- }
- return ret;
- }
- gtp_reset_guitar(ts, 20);
- if (retry++ < GTP_I2C_RETRY_10)
- goto err_retry;
- dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n");
- }
- return ret;
-}
-#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/
-
-/*******************************************************
-Function:
- Initialize gtp.
-Input:
- ts: goodix private data
-Output:
- Executive outcomes.
- > =0: succeed, otherwise: failed
-*******************************************************/
-static int gtp_init_panel(struct goodix_ts_data *ts)
-{
- struct i2c_client *client = ts->client;
- unsigned char *config_data = NULL;
- int ret = -EIO;
- int i;
- u8 check_sum = 0;
- u8 opr_buf[16];
- u8 sensor_id = 0;
-
- if (ts->pdata->driver_send_cfg) {
- for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
- dev_dbg(&client->dev, "Config Groups(%d) Lengths: %zu",
- i, ts->pdata->config_data_len[i]);
-
- ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
- if (ret == SUCCESS) {
- if (opr_buf[0] != 0xBE) {
- ts->fw_error = 1;
- dev_err(&client->dev,
- "Firmware error, no config sent!");
- return -EINVAL;
- }
- }
-
- for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) {
- if (ts->pdata->config_data_len[i])
- break;
- }
-
- if (i == GOODIX_MAX_CFG_GROUP) {
- sensor_id = 0;
- } else {
- ret = gtp_i2c_read_dbl_check(ts->client,
- GTP_REG_SENSOR_ID, &sensor_id, 1);
- if (ret == SUCCESS) {
- if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
- dev_err(&client->dev,
- "Invalid sensor_id(0x%02X), No Config Sent!",
- sensor_id);
- return -EINVAL;
- }
- } else {
- dev_err(&client->dev,
- "Failed to get sensor_id, No config sent!");
- return -EINVAL;
- }
- }
-
- dev_info(&client->dev, "Sensor ID selected: %d", sensor_id);
-
- if (ts->pdata->config_data_len[sensor_id] <
- GTP_CONFIG_MIN_LENGTH ||
- !ts->pdata->config_data[sensor_id]) {
- dev_err(&client->dev,
- "Sensor_ID(%d) matches with NULL or invalid config group!\n",
- sensor_id);
- return -EINVAL;
- }
-
- ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
- &opr_buf[0], 1);
- if (ret == SUCCESS) {
- if (opr_buf[0] < 90) {
- /* backup group config version */
- grp_cfg_version =
- ts->pdata->
- config_data[sensor_id][GTP_ADDR_LENGTH];
- ts->pdata->
- config_data[sensor_id][GTP_ADDR_LENGTH]
- = 0x00;
- ts->fixed_cfg = 0;
- } else {
- /* treated as fixed config, not send config */
- dev_warn(&client->dev,
- "Ic fixed config with config version(%d, 0x%02X)",
- opr_buf[0], opr_buf[0]);
- ts->fixed_cfg = 1;
- }
- } else {
- dev_err(&client->dev,
- "Failed to get ic config version!No config sent!");
- return -EINVAL;
- }
-
- config_data = ts->pdata->config_data[sensor_id];
- ts->config_data = ts->pdata->config_data[sensor_id];
- ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];
-
-#if GTP_CUSTOM_CFG
- config_data[RESOLUTION_LOC] =
- (unsigned char)(GTP_MAX_WIDTH && 0xFF);
- config_data[RESOLUTION_LOC + 1] =
- (unsigned char)(GTP_MAX_WIDTH >> 8);
- config_data[RESOLUTION_LOC + 2] =
- (unsigned char)(GTP_MAX_HEIGHT && 0xFF);
- config_data[RESOLUTION_LOC + 3] =
- (unsigned char)(GTP_MAX_HEIGHT >> 8);
-
- if (GTP_INT_TRIGGER == 0)
- config_data[TRIGGER_LOC] &= 0xfe;
- else if (GTP_INT_TRIGGER == 1)
- config_data[TRIGGER_LOC] |= 0x01;
-#endif /* !GTP_CUSTOM_CFG */
-
- check_sum = 0;
- for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
- check_sum += config_data[i];
-
- config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
-
- } else { /* DRIVER NOT SEND CONFIG */
- ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
- ret = gtp_i2c_read(ts->client, config_data,
- ts->gtp_cfg_len + GTP_ADDR_LENGTH);
- if (ret < 0) {
- dev_err(&client->dev,
- "Read Config Failed, Using DEFAULT Resolution & INT Trigger!\n");
- ts->abs_x_max = GTP_MAX_WIDTH;
- ts->abs_y_max = GTP_MAX_HEIGHT;
- ts->int_trigger_type = GTP_INT_TRIGGER;
- }
- } /* !DRIVER NOT SEND CONFIG */
-
- if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) {
- ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8)
- + config_data[RESOLUTION_LOC];
- ts->abs_y_max = (config_data[RESOLUTION_LOC + 3] << 8)
- + config_data[RESOLUTION_LOC + 2];
- ts->int_trigger_type = (config_data[TRIGGER_LOC]) & 0x03;
- }
- ret = gtp_send_cfg(ts);
- if (ret < 0)
- dev_err(&client->dev, "%s: Send config error.\n", __func__);
-
- msleep(20);
- return ret;
-}
-
-/*******************************************************
-Function:
- Read firmware version
-Input:
- client: i2c device
- version: buffer to keep ic firmware version
-Output:
- read operation return.
- 0: succeed, otherwise: failed
-*******************************************************/
-static int gtp_read_fw_version(struct i2c_client *client, u16 *version)
-{
- int ret = 0;
- u8 buf[GTP_FW_VERSION_BUFFER_MAXSIZE] = {
- GTP_REG_FW_VERSION >> 8, GTP_REG_FW_VERSION & 0xff };
-
- ret = gtp_i2c_read(client, buf, sizeof(buf));
- if (ret < 0) {
- dev_err(&client->dev, "GTP read version failed.\n");
- return -EIO;
- }
-
- if (version)
- *version = (buf[3] << 8) | buf[2];
-
- return ret;
-}
-/*
- * Function:
- * Read and check chip id.
- * Input:
- * client: i2c device
- * Output:
- * read operation return.
- * 0: succeed, otherwise: failed
- */
-static int gtp_check_product_id(struct i2c_client *client)
-{
- int ret = 0;
- char product_id[GTP_PRODUCT_ID_MAXSIZE];
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
- /* 04 bytes are used for the Product-id in the register space.*/
- u8 buf[GTP_PRODUCT_ID_BUFFER_MAXSIZE] = {
- GTP_REG_PRODUCT_ID >> 8, GTP_REG_PRODUCT_ID & 0xff };
-
- ret = gtp_i2c_read(client, buf, sizeof(buf));
- if (ret < 0) {
- dev_err(&client->dev, "GTP read product_id failed.\n");
- return -EIO;
- }
-
- if (buf[5] == 0x00) {
- /* copy (GTP_PRODUCT_ID_MAXSIZE - 1) from buffer. Ex: 915 */
- strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE - 1);
- } else {
- if (buf[5] == 'S' || buf[5] == 's')
- chip_gt9xxs = 1;
- /* copy GTP_PRODUCT_ID_MAXSIZE from buffer. Ex: 915s */
- strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE);
- }
-
- dev_info(&client->dev, "Goodix Product ID = %s\n", product_id);
-
- ret = strcmp(product_id, ts->pdata->product_id);
- if (ret != 0)
- return -EINVAL;
-
- return ret;
-}
-
-/*******************************************************
-Function:
- I2c test Function.
-Input:
- client:i2c client.
-Output:
- Executive outcomes.
- 2: succeed, otherwise failed.
-*******************************************************/
-static int gtp_i2c_test(struct i2c_client *client)
-{
- u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff };
- int retry = GTP_I2C_RETRY_5;
- int ret = -EIO;
-
- while (retry--) {
- ret = gtp_i2c_read(client, buf, 3);
- if (ret > 0)
- return ret;
- dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry);
- msleep(20);
- }
- return ret;
-}
-
-/*******************************************************
-Function:
- Request gpio(INT & RST) ports.
-Input:
- ts: private data.
-Output:
- Executive outcomes.
- = 0: succeed, != 0: failed
-*******************************************************/
-static int gtp_request_io_port(struct goodix_ts_data *ts)
-{
- struct i2c_client *client = ts->client;
- struct goodix_ts_platform_data *pdata = ts->pdata;
- int ret;
-
- if (gpio_is_valid(pdata->irq_gpio)) {
- ret = gpio_request(pdata->irq_gpio, "goodix_ts_irq_gpio");
- if (ret) {
- dev_err(&client->dev, "Unable to request irq gpio [%d]\n",
- pdata->irq_gpio);
- goto err_pwr_off;
- }
- ret = gpio_direction_input(pdata->irq_gpio);
- if (ret) {
- dev_err(&client->dev, "Unable to set direction for irq gpio [%d]\n",
- pdata->irq_gpio);
- goto err_free_irq_gpio;
- }
- } else {
- dev_err(&client->dev, "Invalid irq gpio [%d]!\n",
- pdata->irq_gpio);
- ret = -EINVAL;
- goto err_pwr_off;
- }
-
- if (gpio_is_valid(pdata->reset_gpio)) {
- ret = gpio_request(pdata->reset_gpio, "goodix_ts_reset_gpio");
- if (ret) {
- dev_err(&client->dev, "Unable to request reset gpio [%d]\n",
- pdata->reset_gpio);
- goto err_free_irq_gpio;
- }
-
- ret = gpio_direction_output(pdata->reset_gpio, 0);
- if (ret) {
- dev_err(&client->dev, "Unable to set direction for reset gpio [%d]\n",
- pdata->reset_gpio);
- goto err_free_reset_gpio;
- }
- } else {
- dev_err(&client->dev, "Invalid irq gpio [%d]!\n",
- pdata->reset_gpio);
- ret = -EINVAL;
- goto err_free_irq_gpio;
- }
- /* IRQ GPIO is an input signal, but we are setting it to output
- * direction and pulling it down, to comply with power up timing
- * requirements, mentioned in power up timing section of device
- * datasheet.
- */
- ret = gpio_direction_output(pdata->irq_gpio, 0);
- if (ret)
- dev_warn(&client->dev,
- "pull down interrupt gpio failed\n");
- ret = gpio_direction_output(pdata->reset_gpio, 0);
- if (ret)
- dev_warn(&client->dev,
- "pull down reset gpio failed\n");
-
- return ret;
-
-err_free_reset_gpio:
- if (gpio_is_valid(pdata->reset_gpio))
- gpio_free(pdata->reset_gpio);
-err_free_irq_gpio:
- if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->irq_gpio);
-err_pwr_off:
- return ret;
-}
-
-/*******************************************************
-Function:
- Request interrupt.
-Input:
- ts: private data.
-Output:
- Executive outcomes.
- 0: succeed, -1: failed.
-*******************************************************/
-static int gtp_request_irq(struct goodix_ts_data *ts)
-{
- int ret;
- const u8 irq_table[] = GTP_IRQ_TAB;
-
- dev_dbg(&ts->client->dev, "INT trigger type:%x, irq=%d",
- ts->int_trigger_type,
- ts->client->irq);
-
- ret = request_threaded_irq(ts->client->irq, NULL,
- goodix_ts_irq_handler,
- irq_table[ts->int_trigger_type],
- ts->client->name, ts);
- if (ret) {
- ts->use_irq = false;
- return ret;
- }
- gtp_irq_disable(ts);
- ts->use_irq = true;
- return 0;
-}
-
-/*******************************************************
-Function:
- Request input device Function.
-Input:
- ts:private data.
-Output:
- Executive outcomes.
- 0: succeed, otherwise: failed.
-*******************************************************/
-static int gtp_request_input_dev(struct goodix_ts_data *ts)
-{
- int ret;
- char phys[PHY_BUF_SIZE];
- int index = 0;
-
- ts->input_dev = input_allocate_device();
- if (ts->input_dev == NULL) {
- dev_err(&ts->client->dev,
- "Failed to allocate input device.\n");
- return -ENOMEM;
- }
-
- ts->input_dev->evbit[0] =
- BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit);
- __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
- /* in case of "out of memory" */
- input_mt_init_slots(ts->input_dev, 10, 0);
-
- if (ts->pdata->have_touch_key) {
- for (index = 0; index < ts->pdata->num_button; index++) {
- input_set_capability(ts->input_dev,
- EV_KEY, ts->pdata->button_map[index]);
- }
- }
-
- if (ts->pdata->slide_wakeup)
- input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
-
- if (ts->pdata->with_pen) { /* pen support */
- __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
- __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
- __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit);
- }
-
- if (ts->pdata->change_x2y)
- swap(ts->abs_x_max, ts->abs_y_max);
-
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
- 0, ts->abs_x_max, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
- 0, ts->abs_y_max, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 0, 255, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 0, 255, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
- 0, 255, 0, 0);
-
- snprintf(phys, PHY_BUF_SIZE, "input/ts");
- ts->input_dev->name = GOODIX_DEV_NAME;
- ts->input_dev->phys = phys;
- ts->input_dev->id.bustype = BUS_I2C;
- ts->input_dev->id.vendor = 0xDEAD;
- ts->input_dev->id.product = 0xBEEF;
- ts->input_dev->id.version = 10427;
-
- ret = input_register_device(ts->input_dev);
- if (ret) {
- dev_err(&ts->client->dev,
- "Register %s input device failed.\n",
- ts->input_dev->name);
- goto exit_free_inputdev;
- }
-
- return 0;
-
-exit_free_inputdev:
- input_free_device(ts->input_dev);
- ts->input_dev = NULL;
- return ret;
-}
-
-static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
-{
- return (regulator_count_voltages(reg) > 0) ?
- regulator_set_load(reg, load_uA) : 0;
-}
-
-/**
- * goodix_power_on - Turn device power ON
- * @ts: driver private data
- *
- * Returns zero on success, else an error.
- */
-static int goodix_power_on(struct goodix_ts_data *ts)
-{
- int ret;
-
- if (ts->power_on) {
- dev_info(&ts->client->dev,
- "Device already power on\n");
- return 0;
- }
-
- if (!IS_ERR(ts->avdd)) {
- ret = reg_set_optimum_mode_check(ts->avdd,
- GOODIX_VDD_LOAD_MAX_UA);
- if (ret < 0) {
- dev_err(&ts->client->dev,
- "Regulator avdd set_opt failed rc=%d\n", ret);
- goto err_set_opt_avdd;
- }
- ret = regulator_enable(ts->avdd);
- if (ret) {
- dev_err(&ts->client->dev,
- "Regulator avdd enable failed ret=%d\n", ret);
- goto err_enable_avdd;
- }
- }
-
- if (!IS_ERR(ts->vdd)) {
- ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV,
- GOODIX_VTG_MAX_UV);
- if (ret) {
- dev_err(&ts->client->dev,
- "Regulator set_vtg failed vdd ret=%d\n", ret);
- goto err_set_vtg_vdd;
- }
- ret = reg_set_optimum_mode_check(ts->vdd,
- GOODIX_VDD_LOAD_MAX_UA);
- if (ret < 0) {
- dev_err(&ts->client->dev,
- "Regulator vdd set_opt failed rc=%d\n", ret);
- goto err_set_opt_vdd;
- }
- ret = regulator_enable(ts->vdd);
- if (ret) {
- dev_err(&ts->client->dev,
- "Regulator vdd enable failed ret=%d\n", ret);
- goto err_enable_vdd;
- }
- }
-
- if (!IS_ERR(ts->vcc_i2c)) {
- ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV,
- GOODIX_I2C_VTG_MAX_UV);
- if (ret) {
- dev_err(&ts->client->dev,
- "Regulator set_vtg failed vcc_i2c ret=%d\n",
- ret);
- goto err_set_vtg_vcc_i2c;
- }
- ret = reg_set_optimum_mode_check(ts->vcc_i2c,
- GOODIX_VIO_LOAD_MAX_UA);
- if (ret < 0) {
- dev_err(&ts->client->dev,
- "Regulator vcc_i2c set_opt failed rc=%d\n",
- ret);
- goto err_set_opt_vcc_i2c;
- }
- ret = regulator_enable(ts->vcc_i2c);
- if (ret) {
- dev_err(&ts->client->dev,
- "Regulator vcc_i2c enable failed ret=%d\n",
- ret);
- regulator_disable(ts->vdd);
- goto err_enable_vcc_i2c;
- }
- }
-
- ts->power_on = true;
- return 0;
-
-err_enable_vcc_i2c:
-err_set_opt_vcc_i2c:
- if (!IS_ERR(ts->vcc_i2c))
- regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV);
-err_set_vtg_vcc_i2c:
- if (!IS_ERR(ts->vdd))
- regulator_disable(ts->vdd);
-err_enable_vdd:
-err_set_opt_vdd:
- if (!IS_ERR(ts->vdd))
- regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV);
-err_set_vtg_vdd:
- if (!IS_ERR(ts->avdd))
- regulator_disable(ts->avdd);
-err_enable_avdd:
-err_set_opt_avdd:
- ts->power_on = false;
- return ret;
-}
-
-/**
- * goodix_power_off - Turn device power OFF
- * @ts: driver private data
- *
- * Returns zero on success, else an error.
- */
-static int goodix_power_off(struct goodix_ts_data *ts)
-{
- int ret;
-
- if (!ts->power_on) {
- dev_info(&ts->client->dev,
- "Device already power off\n");
- return 0;
- }
-
- if (!IS_ERR(ts->vcc_i2c)) {
- ret = regulator_set_voltage(ts->vcc_i2c, 0,
- GOODIX_I2C_VTG_MAX_UV);
- if (ret < 0)
- dev_err(&ts->client->dev,
- "Regulator vcc_i2c set_vtg failed ret=%d\n",
- ret);
- ret = regulator_disable(ts->vcc_i2c);
- if (ret)
- dev_err(&ts->client->dev,
- "Regulator vcc_i2c disable failed ret=%d\n",
- ret);
- }
-
- if (!IS_ERR(ts->vdd)) {
- ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV);
- if (ret < 0)
- dev_err(&ts->client->dev,
- "Regulator vdd set_vtg failed ret=%d\n", ret);
- ret = regulator_disable(ts->vdd);
- if (ret)
- dev_err(&ts->client->dev,
- "Regulator vdd disable failed ret=%d\n", ret);
- }
-
- if (!IS_ERR(ts->avdd)) {
- ret = regulator_disable(ts->avdd);
- if (ret)
- dev_err(&ts->client->dev,
- "Regulator avdd disable failed ret=%d\n", ret);
- }
-
- ts->power_on = false;
- return 0;
-}
-
-/**
- * goodix_power_init - Initialize device power
- * @ts: driver private data
- *
- * Returns zero on success, else an error.
- */
-static int goodix_power_init(struct goodix_ts_data *ts)
-{
- int ret;
-
- ts->avdd = regulator_get(&ts->client->dev, "avdd");
- if (IS_ERR(ts->avdd)) {
- ret = PTR_ERR(ts->avdd);
- dev_info(&ts->client->dev,
- "Regulator get failed avdd ret=%d\n", ret);
- }
-
- ts->vdd = regulator_get(&ts->client->dev, "vdd");
- if (IS_ERR(ts->vdd)) {
- ret = PTR_ERR(ts->vdd);
- dev_info(&ts->client->dev,
- "Regulator get failed vdd ret=%d\n", ret);
- }
-
- ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c");
- if (IS_ERR(ts->vcc_i2c)) {
- ret = PTR_ERR(ts->vcc_i2c);
- dev_info(&ts->client->dev,
- "Regulator get failed vcc_i2c ret=%d\n", ret);
- }
-
- return 0;
-}
-
-/**
- * goodix_power_deinit - Deinitialize device power
- * @ts: driver private data
- *
- * Returns zero on success, else an error.
- */
-static int goodix_power_deinit(struct goodix_ts_data *ts)
-{
- regulator_put(ts->vdd);
- regulator_put(ts->vcc_i2c);
- regulator_put(ts->avdd);
-
- return 0;
-}
-
-static ssize_t gtp_fw_name_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
-
- if (!strlen(ts->fw_name))
- return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1,
- "No fw name has been given.");
- else
- return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1,
- "%s\n", ts->fw_name);
-}
-
-static ssize_t gtp_fw_name_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
-
- if (size > GTP_FW_NAME_MAXSIZE - 1) {
- dev_err(dev, "FW name size exceeds the limit.");
- return -EINVAL;
- }
-
- strlcpy(ts->fw_name, buf, size);
- if (ts->fw_name[size-1] == '\n')
- ts->fw_name[size-1] = '\0';
-
- return size;
-}
-
-static ssize_t gtp_fw_upgrade_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
-
- return snprintf(buf, 2, "%d\n", ts->fw_loading);
-}
-
-static ssize_t gtp_fw_upgrade_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- unsigned int val;
- int ret;
-
- if (size > 2)
- return -EINVAL;
-
- ret = kstrtouint(buf, 10, &val);
- if (ret)
- return ret;
-
- if (ts->gtp_is_suspend) {
- dev_err(&ts->client->dev,
- "Can't start fw upgrade. Device is in suspend state");
- return -EBUSY;
- }
-
- mutex_lock(&ts->input_dev->mutex);
- if (!ts->fw_loading && val) {
- disable_irq(ts->client->irq);
- ts->fw_loading = true;
- if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
- ret = gup_update_proc(NULL);
- if (ret == FAIL)
- dev_err(&ts->client->dev,
- "Fail to update GTP firmware\n");
- }
- ts->fw_loading = false;
- enable_irq(ts->client->irq);
- }
- mutex_unlock(&ts->input_dev->mutex);
-
- return size;
-}
-
-static ssize_t gtp_force_fw_upgrade_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- unsigned int val;
- int ret;
-
- if (size > 2)
- return -EINVAL;
-
- ret = kstrtouint(buf, 10, &val);
- if (ret)
- return ret;
-
- if (ts->gtp_is_suspend) {
- dev_err(&ts->client->dev,
- "Can't start fw upgrade. Device is in suspend state.");
- return -EBUSY;
- }
-
- mutex_lock(&ts->input_dev->mutex);
- if (!ts->fw_loading && val) {
- disable_irq(ts->client->irq);
- ts->fw_loading = true;
- ts->force_update = true;
- if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
- ret = gup_update_proc(NULL);
- if (ret == FAIL)
- dev_err(&ts->client->dev,
- "Fail to force update GTP firmware.\n");
- }
- ts->force_update = false;
- ts->fw_loading = false;
- enable_irq(ts->client->irq);
- }
- mutex_unlock(&ts->input_dev->mutex);
-
- return size;
-}
-
-static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP),
- gtp_fw_name_show,
- gtp_fw_name_store);
-static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
- gtp_fw_upgrade_show,
- gtp_fw_upgrade_store);
-static DEVICE_ATTR(force_fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
- gtp_fw_upgrade_show,
- gtp_force_fw_upgrade_store);
-
-static struct attribute *gtp_attrs[] = {
- &dev_attr_fw_name.attr,
- &dev_attr_fw_upgrade.attr,
- &dev_attr_force_fw_upgrade.attr,
- NULL
-};
-
-static const struct attribute_group gtp_attr_grp = {
- .attrs = gtp_attrs,
-};
-
-static int gtp_debug_addr_is_valid(u16 addr)
-{
- if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) {
- pr_err("GTP reg address is invalid: 0x%x\n", addr);
- return false;
- }
-
- return true;
-}
-
-static int gtp_debug_data_set(void *_data, u64 val)
-{
- struct goodix_ts_data *ts = _data;
-
- mutex_lock(&ts->input_dev->mutex);
- if (gtp_debug_addr_is_valid(ts->addr))
- dev_err(&ts->client->dev,
- "Writing to GTP registers not supported\n");
- mutex_unlock(&ts->input_dev->mutex);
-
- return 0;
-}
-
-static int gtp_debug_data_get(void *_data, u64 *val)
-{
- struct goodix_ts_data *ts = _data;
- int ret;
- u8 buf[3] = {0};
-
- mutex_lock(&ts->input_dev->mutex);
- buf[0] = ts->addr >> 8;
- buf[1] = ts->addr & 0x00ff;
-
- if (gtp_debug_addr_is_valid(ts->addr)) {
- ret = gtp_i2c_read(ts->client, buf, 3);
- if (ret < 0)
- dev_err(&ts->client->dev,
- "GTP read register 0x%x failed (%d)\n",
- ts->addr, ret);
- else
- *val = buf[2];
- }
- mutex_unlock(&ts->input_dev->mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get,
- gtp_debug_data_set, "%llx\n");
-
-static int gtp_debug_addr_set(void *_data, u64 val)
-{
- struct goodix_ts_data *ts = _data;
-
- if (gtp_debug_addr_is_valid(val)) {
- mutex_lock(&ts->input_dev->mutex);
- ts->addr = val;
- mutex_unlock(&ts->input_dev->mutex);
- }
-
- return 0;
-}
-
-static int gtp_debug_addr_get(void *_data, u64 *val)
-{
- struct goodix_ts_data *ts = _data;
-
- mutex_lock(&ts->input_dev->mutex);
- if (gtp_debug_addr_is_valid(ts->addr))
- *val = ts->addr;
- mutex_unlock(&ts->input_dev->mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get,
- gtp_debug_addr_set, "%llx\n");
-
-static int gtp_debug_suspend_set(void *_data, u64 val)
-{
- struct goodix_ts_data *ts = _data;
-
- mutex_lock(&ts->input_dev->mutex);
- if (val)
- goodix_ts_suspend(&ts->client->dev);
- else
- goodix_ts_resume(&ts->client->dev);
- mutex_unlock(&ts->input_dev->mutex);
-
- return 0;
-}
-
-static int gtp_debug_suspend_get(void *_data, u64 *val)
-{
- struct goodix_ts_data *ts = _data;
-
- mutex_lock(&ts->input_dev->mutex);
- *val = ts->gtp_is_suspend;
- mutex_unlock(&ts->input_dev->mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get,
- gtp_debug_suspend_set, "%lld\n");
-
-static int gtp_debugfs_init(struct goodix_ts_data *data)
-{
- data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL);
-
- if (IS_ERR_OR_NULL(data->debug_base)) {
- dev_err(&data->client->dev, "Failed to create debugfs dir\n");
- return -EINVAL;
- }
-
- if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND,
- S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
- data->debug_base,
- data,
- &debug_suspend_fops)))) {
- dev_err(&data->client->dev, "Failed to create suspend file\n");
- debugfs_remove_recursive(data->debug_base);
- return -EINVAL;
- }
-
- if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA,
- S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
- data->debug_base,
- data,
- &debug_data_fops)))) {
- dev_err(&data->client->dev, "Failed to create data file\n");
- debugfs_remove_recursive(data->debug_base);
- return -EINVAL;
- }
-
- if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR,
- S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
- data->debug_base,
- data,
- &debug_addr_fops)))) {
- dev_err(&data->client->dev, "Failed to create addr file\n");
- debugfs_remove_recursive(data->debug_base);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int goodix_ts_get_dt_coords(struct device *dev, char *name,
- struct goodix_ts_platform_data *pdata)
-{
- struct property *prop;
- struct device_node *np = dev->of_node;
- int rc;
- u32 coords[GOODIX_COORDS_ARR_SIZE];
-
- prop = of_find_property(np, name, NULL);
- if (!prop)
- return -EINVAL;
- if (!prop->value)
- return -ENODATA;
-
- rc = of_property_read_u32_array(np, name, coords,
- GOODIX_COORDS_ARR_SIZE);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Unable to read %s\n", name);
- return rc;
- }
-
- if (!strcmp(name, "goodix,panel-coords")) {
- pdata->panel_minx = coords[0];
- pdata->panel_miny = coords[1];
- pdata->panel_maxx = coords[2];
- pdata->panel_maxy = coords[3];
- } else if (!strcmp(name, "goodix,display-coords")) {
- pdata->x_min = coords[0];
- pdata->y_min = coords[1];
- pdata->x_max = coords[2];
- pdata->y_max = coords[3];
- } else {
- dev_err(dev, "unsupported property %s\n", name);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int goodix_parse_dt(struct device *dev,
- struct goodix_ts_platform_data *pdata)
-{
- int rc;
- struct device_node *np = dev->of_node;
- struct property *prop;
- u32 temp_val, num_buttons;
- u32 button_map[MAX_BUTTONS];
- char prop_name[PROP_NAME_SIZE];
- int i, read_cfg_num, temp;
-
- rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata);
- if (rc && (rc != -EINVAL))
- return rc;
-
- rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata);
- if (rc)
- return rc;
-
- pdata->i2c_pull_up = of_property_read_bool(np,
- "goodix,i2c-pull-up");
-
- pdata->force_update = of_property_read_bool(np,
- "goodix,force-update");
-
- pdata->enable_power_off = of_property_read_bool(np,
- "goodix,enable-power-off");
-
- pdata->have_touch_key = of_property_read_bool(np,
- "goodix,have-touch-key");
-
- pdata->driver_send_cfg = of_property_read_bool(np,
- "goodix,driver-send-cfg");
-
- pdata->change_x2y = of_property_read_bool(np,
- "goodix,change-x2y");
-
- pdata->with_pen = of_property_read_bool(np,
- "goodix,with-pen");
-
- pdata->slide_wakeup = of_property_read_bool(np,
- "goodix,slide-wakeup");
-
- pdata->dbl_clk_wakeup = of_property_read_bool(np,
- "goodix,dbl_clk_wakeup");
-
- /* reset, irq gpio info */
- pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios",
- 0, &pdata->reset_gpio_flags);
- if (pdata->reset_gpio < 0)
- return pdata->reset_gpio;
-
- pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios",
- 0, &pdata->irq_gpio_flags);
- if (pdata->irq_gpio < 0)
- return pdata->irq_gpio;
-
- rc = of_property_read_string(np, "goodix,product-id",
- &pdata->product_id);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Failed to parse product_id.");
- return -EINVAL;
- }
-
- rc = of_property_read_string(np, "goodix,fw_name",
- &pdata->fw_name);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Failed to parse firmware name.\n");
- return -EINVAL;
- }
-
- prop = of_find_property(np, "goodix,button-map", NULL);
- if (prop) {
- num_buttons = prop->length / sizeof(temp_val);
- if (num_buttons > MAX_BUTTONS)
- return -EINVAL;
-
- rc = of_property_read_u32_array(np,
- "goodix,button-map", button_map,
- num_buttons);
- if (rc) {
- dev_err(dev, "Unable to read key codes\n");
- return rc;
- }
- pdata->num_button = num_buttons;
- memcpy(pdata->button_map, button_map,
- pdata->num_button * sizeof(u32));
- }
-
- read_cfg_num = 0;
- for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) {
- temp = 0;
- snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i);
- prop = of_find_property(np, prop_name, &temp);
- if (!prop || !prop->value) {
- pdata->config_data_len[i] = 0;
- pdata->config_data[i] = NULL;
- continue;
- }
- pdata->config_data_len[i] = temp;
- pdata->config_data[i] = devm_kzalloc(dev,
- GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
- GFP_KERNEL);
- if (!pdata->config_data[i]) {
- dev_err(dev,
- "Not enough memory for panel config data %d\n",
- i);
- return -ENOMEM;
- }
- pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8;
- pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff;
- memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH],
- prop->value, pdata->config_data_len[i]);
- read_cfg_num++;
- }
- dev_dbg(dev, "%d config data read from device tree\n", read_cfg_num);
-
- return 0;
-}
-
-/*******************************************************
-Function:
- I2c probe.
-Input:
- client: i2c device struct.
- id: device id.
-Output:
- Executive outcomes.
- 0: succeed.
-*******************************************************/
-
-static int goodix_ts_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct goodix_ts_platform_data *pdata;
- struct goodix_ts_data *ts;
- u16 version_info;
- int ret;
-
- dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr);
- if (client->dev.of_node) {
- pdata = devm_kzalloc(&client->dev,
- sizeof(struct goodix_ts_platform_data), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
- ret = goodix_parse_dt(&client->dev, pdata);
- if (ret)
- return ret;
- } else {
- pdata = client->dev.platform_data;
- }
-
- if (!pdata) {
- dev_err(&client->dev, "GTP invalid pdata\n");
- return -EINVAL;
- }
-
- i2c_connect_client = client;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "GTP I2C not supported\n");
- return -ENODEV;
- }
-
- ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- memset(ts, 0, sizeof(*ts));
- ts->client = client;
- ts->pdata = pdata;
- /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock)
- * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED
- */
- spin_lock_init(&ts->irq_lock);
- i2c_set_clientdata(client, ts);
- ts->gtp_rawdiff_mode = 0;
- ts->power_on = false;
-
- ret = gtp_request_io_port(ts);
- if (ret) {
- dev_err(&client->dev, "GTP request IO port failed.\n");
- goto exit_free_client_data;
- }
-
- ret = goodix_power_init(ts);
- if (ret) {
- dev_err(&client->dev, "GTP power init failed\n");
- goto exit_free_io_port;
- }
-
- ret = goodix_power_on(ts);
- if (ret) {
- dev_err(&client->dev, "GTP power on failed\n");
- goto exit_deinit_power;
- }
-
- gtp_reset_guitar(ts, 20);
-
- ret = gtp_i2c_test(client);
- if (ret != 2) {
- dev_err(&client->dev, "I2C communication ERROR\n");
- goto exit_power_off;
- }
-
- if (pdata->force_update)
- ts->force_update = true;
-
- if (pdata->fw_name)
- strlcpy(ts->fw_name, pdata->fw_name,
- strlen(pdata->fw_name) + 1);
-
- if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
- ret = gup_init_update_proc(ts);
- if (ret < 0) {
- dev_err(&client->dev,
- "GTP Create firmware update thread error\n");
- goto exit_power_off;
- }
- }
- ret = gtp_init_panel(ts);
- if (ret < 0) {
- dev_err(&client->dev, "GTP init panel failed\n");
- ts->abs_x_max = GTP_MAX_WIDTH;
- ts->abs_y_max = GTP_MAX_HEIGHT;
- ts->int_trigger_type = GTP_INT_TRIGGER;
- }
-
- ret = gtp_request_input_dev(ts);
- if (ret) {
- dev_err(&client->dev, "GTP request input dev failed\n");
- goto exit_free_inputdev;
- }
- input_set_drvdata(ts->input_dev, ts);
-
- mutex_init(&ts->lock);
-#if defined(CONFIG_FB)
- ts->fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&ts->fb_notif);
- if (ret)
- dev_err(&ts->client->dev,
- "Unable to register fb_notifier: %d\n",
- ret);
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
- ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
- ts->early_suspend.suspend = goodix_ts_early_suspend;
- ts->early_suspend.resume = goodix_ts_late_resume;
- register_early_suspend(&ts->early_suspend);
-#endif
-
- ts->goodix_wq = create_singlethread_workqueue("goodix_wq");
- INIT_WORK(&ts->work, goodix_ts_work_func);
-
- ret = gtp_request_irq(ts);
- if (ret)
- dev_info(&client->dev, "GTP request irq failed %d\n", ret);
- else
- dev_info(&client->dev, "GTP works in interrupt mode\n");
-
- ret = gtp_read_fw_version(client, &version_info);
- if (ret != 2)
- dev_err(&client->dev, "GTP firmware version read failed\n");
-
- ret = gtp_check_product_id(client);
- if (ret != 0) {
- dev_err(&client->dev, "GTP Product id doesn't match\n");
- goto exit_free_irq;
- }
- if (ts->use_irq)
- gtp_irq_enable(ts);
-
-#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
- init_wr_node(client);
-#endif
-
-#if GTP_ESD_PROTECT
- gtp_esd_switch(client, SWITCH_ON);
-#endif
- ret = sysfs_create_group(&client->dev.kobj, &gtp_attr_grp);
- if (ret < 0) {
- dev_err(&client->dev, "sys file creation failed\n");
- goto exit_free_irq;
- }
-
- ret = gtp_debugfs_init(ts);
- if (ret != 0)
- goto exit_remove_sysfs;
-
- init_done = true;
- return 0;
-exit_free_irq:
- mutex_destroy(&ts->lock);
-#if defined(CONFIG_FB)
- if (fb_unregister_client(&ts->fb_notif))
- dev_err(&client->dev,
- "Error occurred while unregistering fb_notifier\n");
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
- unregister_early_suspend(&ts->early_suspend);
-#endif
- if (ts->use_irq)
- free_irq(client->irq, ts);
- cancel_work_sync(&ts->work);
- flush_workqueue(ts->goodix_wq);
- destroy_workqueue(ts->goodix_wq);
-
- input_unregister_device(ts->input_dev);
- if (ts->input_dev) {
- input_free_device(ts->input_dev);
- ts->input_dev = NULL;
- }
-exit_remove_sysfs:
- sysfs_remove_group(&ts->input_dev->dev.kobj, &gtp_attr_grp);
-exit_free_inputdev:
- kfree(ts->config_data);
-exit_power_off:
- goodix_power_off(ts);
-exit_deinit_power:
- goodix_power_deinit(ts);
-exit_free_io_port:
- if (gpio_is_valid(pdata->reset_gpio))
- gpio_free(pdata->reset_gpio);
- if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->irq_gpio);
-exit_free_client_data:
- i2c_set_clientdata(client, NULL);
- return ret;
-}
-
-/*******************************************************
-Function:
- Goodix touchscreen driver release function.
-Input:
- client: i2c device struct.
-Output:
- Executive outcomes. 0---succeed.
-*******************************************************/
-static int goodix_ts_remove(struct i2c_client *client)
-{
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
-
- sysfs_remove_group(&ts->input_dev->dev.kobj, &gtp_attr_grp);
-
-#if defined(CONFIG_FB)
- if (fb_unregister_client(&ts->fb_notif))
- dev_err(&client->dev,
- "Error occurred while unregistering fb_notifier\n");
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
- unregister_early_suspend(&ts->early_suspend);
-#endif
- mutex_destroy(&ts->lock);
-
-#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
- uninit_wr_node();
-#endif
-
-#if GTP_ESD_PROTECT
- cancel_work_sync(gtp_esd_check_workqueue);
- flush_workqueue(gtp_esd_check_workqueue);
- destroy_workqueue(gtp_esd_check_workqueue);
-#endif
-
- if (ts) {
- if (ts->use_irq)
- free_irq(client->irq, ts);
-
- cancel_work_sync(&ts->work);
- flush_workqueue(ts->goodix_wq);
- destroy_workqueue(ts->goodix_wq);
-
- input_unregister_device(ts->input_dev);
- if (ts->input_dev) {
- input_free_device(ts->input_dev);
- ts->input_dev = NULL;
- }
-
- if (gpio_is_valid(ts->pdata->reset_gpio))
- gpio_free(ts->pdata->reset_gpio);
- if (gpio_is_valid(ts->pdata->irq_gpio))
- gpio_free(ts->pdata->irq_gpio);
-
- goodix_power_off(ts);
- goodix_power_deinit(ts);
- i2c_set_clientdata(client, NULL);
- }
- debugfs_remove_recursive(ts->debug_base);
-
- return 0;
-}
-
-#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB)
-/*******************************************************
-Function:
- Early suspend function.
-Input:
- h: early_suspend struct.
-Output:
- None.
-*******************************************************/
-static int goodix_ts_suspend(struct device *dev)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- int ret = 0, i;
-
- if (ts->gtp_is_suspend) {
- dev_dbg(&ts->client->dev, "Already in suspend state\n");
- return 0;
- }
-
- mutex_lock(&ts->lock);
-
- if (ts->fw_loading) {
- dev_info(&ts->client->dev,
- "Fw upgrade in progress, can't go to suspend.");
- mutex_unlock(&ts->lock);
- return 0;
- }
-
-#if GTP_ESD_PROTECT
- gtp_esd_switch(ts->client, SWITCH_OFF);
-#endif
-
- if (ts->pdata->slide_wakeup) {
- ret = gtp_enter_doze(ts);
- } else {
- if (ts->use_irq)
- gtp_irq_disable(ts);
-
- for (i = 0; i < GTP_MAX_TOUCH; i++)
- gtp_touch_up(ts, i);
-
- input_sync(ts->input_dev);
-
- ret = gtp_enter_sleep(ts);
- if (ret < 0)
- dev_err(&ts->client->dev, "GTP early suspend failed.\n");
- }
- /* to avoid waking up while not sleeping,
- * delay 48 + 10ms to ensure reliability
- */
- msleep(58);
- mutex_unlock(&ts->lock);
- ts->gtp_is_suspend = 1;
-
- return ret;
-}
-
-/*******************************************************
-Function:
- Late resume function.
-Input:
- h: early_suspend struct.
-Output:
- None.
-*******************************************************/
-static int goodix_ts_resume(struct device *dev)
-{
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- int ret = 0;
-
- if (!ts->gtp_is_suspend) {
- dev_dbg(&ts->client->dev, "Already in awake state\n");
- return 0;
- }
-
- mutex_lock(&ts->lock);
- ret = gtp_wakeup_sleep(ts);
-
- if (ts->pdata->slide_wakeup)
- doze_status = DOZE_DISABLED;
-
- if (ret <= 0)
- dev_err(&ts->client->dev, "GTP resume failed\n");
-
- if (ts->use_irq)
- gtp_irq_enable(ts);
-
-#if GTP_ESD_PROTECT
- gtp_esd_switch(ts->client, SWITCH_ON);
-#endif
- mutex_unlock(&ts->lock);
- ts->gtp_is_suspend = 0;
-
- return ret;
-}
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self,
- unsigned long event, void *data)
-{
- struct fb_event *evdata = data;
- int *blank;
- struct goodix_ts_data *ts =
- container_of(self, struct goodix_ts_data, fb_notif);
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK &&
- ts && ts->client) {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- goodix_ts_resume(&ts->client->dev);
- else if (*blank == FB_BLANK_POWERDOWN)
- goodix_ts_suspend(&ts->client->dev);
- }
-
- return 0;
-}
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-/*
- * Function:
- * Early suspend function.
- * Input:
- * h: early_suspend struct.
- * Output:
- * None.
- */
-static void goodix_ts_early_suspend(struct early_suspend *h)
-{
- struct goodix_ts_data *ts;
-
- ts = container_of(h, struct goodix_ts_data, early_suspend);
- goodix_ts_suspend(&ts->client->dev);
- return;
-}
-
-/*
- * Function:
- * Late resume function.
- * Input:
- * h: early_suspend struct.
- * Output:
- * None.
- */
-static void goodix_ts_late_resume(struct early_suspend *h)
-{
- struct goodix_ts_data *ts;
-
- ts = container_of(h, struct goodix_ts_data, early_suspend);
- goodix_ts_late_resume(ts);
-}
-#endif
-#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/
-
-#if GTP_ESD_PROTECT
-/*
- * Function:
- * switch on & off esd delayed work
- * Input:
- * client: i2c device
- * on: SWITCH_ON / SWITCH_OFF
- * Output:
- * void
- */
-void gtp_esd_switch(struct i2c_client *client, int on)
-{
- struct goodix_ts_data *ts;
-
- ts = i2c_get_clientdata(client);
- if (on == SWITCH_ON) {
- /* switch on esd */
- if (!ts->esd_running) {
- ts->esd_running = 1;
- dev_dbg(&client->dev, "Esd started\n");
- queue_delayed_work(gtp_esd_check_workqueue,
- &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
- }
- } else {
- /* switch off esd */
- if (ts->esd_running) {
- ts->esd_running = 0;
- dev_dbg(&client->dev, "Esd cancelled\n");
- cancel_delayed_work_sync(&gtp_esd_check_work);
- }
- }
-}
-
-/*******************************************************
-Function:
- Initialize external watchdog for esd protect
-Input:
- client: i2c device.
-Output:
- result of i2c write operation.
- 1: succeed, otherwise: failed
-*********************************************************/
-static int gtp_init_ext_watchdog(struct i2c_client *client)
-{
- /* in case of recursively reset by calling gtp_i2c_write*/
- struct i2c_msg msg;
- u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA};
- int ret;
- int retries = 0;
-
- msg.flags = !I2C_M_RD;
- msg.addr = client->addr;
- msg.len = 4;
- msg.buf = opr_buffer;
-
- while (retries < GTP_I2C_RETRY_5) {
- ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret == 1)
- return 1;
- retries++;
- }
- if (retries == GTP_I2C_RETRY_5)
- dev_err(&client->dev, "init external watchdog failed!");
- return 0;
-}
-
-/*******************************************************
-Function:
- Esd protect function.
- Added external watchdog by meta, 2013/03/07
-Input:
- work: delayed work
-Output:
- None.
-*******************************************************/
-static void gtp_esd_check_func(struct work_struct *work)
-{
- s32 retry;
- s32 ret = -1;
- struct goodix_ts_data *ts = NULL;
- u8 test[4] = {0x80, 0x40};
-
- ts = i2c_get_clientdata(i2c_connect_client);
-
- if (ts->gtp_is_suspend) {
- dev_dbg(&ts->client->dev, "Esd terminated!\n");
- ts->esd_running = 0;
- return;
- }
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
- if (ts->enter_update)
- return;
-#endif
-
- for (retry = 0; retry < GTP_I2C_RETRY_3; retry++) {
- ret = gtp_i2c_read(ts->client, test, 4);
-
- if ((ret < 0)) {
- /* IC works abnormally..*/
- continue;
- } else {
- if ((test[2] == 0xAA) || (test[3] != 0xAA)) {
- /* IC works abnormally..*/
- retry = GTP_I2C_RETRY_3;
- break;
- }
- /* IC works normally, Write 0x8040 0xAA*/
- test[2] = 0xAA;
- gtp_i2c_write(ts->client, test, 3);
- break;
- }
- }
- if (retry == GTP_I2C_RETRY_3) {
- dev_err(&ts->client->dev,
- "IC Working ABNORMALLY, Resetting Guitar...\n");
- gtp_reset_guitar(ts, 50);
- }
-
- if (!ts->gtp_is_suspend)
- queue_delayed_work(gtp_esd_check_workqueue,
- &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
- else {
- dev_dbg(&ts->client->dev, "Esd terminated!\n");
- ts->esd_running = 0;
- }
-
- return;
-}
-#endif
-
-#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
-static const struct dev_pm_ops goodix_ts_dev_pm_ops = {
- .suspend = goodix_ts_suspend,
- .resume = goodix_ts_resume,
-};
-#else
-static const struct dev_pm_ops goodix_ts_dev_pm_ops = {
-};
-#endif
-
-static const struct i2c_device_id goodix_ts_id[] = {
- { GTP_I2C_NAME, 0 },
- { }
-};
-
-static const struct of_device_id goodix_match_table[] = {
- { .compatible = "goodix,gt9xx", },
- { },
-};
-
-static struct i2c_driver goodix_ts_driver = {
- .probe = goodix_ts_probe,
- .remove = goodix_ts_remove,
-#ifdef CONFIG_HAS_EARLYSUSPEND
- .suspend = goodix_ts_early_suspend,
- .resume = goodix_ts_late_resume,
-#endif
- .id_table = goodix_ts_id,
- .driver = {
- .name = GTP_I2C_NAME,
- .owner = THIS_MODULE,
- .of_match_table = goodix_match_table,
-#if CONFIG_PM
- .pm = &goodix_ts_dev_pm_ops,
-#endif
- },
-};
-
-/*******************************************************
-Function:
- Driver Install function.
-Input:
- None.
-Output:
- Executive Outcomes. 0---succeed.
-********************************************************/
-static int __init goodix_ts_init(void)
-{
- int ret;
-
-#if GTP_ESD_PROTECT
- INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
- gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
-#endif
- ret = i2c_add_driver(&goodix_ts_driver);
- return ret;
-}
-
-/*******************************************************
-Function:
- Driver uninstall function.
-Input:
- None.
-Output:
- Executive Outcomes. 0---succeed.
-********************************************************/
-static void __exit goodix_ts_exit(void)
-{
- i2c_del_driver(&goodix_ts_driver);
-}
-
-module_init(goodix_ts_init);
-module_exit(goodix_ts_exit);
-
-MODULE_DESCRIPTION("GTP Series Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
deleted file mode 100644
index 1e85e2fce276..000000000000
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/* drivers/input/touchscreen/gt9xx.h
- *
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
- *
- * 2010 - 2013 Goodix Technology.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be a reference
- * to you, when you are integrating the GOODiX's CTP IC into your system,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- */
-
-#ifndef _GOODIX_GT9XX_H_
-#define _GOODIX_GT9XX_H_
-
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/uaccess.h>
-
-#if defined(CONFIG_FB)
-#include <linux/notifier.h>
-#include <linux/fb.h>
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#define GOODIX_SUSPEND_LEVEL 1
-#endif
-
-#define MAX_BUTTONS 4
-#define GOODIX_MAX_CFG_GROUP 6
-#define GTP_FW_NAME_MAXSIZE 50
-
-struct goodix_ts_platform_data {
- int irq_gpio;
- u32 irq_gpio_flags;
- int reset_gpio;
- u32 reset_gpio_flags;
- const char *product_id;
- const char *fw_name;
- u32 x_max;
- u32 y_max;
- u32 x_min;
- u32 y_min;
- u32 panel_minx;
- u32 panel_miny;
- u32 panel_maxx;
- u32 panel_maxy;
- bool force_update;
- bool i2c_pull_up;
- bool enable_power_off;
- size_t config_data_len[GOODIX_MAX_CFG_GROUP];
- u8 *config_data[GOODIX_MAX_CFG_GROUP];
- u32 button_map[MAX_BUTTONS];
- u8 num_button;
- bool have_touch_key;
- bool driver_send_cfg;
- bool change_x2y;
- bool with_pen;
- bool slide_wakeup;
- bool dbl_clk_wakeup;
-};
-struct goodix_ts_data {
- spinlock_t irq_lock;
- struct i2c_client *client;
- struct input_dev *input_dev;
- struct goodix_ts_platform_data *pdata;
- struct hrtimer timer;
- struct workqueue_struct *goodix_wq;
- struct work_struct work;
- char fw_name[GTP_FW_NAME_MAXSIZE];
- struct delayed_work goodix_update_work;
- s32 irq_is_disabled;
- s32 use_irq;
- u16 abs_x_max;
- u16 abs_y_max;
- u16 addr;
- u8 max_touch_num;
- u8 int_trigger_type;
- u8 green_wake_mode;
- u8 chip_type;
- u8 *config_data;
- u8 enter_update;
- u8 gtp_is_suspend;
- u8 gtp_rawdiff_mode;
- u8 gtp_cfg_len;
- u8 fixed_cfg;
- u8 esd_running;
- u8 fw_error;
- bool power_on;
- struct mutex lock;
- bool fw_loading;
- bool force_update;
- struct regulator *avdd;
- struct regulator *vdd;
- struct regulator *vcc_i2c;
-#if defined(CONFIG_FB)
- struct notifier_block fb_notif;
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
- struct early_suspend early_suspend;
-#endif
- struct dentry *debug_base;
-};
-
-extern u16 show_len;
-extern u16 total_len;
-
-/***************************PART1:ON/OFF define*******************************/
-#define GTP_CUSTOM_CFG 0
-#define GTP_ESD_PROTECT 0
-
-#define GTP_IRQ_TAB {\
- IRQ_TYPE_EDGE_RISING,\
- IRQ_TYPE_EDGE_FALLING,\
- IRQ_TYPE_LEVEL_LOW,\
- IRQ_TYPE_LEVEL_HIGH\
- }
-
-
-#define GTP_IRQ_TAB_RISING 0
-#define GTP_IRQ_TAB_FALLING 1
-#if GTP_CUSTOM_CFG
-#define GTP_MAX_HEIGHT 800
-#define GTP_MAX_WIDTH 480
-#define GTP_INT_TRIGGER GTP_IRQ_TAB_RISING
-#else
-#define GTP_MAX_HEIGHT 4096
-#define GTP_MAX_WIDTH 4096
-#define GTP_INT_TRIGGER GTP_IRQ_TAB_FALLING
-#endif
-
-#define GTP_PRODUCT_ID_MAXSIZE 5
-#define GTP_PRODUCT_ID_BUFFER_MAXSIZE 6
-#define GTP_FW_VERSION_BUFFER_MAXSIZE 4
-#define GTP_MAX_TOUCH 5
-#define GTP_ESD_CHECK_CIRCLE 2000 /* jiffy: ms */
-
-/***************************PART3:OTHER define*********************************/
-#define GTP_DRIVER_VERSION "V1.8.1<2013/09/01>"
-#define GTP_I2C_NAME "Goodix-TS"
-#define GTP_POLL_TIME 10 /* jiffy: ms*/
-#define GTP_ADDR_LENGTH 2
-#define GTP_CONFIG_MIN_LENGTH 186
-#define GTP_CONFIG_MAX_LENGTH 240
-#define FAIL 0
-#define SUCCESS 1
-#define SWITCH_OFF 0
-#define SWITCH_ON 1
-
-/* Registers define */
-#define GTP_READ_COOR_ADDR 0x814E
-#define GTP_REG_SLEEP 0x8040
-#define GTP_REG_SENSOR_ID 0x814A
-#define GTP_REG_CONFIG_DATA 0x8047
-#define GTP_REG_FW_VERSION 0x8144
-#define GTP_REG_PRODUCT_ID 0x8140
-
-#define GTP_I2C_RETRY_3 3
-#define GTP_I2C_RETRY_5 5
-#define GTP_I2C_RETRY_10 10
-
-#define RESOLUTION_LOC 3
-#define TRIGGER_LOC 8
-
-/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
-#define GTP_I2C_ADDRESS_HIGH 0x14
-#define GTP_I2C_ADDRESS_LOW 0x5D
-#define GTP_VALID_ADDR_START 0x8040
-#define GTP_VALID_ADDR_END 0x8177
-
-/* GTP CM_HEAD RW flags */
-#define GTP_RW_READ 0
-#define GTP_RW_WRITE 1
-#define GTP_RW_READ_IC_TYPE 2
-#define GTP_RW_WRITE_IC_TYPE 3
-#define GTP_RW_FILL_INFO 4
-#define GTP_RW_NO_WRITE 5
-#define GTP_RW_READ_ERROR 6
-#define GTP_RW_DISABLE_IRQ 7
-#define GTP_RW_READ_VERSION 8
-#define GTP_RW_ENABLE_IRQ 9
-#define GTP_RW_ENTER_UPDATE_MODE 11
-#define GTP_RW_LEAVE_UPDATE_MODE 13
-#define GTP_RW_UPDATE_FW 15
-#define GTP_RW_CHECK_RAWDIFF_MODE 17
-
-/* GTP need flag or interrupt */
-#define GTP_NO_NEED 0
-#define GTP_NEED_FLAG 1
-#define GTP_NEED_INTERRUPT 2
-
-/*****************************End of Part III********************************/
-
-void gtp_esd_switch(struct i2c_client *client, int on);
-
-int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr,
- u8 *rxbuf, int len);
-int gtp_send_cfg(struct goodix_ts_data *ts);
-void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
-void gtp_irq_disable(struct goodix_ts_data *ts);
-void gtp_irq_enable(struct goodix_ts_data *ts);
-
-#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
-s32 init_wr_node(struct i2c_client *client);
-void uninit_wr_node(void);
-#endif
-
-u8 gup_init_update_proc(struct goodix_ts_data *ts);
-s32 gup_enter_update_mode(struct i2c_client *client);
-void gup_leave_update_mode(struct i2c_client *client);
-s32 gup_update_proc(void *dir);
-extern struct i2c_client *i2c_connect_client;
-#endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
deleted file mode 100644
index 6bc243492272..000000000000
--- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c
+++ /dev/null
@@ -1,1530 +0,0 @@
-/* drivers/input/touchscreen/gt9xx_update.c
- *
- * 2010 - 2012 Goodix Technology.
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be a reference
- * to you, when you are integrating the GOODiX's CTP IC into your system,
- * 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.
- *
- * Latest Version:1.6
- * Author: andrew@goodix.com
- * Revision Record:
- * V1.0:
- * first release. By Andrew, 2012/08/31
- * V1.2:
- * add force update,GT9110P pid map. By Andrew, 2012/10/15
- * V1.4:
- * 1. add config auto update function;
- * 2. modify enter_update_mode;
- * 3. add update file cal checksum.
- * By Andrew, 2012/12/12
- * V1.6:
- * 1. replace guitar_client with i2c_connect_client;
- * 2. support firmware header array update.
- * By Meta, 2013/03/11
- */
-#include "gt9xx.h"
-#include <linux/firmware.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-
-#define FIRMWARE_NAME_LEN_MAX 256
-
-#define GUP_REG_HW_INFO 0x4220
-#define GUP_REG_FW_MSG 0x41E4
-#define GUP_REG_PID_VID 0x8140
-
-#define GOODIX_FIRMWARE_FILE_NAME "_goodix_update_.bin"
-#define GOODIX_CONFIG_FILE_NAME "_goodix_config_.cfg"
-
-#define FW_HEAD_LENGTH 14
-#define FW_SECTION_LENGTH 0x2000
-#define FW_DSP_ISP_LENGTH 0x1000
-#define FW_DSP_LENGTH 0x1000
-#define FW_BOOT_LENGTH 0x800
-
-#define PACK_SIZE 256
-#define MAX_FRAME_CHECK_TIME 5
-
-#define _bRW_MISCTL__SRAM_BANK 0x4048
-#define _bRW_MISCTL__MEM_CD_EN 0x4049
-#define _bRW_MISCTL__CACHE_EN 0x404B
-#define _bRW_MISCTL__TMR0_EN 0x40B0
-#define _rRW_MISCTL__SWRST_B0_ 0x4180
-#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184
-#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190
-#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218
-#define _rRW_MISCTL__BOOT_CTL_ 0x5094
-
-#define FAIL 0
-#define SUCCESS 1
-
-#define RESET_DELAY_US 20000
-
-struct st_fw_head {
- u8 hw_info[4]; /* hardware info */
- u8 pid[8]; /* product id */
- u16 vid; /* version id */
-} __packed;
-
-struct st_update_msg {
- u8 force_update;
- u8 fw_flag;
- bool need_free;
- u8 *fw_data;
- u32 fw_len;
- struct st_fw_head ic_fw_msg;
-};
-
-static struct st_update_msg update_msg;
-u16 show_len;
-u16 total_len;
-u8 got_file_flag;
-u8 searching_file;
-/*******************************************************
-Function:
- Read data from the i2c slave device.
-Input:
- client: i2c device.
- buf[0~1]: read start address.
- buf[2~len-1]: read data buffer.
- len: GTP_ADDR_LENGTH + read bytes count
-Output:
- numbers of i2c_msgs to transfer:
- 2: succeed, otherwise: failed
-*********************************************************/
-static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
-{
- s32 ret = -1;
- u8 retries = 0;
- struct i2c_msg msgs[2] = {
- {
- .flags = !I2C_M_RD,
- .addr = client->addr,
- .len = GTP_ADDR_LENGTH,
- .buf = &buf[0],
- },
- {
- .flags = I2C_M_RD,
- .addr = client->addr,
- .len = len - GTP_ADDR_LENGTH,
- .buf = &buf[GTP_ADDR_LENGTH],
- },
- };
-
- while (retries < 5) {
- ret = i2c_transfer(client->adapter, msgs, 2);
- if (ret == 2)
- break;
- retries++;
- }
-
- if (retries == 5) {
- dev_err(&client->dev, "I2C read retry limit over.\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-/*******************************************************
-Function:
- Write data to the i2c slave device.
-Input:
- client: i2c device.
- buf[0~1]: write start address.
- buf[2~len-1]: data buffer
- len: GTP_ADDR_LENGTH + write bytes count
-Output:
- numbers of i2c_msgs to transfer:
- 1: succeed, otherwise: failed
-*********************************************************/
-s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len)
-{
- s32 ret = -1;
- u8 retries = 0;
- struct i2c_msg msg = {
- .flags = !I2C_M_RD,
- .addr = client->addr,
- .len = len,
- .buf = buf,
- };
-
- while (retries < 5) {
- ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret == 1)
- break;
- retries++;
- }
-
- if (retries == 5) {
- dev_err(&client->dev, "I2C write retry limit over\n");
- ret = -EIO;
- }
-
- return ret;
-}
-
-static s32 gup_init_panel(struct goodix_ts_data *ts)
-{
- struct i2c_client *client = ts->client;
- u8 *config_data;
- s32 ret = 0;
- s32 i = 0;
- u8 check_sum = 0;
- u8 opr_buf[16];
- u8 sensor_id = 0;
-
- for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
- if (ts->pdata->config_data_len[i])
- break;
-
- if (i == GOODIX_MAX_CFG_GROUP) {
- sensor_id = 0;
- } else {
- ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID,
- &sensor_id, 1);
- if (ret == SUCCESS) {
- if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
- pr_err("Invalid sensor_id(0x%02X), No Config Sent",
- sensor_id);
- return -EINVAL;
- }
- } else {
- pr_err("Failed to get sensor_id, No config sent\n");
- return -EINVAL;
- }
- }
-
- pr_debug("Sensor ID selected: %d", sensor_id);
-
- if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
- !ts->pdata->config_data_len[sensor_id]) {
- pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP",
- sensor_id);
- return -EINVAL;
- }
-
- ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA,
- &opr_buf[0], 1);
- if (ret == SUCCESS) {
- pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d",
- sensor_id + 1,
- ts->pdata->config_data[sensor_id][0],
- opr_buf[0]);
-
- ts->pdata->config_data[sensor_id][0] = opr_buf[0];
- ts->fixed_cfg = 0;
- } else {
- pr_err("Failed to get ic config version. No config sent");
- return -EINVAL;
- }
-
- config_data = ts->pdata->config_data[sensor_id];
- ts->config_data = ts->pdata->config_data[sensor_id];
- ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];
-
- pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x\n",
- ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type);
-
- config_data[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH;
- config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
- config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
- config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
-
- if (GTP_INT_TRIGGER == 0) /* RISING */
- config_data[TRIGGER_LOC] &= 0xfe;
- else if (GTP_INT_TRIGGER == 1) /* FALLING */
- config_data[TRIGGER_LOC] |= 0x01;
-
- check_sum = 0;
- for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
- check_sum += config_data[i];
-
- config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
-
- ret = gtp_send_cfg(ts);
- if (ret < 0)
- pr_err("Send config error\n");
-
- ts->config_data = NULL;
- ts->gtp_cfg_len = 0;
- msleep(20);
- return 0;
-}
-
-static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len)
-{
- u8 i = 0;
-
- msg[0] = (addr >> 8) & 0xff;
- msg[1] = addr & 0xff;
-
- for (i = 0; i < 5; i++)
- if (gup_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0)
- break;
-
- if (i >= 5) {
- pr_err("Read data from 0x%02x%02x failed\n", msg[0], msg[1]);
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
-{
- u8 i = 0;
- u8 msg[3] = {
- (addr >> 8) & 0xff,
- addr & 0xff,
- val,
- };
-
- for (i = 0; i < 5; i++)
- if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
- break;
-
- if (i >= 5) {
- pr_err("Set data to 0x%02x%02x failed\n", msg[0], msg[1]);
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_get_ic_fw_msg(struct i2c_client *client)
-{
- s32 ret = -1;
- u8 retry = 0;
- u8 buf[16];
- u8 i;
-
- /* step1:get hardware info */
- ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO,
- &buf[GTP_ADDR_LENGTH], 4);
- if (ret == FAIL) {
- pr_err("get hw_info failed,exit");
- return FAIL;
- }
-
- /* buf[2~5]: 00 06 90 00 */
- /* hw_info: 00 90 06 00 */
- for (i = 0; i < 4; i++)
- update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
-
- pr_debug("IC Hardware info:%02x%02x%02x%02x\n",
- update_msg.ic_fw_msg.hw_info[0],
- update_msg.ic_fw_msg.hw_info[1],
- update_msg.ic_fw_msg.hw_info[2],
- update_msg.ic_fw_msg.hw_info[3]);
-
- /* step2:get firmware message */
- for (retry = 0; retry < 2; retry++) {
- ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
- if (ret == FAIL) {
- pr_err("Read firmware message fail\n");
- return ret;
- }
-
- update_msg.force_update = buf[GTP_ADDR_LENGTH];
- if ((update_msg.force_update != 0xBE) && (!retry)) {
- pr_info("The check sum in ic is error\n");
- pr_info("The IC will be updated by force\n");
- continue;
- }
- break;
- }
- pr_debug("IC force update flag:0x%x\n", update_msg.force_update);
-
- /* step3:get pid & vid */
- ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID,
- &buf[GTP_ADDR_LENGTH], 6);
- if (ret == FAIL) {
- pr_err("get pid & vid failed,exit");
- return FAIL;
- }
-
- memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
- memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
- pr_debug("IC Product id:%s\n", update_msg.ic_fw_msg.pid);
-
- /* GT9XX PID MAPPING
- * |-----FLASH-----RAM-----|
- * |------918------918-----|
- * |------968------968-----|
- * |------913------913-----|
- * |------913P-----913P----|
- * |------927------927-----|
- * |------927P-----927P----|
- * |------9110-----9110----|
- * |------9110P----9111----|
- */
- if (update_msg.ic_fw_msg.pid[0] != 0) {
- if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) {
- pr_debug("IC Mapping Product id:%s\n",
- update_msg.ic_fw_msg.pid);
- memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
- }
- }
-
- update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] +
- (buf[GTP_ADDR_LENGTH + 5] << 8);
- pr_debug("IC version id:%04x\n", update_msg.ic_fw_msg.vid);
-
- return SUCCESS;
-}
-
-s32 gup_enter_update_mode(struct i2c_client *client)
-{
- s32 ret = -1;
- u8 retry = 0;
- u8 rd_buf[3];
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
-
- /* step1:RST output low last at least 2ms */
- gpio_direction_output(ts->pdata->reset_gpio, 0);
- usleep_range(RESET_DELAY_US, RESET_DELAY_US + 1);
-
- /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */
- gpio_direction_output(ts->pdata->irq_gpio,
- (client->addr == GTP_I2C_ADDRESS_HIGH));
- msleep(20);
-
- /* step3:RST output high reset guitar */
- gpio_direction_output(ts->pdata->reset_gpio, 1);
-
- /* 20121211 modify start */
- msleep(20);
- while (retry++ < 200) {
- /* step4:Hold ss51 & dsp */
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
- if (ret <= 0) {
- pr_debug("Hold ss51 & dsp I2C error,retry:%d\n", retry);
- continue;
- }
-
- /* step5:Confirm hold */
- ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
- if (ret <= 0) {
- pr_debug("Hold ss51 & dsp I2C error,retry:%d\n", retry);
- continue;
- }
- if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) {
- pr_debug("Hold ss51 & dsp confirm SUCCESS\n");
- break;
- }
- pr_debug("Hold ss51 & dsp confirm 0x4180 failed,value:%d\n",
- rd_buf[GTP_ADDR_LENGTH]);
- }
- if (retry >= 200) {
- pr_err("Enter update Hold ss51 failed\n");
- return FAIL;
- }
-
- /* step6:DSP_CK and DSP_ALU_CK PowerOn */
- ret = gup_set_ic_msg(client, 0x4010, 0x00);
-
- /* 20121211 modify end */
- return ret;
-}
-
-void gup_leave_update_mode(struct i2c_client *client)
-{
- struct goodix_ts_data *ts = i2c_get_clientdata(client);
-
- gpio_direction_input(ts->pdata->irq_gpio);
- pr_debug("reset chip");
- gtp_reset_guitar(ts, 20);
-}
-
-/* Get the correct nvram data
- * The correct conditions:
- * 1. the hardware info is the same
- * 2. the product id is the same
- * 3. the firmware version in update file is greater than the firmware
- * version in ic or the check sum in ic is wrong
-
- * Update Conditions:
- * 1. Same hardware info
- * 2. Same PID
- * 3. File PID > IC PID
-
- * Force Update Conditions:
- * 1. Wrong ic firmware checksum
- * 2. INVALID IC PID or VID
- * 3. IC PID == 91XX || File PID == 91XX
- */
-
-static u8 gup_enter_update_judge(struct i2c_client *client,
- struct st_fw_head *fw_head)
-{
- u16 u16_tmp;
- s32 i = 0;
-
- u16_tmp = fw_head->vid;
- fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
-
- pr_debug("FILE HARDWARE INFO:%02x%02x%02x%02x\n", fw_head->hw_info[0],
- fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]);
- pr_debug("FILE PID:%s\n", fw_head->pid);
- pr_debug("FILE VID:%04x\n", fw_head->vid);
-
- pr_debug("IC HARDWARE INFO:%02x%02x%02x%02x\n",
- update_msg.ic_fw_msg.hw_info[0],
- update_msg.ic_fw_msg.hw_info[1],
- update_msg.ic_fw_msg.hw_info[2],
- update_msg.ic_fw_msg.hw_info[3]);
- pr_debug("IC PID:%s\n", update_msg.ic_fw_msg.pid);
- pr_debug("IC VID:%04x\n", update_msg.ic_fw_msg.vid);
-
- /* First two conditions */
- if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info,
- sizeof(update_msg.ic_fw_msg.hw_info))) {
- pr_debug("Get the same hardware info\n");
- if (update_msg.force_update != 0xBE) {
- pr_info("FW chksum error,need enter update\n");
- return SUCCESS;
- }
-
- /* 20130523 start */
- if (strlen(update_msg.ic_fw_msg.pid) < 3) {
- pr_info("Illegal IC pid, need enter update\n");
- return SUCCESS;
- }
- for (i = 0; i < 3; i++) {
- if ((update_msg.ic_fw_msg.pid[i] < 0x30) ||
- (update_msg.ic_fw_msg.pid[i] > 0x39)) {
- pr_info("Illegal IC pid, out of bound, need enter update\n");
- return SUCCESS;
- }
- }
- /* 20130523 end */
-
- if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid,
- (strlen(fw_head->pid) < 3 ? 3 : strlen(fw_head->pid)))) ||
- (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) ||
- (!memcmp(fw_head->pid, "91XX", 4))) {
- if (!memcmp(fw_head->pid, "91XX", 4))
- pr_debug("Force none same pid update mode\n");
- else
- pr_debug("Get the same pid\n");
-
- /* The third condition */
- if (fw_head->vid > update_msg.ic_fw_msg.vid) {
- pr_info("Need enter update");
- return SUCCESS;
- }
- pr_err("Don't meet the third condition\n");
- pr_err("File VID <= Ic VID, update aborted\n");
- } else {
- pr_err("File PID != Ic PID, update aborted\n");
- }
- } else {
- pr_err("Different Hardware, update aborted\n");
- }
-
- return FAIL;
-}
-
-static s8 gup_update_config(struct i2c_client *client,
- const struct firmware *cfg)
-{
- s32 ret = 0;
- s32 i = 0;
- s32 file_cfg_len = 0;
- u32 chip_cfg_len = 0;
- s32 count = 0;
- u8 *buf;
- u8 *file_config;
- u8 pid[8];
- u8 high, low;
-
- if (!cfg || !cfg->data) {
- pr_err("No need to upgrade config");
- return FAIL;
- }
-
- ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6);
- if (ret == FAIL) {
- pr_err("Read product id & version id fail");
- return FAIL;
- }
- pid[5] = '\0';
- pr_debug("update cfg get pid:%s\n", &pid[GTP_ADDR_LENGTH]);
-
- chip_cfg_len = 186;
- if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) ||
- !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
- !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) {
- chip_cfg_len = 228;
- }
- pr_debug("config file ASCII len: %zu", cfg->size);
- pr_debug("need config binary len: %u", chip_cfg_len);
- if ((cfg->size + 5) < chip_cfg_len * 5) {
- pr_err("Config length error");
- return -EINVAL;
- }
-
- buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH,
- GFP_KERNEL);
- if (!file_config)
- return -ENOMEM;
-
- pr_debug("Delete illegal character");
- for (i = 0, count = 0; i < cfg->size; i++) {
- if (cfg->data[i] == ' ' || cfg->data[i] == '\r'
- || cfg->data[i] == '\n')
- continue;
- buf[count++] = cfg->data[i];
- }
-
- pr_debug("Ascii to hex");
- file_config[0] = GTP_REG_CONFIG_DATA >> 8;
- file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
- for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) {
- if ((buf[i] == '0') && ((buf[i + 1] == 'x') ||
- (buf[i + 1] == 'X'))) {
- ret = hex2bin(&high, &buf[i + 2], 1);
- if (ret) {
- pr_err("Failed to convert high address from hex2bin");
- return ret;
- }
- ret = hex2bin(&low, &buf[i + 3], 1);
- if (ret) {
- pr_err("Failed to convert low address from hex2bin");
- return ret;
- }
-
- if ((high == 0xFF) || (low == 0xFF)) {
- ret = 0;
- pr_err("Illegal config file");
- return ret;
- }
- file_config[file_cfg_len++] = (high<<4) + low;
- } else {
- ret = 0;
- pr_err("Illegal config file");
- return ret;
- }
- }
-
- i = 0;
- while (i++ < 5) {
- ret = gup_i2c_write(client, file_config, file_cfg_len);
- if (ret > 0)
- break;
- pr_err("Send config i2c error");
- }
-
- return ret;
-}
-
-static s32 gup_get_firmware_file(struct i2c_client *client,
- struct st_update_msg *msg, u8 *path)
-{
- s32 ret;
- const struct firmware *fw = NULL;
-
- ret = request_firmware(&fw, path, &client->dev);
- if (ret < 0) {
- dev_info(&client->dev, "Cannot get firmware - %s (%d)\n",
- path, ret);
- return -EEXIST;
- }
-
- dev_dbg(&client->dev, "Config File: %s size: %zu", path, fw->size);
- msg->fw_data =
- devm_kzalloc(&client->dev, fw->size, GFP_KERNEL);
- if (!msg->fw_data) {
- release_firmware(fw);
- return -ENOMEM;
- }
-
- memcpy(msg->fw_data, fw->data, fw->size);
- msg->fw_len = fw->size;
- msg->need_free = true;
- release_firmware(fw);
- return 0;
-}
-
-static u8 gup_check_firmware_name(struct i2c_client *client,
- u8 **path_p)
-{
- u8 len;
- u8 *fname;
-
- if (!(*path_p)) {
- *path_p = GOODIX_FIRMWARE_FILE_NAME;
- return 0;
- }
-
- len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX);
- if (len >= FIRMWARE_NAME_LEN_MAX) {
- dev_err(&client->dev, "firmware name too long");
- return -EINVAL;
- }
-
- fname = strrchr(*path_p, '/');
- if (fname) {
- fname = fname + 1;
- *path_p = fname;
- }
- return 0;
-}
-
-static u8 gup_check_update_file(struct i2c_client *client,
- struct st_fw_head *fw_head, u8 *path)
-{
- s32 ret = 0;
- s32 i = 0;
- s32 fw_checksum = 0;
- u16 temp;
- const struct firmware *fw = NULL;
-
- ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev);
- if (ret < 0) {
- dev_info(&client->dev, "Cannot get config file - %s (%d)\n",
- GOODIX_CONFIG_FILE_NAME, ret);
- } else {
- dev_dbg(&client->dev,
- "Update config File: %s", GOODIX_CONFIG_FILE_NAME);
- ret = gup_update_config(client, fw);
- if (ret <= 0)
- dev_err(&client->dev, "Update config failed");
- release_firmware(fw);
- }
-
- update_msg.need_free = false;
- update_msg.fw_len = 0;
-
- if (gup_check_firmware_name(client, &path))
- goto load_failed;
-
- if (gup_get_firmware_file(client, &update_msg, path))
- goto load_failed;
-
- memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH);
-
- /* check firmware legality */
- fw_checksum = 0;
- for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH +
- FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) {
- temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) +
- update_msg.fw_data[FW_HEAD_LENGTH + i + 1];
- fw_checksum += temp;
- }
-
- pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF);
- if (fw_checksum & 0xFFFF) {
- dev_err(&client->dev, "Illegal firmware file");
- goto load_failed;
- }
-
- return SUCCESS;
-
-load_failed:
- if (update_msg.need_free) {
- devm_kfree(&client->dev, update_msg.fw_data);
- update_msg.need_free = false;
- }
- return FAIL;
-}
-
-static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr,
- u16 total_length)
-{
- s32 ret = 0;
- u16 burn_addr = start_addr;
- u16 frame_length = 0;
- u16 burn_length = 0;
- u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH];
- u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
- u8 retry = 0;
-
- pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024),
- start_addr);
- while (burn_length < total_length) {
- pr_debug("B/T:%04d/%04d", burn_length, total_length);
- frame_length = ((total_length - burn_length) > PACK_SIZE)
- ? PACK_SIZE : (total_length - burn_length);
- wr_buf[0] = (u8)(burn_addr>>8);
- rd_buf[0] = wr_buf[0];
- wr_buf[1] = (u8)burn_addr;
- rd_buf[1] = wr_buf[1];
- memcpy(&wr_buf[GTP_ADDR_LENGTH], &burn_buf[burn_length],
- frame_length);
-
- for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) {
- ret = gup_i2c_write(client, wr_buf,
- GTP_ADDR_LENGTH + frame_length);
- if (ret <= 0) {
- pr_err("Write frame data i2c error\n");
- continue;
- }
- ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH +
- frame_length);
- if (ret <= 0) {
- pr_err("Read back frame data i2c error\n");
- continue;
- }
-
- if (memcmp(&wr_buf[GTP_ADDR_LENGTH],
- &rd_buf[GTP_ADDR_LENGTH], frame_length)) {
- pr_err("Check frame data fail,not equal\n");
- continue;
- } else {
- break;
- }
- }
- if (retry >= MAX_FRAME_CHECK_TIME) {
- pr_err("Burn frame data time out,exit\n");
- return FAIL;
- }
- burn_length += frame_length;
- burn_addr += frame_length;
- }
- return SUCCESS;
-}
-
-static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length)
-{
- if (!update_msg.fw_data ||
- update_msg.fw_len < FW_HEAD_LENGTH + offset + length) {
- pr_err(
- "<<-GTP->> cannot load section data. fw_len=%d read end=%d\n",
- update_msg.fw_len,
- FW_HEAD_LENGTH + offset + length);
- return FAIL;
- }
- memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length);
-
- return SUCCESS;
-}
-
-static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src,
- u16 start_rd_addr, u16 chk_length)
-{
- u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
- s32 ret = 0;
- u16 recall_addr = start_rd_addr;
- u16 recall_length = 0;
- u16 frame_length = 0;
-
- while (recall_length < chk_length) {
- frame_length = ((chk_length - recall_length) > PACK_SIZE)
- ? PACK_SIZE : (chk_length - recall_length);
- ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
- if (ret <= 0) {
- pr_err("recall i2c error,exit\n");
- return FAIL;
- }
-
- if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length],
- frame_length)) {
- pr_err("Recall frame data fail,not equal\n");
- return FAIL;
- }
-
- recall_length += frame_length;
- recall_addr += frame_length;
- }
- pr_debug("Recall check %dk firmware success\n", (chk_length/1024));
-
- return SUCCESS;
-}
-
-static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section,
- u16 start_addr, u8 bank_cmd)
-{
- s32 ret = 0;
- u8 rd_buf[5];
-
- /* step1:hold ss51 & dsp */
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
- if (ret <= 0) {
- pr_err("hold ss51 & dsp fail");
- return FAIL;
- }
-
- /* step2:set scramble */
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
- if (ret <= 0) {
- pr_err("set scramble fail");
- return FAIL;
- }
-
- /* step3:select bank */
- ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
- (bank_cmd >> 4)&0x0F);
- if (ret <= 0) {
- pr_err("select bank %d fail",
- (bank_cmd >> 4)&0x0F);
- return FAIL;
- }
-
- /* step4:enable accessing code */
- ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
- if (ret <= 0) {
- pr_err("enable accessing code fail");
- return FAIL;
- }
-
- /* step5:burn 8k fw section */
- ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("burn fw_section fail");
- return FAIL;
- }
-
- /* step6:hold ss51 & release dsp */
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
- if (ret <= 0) {
- pr_err("hold ss51 & release dsp fail");
- return FAIL;
- }
- /* must delay */
- msleep(20);
-
- /* step7:send burn cmd to move data to flash from sram */
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
- if (ret <= 0) {
- pr_err("send burn cmd fail");
- return FAIL;
- }
- pr_debug("Wait for the burn is complete");
- do {
- ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
- if (ret <= 0) {
- pr_err("Get burn state fail");
- return FAIL;
- }
- msleep(20);
- } while (rd_buf[GTP_ADDR_LENGTH]);
-
- /* step8:select bank */
- ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
- (bank_cmd >> 4)&0x0F);
- if (ret <= 0) {
- pr_err("select bank %d fail",
- (bank_cmd >> 4)&0x0F);
- return FAIL;
- }
-
- /* step9:enable accessing code */
- ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
- if (ret <= 0) {
- pr_err("enable accessing code fail");
- return FAIL;
- }
-
- /* step10:recall 8k fw section */
- ret = gup_recall_check(client, fw_section, start_addr,
- FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("recall check 8k firmware fail");
- return FAIL;
- }
-
- /* step11:disable accessing code */
- ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
- if (ret <= 0) {
- pr_err("disable accessing code fail");
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_burn_dsp_isp(struct i2c_client *client)
-{
- s32 ret = 0;
- u8 *fw_dsp_isp = NULL;
- u8 retry = 0;
-
- pr_debug("Begin burn dsp isp");
-
- /* step1:alloc memory */
- pr_debug("step1:alloc memory");
- while (retry++ < 5) {
- fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH,
- GFP_KERNEL);
- if (fw_dsp_isp == NULL) {
- continue;
- } else {
- break;
- }
- }
- if (retry == 5)
- return FAIL;
-
- /* step2:load dsp isp file data */
- pr_debug("step2:load dsp isp file data");
- ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH +
- FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH);
- if (ret == FAIL) {
- pr_err("load firmware dsp_isp fail");
- return FAIL;
- }
-
- /* step3:disable wdt,clear cache enable */
- pr_debug("step3:disable wdt,clear cache enable");
- ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
- if (ret <= 0) {
- pr_err("disable wdt fail");
- return FAIL;
- }
- ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
- if (ret <= 0) {
- pr_err("clear cache enable fail");
- return FAIL;
- }
-
- /* step4:hold ss51 & dsp */
- pr_debug("step4:hold ss51 & dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
- if (ret <= 0) {
- pr_err("hold ss51 & dsp fail");
- return FAIL;
- }
-
- /* step5:set boot from sram */
- pr_debug("step5:set boot from sram");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
- if (ret <= 0) {
- pr_err("set boot from sram fail");
- return FAIL;
- }
-
- /* step6:software reboot */
- pr_debug("step6:software reboot");
- ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
- if (ret <= 0) {
- pr_err("software reboot fail");
- return FAIL;
- }
-
- /* step7:select bank2 */
- pr_debug("step7:select bank2");
- ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
- if (ret <= 0) {
- pr_err("select bank2 fail");
- return FAIL;
- }
-
- /* step8:enable accessing code */
- pr_debug("step8:enable accessing code");
- ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
- if (ret <= 0) {
- pr_err("enable accessing code fail");
- return FAIL;
- }
-
- /* step9:burn 4k dsp_isp */
- pr_debug("step9:burn 4k dsp_isp");
- ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
- if (ret == FAIL) {
- pr_err("burn dsp_isp fail");
- return FAIL;
- }
-
- /* step10:set scramble */
- pr_debug("step10:set scramble");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
- if (ret <= 0) {
- pr_err("set scramble fail");
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_burn_fw_ss51(struct i2c_client *client)
-{
- u8 *fw_ss51 = NULL;
- u8 retry = 0;
- s32 ret = 0;
-
- pr_debug("Begin burn ss51 firmware");
-
- /* step1:alloc memory */
- pr_debug("step1:alloc memory");
- while (retry++ < 5) {
- fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH,
- GFP_KERNEL);
- if (fw_ss51 == NULL) {
- continue;
- } else {
- break;
- }
- }
- if (retry == 5)
- return FAIL;
-
- /* step2:load ss51 firmware section 1 file data */
- pr_debug("step2:load ss51 firmware section 1 file data");
- ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("load ss51 firmware section 1 fail");
- return FAIL;
- }
-
- /* step3:clear control flag */
- pr_debug("step3:clear control flag");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
- if (ret <= 0) {
- pr_err("clear control flag fail");
- return FAIL;
- }
-
- /* step4:burn ss51 firmware section 1 */
- pr_debug("step4:burn ss51 firmware section 1");
- ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
- if (ret == FAIL) {
- pr_err("burn ss51 firmware section 1 fail");
- return FAIL;
- }
-
- /* step5:load ss51 firmware section 2 file data */
- pr_debug("step5:load ss51 firmware section 2 file data");
- ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH,
- FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail\n");
- return FAIL;
- }
-
- /* step6:burn ss51 firmware section 2 */
- pr_debug("step6:burn ss51 firmware section 2");
- ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
- if (ret == FAIL) {
- pr_err("burn ss51 firmware section 2 fail");
- return FAIL;
- }
-
- /* step7:load ss51 firmware section 3 file data */
- pr_debug("step7:load ss51 firmware section 3 file data");
- ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH,
- FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("load ss51 firmware section 3 fail");
- return FAIL;
- }
-
- /* step8:burn ss51 firmware section 3 */
- pr_debug("step8:burn ss51 firmware section 3");
- ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
- if (ret == FAIL) {
- pr_err("burn ss51 firmware section 3 fail");
- return FAIL;
- }
-
- /* step9:load ss51 firmware section 4 file data */
- pr_debug("step9:load ss51 firmware section 4 file data");
- ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH,
- FW_SECTION_LENGTH);
- if (ret == FAIL) {
- pr_err("load ss51 firmware section 4 fail");
- return FAIL;
- }
-
- /* step10:burn ss51 firmware section 4 */
- pr_debug("step10:burn ss51 firmware section 4");
- ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
- if (ret == FAIL) {
- pr_err("burn ss51 firmware section 4 fail");
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_burn_fw_dsp(struct i2c_client *client)
-{
- s32 ret = 0;
- u8 *fw_dsp = NULL;
- u8 retry = 0;
- u8 rd_buf[5];
-
- pr_debug("Begin burn dsp firmware");
- /* step1:alloc memory */
- pr_debug("step1:alloc memory");
- while (retry++ < 5) {
- fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH,
- GFP_KERNEL);
- if (fw_dsp == NULL) {
- continue;
- } else {
- break;
- }
- }
- if (retry == 5)
- return FAIL;
-
- /* step2:load firmware dsp */
- pr_debug("step2:load firmware dsp");
- ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH);
- if (ret == FAIL) {
- pr_err("load firmware dsp fail");
- return ret;
- }
-
- /* step3:select bank3 */
- pr_debug("step3:select bank3");
- ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
- if (ret <= 0) {
- pr_err("select bank3 fail");
- return FAIL;
- }
-
- /* Step4:hold ss51 & dsp */
- pr_debug("step4:hold ss51 & dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
- if (ret <= 0) {
- pr_err("hold ss51 & dsp fail");
- return FAIL;
- }
-
- /* step5:set scramble */
- pr_debug("step5:set scramble");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
- if (ret <= 0) {
- pr_err("set scramble fail");
- return FAIL;
- }
-
- /* step6:release ss51 & dsp */
- pr_debug("step6:release ss51 & dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
- if (ret <= 0) {
- pr_err("release ss51 & dsp fail");
- return FAIL;
- }
- /* must delay */
- msleep(20);
-
- /* step7:burn 4k dsp firmware */
- pr_debug("step7:burn 4k dsp firmware");
- ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
- if (ret == FAIL) {
- pr_err("[burn_fw_dsp]burn fw_section fail\n");
- return ret;
- }
-
- /* step8:send burn cmd to move data to flash from sram */
- pr_debug("step8:send burn cmd to move data to flash from sram");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
- if (ret <= 0) {
- pr_err("send burn cmd fail");
- return ret;
- }
- pr_debug("Wait for the burn is complete");
- do {
- ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
- if (ret <= 0) {
- pr_err("Get burn state fail");
- return ret;
- }
- msleep(20);
- } while (rd_buf[GTP_ADDR_LENGTH]);
-
- /* step9:recall check 4k dsp firmware */
- pr_debug("step9:recall check 4k dsp firmware");
- ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
- if (ret == FAIL) {
- pr_err("recall check 4k dsp firmware fail");
- return ret;
- }
-
- return SUCCESS;
-}
-
-static u8 gup_burn_fw_boot(struct i2c_client *client)
-{
- s32 ret = 0;
- u8 *fw_boot = NULL;
- u8 retry = 0;
- u8 rd_buf[5];
-
- pr_debug("Begin burn bootloader firmware");
-
- /* step1:Alloc memory */
- pr_debug("step1:Alloc memory");
- while (retry++ < 5) {
- fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH,
- GFP_KERNEL);
- if (fw_boot == NULL) {
- continue;
- } else {
- break;
- }
- }
- if (retry == 5)
- return FAIL;
-
- /* step2:load firmware bootloader */
- pr_debug("step2:load firmware bootloader");
- ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH +
- FW_DSP_LENGTH), FW_BOOT_LENGTH);
- if (ret == FAIL) {
- pr_err("load firmware dsp fail");
- return ret;
- }
-
- /* step3:hold ss51 & dsp */
- pr_debug("step3:hold ss51 & dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
- if (ret <= 0) {
- pr_err("hold ss51 & dsp fail");
- return FAIL;
- }
-
- /* step4:set scramble */
- pr_debug("step4:set scramble");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
- if (ret <= 0) {
- pr_err("set scramble fail");
- return FAIL;
- }
-
- /* step5:release ss51 & dsp */
- pr_debug("step5:release ss51 & dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
- if (ret <= 0) {
- pr_err("release ss51 & dsp fail");
- return FAIL;
- }
- /* must delay */
- msleep(20);
-
- /* step6:select bank3 */
- pr_debug("step6:select bank3");
- ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
- if (ret <= 0) {
- pr_err("select bank3 fail");
- return FAIL;
- }
-
- /* step7:burn 2k bootloader firmware */
- pr_debug("step7:burn 2k bootloader firmware");
- ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
- if (ret == FAIL) {
- pr_err("burn fw_section fail");
- return ret;
- }
-
- /* step7:send burn cmd to move data to flash from sram */
- pr_debug("step7:send burn cmd to flash data from sram");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
- if (ret <= 0) {
- pr_err("send burn cmd fail");
- return ret;
- }
- pr_debug("Wait for the burn is complete");
- do {
- ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
- if (ret <= 0) {
- pr_err("Get burn state fail");
- return ret;
- }
- msleep(20);
- } while (rd_buf[GTP_ADDR_LENGTH]);
-
- /* step8:recall check 2k bootloader firmware */
- pr_debug("step8:recall check 2k bootloader firmware");
- ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
- if (ret == FAIL) {
- pr_err("recall check 4k dsp firmware fail");
- return ret;
- }
-
- /* step9:enable download DSP code */
- pr_debug("step9:enable download DSP code ");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
- if (ret <= 0) {
- pr_err("enable download DSP code fail");
- return FAIL;
- }
-
- /* step10:release ss51 & hold dsp */
- pr_debug("step10:release ss51 & hold dsp");
- ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
- if (ret <= 0) {
- pr_err("release ss51 & hold dsp fail");
- return FAIL;
- }
-
- return SUCCESS;
-}
-
-s32 gup_update_proc(void *dir)
-{
- s32 ret = 0;
- u8 retry = 0;
- struct st_fw_head fw_head;
- struct goodix_ts_data *ts = NULL;
-
- pr_debug("Begin update.");
-
- if (!i2c_connect_client) {
- pr_err("No i2c connect client for %s\n", __func__);
- return -EIO;
- }
-
- show_len = 1;
- total_len = 100;
-
- ts = i2c_get_clientdata(i2c_connect_client);
-
- if (searching_file) {
- /* exit .bin update file searching */
- searching_file = 0;
- pr_info("Exiting searching .bin update file.");
- /* wait for auto update quitted completely */
- while ((show_len != 200) && (show_len != 100))
- msleep(100);
- }
-
- ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir);
- if (ret == FAIL) {
- pr_err("check update file fail");
- goto file_fail;
- }
-
- /* gtp_reset_guitar(i2c_connect_client, 20); */
- ret = gup_get_ic_fw_msg(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("get ic message fail");
- goto file_fail;
- }
-
- if (ts->force_update) {
- dev_dbg(&ts->client->dev, "Enter force update.");
- } else {
- ret = gup_enter_update_judge(ts->client, &fw_head);
- if (ret == FAIL) {
- dev_err(&ts->client->dev,
- "Check *.bin file fail.");
- goto file_fail;
- }
- }
-
- ts->enter_update = 1;
- gtp_irq_disable(ts);
-#if GTP_ESD_PROTECT
- gtp_esd_switch(ts->client, SWITCH_OFF);
-#endif
- ret = gup_enter_update_mode(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("enter update mode fail");
- goto update_fail;
- }
-
- while (retry++ < 5) {
- show_len = 10;
- total_len = 100;
- ret = gup_burn_dsp_isp(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("burn dsp isp fail");
- continue;
- }
-
- show_len += 10;
- ret = gup_burn_fw_ss51(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("burn ss51 firmware fail");
- continue;
- }
-
- show_len += 40;
- ret = gup_burn_fw_dsp(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("burn dsp firmware fail");
- continue;
- }
-
- show_len += 20;
- ret = gup_burn_fw_boot(i2c_connect_client);
- if (ret == FAIL) {
- pr_err("burn bootloader fw fail");
- continue;
- }
- show_len += 10;
- pr_info("UPDATE SUCCESS");
- break;
- }
- if (retry >= 5) {
- pr_err("retry timeout,UPDATE FAIL");
- goto update_fail;
- }
-
- pr_debug("leave update mode");
- gup_leave_update_mode(i2c_connect_client);
-
- msleep(100);
-
- if (ts->fw_error) {
- pr_info("firmware error auto update, resent config\n");
- gup_init_panel(ts);
- }
- show_len = 100;
- total_len = 100;
- ts->enter_update = 0;
- gtp_irq_enable(ts);
-
-#if GTP_ESD_PROTECT
- gtp_esd_switch(ts->client, SWITCH_ON);
-#endif
- if (update_msg.need_free) {
- devm_kfree(&ts->client->dev, update_msg.fw_data);
- update_msg.need_free = false;
- }
-
- return SUCCESS;
-
-update_fail:
- ts->enter_update = 0;
- gtp_irq_enable(ts);
-
-#if GTP_ESD_PROTECT
- gtp_esd_switch(ts->client, SWITCH_ON);
-#endif
-
-file_fail:
- show_len = 200;
- total_len = 100;
- if (update_msg.need_free) {
- devm_kfree(&ts->client->dev, update_msg.fw_data);
- update_msg.need_free = false;
- }
- return FAIL;
-}
-
-static void gup_update_work(struct work_struct *work)
-{
- if (gup_update_proc(NULL) == FAIL)
- pr_err("Goodix update work fail\n");
-}
-
-u8 gup_init_update_proc(struct goodix_ts_data *ts)
-{
- dev_dbg(&ts->client->dev, "Ready to run update work\n");
-
- INIT_DELAYED_WORK(&ts->goodix_update_work, gup_update_work);
- schedule_delayed_work(&ts->goodix_update_work,
- msecs_to_jiffies(3000));
-
- return 0;
-}
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
index 52bd5cfc37c8..168318f85e53 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c
@@ -2218,10 +2218,12 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id)
__func__);
return -ENOMEM;
}
- while (strptr[index] >= '0' && strptr[index] <= '9') {
+ while ((index < MAX_FIRMWARE_ID_LEN - 1) && strptr[index] >= '0'
+ && strptr[index] <= '9') {
firmware_id[index] = strptr[index];
index++;
}
+ firmware_id[index] = '\0';
retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id);
kfree(firmware_id);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
index a0f1d5148c94..01b8e0878ea9 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
@@ -894,8 +894,13 @@ static int cam_smmu_attach_sec_cpp(int idx)
rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_SECURE,
MSM_CAMERA_TZ_HW_BLOCK_CPP);
if (rc != 0) {
- pr_err("fail to set secure mode for cpp, rc %d", rc);
- return rc;
+ pr_err("secure mode TA notification for cpp unsuccessful, rc %d\n",
+ rc);
+ /*
+ * Although the TA notification failed, the flow should proceed
+ * without returning an error as at this point cpp had already
+ * entered the secure mode.
+ */
}
iommu_cb_set.cb_info[idx].state = CAM_SMMU_ATTACH;
@@ -910,8 +915,13 @@ static int cam_smmu_detach_sec_cpp(int idx)
rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_NON_SECURE,
MSM_CAMERA_TZ_HW_BLOCK_CPP);
if (rc != 0) {
- pr_err("fail to switch to non secure mode for cpp, rc %d", rc);
- return rc;
+ pr_err("secure mode TA notification for cpp unsuccessful, rc %d\n",
+ rc);
+ /*
+ * Although the TA notification failed, the flow should proceed
+ * without returning an error, as at this point cpp is in secure
+ * mode and should be switched to non-secure regardless
+ */
}
iommu_cb_set.cb_info[idx].state = CAM_SMMU_DETACH;
@@ -950,8 +960,13 @@ static int cam_smmu_attach_sec_vfe_ns_stats(int idx)
rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_SECURE,
MSM_CAMERA_TZ_HW_BLOCK_ISP);
if (rc != 0) {
- pr_err("fail to set secure mode for vfe, rc %d", rc);
- return rc;
+ pr_err("secure mode TA notification for vfe unsuccessful, rc %d\n",
+ rc);
+ /*
+ * Although the TA notification failed, the flow should proceed
+ * without returning an error as at this point vfe had already
+ * entered the secure mode
+ */
}
return 0;
@@ -964,8 +979,13 @@ static int cam_smmu_detach_sec_vfe_ns_stats(int idx)
rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_NON_SECURE,
MSM_CAMERA_TZ_HW_BLOCK_ISP);
if (rc != 0) {
- pr_err("fail to switch to non secure mode for vfe, rc %d", rc);
- return rc;
+ pr_err("secure mode TA notification for vfe unsuccessful, rc %d\n",
+ rc);
+ /*
+ * Although the TA notification failed, the flow should proceed
+ * without returning an error, as at this point vfe is in secure
+ * mode and should be switched to non-secure regardless
+ */
}
/*
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 8d66232dbda1..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
@@ -229,8 +229,8 @@ static int msm_isp_prepare_v4l2_buf(struct msm_isp_buf_mgr *buf_mgr,
mapped_info->paddr += accu_length;
accu_length += qbuf_buf->planes[i].length;
- CDBG("%s: plane: %d addr:%lu\n",
- __func__, i, (unsigned long)mapped_info->paddr);
+ CDBG("%s: plane: %d addr:%pK\n",
+ __func__, i, (void *)mapped_info->paddr);
}
buf_info->num_planes = qbuf_buf->num_planes;
@@ -312,8 +312,8 @@ static int msm_isp_map_buf(struct msm_isp_buf_mgr *buf_mgr,
pr_err_ratelimited("%s: cannot map address", __func__);
goto smmu_map_error;
}
- CDBG("%s: addr:%lu\n",
- __func__, (unsigned long)mapped_info->paddr);
+ CDBG("%s: addr:%pK\n",
+ __func__, (void *)mapped_info->paddr);
return rc;
smmu_map_error:
@@ -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,
@@ -1335,14 +1336,15 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
struct msm_isp_buffer *bufs = NULL;
uint32_t i = 0, j = 0, k = 0, rc = 0;
char *print_buf = NULL, temp_buf[100];
- uint32_t start_addr = 0, end_addr = 0, print_buf_size = 2000;
+ uint32_t print_buf_size = 2000;
+ unsigned long start_addr = 0, end_addr = 0;
int buf_addr_delta = -1;
int temp_delta = 0;
uint32_t debug_stream_id = 0;
uint32_t debug_buf_idx = 0;
uint32_t debug_buf_plane = 0;
- uint32_t debug_start_addr = 0;
- uint32_t debug_end_addr = 0;
+ unsigned long debug_start_addr = 0;
+ unsigned long debug_end_addr = 0;
uint32_t debug_frame_id = 0;
enum msm_isp_buffer_state debug_state = MSM_ISP_BUFFER_STATE_UNUSED;
unsigned long flags;
@@ -1401,8 +1403,8 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
debug_stream_id, debug_frame_id);
pr_err("%s: nearby buf index %d, plane %d, state %d\n", __func__,
debug_buf_idx, debug_buf_plane, debug_state);
- pr_err("%s: buf address 0x%x -- 0x%x\n", __func__,
- debug_start_addr, debug_end_addr);
+ pr_err("%s: buf address %pK -- %pK\n", __func__,
+ (void *)debug_start_addr, (void *)debug_end_addr);
if (BUF_DEBUG_FULL) {
print_buf = kzalloc(print_buf_size, GFP_ATOMIC);
@@ -1437,9 +1439,10 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
mapped_info[k].len;
snprintf(temp_buf,
sizeof(temp_buf),
- " buf %d plane %d start_addr %x end_addr %x\n",
- j, k, start_addr,
- end_addr);
+ " buf %d plane %d start_addr %pK end_addr %pK\n",
+ j, k,
+ (void *)start_addr,
+ (void *)end_addr);
strlcat(print_buf, temp_buf,
print_buf_size);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index bb3f0dca9d92..f2f3388b41c1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -590,9 +590,9 @@ int vfe_hw_probe(struct platform_device *pdev)
(struct msm_vfe_hardware_info *) match_dev->data;
/* Cx ipeak support */
if (of_find_property(pdev->dev.of_node,
- "qcom,vfe_cx_ipeak", NULL)) {
+ "qcom,vfe-cx-ipeak", NULL)) {
vfe_dev->vfe_cx_ipeak = cx_ipeak_register(
- pdev->dev.of_node, "qcom,vfe_cx_ipeak");
+ pdev->dev.of_node, "qcom,vfe-cx-ipeak");
}
} else {
vfe_dev->hw_info = (struct msm_vfe_hardware_info *)
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 e54342e3935a..0325c5ded3cf 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -768,7 +768,6 @@ struct vfe_device {
size_t num_hvx_clk;
size_t num_norm_clk;
enum cam_ahb_clk_vote ahb_vote;
- bool turbo_vote;
struct cx_ipeak_client *vfe_cx_ipeak;
/* Sync variables*/
@@ -809,6 +808,7 @@ struct vfe_device {
uint32_t is_split;
uint32_t dual_vfe_enable;
unsigned long page_fault_addr;
+ uint32_t vfe_hw_limit;
/* Debug variables */
int dump_reg;
@@ -830,6 +830,8 @@ struct vfe_device {
uint32_t recovery_irq1_mask;
/* Store the buf_idx for pd stats RDI stream */
uint8_t pd_buf_idx;
+ /* total bandwidth per vfe */
+ uint64_t total_bandwidth;
};
struct vfe_parent_device {
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 d829aefe6c98..b704e84cc140 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -331,7 +331,6 @@ int msm_vfe47_init_hardware(struct vfe_device *vfe_dev)
goto ahb_vote_fail;
}
vfe_dev->ahb_vote = CAM_AHB_SVS_VOTE;
- vfe_dev->turbo_vote = 0;
vfe_dev->common_data->dual_vfe_res->vfe_base[vfe_dev->pdev->id] =
vfe_dev->vfe_base;
@@ -2563,31 +2562,53 @@ int msm_vfe47_set_clk_rate(struct vfe_device *vfe_dev, long *rate)
int rc = 0;
int clk_idx = vfe_dev->hw_info->vfe_clk_idx;
int ret;
+ long clk_rate, prev_clk_rate;
+ clk_rate = clk_round_rate(vfe_dev->vfe_clk[clk_idx], *rate);
+ if (vfe_dev->msm_isp_vfe_clk_rate == clk_rate)
+ return rc;
+
+ prev_clk_rate = vfe_dev->msm_isp_vfe_clk_rate;
+ vfe_dev->msm_isp_vfe_clk_rate = clk_rate;
+ /*
+ * if cx_ipeak is supported vote first so that dsp throttling is
+ * reduced before we go to turbo
+ */
+ if ((vfe_dev->vfe_cx_ipeak) &&
+ (vfe_dev->msm_isp_vfe_clk_rate >=
+ vfe_dev->vfe_clk_rates[MSM_VFE_CLK_RATE_TURBO]
+ [vfe_dev->hw_info->vfe_clk_idx]) &&
+ prev_clk_rate <
+ vfe_dev->vfe_clk_rates[MSM_VFE_CLK_RATE_TURBO]
+ [vfe_dev->hw_info->vfe_clk_idx]) {
+ ret = cx_ipeak_update(vfe_dev->vfe_cx_ipeak, true);
+ if (ret) {
+ pr_err("%s: cx_ipeak_update failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+ /*set vfe clock*/
rc = msm_camera_clk_set_rate(&vfe_dev->pdev->dev,
vfe_dev->vfe_clk[clk_idx], *rate);
if (rc < 0)
return rc;
- *rate = clk_round_rate(vfe_dev->vfe_clk[clk_idx], *rate);
- vfe_dev->msm_isp_vfe_clk_rate = *rate;
- if (vfe_dev->vfe_cx_ipeak) {
- if (vfe_dev->msm_isp_vfe_clk_rate >=
- vfe_dev->vfe_clk_rates[MSM_VFE_CLK_RATE_TURBO]
- [vfe_dev->hw_info->vfe_clk_idx] &&
- vfe_dev->turbo_vote == 0) {
- ret = cx_ipeak_update(vfe_dev->vfe_cx_ipeak, true);
- if (ret)
- pr_debug("%s: cx_ipeak_update failed %d\n",
- __func__, ret);
- else
- vfe_dev->turbo_vote = 1;
- } else if (vfe_dev->turbo_vote == 1) {
- ret = cx_ipeak_update(vfe_dev->vfe_cx_ipeak, false);
- if (ret)
- pr_debug("%s: cx_ipeak_update failed %d\n",
- __func__, ret);
- else
- vfe_dev->turbo_vote = 0;
+ /*
+ * if cx_ipeak is supported remove the vote for non-turbo clock and
+ * if voting done earlier
+ */
+ if ((vfe_dev->vfe_cx_ipeak) &&
+ (vfe_dev->msm_isp_vfe_clk_rate <
+ vfe_dev->vfe_clk_rates[MSM_VFE_CLK_RATE_TURBO]
+ [vfe_dev->hw_info->vfe_clk_idx]) &&
+ prev_clk_rate >=
+ vfe_dev->vfe_clk_rates[MSM_VFE_CLK_RATE_TURBO]
+ [vfe_dev->hw_info->vfe_clk_idx]) {
+ ret = cx_ipeak_update(vfe_dev->vfe_cx_ipeak, false);
+ if (ret) {
+ pr_err("%s: cx_ipeak_update failed %d\n",
+ __func__, ret);
+ return ret;
}
}
if (vfe_dev->hw_info->vfe_ops.core_ops.ahb_clk_cfg)
@@ -2742,6 +2763,8 @@ int msm_vfe47_enable_regulators(struct vfe_device *vfe_dev, int enable)
int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev)
{
int rc = 0;
+ void __iomem *vfe_fuse_base;
+ uint32_t vfe_fuse_base_size;
vfe_dev->vfe_base = msm_camera_get_reg_base(vfe_dev->pdev, "vfe", 0);
if (!vfe_dev->vfe_base)
@@ -2766,7 +2789,18 @@ int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev)
rc = -ENOMEM;
goto get_res_fail;
}
-
+ vfe_dev->vfe_hw_limit = 0;
+ vfe_fuse_base = msm_camera_get_reg_base(vfe_dev->pdev,
+ "vfe_fuse", 0);
+ vfe_fuse_base_size = msm_camera_get_res_size(vfe_dev->pdev,
+ "vfe_fuse");
+ if (vfe_fuse_base) {
+ if (vfe_fuse_base_size)
+ vfe_dev->vfe_hw_limit =
+ (msm_camera_io_r(vfe_fuse_base) >> 5) & 0x1;
+ msm_camera_put_reg_base(vfe_dev->pdev, vfe_fuse_base,
+ "vfe_fuse", 0);
+ }
rc = vfe_dev->hw_info->vfe_ops.platform_ops.get_regulators(vfe_dev);
if (rc)
goto get_regulator_fail;
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 4e74851dc67d..8488405b561a 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
@@ -1734,7 +1734,7 @@ int msm_isp_print_ping_pong_address(struct vfe_device *vfe_dev,
}
temp = buf->mapped_info[0].paddr +
buf->mapped_info[0].len;
- pr_err("%s: stream %x ping bit %d uses buffer %pa-%pa, num_isp %d\n",
+ pr_err("%s: stream %x ping bit %d uses buffer %pK-%pK, num_isp %d\n",
__func__, stream_info->stream_src,
pingpong_bit,
&buf->mapped_info[0].paddr, &temp,
@@ -1743,10 +1743,10 @@ int msm_isp_print_ping_pong_address(struct vfe_device *vfe_dev,
for (i = 0; i < stream_info->num_planes; i++) {
for (k = 0; k < stream_info->num_isp; k++) {
pr_debug(
- "%s: stream_id %x ping-pong %d plane %d start_addr %lu addr_offset %x len %zx stride %d scanline %d\n"
+ "%s: stream_id %x ping-pong %d plane %d start_addr %pK addr_offset %x len %zx stride %d scanline %d\n"
, __func__, stream_info->stream_id,
- pingpong_bit, i, (unsigned long)
- buf->mapped_info[i].paddr,
+ pingpong_bit, i,
+ (void *)buf->mapped_info[i].paddr,
stream_info->
plane_cfg[k][i].plane_addr_offset,
buf->mapped_info[i].len,
@@ -2382,7 +2382,6 @@ static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
struct msm_vfe_axi_stream *stream_info;
uint64_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
uint32_t num_pix_streams = 0;
- uint64_t total_bandwidth = 0;
int vfe_idx;
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
@@ -2401,10 +2400,10 @@ static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
}
}
}
- total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
+ vfe_dev->total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
- (total_bandwidth + vfe_dev->hw_info->min_ab),
- (total_bandwidth + vfe_dev->hw_info->min_ib));
+ (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
+ (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
if (rc < 0)
pr_err("%s: update failed\n", __func__);
@@ -2412,6 +2411,66 @@ static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
return rc;
}
+int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
+{
+ int i, rc = 0;
+ uint64_t total_bandwidth = 0;
+ int vfe_idx;
+ unsigned long flags;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_dual_lpm_mode *ab_ib_vote = NULL;
+
+ ab_ib_vote = (struct msm_vfe_dual_lpm_mode *)arg;
+ if (!ab_ib_vote) {
+ pr_err("%s: ab_ib_vote is NULL !!!\n", __func__);
+ rc = -1;
+ return rc;
+ }
+ if (ab_ib_vote->lpm_mode) {
+ for (i = 0; i < ab_ib_vote->num_src; i++) {
+ stream_info =
+ msm_isp_get_stream_common_data(vfe_dev,
+ ab_ib_vote->stream_src[i]);
+ spin_lock_irqsave(&stream_info->lock, flags);
+ if (stream_info->state == ACTIVE) {
+ vfe_idx =
+ msm_isp_get_vfe_idx_for_stream(vfe_dev,
+ stream_info);
+ total_bandwidth +=
+ stream_info->bandwidth[
+ vfe_idx];
+ stream_info->state = PAUSING;
+ }
+ spin_unlock_irqrestore(&stream_info->lock, flags);
+ }
+ vfe_dev->total_bandwidth -= total_bandwidth;
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ (vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ab),
+ (vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ib));
+ } else {
+ for (i = 0; i < ab_ib_vote->num_src; i++) {
+ stream_info =
+ msm_isp_get_stream_common_data(vfe_dev,
+ ab_ib_vote->stream_src[i]);
+ spin_lock_irqsave(&stream_info->lock, flags);
+ if (stream_info->state == PAUSING) {
+ vfe_idx =
+ msm_isp_get_vfe_idx_for_stream(vfe_dev,
+ stream_info);
+ total_bandwidth +=
+ stream_info->bandwidth[
+ vfe_idx];
+ stream_info->state = ACTIVE;
+ }
+ spin_unlock_irqrestore(&stream_info->lock, flags);
+ }
+ vfe_dev->total_bandwidth += total_bandwidth;
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
+ (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
+ }
+ return rc;
+}
static int msm_isp_init_stream_ping_pong_reg(
struct msm_vfe_axi_stream *stream_info)
{
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index f9ae5fb74281..65009cb22286 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -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
@@ -160,4 +160,6 @@ static inline struct msm_vfe_axi_stream *msm_isp_vfe_get_stream(
int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
uint32_t buf_idx);
+int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev,
+ void *arg);
#endif /* __MSM_ISP_AXI_UTIL_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index f40af6e95272..9ce2218d5e0d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -1231,6 +1231,12 @@ int msm_isp_update_stats_stream(struct vfe_device *vfe_dev, void *arg)
int vfe_idx;
int k;
+ if (update_cmd->num_streams > MSM_ISP_STATS_MAX) {
+ pr_err("%s: Invalid num_streams %d\n",
+ __func__, update_cmd->num_streams);
+ return -EINVAL;
+ }
+
/*validate request*/
for (i = 0; i < update_cmd->num_streams; i++) {
update_info = (struct msm_vfe_axi_stream_cfg_update_info *)
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 86b500973538..507198721ccc 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
@@ -951,6 +951,11 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
rc = msm_isp_dual_hw_master_slave_sync(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex);
break;
+ case VIDIOC_MSM_ISP_DUAL_HW_LPM_MODE:
+ mutex_lock(&vfe_dev->core_mutex);
+ rc = msm_isp_ab_ib_update_lpm_mode(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
+ break;
case VIDIOC_MSM_ISP_FETCH_ENG_START:
case VIDIOC_MSM_ISP_MAP_BUF_START_FE:
mutex_lock(&vfe_dev->core_mutex);
@@ -1423,6 +1428,20 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
vfe_dev->vfe_ub_policy = *cfg_data;
break;
}
+ case GET_VFE_HW_LIMIT: {
+ uint32_t *hw_limit = NULL;
+
+ if (cmd_len < sizeof(uint32_t)) {
+ pr_err("%s:%d failed: invalid cmd len %u exp %zu\n",
+ __func__, __LINE__, cmd_len,
+ sizeof(uint32_t));
+ return -EINVAL;
+ }
+
+ hw_limit = (uint32_t *)cfg_data;
+ *hw_limit = vfe_dev->vfe_hw_limit;
+ break;
+ }
}
return 0;
}
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..8402e31364b9 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
@@ -980,6 +980,7 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)
{
int rc = 0;
uint32_t vbif_version;
+ cpp_dev->turbo_vote = 0;
rc = msm_camera_regulator_enable(cpp_dev->cpp_vdd,
cpp_dev->num_reg, true);
@@ -1432,6 +1433,14 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return -ENODEV;
}
+ if (cpp_dev->turbo_vote == 1) {
+ rc = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false);
+ if (rc)
+ pr_err("cx_ipeak_update failed");
+ else
+ cpp_dev->turbo_vote = 0;
+ }
+
cpp_dev->cpp_open_cnt--;
if (cpp_dev->cpp_open_cnt == 0) {
pr_debug("irq_status: 0x%x\n",
@@ -2116,6 +2125,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];
@@ -2953,6 +2964,38 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg,
return 0;
}
+unsigned long cpp_cx_ipeak_update(struct cpp_device *cpp_dev,
+ unsigned long clock, int idx)
+{
+ unsigned long clock_rate = 0;
+ int ret = 0;
+
+ if ((clock >= cpp_dev->hw_info.freq_tbl
+ [(cpp_dev->hw_info.freq_tbl_count) - 1]) &&
+ (cpp_dev->turbo_vote == 0)) {
+ ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, true);
+ if (ret) {
+ pr_err("cx_ipeak voting failed setting clock below turbo");
+ clock = cpp_dev->hw_info.freq_tbl
+ [(cpp_dev->hw_info.freq_tbl_count) - 2];
+ } else {
+ cpp_dev->turbo_vote = 1;
+ }
+ clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx);
+ } else if (clock < cpp_dev->hw_info.freq_tbl
+ [(cpp_dev->hw_info.freq_tbl_count) - 1]) {
+ clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx);
+ if (cpp_dev->turbo_vote == 1) {
+ ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false);
+ if (ret)
+ pr_err("cx_ipeak unvoting failed");
+ else
+ cpp_dev->turbo_vote = 0;
+ }
+ }
+ return clock_rate;
+}
+
long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
@@ -3335,9 +3378,15 @@ STREAM_BUFF_END:
mutex_unlock(&cpp_dev->mutex);
return -EINVAL;
}
- clock_rate = msm_cpp_set_core_clk(cpp_dev,
- clock_settings.clock_rate,
- msm_cpp_core_clk_idx);
+ if (cpp_dev->cpp_cx_ipeak) {
+ clock_rate = cpp_cx_ipeak_update(cpp_dev,
+ clock_settings.clock_rate,
+ msm_cpp_core_clk_idx);
+ } else {
+ clock_rate = msm_cpp_set_core_clk(cpp_dev,
+ clock_settings.clock_rate,
+ msm_cpp_core_clk_idx);
+ }
if (rc < 0) {
pr_err("Fail to set core clk\n");
mutex_unlock(&cpp_dev->mutex);
@@ -4389,6 +4438,15 @@ static int cpp_probe(struct platform_device *pdev)
}
}
+ if (of_find_property(pdev->dev.of_node, "qcom,cpp-cx-ipeak", NULL)) {
+ cpp_dev->cpp_cx_ipeak = cx_ipeak_register(
+ pdev->dev.of_node, "qcom,cpp-cx-ipeak");
+ if (cpp_dev->cpp_cx_ipeak)
+ CPP_DBG("Cx ipeak Registration Successful ");
+ else
+ pr_err("Cx ipeak Registration Unsuccessful");
+ }
+
rc = msm_camera_get_reset_info(pdev,
&cpp_dev->micro_iface_reset);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index e69b9d633a1f..a05448091e42 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -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
@@ -24,6 +24,7 @@
#include "cam_soc_api.h"
#include "cam_hw_ops.h"
#include <media/msmb_pproc.h>
+#include <soc/qcom/cx_ipeak.h>
/* hw version info:
31:28 Major version
@@ -284,6 +285,8 @@ struct cpp_device {
uint32_t micro_reset;
struct msm_cpp_payload_params payload_params;
struct msm_cpp_vbif_data *vbif_data;
+ bool turbo_vote;
+ struct cx_ipeak_client *cpp_cx_ipeak;
};
int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev);
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 48872334cd83..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
@@ -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)
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 ce0ecd1e9b7a..5d6c44b00bc2 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -875,6 +875,14 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
cmd.arg = idata->ic.arg;
cmd.flags = idata->ic.flags;
+ if (idata->ic.postsleep_max_us < idata->ic.postsleep_min_us) {
+ pr_err("%s: min value: %u must not be greater than max value: %u\n",
+ __func__, idata->ic.postsleep_min_us,
+ idata->ic.postsleep_max_us);
+ WARN_ON(1);
+ return -EPERM;
+ }
+
if (idata->buf_bytes) {
data.sg = &sg;
data.sg_len = 1;
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/mmc.c b/drivers/mmc/core/mmc.c
index 414877874190..4567b7526469 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2494,7 +2494,7 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host)
static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
{
- int err = 0;
+ int err = 0, ret;
BUG_ON(!host);
BUG_ON(!host->card);
@@ -2503,6 +2503,8 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
if (err) {
pr_err("%s: %s: fail to suspend clock scaling (%d)\n",
mmc_hostname(host), __func__, err);
+ if (host->card->cmdq_init)
+ wake_up(&host->cmdq_ctx.wait);
return err;
}
@@ -2527,12 +2529,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
if (mmc_card_doing_bkops(host->card)) {
err = mmc_stop_bkops(host->card);
if (err)
- goto out;
+ goto out_err;
}
err = mmc_flush_cache(host->card);
if (err)
- goto out;
+ goto out_err;
if (mmc_can_sleepawake(host)) {
/*
@@ -2549,16 +2551,38 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
err = mmc_deselect_cards(host);
}
- if (!err) {
- mmc_power_off(host);
- mmc_card_set_suspended(host->card);
+ if (err)
+ goto out_err;
+ mmc_power_off(host);
+ mmc_card_set_suspended(host->card);
+
+ goto out;
+
+out_err:
+ /*
+ * In case of err let's put controller back in cmdq mode and unhalt
+ * the controller.
+ * We expect cmdq_enable and unhalt won't return any error
+ * since it is anyway enabling few registers.
+ */
+ if (host->card->cmdq_init) {
+ mmc_host_clk_hold(host);
+ ret = host->cmdq_ops->enable(host);
+ if (ret)
+ pr_err("%s: %s: enabling CMDQ mode failed (%d)\n",
+ mmc_hostname(host), __func__, ret);
+ mmc_host_clk_release(host);
+ mmc_cmdq_halt(host, false);
}
+
out:
/* Kick CMDQ thread to process any requests came in while suspending */
if (host->card->cmdq_init)
wake_up(&host->cmdq_ctx.wait);
mmc_release_host(host);
+ if (err)
+ mmc_resume_clk_scaling(host);
return err;
}
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 1ad5fd0e0a78..a83960fd474f 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -852,6 +852,7 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
struct mmc_request *mrq;
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
int offset = 0;
+ int err = 0;
if (cq_host->offset_changed)
offset = CQ_V5_VENDOR_CFG;
@@ -865,6 +866,14 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG + offset);
cmdq_runtime_pm_put(cq_host);
+
+ if (cq_host->ops->crypto_cfg_end) {
+ err = cq_host->ops->crypto_cfg_end(mmc, mrq);
+ if (err) {
+ pr_err("%s: failed to end ice config: err %d tag %d\n",
+ mmc_hostname(mmc), err, tag);
+ }
+ }
if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) &&
cq_host->ops->crypto_cfg_reset)
cq_host->ops->crypto_cfg_reset(mmc, tag);
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index db0cd956ae90..ee5e6549fa4a 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -223,6 +223,7 @@ struct cmdq_host_ops {
int (*reset)(struct mmc_host *mmc);
int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
u32 slot, u64 *ice_ctx);
+ int (*crypto_cfg_end)(struct mmc_host *mmc, struct mmc_request *mrq);
void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot);
void (*post_cqe_halt)(struct mmc_host *mmc);
};
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index a6ef06aa6f1d..2799b21fb6e3 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -414,6 +414,37 @@ int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
return 0;
}
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ int err = 0;
+ struct request *req;
+
+ if (!host->is_crypto_en)
+ return 0;
+
+ if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
+ pr_err("%s: ice is in invalid state %d\n",
+ mmc_hostname(host->mmc), msm_host->ice.state);
+ return -EINVAL;
+ }
+
+ req = mrq->req;
+ if (req) {
+ if (msm_host->ice.vops->config_end) {
+ err = msm_host->ice.vops->config_end(req);
+ if (err) {
+ pr_err("%s: ice config end failed %d\n",
+ mmc_hostname(host->mmc), err);
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
int sdhci_msm_ice_reset(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h
index d8d640437522..7699464cf71e 100644
--- a/drivers/mmc/host/sdhci-msm-ice.h
+++ b/drivers/mmc/host/sdhci-msm-ice.h
@@ -107,6 +107,7 @@ int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
u32 slot);
int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq);
int sdhci_msm_ice_reset(struct sdhci_host *host);
int sdhci_msm_ice_resume(struct sdhci_host *host);
int sdhci_msm_ice_suspend(struct sdhci_host *host);
@@ -143,6 +144,11 @@ inline int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
{
return 0;
}
+inline int sdhci_msm_ice_cfg_end(struct sdhci_host *host,
+ struct mmc_request *mrq)
+{
+ return 0;
+}
inline int sdhci_msm_ice_reset(struct sdhci_host *host)
{
return 0;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 15d1eface2d4..7274a6d2cce0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -4008,6 +4008,7 @@ static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host)
static struct sdhci_ops sdhci_msm_ops = {
.crypto_engine_cfg = sdhci_msm_ice_cfg,
.crypto_engine_cmdq_cfg = sdhci_msm_ice_cmdq_cfg,
+ .crypto_engine_cfg_end = sdhci_msm_ice_cfg_end,
.crypto_cfg_reset = sdhci_msm_ice_cfg_reset,
.crypto_engine_reset = sdhci_msm_ice_reset,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1fdc23365c8f..083cb8cdf1ca 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1668,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;
@@ -2787,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);
}
@@ -3665,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);
@@ -3730,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)
{
@@ -3747,6 +3781,7 @@ static const struct cmdq_host_ops sdhci_cmdq_ops = {
.clear_set_dumpregs = sdhci_cmdq_clear_set_dumpregs,
.enhanced_strobe_mask = sdhci_enhanced_strobe_mask,
.crypto_cfg = sdhci_cmdq_crypto_cfg,
+ .crypto_cfg_end = sdhci_cmdq_crypto_cfg_end,
.crypto_cfg_reset = sdhci_cmdq_crypto_cfg_reset,
.post_cqe_halt = sdhci_cmdq_post_cqe_halt,
.set_transfer_params = sdhci_cmdq_set_transfer_params,
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c4bbdd80f29c..93129b26dc5e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -659,6 +659,8 @@ struct sdhci_ops {
struct mmc_request *mrq, u32 slot);
int (*crypto_engine_cmdq_cfg)(struct sdhci_host *host,
struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+ int (*crypto_engine_cfg_end)(struct sdhci_host *host,
+ struct mmc_request *mrq);
int (*crypto_engine_reset)(struct sdhci_host *host);
void (*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot);
void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 2e51590dacbb..8d49acd3c9f5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3506,6 +3506,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret;
+ skb_orphan(skb);
/* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 081e44b3277a..f6eb131e1e1b 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -96,8 +96,8 @@ static struct ce_attr host_ce_config_wlan[] = {
/* CE4: host->target HTT */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 256,
- .src_sz_max = 256,
+ .src_nentries = 2048,
+ .src_sz_max = 2048,
.dest_nentries = 0,
.send_cb = ath10k_snoc_htt_tx_cb,
},
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 9d296a911daa..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;
}
@@ -1290,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,
@@ -1313,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;
}
@@ -1346,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) {
@@ -1354,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) {
@@ -2955,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);
@@ -3170,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));
}
@@ -3279,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/core.c b/drivers/regulator/core.c
index a878dc6a97db..88a5c497d5ed 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2931,7 +2931,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
goto out2;
if (rdev->supply && (rdev->desc->min_dropout_uV ||
- !rdev->desc->ops->get_voltage)) {
+ !(rdev->desc->ops->get_voltage ||
+ rdev->desc->ops->get_voltage_sel))) {
int current_supply_uV;
int selector;
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/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-locator.c b/drivers/soc/qcom/service-locator.c
index 8581ed587ead..0d6c1d62c732 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -266,10 +266,9 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
if (!domains_read) {
db_rev_count = pd->db_rev_count = resp->db_rev_count;
pd->total_domains = resp->total_domains;
- if (!pd->total_domains && resp->domain_list_len) {
- pr_err("total domains not set\n");
- pd->total_domains = resp->domain_list_len;
- }
+ if (!resp->total_domains)
+ pr_info("No matching domains found\n");
+
pd->domain_list = kmalloc(
sizeof(struct servreg_loc_entry_v01) *
resp->total_domains, GFP_KERNEL);
@@ -286,6 +285,10 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
rc = -EAGAIN;
goto out;
}
+ if (resp->domain_list_len > resp->total_domains) {
+ /* Always read total_domains from the response msg */
+ resp->domain_list_len = resp->total_domains;
+ }
/* Copy the response*/
store_get_domain_list_response(pd, resp, domains_read);
domains_read += resp->domain_list_len;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index c1c65cd25558..ebea5b7726e4 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -99,6 +99,7 @@ struct ind_req_resp {
*/
struct qmi_client_info {
int instance_id;
+ int subsys_state;
struct work_struct svc_arrive;
struct work_struct svc_exit;
struct work_struct svc_rcv_msg;
@@ -436,7 +437,7 @@ static void root_service_exit_work(struct work_struct *work)
{
struct qmi_client_info *data = container_of(work,
struct qmi_client_info, svc_exit);
- root_service_service_exit(data, ROOT_PD_DOWN);
+ root_service_service_exit(data, data->subsys_state);
}
static int service_event_notify(struct notifier_block *this,
@@ -453,6 +454,7 @@ static int service_event_notify(struct notifier_block *this,
break;
case QMI_SERVER_EXIT:
pr_debug("Root PD service DOWN\n");
+ data->subsys_state = ROOT_PD_DOWN;
queue_work(data->svc_event_wq, &data->svc_exit);
break;
default:
@@ -468,7 +470,6 @@ static int ssr_event_notify(struct notifier_block *this,
struct qmi_client_info *info = container_of(this,
struct qmi_client_info, ssr_notifier);
struct notif_data *notif = data;
- enum pd_subsys_state state;
switch (code) {
case SUBSYS_BEFORE_SHUTDOWN:
@@ -476,16 +477,16 @@ static int ssr_event_notify(struct notifier_block *this,
notif->crashed);
switch (notif->crashed) {
case CRASH_STATUS_ERR_FATAL:
- state = ROOT_PD_ERR_FATAL;
+ info->subsys_state = ROOT_PD_ERR_FATAL;
break;
case CRASH_STATUS_WDOG_BITE:
- state = ROOT_PD_WDOG_BITE;
+ info->subsys_state = ROOT_PD_WDOG_BITE;
break;
default:
- state = ROOT_PD_SHUTDOWN;
+ info->subsys_state = ROOT_PD_SHUTDOWN;
break;
}
- root_service_service_exit(info, state);
+ queue_work(info->svc_event_wq, &info->svc_exit);
break;
default:
break;
diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c
index 4ebfc713cb28..cff5b6e3fc63 100644
--- a/drivers/thermal/msm_lmh_dcvs.c
+++ b/drivers/thermal/msm_lmh_dcvs.c
@@ -78,6 +78,7 @@ enum lmh_hw_trips {
};
struct msm_lmh_dcvs_hw {
+ char sensor_name[THERMAL_NAME_LENGTH];
uint32_t affinity;
uint32_t temp_limits[LIMITS_TRIP_MAX];
struct sensor_threshold default_lo, default_hi;
@@ -381,7 +382,6 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
int ret;
int affinity = -1;
struct msm_lmh_dcvs_hw *hw;
- char sensor_name[] = "limits_sensor-00";
struct thermal_zone_device *tzdev;
struct thermal_cooling_device *cdev;
struct device_node *dn = pdev->dev.of_node;
@@ -450,9 +450,9 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
* Let's register with thermal framework, so we have the ability
* to set low/high thresholds.
*/
- snprintf(sensor_name, sizeof(sensor_name), "limits_sensor-%02d",
+ snprintf(hw->sensor_name, sizeof(hw->sensor_name), "limits_sensor-%02d",
affinity);
- tzdev = thermal_zone_device_register(sensor_name, LIMITS_TRIP_MAX,
+ tzdev = thermal_zone_device_register(hw->sensor_name, LIMITS_TRIP_MAX,
(1 << LIMITS_TRIP_MAX) - 1, hw, &limits_sensor_ops,
NULL, 0, 0);
if (IS_ERR_OR_NULL(tzdev))
@@ -467,7 +467,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
* Since we make a check for hi > lo value, set the hi threshold
* before the low threshold
*/
- id = sensor_get_id(sensor_name);
+ id = sensor_get_id(hw->sensor_name);
if (id < 0)
return id;
@@ -525,7 +525,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
set_bit(1, hw->is_irq_enabled);
ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL,
lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT
- | IRQF_NO_SUSPEND, sensor_name, hw);
+ | IRQF_NO_SUSPEND, hw->sensor_name, hw);
if (ret) {
pr_err("Error registering for irq. err:%d\n", ret);
return ret;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 9622514e3df9..9d795489c285 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2470,6 +2470,7 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev)
}
spin_unlock_irqrestore(&cdev->lock, flags);
WARN(cdev, "%s: Unexpected call\n", __func__);
+ return;
} else if (--cdev->delayed_status == 0) {
DBG(cdev, "%s: Completing delayed status\n", __func__);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index ab44bd316217..31d3022b6ce7 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1879,8 +1879,8 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
ffs->epfiles = epfiles;
- ffs_log("exit: epfile name %s state %d setup_state %d flag %lu",
- epfile->name, ffs->state, ffs->setup_state, ffs->flags);
+ ffs_log("exit: eps_count %u state %d setup_state %d flag %lu",
+ count, ffs->state, ffs->setup_state, ffs->flags);
return 0;
}
@@ -1891,7 +1891,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
- ffs_log("enter: epfilename %s", epfile->name);
+ ffs_log("enter: count %u", count);
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) ||
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index e46edc83430c..be532503954f 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -148,15 +148,10 @@ int gsi_wakeup_host(struct f_gsi *gsi)
struct usb_function *func;
func = &gsi->function;
- gadget = gsi->function.config->cdev->gadget;
+ gadget = gsi->gadget;
log_event_dbg("Entering %s", __func__);
- if (!gadget) {
- log_event_err("FAILED: d_port->cdev->gadget == NULL");
- return -ENODEV;
- }
-
/*
* In Super-Speed mode, remote wakeup is not allowed for suspended
* functions which have been disallowed by the host to issue Function
@@ -276,7 +271,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
&d_port->ipa_out_channel_params;
struct ipa_usb_xdci_connect_params *conn_params =
&d_port->ipa_conn_pms;
- struct usb_composite_dev *cdev = gsi->function.config->cdev;
+ struct usb_gadget *gadget = gsi->gadget;
struct gsi_channel_info gsi_channel_info;
struct ipa_req_chan_out_params ipa_in_channel_out_params;
struct ipa_req_chan_out_params ipa_out_channel_out_params;
@@ -366,7 +361,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
/* Populate connection params */
conn_params->max_pkt_size =
- (cdev->gadget->speed == USB_SPEED_SUPER) ?
+ (gadget->speed == USB_SPEED_SUPER) ?
IPA_USB_SUPER_SPEED_1024B : IPA_USB_HIGH_SPEED_512B;
conn_params->ipa_to_usb_xferrscidx =
d_port->in_xfer_rsc_index;
@@ -392,7 +387,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
conn_params->teth_prot_params.max_packet_number_to_dev =
DEFAULT_MAX_PKT_PER_XFER;
conn_params->max_supported_bandwidth_mbps =
- (cdev->gadget->speed == USB_SPEED_SUPER) ? 3600 : 400;
+ (gadget->speed == USB_SPEED_SUPER) ? 3600 : 400;
memset(&ipa_in_channel_out_params, 0x0,
sizeof(ipa_in_channel_out_params));
@@ -604,12 +599,12 @@ static void ipa_work_handler(struct work_struct *w)
{
struct gsi_data_port *d_port = container_of(w, struct gsi_data_port,
usb_ipa_w);
+ struct f_gsi *gsi = d_port_to_gsi(d_port);
u8 event;
int ret = 0;
- struct usb_gadget *gadget = d_port->gadget;
+ struct usb_gadget *gadget = gsi->gadget;
struct device *dev;
struct device *gad_dev;
- struct f_gsi *gsi;
event = read_event(d_port);
@@ -636,7 +631,7 @@ static void ipa_work_handler(struct work_struct *w)
break;
case STATE_INITIALIZED:
if (event == EVT_CONNECT_IN_PROGRESS) {
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
/* allocate buffers used with each TRB */
@@ -661,7 +656,7 @@ static void ipa_work_handler(struct work_struct *w)
* EVT_HOST_READY is posted to the state machine
* in the handler for this msg.
*/
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
/* allocate buffers used with each TRB */
@@ -716,7 +711,7 @@ static void ipa_work_handler(struct work_struct *w)
read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUS_DIS",
__func__);
log_event_dbg("%s: put_async1 = %d", __func__,
@@ -726,7 +721,7 @@ static void ipa_work_handler(struct work_struct *w)
}
ret = ipa_suspend_work_handler(d_port);
if (!ret) {
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUS",
__func__);
log_event_dbg("%s: put_async2 = %d", __func__,
@@ -736,7 +731,7 @@ static void ipa_work_handler(struct work_struct *w)
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_IN_PROG_EVT_DIS",
__func__);
log_event_dbg("%s: put_async3 = %d",
@@ -760,7 +755,7 @@ static void ipa_work_handler(struct work_struct *w)
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_DIS", __func__);
log_event_dbg("%s: put_async4 = %d",
__func__, atomic_read(
@@ -770,7 +765,7 @@ static void ipa_work_handler(struct work_struct *w)
read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_SUS_DIS",
__func__);
log_event_dbg("%s: put_async5 = %d",
@@ -780,7 +775,7 @@ static void ipa_work_handler(struct work_struct *w)
}
ret = ipa_suspend_work_handler(d_port);
if (!ret) {
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_CON_EVT_SUS",
__func__);
log_event_dbg("%s: put_async6 = %d",
@@ -805,7 +800,7 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPEND_IN_PROGRESS:
if (event == EVT_IPA_SUSPEND) {
d_port->sm_state = STATE_SUSPENDED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_IPA_SUS",
__func__);
log_event_dbg("%s: put_async6 = %d",
@@ -820,7 +815,7 @@ static void ipa_work_handler(struct work_struct *w)
* after IPA disconnect is done in disconnect work
* (due to cable disconnect) or in suspended state.
*/
- usb_gadget_autopm_get_noresume(d_port->gadget);
+ usb_gadget_autopm_get_noresume(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_RES", __func__);
log_event_dbg("%s: get_nores1 = %d", __func__,
atomic_read(
@@ -828,7 +823,7 @@ static void ipa_work_handler(struct work_struct *w)
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
- usb_gadget_autopm_put_async(d_port->gadget);
+ usb_gadget_autopm_put_async(gadget);
log_event_dbg("%s: ST_SUS_IN_PROG_EVT_DIS", __func__);
log_event_dbg("%s: put_async7 = %d", __func__,
atomic_read(
@@ -838,7 +833,7 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPENDED:
if (event == EVT_RESUMED) {
- usb_gadget_autopm_get(d_port->gadget);
+ usb_gadget_autopm_get(gadget);
log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
@@ -1425,7 +1420,6 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
__le32 *data;
struct usb_cdc_notification *event;
struct usb_request *req = gsi->c_port.notify_req;
- struct usb_composite_dev *cdev = gsi->function.config->cdev;
struct gsi_ctrl_pkt *cpkt;
unsigned long flags;
bool del_free_cpkt = false;
@@ -1472,11 +1466,11 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
/* SPEED_CHANGE data is up/down speeds in bits/sec */
data = req->buf + sizeof(*event);
- data[0] = cpu_to_le32(gsi_xfer_bitrate(cdev->gadget));
+ data[0] = cpu_to_le32(gsi_xfer_bitrate(gsi->gadget));
data[1] = data[0];
log_event_dbg("notify speed %d",
- gsi_xfer_bitrate(cdev->gadget));
+ gsi_xfer_bitrate(gsi->gadget));
break;
case GSI_CTRL_NOTIFY_OFFLINE:
del_free_cpkt = true;
@@ -1868,10 +1862,10 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
len_in = gsi->d_port.in_request.buf_len *
gsi->d_port.in_request.num_bufs;
gsi->d_port.in_request.buf_base_addr =
- dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ dma_zalloc_coherent(gsi->gadget->dev.parent,
len_in, &gsi->d_port.in_request.dma, GFP_KERNEL);
if (!gsi->d_port.in_request.buf_base_addr) {
- dev_err(&gsi->d_port.gadget->dev,
+ dev_err(&gsi->gadget->dev,
"IN buf_base_addr allocate failed %s\n",
gsi->function.name);
ret = -ENOMEM;
@@ -1887,10 +1881,10 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
len_out = gsi->d_port.out_request.buf_len *
gsi->d_port.out_request.num_bufs;
gsi->d_port.out_request.buf_base_addr =
- dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ dma_zalloc_coherent(gsi->gadget->dev.parent,
len_out, &gsi->d_port.out_request.dma, GFP_KERNEL);
if (!gsi->d_port.out_request.buf_base_addr) {
- dev_err(&gsi->d_port.gadget->dev,
+ dev_err(&gsi->gadget->dev,
"OUT buf_base_addr allocate failed %s\n",
gsi->function.name);
ret = -ENOMEM;
@@ -1903,7 +1897,7 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
fail:
if (len_in && gsi->d_port.in_request.buf_base_addr) {
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len_in,
+ dma_free_coherent(gsi->gadget->dev.parent, len_in,
gsi->d_port.in_request.buf_base_addr,
gsi->d_port.in_request.dma);
gsi->d_port.in_request.buf_base_addr = NULL;
@@ -1922,7 +1916,7 @@ static void gsi_free_trb_buffer(struct f_gsi *gsi)
gsi->d_port.out_request.buf_base_addr) {
len = gsi->d_port.out_request.buf_len *
gsi->d_port.out_request.num_bufs;
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ dma_free_coherent(gsi->gadget->dev.parent, len,
gsi->d_port.out_request.buf_base_addr,
gsi->d_port.out_request.dma);
gsi->d_port.out_request.buf_base_addr = NULL;
@@ -1932,7 +1926,7 @@ static void gsi_free_trb_buffer(struct f_gsi *gsi)
gsi->d_port.in_request.buf_base_addr) {
len = gsi->d_port.in_request.buf_len *
gsi->d_port.in_request.num_bufs;
- dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ dma_free_coherent(gsi->gadget->dev.parent, len,
gsi->d_port.in_request.buf_base_addr,
gsi->d_port.in_request.dma);
gsi->d_port.in_request.buf_base_addr = NULL;
@@ -2035,7 +2029,7 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
GSI_EP_OP_CONFIG);
}
- gsi->d_port.gadget = cdev->gadget;
+ gsi->gadget = cdev->gadget;
if (gsi->prot_id == IPA_USB_RNDIS) {
gsi_rndis_open(gsi);
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 3baf65572afc..262a60e8a450 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -192,7 +192,6 @@ struct gsi_data_port {
struct usb_ep *out_ep;
struct usb_gsi_request in_request;
struct usb_gsi_request out_request;
- struct usb_gadget *gadget;
int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *driver_data);
struct ipa_usb_teth_params ipa_init_params;
int in_channel_handle;
@@ -228,6 +227,7 @@ struct gsi_data_port {
struct f_gsi {
struct usb_function function;
+ struct usb_gadget *gadget;
enum ipa_usb_teth_prot prot_id;
int ctrl_id;
int data_id;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 098df6ced1c3..8e5ab373dce9 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1476,6 +1476,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
}
break;
case USB_SPEED_FULL:
+ if (usb_endpoint_xfer_bulk(&ep->desc) && max_packet < 8)
+ max_packet = 8;
case USB_SPEED_LOW:
break;
default:
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 05d96fd8c07c..3f106b428dba 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -38,12 +38,19 @@ static const struct xhci_driver_overrides xhci_plat_overrides __initconst = {
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
+ struct device_node *node = dev->of_node;
+ struct usb_xhci_pdata *pdata = dev_get_platdata(dev);
+
/*
* As of now platform drivers don't provide MSI support so we ensure
* here that the generic code does not try to make a pci_dev from our
* dev struct in order to setup MSI
*/
xhci->quirks |= XHCI_PLAT;
+
+ if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
+ (pdata && pdata->usb3_lpm_capable))
+ xhci->quirks |= XHCI_LPM_SUPPORT;
}
/* called during probe() after chip reset completes */
@@ -129,7 +136,6 @@ static DEVICE_ATTR(config_imod, S_IRUGO | S_IWUSR,
static int xhci_plat_probe(struct platform_device *pdev)
{
- struct device_node *node = pdev->dev.of_node;
struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev);
const struct hc_driver *driver;
struct xhci_hcd *xhci;
@@ -227,10 +233,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd_to_bus(xhci->shared_hcd)->skip_resume = true;
- if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
- (pdata && pdata->usb3_lpm_capable))
- xhci->quirks |= XHCI_LPM_SUPPORT;
-
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index 14d998d14eeb..17644e3556b6 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -125,6 +125,7 @@ static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit,
commit32->commit_v1.input_layer_cnt;
commit->commit_v1.left_roi = commit32->commit_v1.left_roi;
commit->commit_v1.right_roi = commit32->commit_v1.right_roi;
+ commit->commit_v1.bl_level = commit32->commit_v1.bl_level;
memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved,
sizeof(commit32->commit_v1.reserved));
}
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h
index 626792925cb6..4f44cd1c9471 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.h
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.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
@@ -19,9 +19,9 @@
* To allow proper structure padding for 64bit/32bit target
*/
#ifdef __LP64
-#define MDP_LAYER_COMMIT_V1_PAD 3
+#define MDP_LAYER_COMMIT_V1_PAD 2
#else
-#define MDP_LAYER_COMMIT_V1_PAD 4
+#define MDP_LAYER_COMMIT_V1_PAD 3
#endif
struct mdp_buf_sync32 {
@@ -537,6 +537,7 @@ struct mdp_layer_commit_v1_32 {
compat_caddr_t dest_scaler;
uint32_t dest_scaler_cnt;
compat_caddr_t frc_info;
+ uint32_t bl_level; /* BL level to be updated in commit */
uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD];
};
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..88eb794a5ff5 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1576,10 +1576,12 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
mdss_dsi_clk_ctrl(sctrl, sctrl->dsi_clk_handle,
MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON);
- if (mdss_dsi_is_panel_on_lp(pdata)) {
+ if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_LP) {
pr_debug("%s: dsi_unblank with panel always on\n", __func__);
if (ctrl_pdata->low_power_config)
ret = ctrl_pdata->low_power_config(pdata, false);
+ if (!ret)
+ ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_LP;
goto error;
}
@@ -1644,6 +1646,8 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
pr_debug("%s: low power state requested\n", __func__);
if (ctrl_pdata->low_power_config)
ret = ctrl_pdata->low_power_config(pdata, true);
+ if (!ret)
+ ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_LP;
goto error;
}
@@ -1686,7 +1690,8 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
}
ATRACE_END("dsi_panel_off");
}
- ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
+ ctrl_pdata->ctrl_state &= ~(CTRL_STATE_PANEL_INIT |
+ CTRL_STATE_PANEL_LP);
}
error:
@@ -2550,8 +2555,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.h b/drivers/video/fbdev/msm/mdss_dsi.h
index df24352ff87d..bd9fd6c7d6c5 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -166,6 +166,7 @@ enum dsi_pm_type {
#define CTRL_STATE_PANEL_INIT BIT(0)
#define CTRL_STATE_MDP_ACTIVE BIT(1)
#define CTRL_STATE_DSI_ACTIVE BIT(2)
+#define CTRL_STATE_PANEL_LP BIT(3)
#define DSI_NON_BURST_SYNCH_PULSE 0
#define DSI_NON_BURST_SYNCH_EVENT 1
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 734d3bee8fd0..98c5eda02f5b 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -766,6 +766,8 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
u32 data0, data1, mask = 0, data_lane_en = 0;
struct mdss_dsi_ctrl_pdata *ctrl0, *ctrl1;
u32 ln0, ln1, ln_ctrl0, ln_ctrl1, i;
+ int rc = 0;
+
/*
* Add 2 ms delay suggested by HW team.
* Check clk lane stop state after every 200 us
@@ -787,9 +789,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
ctrl0 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0);
ctrl1 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_1);
- if (ctrl0->recovery)
- ctrl0->recovery->fxn(ctrl0->recovery->data,
+ if (ctrl0->recovery) {
+ rc = ctrl0->recovery->fxn(ctrl0->recovery->data,
MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW);
+ if (rc < 0) {
+ pr_debug("%s: Target is in suspend/shutdown\n",
+ __func__);
+ return;
+ }
+ }
/*
* Disable PHY contention detection and receive.
* Configure the strength ctrl 1 register.
@@ -879,9 +887,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
*/
udelay(200);
} else {
- if (ctrl->recovery)
- ctrl->recovery->fxn(ctrl->recovery->data,
+ if (ctrl->recovery) {
+ rc = ctrl->recovery->fxn(ctrl->recovery->data,
MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW);
+ if (rc < 0) {
+ pr_debug("%s: Target is in suspend/shutdown\n",
+ __func__);
+ return;
+ }
+ }
/* Disable PHY contention detection and receive */
MIPI_OUTP((ctrl->phy_io.base) + 0x0188, 0);
@@ -2134,8 +2148,8 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
status = reg_val & DSI_INTR_CMD_DMA_DONE;
if (status) {
reg_val &= DSI_INTR_MASK_ALL;
- /* clear CMD DMA isr only */
- reg_val |= DSI_INTR_CMD_DMA_DONE;
+ /* clear CMD DMA and BTA_DONE isr only */
+ reg_val |= (DSI_INTR_CMD_DMA_DONE | DSI_INTR_BTA_DONE);
MIPI_OUTP(ctrl->ctrl_base + 0x0110, reg_val);
mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
complete(&ctrl->dma_comp);
@@ -3030,6 +3044,13 @@ static bool mdss_dsi_fifo_status(struct mdss_dsi_ctrl_pdata *ctrl)
pr_err("%s: status=%x\n", __func__, status);
+ /*
+ * if DSI FIFO overflow is masked,
+ * do not report overflow error
+ */
+ if (MIPI_INP(base + 0x10c) & 0xf0000)
+ status = status & 0xaaaaffff;
+
if (status & 0x44440000) {/* DLNx_HS_FIFO_OVERFLOW */
dsi_send_events(ctrl, DSI_EV_DLNx_FIFO_OVERFLOW, 0);
/* Ignore FIFO EMPTY when overflow happens */
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index db27842eaccc..bf66c0cd430c 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -303,10 +303,23 @@ static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev,
}
}
+static enum led_brightness mdss_fb_get_bl_brightness(
+ struct led_classdev *led_cdev)
+{
+ struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+ enum led_brightness value;
+
+ MDSS_BL_TO_BRIGHT(value, mfd->bl_level, mfd->panel_info->bl_max,
+ mfd->panel_info->brightness_max);
+
+ return value;
+}
+
static struct led_classdev backlight_led = {
.name = "lcd-backlight",
.brightness = MDSS_MAX_BL_BRIGHTNESS / 2,
.brightness_set = mdss_fb_set_bl_brightness,
+ .brightness_get = mdss_fb_get_bl_brightness,
.max_brightness = MDSS_MAX_BL_BRIGHTNESS,
};
@@ -3422,6 +3435,14 @@ int mdss_fb_atomic_commit(struct fb_info *info,
mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi;
mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi;
mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags;
+ if (commit_v1->flags & MDP_COMMIT_UPDATE_BRIGHTNESS) {
+ MDSS_BRIGHT_TO_BL(mfd->bl_extn_level, commit_v1->bl_level,
+ mfd->panel_info->bl_max,
+ mfd->panel_info->brightness_max);
+ if (!mfd->bl_extn_level && commit_v1->bl_level)
+ mfd->bl_extn_level = 1;
+ } else
+ mfd->bl_extn_level = -1;
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index d64580a35775..321531c72a08 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -241,6 +241,10 @@ struct msm_mdp_interface {
out = (2 * (v) * (bl_max) + max_bright);\
do_div(out, 2 * max_bright);\
} while (0)
+#define MDSS_BL_TO_BRIGHT(out, v, bl_max, max_bright) do {\
+ out = ((v) * (max_bright));\
+ do_div(out, bl_max);\
+ } while (0)
struct mdss_fb_file_info {
struct file *file;
@@ -305,6 +309,7 @@ struct msm_fb_data_type {
u32 calib_mode_bl;
u32 ad_bl_level;
u32 bl_level;
+ int bl_extn_level;
u32 bl_scale;
u32 unset_bl_level;
bool allow_bl_update;
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.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 36a866685f21..ada39f5f486a 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -164,6 +164,14 @@ enum mdss_mdp_mixer_mux {
MDSS_MDP_MIXER_MUX_RIGHT,
};
+enum mdss_secure_transition {
+ SECURE_TRANSITION_NONE,
+ SD_NON_SECURE_TO_SECURE,
+ SD_SECURE_TO_NON_SECURE,
+ SC_NON_SECURE_TO_SECURE,
+ SC_SECURE_TO_NON_SECURE,
+};
+
static inline enum mdss_mdp_sspp_index get_pipe_num_from_ndx(u32 ndx)
{
u32 id;
@@ -421,6 +429,9 @@ struct mdss_mdp_ctl_intfs_ops {
/* to update lineptr, [1..yres] - enable, 0 - disable */
int (*update_lineptr)(struct mdss_mdp_ctl *ctl, bool enable);
int (*avr_ctrl_fnc)(struct mdss_mdp_ctl *, bool enable);
+
+ /* to wait for vsync */
+ int (*wait_for_vsync_fnc)(struct mdss_mdp_ctl *ctl);
};
struct mdss_mdp_cwb {
@@ -953,6 +964,8 @@ struct mdss_overlay_private {
struct kthread_worker worker;
struct kthread_work vsync_work;
struct task_struct *thread;
+
+ u8 secure_transition_state;
};
struct mdss_mdp_set_ot_params {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 7b0207de101a..bec652f7e4ba 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;
}
@@ -5704,6 +5716,15 @@ static void mdss_mdp_force_border_color(struct mdss_mdp_ctl *ctl)
ctl->mixer_right->params_changed++;
}
+static bool mdss_mdp_handle_backlight_extn(struct mdss_mdp_ctl *ctl)
+{
+ if (ctl->intf_type == MDSS_INTF_DSI && !ctl->is_video_mode &&
+ ctl->mfd->bl_extn_level >= 0)
+ return true;
+ else
+ return false;
+}
+
int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
struct mdss_mdp_commit_cb *commit_cb)
{
@@ -5872,6 +5893,15 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
if (ctl->ops.wait_pingpong && !mdata->serialize_wait4pp)
mdss_mdp_display_wait4pingpong(ctl, false);
+ /*
+ * If backlight needs to change, wait for 1 vsync before setting
+ * PCC and kickoff
+ */
+ if (mdss_mdp_handle_backlight_extn(ctl) &&
+ ctl->ops.wait_for_vsync_fnc) {
+ ret = ctl->ops.wait_for_vsync_fnc(ctl);
+ }
+
/* Moved pp programming to post ping pong */
if (!ctl->is_video_mode && ctl->mfd &&
ctl->mfd->dcm_state != DTM_ENTER) {
@@ -6020,6 +6050,17 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
if (ret)
pr_warn("ctl %d error displaying frame\n", ctl->num);
+ /* update backlight in commit */
+ if (mdss_mdp_handle_backlight_extn(ctl)) {
+ if (!IS_CALIB_MODE_BL(ctl->mfd) && (!ctl->mfd->ext_bl_ctrl ||
+ !ctl->mfd->bl_level)) {
+ mutex_lock(&ctl->mfd->bl_lock);
+ mdss_fb_set_backlight(ctl->mfd,
+ ctl->mfd->bl_extn_level);
+ mutex_unlock(&ctl->mfd->bl_lock);
+ }
+ }
+
ctl->play_cnt++;
ATRACE_END("flush_kickoff");
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index dfd6226ce602..583cfed598cd 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1197,7 +1197,7 @@ static int mdss_mdp_cmd_wait4readptr(struct mdss_mdp_cmd_ctx *ctx)
return rc;
}
-static void mdss_mdp_cmd_intf_callback(void *data, int event)
+static int mdss_mdp_cmd_intf_callback(void *data, int event)
{
struct mdss_mdp_cmd_ctx *ctx = data;
struct mdss_mdp_pp_tear_check *te = NULL;
@@ -1206,11 +1206,11 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event)
if (!data) {
pr_err("%s: invalid ctx\n", __func__);
- return;
+ return -EINVAL;
}
if (!ctx->ctl)
- return;
+ return -EINVAL;
switch (event) {
case MDP_INTF_CALLBACK_DSI_WAIT:
@@ -1222,7 +1222,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event)
* just return
*/
if (ctx->intf_stopped || !is_pingpong_split(ctx->ctl->mfd))
- return;
+ return -EINVAL;
atomic_inc(&ctx->rdptr_cnt);
/* enable clks and rd_ptr interrupt */
@@ -1231,7 +1231,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event)
mixer = mdss_mdp_mixer_get(ctx->ctl, MDSS_MDP_MIXER_MUX_LEFT);
if (!mixer) {
pr_err("%s: null mixer\n", __func__);
- return;
+ return -EINVAL;
}
/* wait for read pointer */
@@ -1255,6 +1255,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event)
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
}
+ return 0;
}
static void mdss_mdp_cmd_lineptr_done(void *arg)
@@ -1280,7 +1281,7 @@ static void mdss_mdp_cmd_lineptr_done(void *arg)
spin_unlock(&ctx->clk_lock);
}
-static void mdss_mdp_cmd_intf_recovery(void *data, int event)
+static int mdss_mdp_cmd_intf_recovery(void *data, int event)
{
struct mdss_mdp_cmd_ctx *ctx = data;
unsigned long flags;
@@ -1288,11 +1289,11 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event)
if (!data) {
pr_err("%s: invalid ctx\n", __func__);
- return;
+ return -EINVAL;
}
if (!ctx->ctl)
- return;
+ return -EINVAL;
/*
* Currently, only intf_fifo_underflow is
@@ -1302,7 +1303,7 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event)
if (event != MDP_INTF_DSI_CMD_FIFO_UNDERFLOW) {
pr_warn("%s: unsupported recovery event:%d\n",
__func__, event);
- return;
+ return -EPERM;
}
if (atomic_read(&ctx->koff_cnt)) {
@@ -1326,6 +1327,7 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event)
if (notify_frame_timeout)
mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_TIMEOUT);
+ return 0;
}
static void mdss_mdp_cmd_pingpong_done(void *arg)
@@ -2917,6 +2919,41 @@ static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl,
}
}
+int mdss_mdp_cmd_wait4_vsync(struct mdss_mdp_ctl *ctl)
+{
+ int rc = 0;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ if (!ctx) {
+ pr_err("invalid context to wait for vsync\n");
+ return rc;
+ }
+
+ atomic_inc(&ctx->rdptr_cnt);
+
+ /* enable clks and rd_ptr interrupt */
+ mdss_mdp_setup_vsync(ctx, true);
+
+ /* wait for read pointer */
+ MDSS_XLOG(atomic_read(&ctx->rdptr_cnt));
+ pr_debug("%s: wait for vsync cnt:%d\n",
+ __func__, atomic_read(&ctx->rdptr_cnt));
+
+ rc = mdss_mdp_cmd_wait4readptr(ctx);
+
+ /* wait for 1ms to make sure we are out from trigger window */
+ usleep_range(1000, 1010);
+
+ /* disable rd_ptr interrupt */
+ mdss_mdp_setup_vsync(ctx, false);
+
+ MDSS_XLOG(ctl->num);
+ pr_debug("%s: out from wait for rd_ptr ctl:%d\n", __func__, ctl->num);
+
+ return rc;
+}
+
+
/*
* There are 3 partial update possibilities
* left only ==> enable left pingpong_done
@@ -3170,6 +3207,8 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl,
ctx->default_pp_num, NULL, NULL);
memset(ctx, 0, sizeof(*ctx));
+ /* intf stopped, no more kickoff */
+ ctx->intf_stopped = 1;
return 0;
}
@@ -3315,7 +3354,11 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
ctx->intf_stopped = 0;
if (sctx)
sctx->intf_stopped = 0;
-
+ /*
+ * Tearcheck was disabled while entering LP2 state.
+ * Enable it back to allow updates in LP1 state.
+ */
+ mdss_mdp_tearcheck_enable(ctl, true);
goto end;
}
}
@@ -3373,6 +3416,7 @@ panel_events:
ctl->ops.add_vsync_handler = NULL;
ctl->ops.remove_vsync_handler = NULL;
ctl->ops.reconfigure = NULL;
+ ctl->ops.wait_for_vsync_fnc = NULL;
end:
if (!IS_ERR_VALUE(ret)) {
@@ -3773,6 +3817,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
ctl->ops.pre_programming = mdss_mdp_cmd_pre_programming;
ctl->ops.update_lineptr = mdss_mdp_cmd_update_lineptr;
ctl->ops.panel_disable_cfg = mdss_mdp_cmd_panel_disable_cfg;
+ ctl->ops.wait_for_vsync_fnc = mdss_mdp_cmd_wait4_vsync;
pr_debug("%s:-\n", __func__);
return 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 97be2fd728c8..67cbf076b8ac 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -315,7 +315,7 @@ int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
return 0;
}
-static void mdss_mdp_video_intf_recovery(void *data, int event)
+static int mdss_mdp_video_intf_recovery(void *data, int event)
{
struct mdss_mdp_video_ctx *ctx;
struct mdss_mdp_ctl *ctl = data;
@@ -327,7 +327,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
if (!data) {
pr_err("%s: invalid ctl\n", __func__);
- return;
+ return -EINVAL;
}
/*
@@ -338,7 +338,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
if (event != MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW) {
pr_warn("%s: unsupported recovery event:%d\n",
__func__, event);
- return;
+ return -EPERM;
}
ctx = ctl->intf_ctx[MASTER_CTX];
@@ -353,7 +353,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
clk_rate = DIV_ROUND_UP_ULL(clk_rate, 1000); /* in kHz */
if (!clk_rate) {
pr_err("Unable to get proper clk_rate\n");
- return;
+ return -EINVAL;
}
/*
* calculate clk_period as pico second to maintain good
@@ -363,7 +363,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
clk_period = DIV_ROUND_UP_ULL(1000000000, clk_rate);
if (!clk_period) {
pr_err("Unable to calculate clock period\n");
- return;
+ return -EINVAL;
}
min_ln_cnt = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width;
active_lns_cnt = pinfo->yres;
@@ -389,7 +389,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
!ctx->timegen_en) {
pr_warn("Target is in suspend or shutdown pending\n");
mutex_unlock(&ctl->offlock);
- return;
+ return -EPERM;
}
line_cnt = mdss_mdp_video_line_count(ctl);
@@ -399,7 +399,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
pr_debug("%s, Needed lines left line_cnt=%d\n",
__func__, line_cnt);
mutex_unlock(&ctl->offlock);
- return;
+ return 0;
} else {
pr_warn("line count is less. line_cnt = %d\n",
line_cnt);
@@ -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,
@@ -2345,6 +2348,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
ctl->ops.early_wake_up_fnc = mdss_mdp_video_early_wake_up;
ctl->ops.update_lineptr = mdss_mdp_video_lineptr_ctrl;
ctl->ops.avr_ctrl_fnc = mdss_mdp_video_avr_ctrl;
+ ctl->ops.wait_for_vsync_fnc = NULL;
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index c9e32d69d444..f78600072ed0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -1123,6 +1123,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
int ret = 0;
u32 left_lm_w = left_lm_w_from_mfd(mfd);
u64 flags;
+ bool is_right_blend = false;
struct mdss_mdp_mixer *mixer = NULL;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -1234,6 +1235,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
* staging, same pipe will be stagged on both layer mixers.
*/
if (mdata->has_src_split) {
+ is_right_blend = pipe->is_right_blend;
if (left_blend_pipe) {
if (__validate_pipe_priorities(left_blend_pipe, pipe)) {
pr_err("priority limitation. left:%d rect:%d, right:%d rect:%d\n",
@@ -1245,7 +1247,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
goto end;
} else {
pr_debug("pipe%d is a right_pipe\n", pipe->num);
- pipe->is_right_blend = true;
+ is_right_blend = true;
}
} else if (pipe->is_right_blend) {
/*
@@ -1254,7 +1256,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
*/
mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
- pipe->is_right_blend = false;
+ is_right_blend = false;
}
if (is_split_lm(mfd) && __layer_needs_src_split(layer)) {
@@ -1280,6 +1282,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
}
pipe->src_split_req = false;
}
+ pipe->is_right_blend = is_right_blend;
}
pipe->multirect.mode = vinfo->multirect.mode;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 9e295815da77..5daa8a7a2752 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2322,14 +2322,12 @@ set_roi:
}
/*
- * Enables/disable secure (display or camera) sessions
+ * Check if there is any change in secure state and store it.
*/
-static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
+static void __overlay_set_secure_transition_state(struct msm_fb_data_type *mfd)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_pipe *pipe;
- int ret = 0;
int sd_in_pipe = 0;
int sc_in_pipe = 0;
u64 pipes_flags = 0;
@@ -2350,25 +2348,53 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
MDSS_XLOG(sd_in_pipe, sc_in_pipe, pipes_flags,
mdp5_data->sc_enabled, mdp5_data->sd_enabled);
pr_debug("sd:%d sd_in_pipe:%d sc:%d sc_in_pipe:%d flags:0x%llx\n",
- mdp5_data->sd_enabled, sd_in_pipe,
- mdp5_data->sc_enabled, sc_in_pipe, pipes_flags);
+ mdp5_data->sd_enabled, sd_in_pipe,
+ mdp5_data->sc_enabled, sc_in_pipe, pipes_flags);
+
+ /* Reset the secure transition state */
+ mdp5_data->secure_transition_state = SECURE_TRANSITION_NONE;
/*
- * Return early in only two conditions:
- * 1. All the features are already disabled and state remains
- * disabled for the pipes.
- * 2. One of the features is already enabled and state remains
- * enabled for the pipes.
- */
+ * Secure transition would be NONE in two conditions:
+ * 1. All the features are already disabled and state remains
+ * disabled for the pipes.
+ * 2. One of the features is already enabled and state remains
+ * enabled for the pipes.
+ */
if (!sd_in_pipe && !mdp5_data->sd_enabled &&
!sc_in_pipe && !mdp5_data->sc_enabled)
- return ret;
+ return;
else if ((sd_in_pipe && mdp5_data->sd_enabled) ||
(sc_in_pipe && mdp5_data->sc_enabled))
+ return;
+
+ /* Secure Display */
+ if (!mdp5_data->sd_enabled && sd_in_pipe)
+ mdp5_data->secure_transition_state |= SD_NON_SECURE_TO_SECURE;
+ else if (mdp5_data->sd_enabled && !sd_in_pipe)
+ mdp5_data->secure_transition_state |= SD_SECURE_TO_NON_SECURE;
+
+ /* Secure Camera */
+ if (!mdp5_data->sc_enabled && sc_in_pipe)
+ mdp5_data->secure_transition_state |= SC_NON_SECURE_TO_SECURE;
+ else if (mdp5_data->sc_enabled && !sc_in_pipe)
+ mdp5_data->secure_transition_state |= SC_SECURE_TO_NON_SECURE;
+}
+
+/*
+ * Enable/disable secure (display or camera) sessions
+ */
+static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ int ret = 0;
+
+ if (mdp5_data->secure_transition_state == SECURE_TRANSITION_NONE)
return ret;
/* Secure Display */
- if (!mdp5_data->sd_enabled && sd_in_pipe) {
+ if (mdp5_data->secure_transition_state == SD_NON_SECURE_TO_SECURE) {
if (!mdss_get_sd_client_cnt()) {
MDSS_XLOG(0x11);
/*wait for ping pong done */
@@ -2390,7 +2416,8 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
}
mdp5_data->sd_enabled = 1;
mdss_update_sd_client(mdp5_data->mdata, true);
- } else if (mdp5_data->sd_enabled && !sd_in_pipe) {
+ } else if (mdp5_data->secure_transition_state ==
+ SD_SECURE_TO_NON_SECURE) {
/* disable the secure display on last client */
if (mdss_get_sd_client_cnt() == 1) {
MDSS_XLOG(0x22);
@@ -2408,11 +2435,9 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
}
/* Secure Camera */
- if (!mdp5_data->sc_enabled && sc_in_pipe) {
+ if (mdp5_data->secure_transition_state == SC_NON_SECURE_TO_SECURE) {
if (!mdss_get_sc_client_cnt()) {
MDSS_XLOG(0x33);
- if (ctl->ops.wait_pingpong)
- mdss_mdp_display_wait4pingpong(ctl, true);
ret = mdss_mdp_secure_session_ctrl(1,
MDP_SECURE_CAMERA_OVERLAY_SESSION);
if (ret) {
@@ -2422,7 +2447,8 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
}
mdp5_data->sc_enabled = 1;
mdss_update_sc_client(mdp5_data->mdata, true);
- } else if (mdp5_data->sc_enabled && !sc_in_pipe) {
+ } else if (mdp5_data->secure_transition_state ==
+ SC_SECURE_TO_NON_SECURE) {
/* disable the secure camera on last client */
if (mdss_get_sc_client_cnt() == 1) {
MDSS_XLOG(0x44);
@@ -2501,15 +2527,23 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
list_move(&pipe->list, &mdp5_data->pipes_destroy);
}
+ __overlay_set_secure_transition_state(mfd);
/*
* go to secure state if required, this should be done
* after moving the buffers from the previous commit to
- * destroy list
+ * destroy list.
+ * For video mode panels, secure display/camera should be disabled
+ * after flushing the new buffer. Skip secure disable here for those
+ * cases.
*/
- ret = __overlay_secure_ctrl(mfd);
- if (IS_ERR_VALUE(ret)) {
- pr_err("secure operation failed %d\n", ret);
- goto commit_fail;
+ if (!((mfd->panel_info->type == MIPI_VIDEO_PANEL) &&
+ ((mdp5_data->secure_transition_state == SD_SECURE_TO_NON_SECURE) ||
+ (mdp5_data->secure_transition_state == SC_SECURE_TO_NON_SECURE)))) {
+ ret = __overlay_secure_ctrl(mfd);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("secure operation failed %d\n", ret);
+ goto commit_fail;
+ }
}
/* call this function before any registers programming */
@@ -2581,6 +2615,17 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
mutex_lock(&mdp5_data->ov_lock);
+ /* Disable secure display/camera for video mode panels */
+ if ((mfd->panel_info->type == MIPI_VIDEO_PANEL) &&
+ ((mdp5_data->secure_transition_state == SD_SECURE_TO_NON_SECURE) ||
+ (mdp5_data->secure_transition_state == SC_SECURE_TO_NON_SECURE))) {
+ ret = __overlay_secure_ctrl(mfd);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("secure operation failed %d\n", ret);
+ goto commit_fail;
+ }
+ }
+
mdss_fb_update_notify_update(mfd);
commit_fail:
ATRACE_BEGIN("overlay_cleanup");
@@ -4367,12 +4412,21 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
start_y = 0;
}
+ if ((img->width > mdata->max_cursor_size) ||
+ (img->height > mdata->max_cursor_size) ||
+ (img->depth != 32) || (start_x >= xres) ||
+ (start_y >= yres)) {
+ pr_err("Invalid cursor image coordinates\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
roi.w = min(xres - start_x, img->width - roi.x);
roi.h = min(yres - start_y, img->height - roi.y);
if ((roi.w > mdata->max_cursor_size) ||
- (roi.h > mdata->max_cursor_size) ||
- (img->depth != 32) || (start_x >= xres) || (start_y >= yres)) {
+ (roi.h > mdata->max_cursor_size)) {
+ pr_err("Invalid cursor ROI size\n");
ret = -EINVAL;
goto done;
}
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/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index e466c0097540..e75c4a3a7cc1 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -112,12 +112,6 @@ enum {
};
enum {
- MDSS_PANEL_BLANK_BLANK = 0,
- MDSS_PANEL_BLANK_UNBLANK,
- MDSS_PANEL_BLANK_LOW_POWER,
-};
-
-enum {
MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0,
MDSS_PANEL_LOW_PERSIST_MODE_ON,
};
@@ -195,7 +189,7 @@ enum {
};
struct mdss_intf_recovery {
- void (*fxn)(void *ctx, int event);
+ int (*fxn)(void *ctx, int event);
void *data;
};
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/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/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index d2f19ac6f536..99fe34d25fc5 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -263,10 +263,10 @@ struct drm_msm_event_resp {
#define DRM_MSM_GEM_CPU_FINI 0x05
#define DRM_MSM_GEM_SUBMIT 0x06
#define DRM_MSM_WAIT_FENCE 0x07
-#define DRM_SDE_WB_CONFIG 0x08
-#define DRM_MSM_REGISTER_EVENT 0x09
-#define DRM_MSM_DEREGISTER_EVENT 0x0A
-#define DRM_MSM_NUM_IOCTLS 0x0B
+
+#define DRM_SDE_WB_CONFIG 0x40
+#define DRM_MSM_REGISTER_EVENT 0x41
+#define DRM_MSM_DEREGISTER_EVENT 0x42
/**
* Currently DRM framework supports only VSYNC event.
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/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index ee68675bfe13..35029f227f8b 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -40,9 +40,9 @@
* To allow proper structure padding for 64bit/32bit target
*/
#ifdef __LP64
-#define MDP_LAYER_COMMIT_V1_PAD 3
+#define MDP_LAYER_COMMIT_V1_PAD 2
#else
-#define MDP_LAYER_COMMIT_V1_PAD 4
+#define MDP_LAYER_COMMIT_V1_PAD 3
#endif
/**********************************************************************
@@ -166,6 +166,9 @@ VALIDATE/COMMIT FLAG CONFIGURATION
/* Flag to indicate dual partial ROI update */
#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20
+/* Flag to update brightness when commit */
+#define MDP_COMMIT_UPDATE_BRIGHTNESS 0x40
+
/* Flag to enable concurrent writeback for the frame */
#define MDP_COMMIT_CWB_EN 0x800
@@ -568,6 +571,9 @@ struct mdp_layer_commit_v1 {
*/
uint32_t dest_scaler_cnt;
+ /* Backlight level that would update when display commit */
+ uint32_t bl_level;
+
/* 32-bits reserved value for future usage. */
uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD];
};
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_isp.h b/include/uapi/media/msmb_isp.h
index fac254c4361b..d84bb30d56fa 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -24,6 +24,8 @@
#define ISP_STATS_STREAM_BIT 0x80000000
+#define VFE_HW_LIMIT 1
+
struct msm_vfe_cfg_cmd_list;
enum ISP_START_PIXEL_PATTERN {
@@ -456,6 +458,7 @@ enum msm_vfe_reg_cfg_type {
VFE_HW_UPDATE_UNLOCK,
SET_WM_UB_SIZE,
SET_UB_POLICY,
+ GET_VFE_HW_LIMIT,
};
struct msm_vfe_cfg_cmd2 {
@@ -842,6 +845,11 @@ struct msm_isp_dual_hw_master_slave_sync {
uint32_t reserved[2];
};
+struct msm_vfe_dual_lpm_mode {
+ enum msm_vfe_axi_stream_src stream_src[VFE_AXI_SRC_MAX];
+ uint32_t num_src;
+ uint32_t lpm_mode;
+};
#define V4L2_PIX_FMT_QBGGR8 v4l2_fourcc('Q', 'B', 'G', '8')
#define V4L2_PIX_FMT_QGBRG8 v4l2_fourcc('Q', 'G', 'B', '8')
#define V4L2_PIX_FMT_QGRBG8 v4l2_fourcc('Q', 'G', 'R', '8')
@@ -902,6 +910,7 @@ enum msm_isp_ioctl_cmd_code {
MSM_ISP_FETCH_ENG_MULTI_PASS_START,
MSM_ISP_MAP_BUF_START_MULTI_PASS_FE,
MSM_ISP_REQUEST_BUF_VER2,
+ MSM_ISP_DUAL_HW_LPM_MODE,
};
#define VIDIOC_MSM_VFE_REG_CFG \
@@ -1022,4 +1031,8 @@ enum msm_isp_ioctl_cmd_code {
#define VIDIOC_MSM_ISP_REQUEST_BUF_VER2 \
_IOWR('V', MSM_ISP_REQUEST_BUF_VER2, struct msm_isp_buf_request_ver2)
+#define VIDIOC_MSM_ISP_DUAL_HW_LPM_MODE \
+ _IOWR('V', MSM_ISP_DUAL_HW_LPM_MODE, \
+ struct msm_vfe_dual_lpm_mode)
+
#endif /* __MSMB_ISP__ */
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/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/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..e5e71939f529 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,54 @@ 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;
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
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 +4101,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 +4119,52 @@ 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);
+
+ snd_soc_dapm_ignore_suspend(dapm, "PDM Playback");
+ snd_soc_dapm_ignore_suspend(dapm, "PDM Capture");
+
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 +4176,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 +4209,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;
@@ -4255,24 +4233,10 @@ 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;
- pdata = snd_soc_card_get_drvdata(codec->component.card);
- pr_debug("%s: mclk cnt = %d, mclk_enabled = %d\n",
- __func__, atomic_read(&pdata->int_mclk0_rsc_ref),
- atomic_read(&pdata->int_mclk0_enabled));
- if (atomic_read(&pdata->int_mclk0_enabled) == true) {
- cancel_delayed_work_sync(&pdata->disable_int_mclk0_work);
- mutex_lock(&pdata->cdc_int_mclk0_mutex);
- pdata->digital_cdc_core_clk.enable = 0;
- afe_set_lpass_clock_v2(AFE_PORT_ID_INT0_MI2S_RX,
- &pdata->digital_cdc_core_clk);
- atomic_set(&pdata->int_mclk0_enabled, false);
- mutex_unlock(&pdata->cdc_int_mclk0_mutex);
- }
msm_anlg_cdc_disable_static_supplies_to_optimum(sdm660_cdc,
sdm660_cdc_pdata);
return 0;
@@ -4281,7 +4245,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 +4275,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 +4350,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 +4375,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 +4402,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 +4410,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 +4491,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 +4518,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 +4542,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 +4551,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 +4563,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 +4584,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..91faee1ffd32 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -79,7 +79,7 @@ static int msm_digcdc_clock_control(bool flag)
if (atomic_read(&pdata->int_mclk0_enabled) == false) {
pdata->digital_cdc_core_clk.enable = 1;
ret = afe_set_lpass_clock_v2(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
+ AFE_PORT_ID_INT0_MI2S_RX,
&pdata->digital_cdc_core_clk);
if (ret < 0) {
pr_err("%s:failed to enable the MCLK\n",
@@ -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,35 @@ 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);
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
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 +1196,23 @@ 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;
+
+ snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
+ snd_soc_dapm_ignore_suspend(dapm, "ADC1_IN");
+ snd_soc_dapm_ignore_suspend(dapm, "ADC2_IN");
+ snd_soc_dapm_ignore_suspend(dapm, "ADC3_IN");
+ snd_soc_dapm_ignore_suspend(dapm, "PDM_OUT_RX1");
+ snd_soc_dapm_ignore_suspend(dapm, "PDM_OUT_RX2");
+ snd_soc_dapm_ignore_suspend(dapm, "PDM_OUT_RX3");
+
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,14 +1974,32 @@ 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;
}
+static int msm_dig_cdc_suspend(struct snd_soc_codec *codec)
+{
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(codec->dev);
+
+ msm_dig_cdc->dapm_bias_off = 1;
+ return 0;
+}
+
+static int msm_dig_cdc_resume(struct snd_soc_codec *codec)
+{
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(codec->dev);
+
+ msm_dig_cdc->dapm_bias_off = 0;
+ return 0;
+}
+
static struct snd_soc_codec_driver soc_msm_dig_codec = {
.probe = msm_dig_cdc_soc_probe,
.remove = msm_dig_cdc_soc_remove,
+ .suspend = msm_dig_cdc_suspend,
+ .resume = msm_dig_cdc_resume,
.controls = msm_dig_snd_controls,
.num_controls = ARRAY_SIZE(msm_dig_snd_controls),
.dapm_widgets = msm_dig_dapm_widgets,
@@ -2005,10 +2029,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 +2043,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 +2067,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",
@@ -2058,6 +2082,44 @@ static int msm_dig_cdc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int msm_dig_suspend(struct device *dev)
+{
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(registered_digcodec->component.card);
+ struct msm_dig_priv *msm_dig_cdc = dev_get_drvdata(dev);
+
+ if (msm_dig_cdc->dapm_bias_off) {
+ pr_debug("%s: mclk cnt = %d, mclk_enabled = %d\n",
+ __func__, atomic_read(&pdata->int_mclk0_rsc_ref),
+ atomic_read(&pdata->int_mclk0_enabled));
+
+ if (atomic_read(&pdata->int_mclk0_enabled) == true) {
+ cancel_delayed_work_sync(
+ &pdata->disable_int_mclk0_work);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ pdata->digital_cdc_core_clk.enable = 0;
+ afe_set_lpass_clock_v2(AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ atomic_set(&pdata->int_mclk0_enabled, false);
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ }
+ }
+
+ return 0;
+}
+
+static int msm_dig_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops msm_dig_pm_ops = {
+ .suspend = msm_dig_suspend,
+ .resume = msm_dig_resume,
+};
+#endif
+
static const struct of_device_id msm_dig_cdc_of_match[] = {
{.compatible = "qcom,msm-digital-codec"},
{},
@@ -2068,6 +2130,9 @@ static struct platform_driver msm_digcodec_driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
.of_match_table = msm_dig_cdc_of_match,
+#ifdef CONFIG_PM
+ .pm = &msm_dig_pm_ops,
+#endif
},
.probe = msm_dig_cdc_probe,
.remove = msm_dig_cdc_remove,
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.h
index 4cb82cd421b0..f0e7a9cf9228 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,13 +43,11 @@ 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;
u32 mute_mask;
+ int dapm_bias_off;
void *handle;
void (*update_clkdiv)(void *handle, int val);
int (*get_cdc_version)(void *handle);
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 4fa80c679b46..8e986a74ffff 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -56,8 +56,8 @@
#define FLAC_BLK_SIZE_LIMIT 65535
/* Timestamp mode payload offsets */
-#define TS_LSW_OFFSET 6
-#define TS_MSW_OFFSET 7
+#define CAPTURE_META_DATA_TS_OFFSET_LSW 6
+#define CAPTURE_META_DATA_TS_OFFSET_MSW 7
/* decoder parameter length */
#define DDP_DEC_MAX_NUM_PARAM 18
@@ -410,6 +410,7 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
int buffer_length;
uint64_t bytes_available;
struct audio_aio_write_param param;
+ struct snd_codec_metadata *buff_addr;
if (!atomic_read(&prtd->start)) {
pr_err("%s: stream is not in started state\n", __func__);
@@ -442,23 +443,34 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
}
if (buffer_length) {
- param.paddr = prtd->buffer_paddr + prtd->byte_offset;
+ param.paddr = prtd->buffer_paddr + prtd->byte_offset;
WARN(prtd->byte_offset % 32 != 0, "offset %x not multiple of 32",
prtd->byte_offset);
}
else
- param.paddr = prtd->buffer_paddr;
-
+ param.paddr = prtd->buffer_paddr;
param.len = buffer_length;
- param.msw_ts = 0;
- param.lsw_ts = 0;
- param.flags = NO_TIMESTAMP;
+ if (prtd->ts_header_offset) {
+ buff_addr = (struct snd_codec_metadata *)
+ (prtd->buffer + prtd->byte_offset);
+ param.len = buff_addr->length;
+ param.msw_ts = (uint32_t)
+ ((buff_addr->timestamp & 0xFFFFFFFF00000000LL) >> 32);
+ param.lsw_ts = (uint32_t) (buff_addr->timestamp & 0xFFFFFFFFLL);
+ param.paddr += prtd->ts_header_offset;
+ param.flags = SET_TIMESTAMP;
+ param.metadata_len = prtd->ts_header_offset;
+ } else {
+ param.msw_ts = 0;
+ param.lsw_ts = 0;
+ param.flags = NO_TIMESTAMP;
+ param.metadata_len = 0;
+ }
param.uid = buffer_length;
- param.metadata_len = 0;
param.last_buffer = prtd->last_buffer;
pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n",
- __func__, buffer_length, prtd->byte_offset);
+ __func__, param.len, prtd->byte_offset);
if (q6asm_async_write(prtd->audio_client, &param) < 0) {
pr_err("%s:q6asm_async_write failed\n", __func__);
} else {
@@ -577,9 +589,21 @@ static void compr_event_handler(uint32_t opcode,
* written to ADSP in the last write, update offset and
* total copied data accordingly.
*/
-
- prtd->byte_offset += token;
- prtd->copied_total += token;
+ if (prtd->ts_header_offset) {
+ /* Always assume that the data will be sent to DSP on
+ * frame boundary.
+ * i.e, one frame of userspace write will result in
+ * one kernel write to DSP. This is needed as
+ * timestamp will be sent per frame.
+ */
+ prtd->byte_offset +=
+ prtd->codec_param.buffer.fragment_size;
+ prtd->copied_total +=
+ prtd->codec_param.buffer.fragment_size;
+ } else {
+ prtd->byte_offset += token;
+ prtd->copied_total += token;
+ }
if (prtd->byte_offset >= prtd->buffer_size)
prtd->byte_offset -= prtd->buffer_size;
@@ -634,10 +658,10 @@ static void compr_event_handler(uint32_t opcode,
*buff_addr = prtd->ts_header_offset;
buff_addr++;
/* Write the TS LSW */
- *buff_addr = payload[TS_LSW_OFFSET];
+ *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_LSW];
buff_addr++;
/* Write the TS MSW */
- *buff_addr = payload[TS_MSW_OFFSET];
+ *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_MSW];
}
/* Always assume read_size is same as fragment_size */
read_size = prtd->codec_param.buffer.fragment_size;
@@ -1320,6 +1344,12 @@ static int msm_compr_configure_dsp_for_playback
prtd->buffer_paddr = ac->port[dir].buf[0].phys;
prtd->buffer_size = runtime->fragments * runtime->fragment_size;
+ /* Bit-0 of flags represent timestamp mode */
+ if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
+ prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
+ else
+ prtd->ts_header_offset = 0;
+
ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
if (ret < 0) {
pr_err("%s, failed to send media format block\n", __func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 9c247124a383..c0ca9b24f544 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -836,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;
@@ -862,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-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index c3db926be5d9..e8bf562acc4f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2758,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]) {
@@ -2868,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;
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c3a4719542ef..f38108258306 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -7466,9 +7466,13 @@ int q6asm_async_write(struct audio_client *ac,
else if (ac->io_mode == io_compressed ||
ac->io_mode == io_compressed_stream)
lbuf_phys_addr = (param->paddr - param->metadata_len);
- else
- lbuf_phys_addr = param->paddr;
-
+ else {
+ if (param->flags & SET_TIMESTAMP)
+ lbuf_phys_addr = param->paddr -
+ sizeof(struct snd_codec_metadata);
+ else
+ lbuf_phys_addr = param->paddr;
+ }
dev_vdbg(ac->dev, "%s: token[0x%x], buf_addr[%pK], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_phys_addr: 0x[%pK]\n",
__func__,
write.hdr.token, &param->paddr,
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",