summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt13
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt12
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--android/configs/android-base.cfg1
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-rm67195-amoled-fhd-cmd.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi264
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi91
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-regulator.dtsi68
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-common.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi34
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-regulator.dtsi2
-rw-r--r--arch/arm/configs/sdm660_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig3
-rw-r--r--arch/arm64/configs/msmcortex_mediabox_defconfig1
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig1
-rw-r--r--arch/arm64/configs/sdm660_defconfig3
-rw-r--r--drivers/android/Kconfig2
-rw-r--r--drivers/android/binder.c392
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/adsprpc.c99
-rw-r--r--drivers/char/diag/diagfwd_peripheral.c23
-rw-r--r--drivers/cpuidle/lpm-levels.c8
-rw-r--r--drivers/gpu/msm/kgsl.c28
-rw-r--r--drivers/input/misc/hbtp_input.c104
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h3
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c30
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c1
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c335
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h6
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h8
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v3.h7
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c20
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h1
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c30
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c100
-rw-r--r--drivers/mfd/wcd934x-regmap.c1
-rw-r--r--drivers/misc/qcom/qdsp6v2/ultrasound/usf.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c3
-rw-r--r--drivers/net/wireless/cnss_prealloc/cnss_prealloc.c1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c1
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c37
-rw-r--r--drivers/power/supply/qcom/smb-lib.c17
-rw-r--r--drivers/power/supply/qcom/smb-lib.h1
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c2
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio_notifier.c2
-rw-r--r--drivers/soc/qcom/rpm-smd.c6
-rw-r--r--drivers/soc/qcom/service-locator.c138
-rw-r--r--drivers/soc/qcom/service-notifier.c177
-rw-r--r--drivers/soc/qcom/subsystem_restart.c105
-rw-r--r--drivers/usb/gadget/function/f_ccid.h36
-rw-r--r--drivers/usb/gadget/function/f_fs.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c69
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c44
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c10
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c10
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.c37
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c329
-rw-r--r--include/linux/mm.h12
-rw-r--r--include/linux/poison.h4
-rw-r--r--include/linux/usb/ccid_desc.h44
-rw-r--r--include/media/msm_cam_sensor.h1
-rw-r--r--include/soc/qcom/subsystem_restart.h3
-rw-r--r--include/uapi/linux/hbtp_input.h9
-rw-r--r--include/uapi/media/msm_camsensor_sdk.h3
-rw-r--r--include/uapi/media/msmb_ispif.h10
-rw-r--r--kernel/cpu.c5
-rw-r--r--kernel/power/hibernate.c17
-rw-r--r--mm/Kconfig.debug53
-rw-r--r--mm/Makefile2
-rw-r--r--mm/page_alloc.c10
-rw-r--r--mm/page_ext.c13
-rw-r--r--mm/page_poison.c (renamed from mm/debug-pagealloc.c)93
-rw-r--r--sound/soc/codecs/wcd-spi.c2
-rw-r--r--sound/soc/codecs/wcd9335.c2
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c11
-rw-r--r--sound/soc/codecs/wcd_cpe_core.c2
-rw-r--r--sound/soc/msm/msm8998.c3
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-slim.c20
-rw-r--r--sound/soc/msm/sdm660-common.c3
90 files changed, 2078 insertions, 1058 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 90ccfa7c62e2..ce5ee56ada68 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -581,6 +581,15 @@ Additional properties added to the second level nodes that represent timings pro
commands.
"dsi_lp_mode" = DSI low power mode (default)
"dsi_hs_mode" = DSI high speed mode
+- qcom,sublinks-count: An integer value indicates the number of sublinks in the panel.
+ Default value is 1. This property is used only if qcom,split-link-enabled
+ is defined.
+- qcom,lanes-per-sublink: An integer value indicates the number of data lanes per sublink in the panel.
+ Default value is 1. This property is used only if qcom,split-link-enabled
+ is defined.
+- qcom,split-link-enabled: A boolean value to enable/disable the split link feature. If qcom,sublinks-count
+ or qcom,lanes-per-sublink are not defined, default values are used.
+
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
@@ -808,6 +817,10 @@ Example:
qcom,mdss-dsc-version = <0x11>;
qcom,mdss-dsc-scr-version = <0x1>;
+ qcom,split-link-enabled;
+ qcom,sublinks-count = <2>;
+ qcom,lanes-per-sublink = <2>;
+
dsi_sim_vid_config0: config0 {
qcom,lm-split = <360 360>;
qcom,mdss-dsc-encoders = <2>;
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
index 5a2c3ecd3d1e..894c34553a22 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
@@ -169,6 +169,18 @@ Charger specific properties:
Definition: Boolean flag which when present enables intput suspend for
debug battery.
+- qcom,min-freq-khz
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the minimum charger buck/boost switching frequency
+ in KHz. It overrides the min frequency defined for the charger.
+
+- qcom,max-freq-khz
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the maximum charger buck/boost switching frequency in
+ KHz. It overrides the max frequency defined for the charger.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0220f18658e8..e953469cbe5e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2692,6 +2692,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
we can turn it on.
on: enable the feature
+ page_poison= [KNL] Boot-time parameter changing the state of
+ poisoning on the buddy allocator.
+ off: turn off poisoning
+ on: turn on poisoning
+
panic= [KNL] Kernel behaviour on panic: delay <timeout>
timeout > 0: seconds before rebooting
timeout = 0: wait forever
diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg
index f10371a981b7..7f672485f9c2 100644
--- a/android/configs/android-base.cfg
+++ b/android/configs/android-base.cfg
@@ -7,6 +7,7 @@
# CONFIG_SYSVIPC is not set
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_ASHMEM=y
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi
index 62115cf6f98a..0ff02042600d 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi
@@ -15,6 +15,7 @@
qcom,mdss-dsi-panel-name = "JDI a407 wqhd cmd mode dsi panel";
qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-panel-clockrate = <838600000>;
qcom,mdss-dsi-virtual-channel-id = <0>;
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <720>;
@@ -79,6 +80,8 @@
qcom,adjust-timer-wakeup-ms = <1>;
qcom,mdss-dsi-reset-sequence = <1 20>, <0 10>, <1 20>;
+ qcom,dcs-cmd-by-left;
+
qcom,config-select = <&dsi_dual_jdi_a407_cmd_config0>;
dsi_dual_jdi_a407_cmd_config0: config0 {
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
index 49ae94e7a975..7d3e3d362946 100644
--- 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
@@ -52,8 +52,12 @@
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 0a d8
+ 15 01 00 00 00 00 02 0c e6
+ 15 01 00 00 00 00 02 4e 20
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 50 2f
+ 15 01 00 00 02 00 02 51 08
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
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index c73a2ff23369..398aee9d3ab8 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -1284,50 +1284,50 @@
39 40 41 42 43>;
#interrupt-cells = <1>;
interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>;
- interrupt-map = <0x0 0x0 0x0 0 &intc 0 405 0
- 0x0 0x0 0x0 1 &intc 0 244 0
- 0x0 0x0 0x0 2 &intc 0 245 0
- 0x0 0x0 0x0 3 &intc 0 247 0
- 0x0 0x0 0x0 4 &intc 0 248 0
- 0x0 0x0 0x0 5 &intc 0 249 0
- 0x0 0x0 0x0 6 &intc 0 250 0
- 0x0 0x0 0x0 7 &intc 0 251 0
- 0x0 0x0 0x0 8 &intc 0 252 0
- 0x0 0x0 0x0 9 &intc 0 253 0
- 0x0 0x0 0x0 10 &intc 0 254 0
- 0x0 0x0 0x0 11 &intc 0 255 0
- 0x0 0x0 0x0 12 &intc 0 512 0
- 0x0 0x0 0x0 13 &intc 0 513 0
- 0x0 0x0 0x0 14 &intc 0 514 0
- 0x0 0x0 0x0 15 &intc 0 515 0
- 0x0 0x0 0x0 16 &intc 0 516 0
- 0x0 0x0 0x0 17 &intc 0 517 0
- 0x0 0x0 0x0 18 &intc 0 518 0
- 0x0 0x0 0x0 19 &intc 0 519 0
- 0x0 0x0 0x0 20 &intc 0 520 0
- 0x0 0x0 0x0 21 &intc 0 521 0
- 0x0 0x0 0x0 22 &intc 0 522 0
- 0x0 0x0 0x0 23 &intc 0 523 0
- 0x0 0x0 0x0 24 &intc 0 524 0
- 0x0 0x0 0x0 25 &intc 0 525 0
- 0x0 0x0 0x0 26 &intc 0 526 0
- 0x0 0x0 0x0 27 &intc 0 527 0
- 0x0 0x0 0x0 28 &intc 0 528 0
- 0x0 0x0 0x0 29 &intc 0 529 0
- 0x0 0x0 0x0 30 &intc 0 530 0
- 0x0 0x0 0x0 31 &intc 0 531 0
- 0x0 0x0 0x0 32 &intc 0 532 0
- 0x0 0x0 0x0 33 &intc 0 533 0
- 0x0 0x0 0x0 34 &intc 0 534 0
- 0x0 0x0 0x0 35 &intc 0 535 0
- 0x0 0x0 0x0 36 &intc 0 536 0
- 0x0 0x0 0x0 37 &intc 0 537 0
- 0x0 0x0 0x0 38 &intc 0 538 0
- 0x0 0x0 0x0 39 &intc 0 539 0
- 0x0 0x0 0x0 40 &intc 0 540 0
- 0x0 0x0 0x0 41 &intc 0 541 0
- 0x0 0x0 0x0 42 &intc 0 542 0
- 0x0 0x0 0x0 43 &intc 0 543 0>;
+ interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 405 0
+ 0x0 0x0 0x0 1 &intc 0 0 244 0
+ 0x0 0x0 0x0 2 &intc 0 0 245 0
+ 0x0 0x0 0x0 3 &intc 0 0 247 0
+ 0x0 0x0 0x0 4 &intc 0 0 248 0
+ 0x0 0x0 0x0 5 &intc 0 0 249 0
+ 0x0 0x0 0x0 6 &intc 0 0 250 0
+ 0x0 0x0 0x0 7 &intc 0 0 251 0
+ 0x0 0x0 0x0 8 &intc 0 0 252 0
+ 0x0 0x0 0x0 9 &intc 0 0 253 0
+ 0x0 0x0 0x0 10 &intc 0 0 254 0
+ 0x0 0x0 0x0 11 &intc 0 0 255 0
+ 0x0 0x0 0x0 12 &intc 0 0 512 0
+ 0x0 0x0 0x0 13 &intc 0 0 513 0
+ 0x0 0x0 0x0 14 &intc 0 0 514 0
+ 0x0 0x0 0x0 15 &intc 0 0 515 0
+ 0x0 0x0 0x0 16 &intc 0 0 516 0
+ 0x0 0x0 0x0 17 &intc 0 0 517 0
+ 0x0 0x0 0x0 18 &intc 0 0 518 0
+ 0x0 0x0 0x0 19 &intc 0 0 519 0
+ 0x0 0x0 0x0 20 &intc 0 0 520 0
+ 0x0 0x0 0x0 21 &intc 0 0 521 0
+ 0x0 0x0 0x0 22 &intc 0 0 522 0
+ 0x0 0x0 0x0 23 &intc 0 0 523 0
+ 0x0 0x0 0x0 24 &intc 0 0 524 0
+ 0x0 0x0 0x0 25 &intc 0 0 525 0
+ 0x0 0x0 0x0 26 &intc 0 0 526 0
+ 0x0 0x0 0x0 27 &intc 0 0 527 0
+ 0x0 0x0 0x0 28 &intc 0 0 528 0
+ 0x0 0x0 0x0 29 &intc 0 0 529 0
+ 0x0 0x0 0x0 30 &intc 0 0 530 0
+ 0x0 0x0 0x0 31 &intc 0 0 531 0
+ 0x0 0x0 0x0 32 &intc 0 0 532 0
+ 0x0 0x0 0x0 33 &intc 0 0 533 0
+ 0x0 0x0 0x0 34 &intc 0 0 534 0
+ 0x0 0x0 0x0 35 &intc 0 0 535 0
+ 0x0 0x0 0x0 36 &intc 0 0 536 0
+ 0x0 0x0 0x0 37 &intc 0 0 537 0
+ 0x0 0x0 0x0 38 &intc 0 0 538 0
+ 0x0 0x0 0x0 39 &intc 0 0 539 0
+ 0x0 0x0 0x0 40 &intc 0 0 540 0
+ 0x0 0x0 0x0 41 &intc 0 0 541 0
+ 0x0 0x0 0x0 42 &intc 0 0 542 0
+ 0x0 0x0 0x0 43 &intc 0 0 543 0>;
interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d",
"int_pls_pme", "int_pme_legacy", "int_pls_err",
@@ -1440,50 +1440,50 @@
39 40 41 42 43>;
#interrupt-cells = <1>;
interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>;
- interrupt-map = <0x0 0x0 0x0 0 &intc 0 413 0
- 0x0 0x0 0x0 1 &intc 0 272 0
- 0x0 0x0 0x0 2 &intc 0 273 0
- 0x0 0x0 0x0 3 &intc 0 274 0
- 0x0 0x0 0x0 4 &intc 0 275 0
- 0x0 0x0 0x0 5 &intc 0 276 0
- 0x0 0x0 0x0 6 &intc 0 277 0
- 0x0 0x0 0x0 7 &intc 0 278 0
- 0x0 0x0 0x0 8 &intc 0 279 0
- 0x0 0x0 0x0 9 &intc 0 280 0
- 0x0 0x0 0x0 10 &intc 0 281 0
- 0x0 0x0 0x0 11 &intc 0 282 0
- 0x0 0x0 0x0 12 &intc 0 544 0
- 0x0 0x0 0x0 13 &intc 0 545 0
- 0x0 0x0 0x0 14 &intc 0 546 0
- 0x0 0x0 0x0 15 &intc 0 547 0
- 0x0 0x0 0x0 16 &intc 0 548 0
- 0x0 0x0 0x0 17 &intc 0 549 0
- 0x0 0x0 0x0 18 &intc 0 550 0
- 0x0 0x0 0x0 19 &intc 0 551 0
- 0x0 0x0 0x0 20 &intc 0 552 0
- 0x0 0x0 0x0 21 &intc 0 553 0
- 0x0 0x0 0x0 22 &intc 0 554 0
- 0x0 0x0 0x0 23 &intc 0 555 0
- 0x0 0x0 0x0 24 &intc 0 556 0
- 0x0 0x0 0x0 25 &intc 0 557 0
- 0x0 0x0 0x0 26 &intc 0 558 0
- 0x0 0x0 0x0 27 &intc 0 559 0
- 0x0 0x0 0x0 28 &intc 0 560 0
- 0x0 0x0 0x0 29 &intc 0 561 0
- 0x0 0x0 0x0 30 &intc 0 562 0
- 0x0 0x0 0x0 31 &intc 0 563 0
- 0x0 0x0 0x0 32 &intc 0 564 0
- 0x0 0x0 0x0 33 &intc 0 565 0
- 0x0 0x0 0x0 34 &intc 0 566 0
- 0x0 0x0 0x0 35 &intc 0 567 0
- 0x0 0x0 0x0 36 &intc 0 568 0
- 0x0 0x0 0x0 37 &intc 0 569 0
- 0x0 0x0 0x0 38 &intc 0 570 0
- 0x0 0x0 0x0 39 &intc 0 571 0
- 0x0 0x0 0x0 40 &intc 0 572 0
- 0x0 0x0 0x0 41 &intc 0 573 0
- 0x0 0x0 0x0 42 &intc 0 574 0
- 0x0 0x0 0x0 43 &intc 0 575 0>;
+ interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 413 0
+ 0x0 0x0 0x0 1 &intc 0 0 272 0
+ 0x0 0x0 0x0 2 &intc 0 0 273 0
+ 0x0 0x0 0x0 3 &intc 0 0 274 0
+ 0x0 0x0 0x0 4 &intc 0 0 275 0
+ 0x0 0x0 0x0 5 &intc 0 0 276 0
+ 0x0 0x0 0x0 6 &intc 0 0 277 0
+ 0x0 0x0 0x0 7 &intc 0 0 278 0
+ 0x0 0x0 0x0 8 &intc 0 0 279 0
+ 0x0 0x0 0x0 9 &intc 0 0 280 0
+ 0x0 0x0 0x0 10 &intc 0 0 281 0
+ 0x0 0x0 0x0 11 &intc 0 0 282 0
+ 0x0 0x0 0x0 12 &intc 0 0 544 0
+ 0x0 0x0 0x0 13 &intc 0 0 545 0
+ 0x0 0x0 0x0 14 &intc 0 0 546 0
+ 0x0 0x0 0x0 15 &intc 0 0 547 0
+ 0x0 0x0 0x0 16 &intc 0 0 548 0
+ 0x0 0x0 0x0 17 &intc 0 0 549 0
+ 0x0 0x0 0x0 18 &intc 0 0 550 0
+ 0x0 0x0 0x0 19 &intc 0 0 551 0
+ 0x0 0x0 0x0 20 &intc 0 0 552 0
+ 0x0 0x0 0x0 21 &intc 0 0 553 0
+ 0x0 0x0 0x0 22 &intc 0 0 554 0
+ 0x0 0x0 0x0 23 &intc 0 0 555 0
+ 0x0 0x0 0x0 24 &intc 0 0 556 0
+ 0x0 0x0 0x0 25 &intc 0 0 557 0
+ 0x0 0x0 0x0 26 &intc 0 0 558 0
+ 0x0 0x0 0x0 27 &intc 0 0 559 0
+ 0x0 0x0 0x0 28 &intc 0 0 560 0
+ 0x0 0x0 0x0 29 &intc 0 0 561 0
+ 0x0 0x0 0x0 30 &intc 0 0 562 0
+ 0x0 0x0 0x0 31 &intc 0 0 563 0
+ 0x0 0x0 0x0 32 &intc 0 0 564 0
+ 0x0 0x0 0x0 33 &intc 0 0 565 0
+ 0x0 0x0 0x0 34 &intc 0 0 566 0
+ 0x0 0x0 0x0 35 &intc 0 0 567 0
+ 0x0 0x0 0x0 36 &intc 0 0 568 0
+ 0x0 0x0 0x0 37 &intc 0 0 569 0
+ 0x0 0x0 0x0 38 &intc 0 0 570 0
+ 0x0 0x0 0x0 39 &intc 0 0 571 0
+ 0x0 0x0 0x0 40 &intc 0 0 572 0
+ 0x0 0x0 0x0 41 &intc 0 0 573 0
+ 0x0 0x0 0x0 42 &intc 0 0 574 0
+ 0x0 0x0 0x0 43 &intc 0 0 575 0>;
interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d",
"int_pls_pme", "int_pme_legacy", "int_pls_err",
@@ -1592,50 +1592,50 @@
39 40 41 42 43>;
#interrupt-cells = <1>;
interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>;
- interrupt-map = <0x0 0x0 0x0 0 &intc 0 421 0
- 0x0 0x0 0x0 1 &intc 0 142 0
- 0x0 0x0 0x0 2 &intc 0 143 0
- 0x0 0x0 0x0 3 &intc 0 144 0
- 0x0 0x0 0x0 4 &intc 0 145 0
- 0x0 0x0 0x0 5 &intc 0 146 0
- 0x0 0x0 0x0 6 &intc 0 147 0
- 0x0 0x0 0x0 7 &intc 0 148 0
- 0x0 0x0 0x0 8 &intc 0 149 0
- 0x0 0x0 0x0 9 &intc 0 260 0
- 0x0 0x0 0x0 10 &intc 0 261 0
- 0x0 0x0 0x0 11 &intc 0 262 0
- 0x0 0x0 0x0 12 &intc 0 576 0
- 0x0 0x0 0x0 13 &intc 0 577 0
- 0x0 0x0 0x0 14 &intc 0 578 0
- 0x0 0x0 0x0 15 &intc 0 579 0
- 0x0 0x0 0x0 16 &intc 0 580 0
- 0x0 0x0 0x0 17 &intc 0 581 0
- 0x0 0x0 0x0 18 &intc 0 582 0
- 0x0 0x0 0x0 19 &intc 0 583 0
- 0x0 0x0 0x0 20 &intc 0 584 0
- 0x0 0x0 0x0 21 &intc 0 585 0
- 0x0 0x0 0x0 22 &intc 0 586 0
- 0x0 0x0 0x0 23 &intc 0 587 0
- 0x0 0x0 0x0 24 &intc 0 588 0
- 0x0 0x0 0x0 25 &intc 0 589 0
- 0x0 0x0 0x0 26 &intc 0 590 0
- 0x0 0x0 0x0 27 &intc 0 591 0
- 0x0 0x0 0x0 28 &intc 0 592 0
- 0x0 0x0 0x0 29 &intc 0 593 0
- 0x0 0x0 0x0 30 &intc 0 594 0
- 0x0 0x0 0x0 31 &intc 0 595 0
- 0x0 0x0 0x0 32 &intc 0 596 0
- 0x0 0x0 0x0 33 &intc 0 597 0
- 0x0 0x0 0x0 34 &intc 0 598 0
- 0x0 0x0 0x0 35 &intc 0 599 0
- 0x0 0x0 0x0 36 &intc 0 600 0
- 0x0 0x0 0x0 37 &intc 0 601 0
- 0x0 0x0 0x0 38 &intc 0 602 0
- 0x0 0x0 0x0 39 &intc 0 603 0
- 0x0 0x0 0x0 40 &intc 0 604 0
- 0x0 0x0 0x0 41 &intc 0 605 0
- 0x0 0x0 0x0 42 &intc 0 606 0
- 0x0 0x0 0x0 43 &intc 0 607 0>;
+ interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 421 0
+ 0x0 0x0 0x0 1 &intc 0 0 142 0
+ 0x0 0x0 0x0 2 &intc 0 0 143 0
+ 0x0 0x0 0x0 3 &intc 0 0 144 0
+ 0x0 0x0 0x0 4 &intc 0 0 145 0
+ 0x0 0x0 0x0 5 &intc 0 0 146 0
+ 0x0 0x0 0x0 6 &intc 0 0 147 0
+ 0x0 0x0 0x0 7 &intc 0 0 148 0
+ 0x0 0x0 0x0 8 &intc 0 0 149 0
+ 0x0 0x0 0x0 9 &intc 0 0 260 0
+ 0x0 0x0 0x0 10 &intc 0 0 261 0
+ 0x0 0x0 0x0 11 &intc 0 0 262 0
+ 0x0 0x0 0x0 12 &intc 0 0 576 0
+ 0x0 0x0 0x0 13 &intc 0 0 577 0
+ 0x0 0x0 0x0 14 &intc 0 0 578 0
+ 0x0 0x0 0x0 15 &intc 0 0 579 0
+ 0x0 0x0 0x0 16 &intc 0 0 580 0
+ 0x0 0x0 0x0 17 &intc 0 0 581 0
+ 0x0 0x0 0x0 18 &intc 0 0 582 0
+ 0x0 0x0 0x0 19 &intc 0 0 583 0
+ 0x0 0x0 0x0 20 &intc 0 0 584 0
+ 0x0 0x0 0x0 21 &intc 0 0 585 0
+ 0x0 0x0 0x0 22 &intc 0 0 586 0
+ 0x0 0x0 0x0 23 &intc 0 0 587 0
+ 0x0 0x0 0x0 24 &intc 0 0 588 0
+ 0x0 0x0 0x0 25 &intc 0 0 589 0
+ 0x0 0x0 0x0 26 &intc 0 0 590 0
+ 0x0 0x0 0x0 27 &intc 0 0 591 0
+ 0x0 0x0 0x0 28 &intc 0 0 592 0
+ 0x0 0x0 0x0 29 &intc 0 0 593 0
+ 0x0 0x0 0x0 30 &intc 0 0 594 0
+ 0x0 0x0 0x0 31 &intc 0 0 595 0
+ 0x0 0x0 0x0 32 &intc 0 0 596 0
+ 0x0 0x0 0x0 33 &intc 0 0 597 0
+ 0x0 0x0 0x0 34 &intc 0 0 598 0
+ 0x0 0x0 0x0 35 &intc 0 0 599 0
+ 0x0 0x0 0x0 36 &intc 0 0 600 0
+ 0x0 0x0 0x0 37 &intc 0 0 601 0
+ 0x0 0x0 0x0 38 &intc 0 0 602 0
+ 0x0 0x0 0x0 39 &intc 0 0 603 0
+ 0x0 0x0 0x0 40 &intc 0 0 604 0
+ 0x0 0x0 0x0 41 &intc 0 0 605 0
+ 0x0 0x0 0x0 42 &intc 0 0 606 0
+ 0x0 0x0 0x0 43 &intc 0 0 607 0>;
interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d",
"int_pls_pme", "int_pme_legacy", "int_pls_err",
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index 55e6943bf327..9df521f33e05 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -192,3 +192,26 @@
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <2 2 4 2 1080 2>;
};
+
+&pm660l_pwm_4 {
+ qcom,dtest-line = <2>; /* DTEST2 */
+ qcom,dtest-output = <2>; /* OUTPUT PWM */
+};
+
+&pm660l_gpios {
+ gpio@c500 {
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,src-sel = <7>; /* DTEST2 */
+ qcom,master-en = <1>; /* Enable MPP */
+ qcom,invert = <0>; /* Enable MPP */
+ };
+};
+
+&dsi_sharp_split_link_wuxga_video {
+ pwms = <&pm660l_pwm_4 0 0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pwm-pmi;
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,panel-supply-entries = <&dsi_panel_split_link_pwr_supply>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
index dfed9ec80a34..4e3ebd445814 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
@@ -16,6 +16,7 @@
#include "dsi-panel-truly-1080p-cmd.dtsi"
#include "dsi-panel-truly-1080p-video.dtsi"
#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
+#include "dsi-panel-sharp-split-link-wuxga-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -51,6 +52,48 @@
};
};
+ dsi_panel_split_link_pwr_supply: dsi_panel_split_link_pwr_supply {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,panel-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "wqhd-vddio";
+ qcom,supply-min-voltage = <1800000>;
+ qcom,supply-max-voltage = <1950000>;
+ qcom,supply-enable-load = <32000>;
+ qcom,supply-disable-load = <80>;
+ };
+
+ qcom,panel-supply-entry@1 {
+ reg = <1>;
+ qcom,supply-name = "vdda-3p3";
+ qcom,supply-min-voltage = <3300000>;
+ qcom,supply-max-voltage = <3300000>;
+ qcom,supply-enable-load = <13900>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <5500000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@3 {
+ reg = <3>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <5500000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-post-on-sleep = <10>;
+ };
+ };
+
dsi_panel_pwr_supply_labibb_amoled:
dsi_panel_pwr_supply_labibb_amoled {
#address-cells = <1>;
@@ -114,7 +157,14 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_nt35695b_truly_fhd_cmd {
@@ -124,7 +174,14 @@
24 1e 08 09 05 03 04 a0
24 1a 08 09 05 03 04 a0];
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_truly_1080_vid {
@@ -138,7 +195,14 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x1c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x1c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_truly_1080_cmd {
@@ -148,7 +212,14 @@
23 1e 08 09 05 03 04 a0
23 1a 08 09 05 03 04 a0];
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x1c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x1c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_rm67195_amoled_fhd_cmd {
@@ -160,3 +231,15 @@
qcom,mdss-dsi-t-clk-post = <0x0d>;
qcom,mdss-dsi-t-clk-pre = <0x2f>;
};
+
+&dsi_sharp_split_link_wuxga_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0
+ 25 1f 09 0a 06 03 04 a0
+ 25 1f 09 0a 06 03 04 a0
+ 25 1f 09 0a 06 03 04 a0
+ 25 1f 08 0a 06 03 04 a0];
+ qcom,mdss-dsi-min-refresh-rate = <48>;
+ 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";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
index eded8b08528a..c4adcfe1bdfb 100644
--- a/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
@@ -28,7 +28,7 @@
rpm-regulator-smpa5 {
status = "okay";
pm660_s5: regulator-s5 {
- regulator-min-microvolt = <1350000>;
+ regulator-min-microvolt = <1224000>;
regulator-max-microvolt = <1350000>;
status = "okay";
};
@@ -657,6 +657,7 @@
qcom,cpr-up-error-step-limit = <1>;
qcom,cpr-corner-switch-delay-time = <1042>;
qcom,cpr-voltage-settling-time = <1760>;
+ qcom,cpr-reset-step-quot-loop-en;
qcom,apm-threshold-voltage = <872000>;
qcom,apm-crossover-voltage = <872000>;
@@ -665,6 +666,9 @@
qcom,voltage-base = <400000>;
qcom,cpr-saw-use-unit-mV;
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
qcom,cpr-panic-reg-addr-list =
<0x179cbaa4 0x17912c18>;
qcom,cpr-panic-reg-name-list =
@@ -705,6 +709,24 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-ro-scaling-factor =
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <(-30000) (-30000) (-30000)>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <32000 32000 32000 40000 44000
+ 40000 40000 40000>;
};
};
};
@@ -731,6 +753,7 @@
qcom,cpr-up-error-step-limit = <1>;
qcom,cpr-corner-switch-delay-time = <1042>;
qcom,cpr-voltage-settling-time = <1760>;
+ qcom,cpr-reset-step-quot-loop-en;
qcom,apm-threshold-voltage = <872000>;
qcom,apm-crossover-voltage = <872000>;
@@ -739,6 +762,9 @@
qcom,voltage-base = <400000>;
qcom,cpr-saw-use-unit-mV;
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
qcom,cpr-panic-reg-addr-list =
<0x179c7aa4 0x17812c18>;
qcom,cpr-panic-reg-name-list =
@@ -834,6 +860,46 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-ro-scaling-factor =
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ <15000 5000 5000 0 0>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <(-30000) (-30000) (-30000)
+ (-30000) (-30000)>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ /* Speed bin 0 */
+ <40000 40000 40000 40000
+ 40000 40000 40000 66000
+ 66000 40000>,
+
+ /* Speed bin 1 */
+ <40000 40000 40000 40000
+ 40000 40000 40000 66000
+ 66000 40000>,
+
+ /* Speed bin 2 */
+ <40000 40000 40000 40000
+ 40000 40000 40000 66000
+ 66000 40000 40000>;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
index 33edebec2f72..76130f177fad 100644
--- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
@@ -181,6 +181,7 @@
"cfg_ahb_clk", "xo";
qcom,core-clk-rate = <133330000>;
+ qcom,core-clk-rate-hs = <66666667>;
resets = <&clock_gcc GCC_USB_30_BCR>;
reset-names = "core_reset";
@@ -192,6 +193,7 @@
interrupts = <0 131 0>;
usb-phy = <&qusb_phy0>, <&ssphy>;
tx-fifo-resize;
+ snps,usb3-u1u2-disable;
snps,nominal-elastic-buffer;
snps,disable-clk-gating;
snps,has-lpm-erratum;
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index 7d293f8d821c..4cd8bf4407ac 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -229,7 +229,13 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
};
&dsi_nt35695b_truly_fhd_cmd {
@@ -239,7 +245,13 @@
24 1e 08 09 05 03 04 a0
24 1a 08 09 05 03 04 a0];
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
};
&dsi_truly_1080_vid {
@@ -253,7 +265,14 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x1c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x1c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_truly_1080_cmd {
@@ -263,7 +282,14 @@
23 1e 08 09 05 03 04 a0
23 1a 08 09 05 03 04 a0];
qcom,esd-check-enabled;
- qcom,mdss-dsi-panel-status-check-mode = "bta_check";
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x1c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x1c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+
};
&dsi_rm67195_amoled_fhd_cmd {
diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
index a93efdc38f41..8b6bbac171f4 100644
--- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
@@ -28,7 +28,7 @@
rpm-regulator-smpa5 {
status = "okay";
pm660_s5: regulator-s5 {
- regulator-min-microvolt = <1350000>;
+ regulator-min-microvolt = <1224000>;
regulator-max-microvolt = <1350000>;
status = "okay";
};
diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig
index c4b0eabe2fbf..30a71904747f 100644
--- a/arch/arm/configs/sdm660_defconfig
+++ b/arch/arm/configs/sdm660_defconfig
@@ -635,6 +635,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index dc50257f5b7a..9814d1826d93 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -82,6 +82,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -638,6 +639,8 @@ CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_PAGE_POISONING=y
+CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
diff --git a/arch/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig
index ccd653eaec7d..29a511d3eec5 100644
--- a/arch/arm64/configs/msmcortex_mediabox_defconfig
+++ b/arch/arm64/configs/msmcortex_mediabox_defconfig
@@ -543,7 +543,6 @@ CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
-CONFIG_ICNSS_DEBUG=y
CONFIG_MSM_GLADIATOR_ERP_V2=y
CONFIG_PANIC_ON_GLADIATOR_ERROR_V2=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index ffb983587c31..b7f47de09ecd 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -594,6 +594,7 @@ CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder"
CONFIG_MSM_TZ_LOG=y
CONFIG_SENSORS_SSC=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index bba52749284a..cf2395e5e86c 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -617,6 +617,7 @@ CONFIG_ARM_GIC_V3_ACL=y
CONFIG_PHY_XGENE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder"
CONFIG_MSM_TZ_LOG=y
CONFIG_SENSORS_SSC=y
CONFIG_EXT2_FS=y
@@ -645,6 +646,8 @@ CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_PAGE_POISONING=y
+CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index a82fc022d34b..4d4cdc1a6e25 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -22,7 +22,7 @@ config ANDROID_BINDER_IPC
config ANDROID_BINDER_DEVICES
string "Android Binder devices"
depends on ANDROID_BINDER_IPC
- default "binder"
+ default "binder,hwbinder,vndbinder"
---help---
Default value for the binder.devices parameter.
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 37b9eecf5c71..d1490be45c67 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -18,6 +18,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <asm/cacheflush.h>
+#include <linux/atomic.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/freezer.h>
@@ -46,19 +47,11 @@
#include <uapi/linux/android/binder.h>
#include "binder_trace.h"
-static DEFINE_MUTEX(binder_main_lock);
-static DEFINE_MUTEX(binder_deferred_lock);
-static DEFINE_MUTEX(binder_mmap_lock);
-
static HLIST_HEAD(binder_devices);
-static HLIST_HEAD(binder_procs);
-static HLIST_HEAD(binder_deferred_list);
-static HLIST_HEAD(binder_dead_nodes);
static struct dentry *binder_debugfs_dir_entry_root;
static struct dentry *binder_debugfs_dir_entry_proc;
-static int binder_last_id;
-static struct workqueue_struct *binder_deferred_workqueue;
+atomic_t binder_last_id;
#define BINDER_DEBUG_ENTRY(name) \
static int binder_##name##_open(struct inode *inode, struct file *file) \
@@ -173,20 +166,24 @@ enum binder_stat_types {
struct binder_stats {
int br[_IOC_NR(BR_FAILED_REPLY) + 1];
int bc[_IOC_NR(BC_REPLY_SG) + 1];
- int obj_created[BINDER_STAT_COUNT];
- int obj_deleted[BINDER_STAT_COUNT];
};
-static struct binder_stats binder_stats;
+/* These are still global, since it's not always easy to get the context */
+struct binder_obj_stats {
+ atomic_t obj_created[BINDER_STAT_COUNT];
+ atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+static struct binder_obj_stats binder_obj_stats;
static inline void binder_stats_deleted(enum binder_stat_types type)
{
- binder_stats.obj_deleted[type]++;
+ atomic_inc(&binder_obj_stats.obj_deleted[type]);
}
static inline void binder_stats_created(enum binder_stat_types type)
{
- binder_stats.obj_created[type]++;
+ atomic_inc(&binder_obj_stats.obj_created[type]);
}
struct binder_transaction_log_entry {
@@ -207,8 +204,6 @@ struct binder_transaction_log {
int full;
struct binder_transaction_log_entry entry[32];
};
-static struct binder_transaction_log binder_transaction_log;
-static struct binder_transaction_log binder_transaction_log_failed;
static struct binder_transaction_log_entry *binder_transaction_log_add(
struct binder_transaction_log *log)
@@ -229,6 +224,21 @@ struct binder_context {
struct binder_node *binder_context_mgr_node;
kuid_t binder_context_mgr_uid;
const char *name;
+
+ struct mutex binder_main_lock;
+ struct mutex binder_deferred_lock;
+ struct mutex binder_mmap_lock;
+
+ struct hlist_head binder_procs;
+ struct hlist_head binder_dead_nodes;
+ struct hlist_head binder_deferred_list;
+
+ struct work_struct deferred_work;
+ struct workqueue_struct *binder_deferred_workqueue;
+ struct binder_transaction_log transaction_log;
+ struct binder_transaction_log transaction_log_failed;
+
+ struct binder_stats binder_stats;
};
struct binder_device {
@@ -459,18 +469,19 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
return retval;
}
-static inline void binder_lock(const char *tag)
+static inline void binder_lock(struct binder_context *context, const char *tag)
{
trace_binder_lock(tag);
- mutex_lock(&binder_main_lock);
+ mutex_lock(&context->binder_main_lock);
preempt_disable();
trace_binder_locked(tag);
}
-static inline void binder_unlock(const char *tag)
+static inline void binder_unlock(struct binder_context *context,
+ const char *tag)
{
trace_binder_unlock(tag);
- mutex_unlock(&binder_main_lock);
+ mutex_unlock(&context->binder_main_lock);
preempt_enable();
}
@@ -1017,7 +1028,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
binder_stats_created(BINDER_STAT_NODE);
rb_link_node(&node->rb_node, parent, p);
rb_insert_color(&node->rb_node, &proc->nodes);
- node->debug_id = ++binder_last_id;
+ node->debug_id = atomic_inc_return(&binder_last_id);
node->proc = proc;
node->ptr = ptr;
node->cookie = cookie;
@@ -1159,7 +1170,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
if (new_ref == NULL)
return NULL;
binder_stats_created(BINDER_STAT_REF);
- new_ref->debug_id = ++binder_last_id;
+ new_ref->debug_id = atomic_inc_return(&binder_last_id);
new_ref->proc = proc;
new_ref->node = node;
rb_link_node(&new_ref->rb_node_node, parent, p);
@@ -1920,7 +1931,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
- e = binder_transaction_log_add(&binder_transaction_log);
+ e = binder_transaction_log_add(&context->transaction_log);
e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
e->from_proc = proc->pid;
e->from_thread = thread->pid;
@@ -2042,7 +2053,7 @@ static void binder_transaction(struct binder_proc *proc,
}
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
- t->debug_id = ++binder_last_id;
+ t->debug_id = atomic_inc_return(&binder_last_id);
e->debug_id = t->debug_id;
if (reply)
@@ -2315,7 +2326,8 @@ err_no_context_mgr_node:
{
struct binder_transaction_log_entry *fe;
- fe = binder_transaction_log_add(&binder_transaction_log_failed);
+ fe = binder_transaction_log_add(
+ &context->transaction_log_failed);
*fe = *e;
}
@@ -2343,8 +2355,8 @@ static int binder_thread_write(struct binder_proc *proc,
return -EFAULT;
ptr += sizeof(uint32_t);
trace_binder_command(cmd);
- if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
- binder_stats.bc[_IOC_NR(cmd)]++;
+ if (_IOC_NR(cmd) < ARRAY_SIZE(context->binder_stats.bc)) {
+ context->binder_stats.bc[_IOC_NR(cmd)]++;
proc->stats.bc[_IOC_NR(cmd)]++;
thread->stats.bc[_IOC_NR(cmd)]++;
}
@@ -2710,8 +2722,8 @@ static void binder_stat_br(struct binder_proc *proc,
struct binder_thread *thread, uint32_t cmd)
{
trace_binder_return(cmd);
- if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
- binder_stats.br[_IOC_NR(cmd)]++;
+ if (_IOC_NR(cmd) < ARRAY_SIZE(proc->stats.br)) {
+ proc->context->binder_stats.br[_IOC_NR(cmd)]++;
proc->stats.br[_IOC_NR(cmd)]++;
thread->stats.br[_IOC_NR(cmd)]++;
}
@@ -2775,7 +2787,7 @@ retry:
if (wait_for_proc_work)
proc->ready_threads++;
- binder_unlock(__func__);
+ binder_unlock(proc->context, __func__);
trace_binder_wait_for_work(wait_for_proc_work,
!!thread->transaction_stack,
@@ -2802,7 +2814,7 @@ retry:
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
- binder_lock(__func__);
+ binder_lock(proc->context, __func__);
if (wait_for_proc_work)
proc->ready_threads--;
@@ -3188,14 +3200,14 @@ static unsigned int binder_poll(struct file *filp,
struct binder_thread *thread = NULL;
int wait_for_proc_work;
- binder_lock(__func__);
+ binder_lock(proc->context, __func__);
thread = binder_get_thread(proc);
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo) && thread->return_error == BR_OK;
- binder_unlock(__func__);
+ binder_unlock(proc->context, __func__);
if (wait_for_proc_work) {
if (binder_has_proc_work(proc, thread))
@@ -3322,6 +3334,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
+ struct binder_context *context = proc->context;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
@@ -3335,7 +3348,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (ret)
goto err_unlocked;
- binder_lock(__func__);
+ binder_lock(context, __func__);
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
@@ -3386,7 +3399,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
- binder_unlock(__func__);
+ binder_unlock(context, __func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
@@ -3459,7 +3472,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
}
vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
- mutex_lock(&binder_mmap_lock);
+ mutex_lock(&proc->context->binder_mmap_lock);
if (proc->buffer) {
ret = -EBUSY;
failure_string = "already mapped";
@@ -3474,7 +3487,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
}
proc->buffer = area->addr;
proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
- mutex_unlock(&binder_mmap_lock);
+ mutex_unlock(&proc->context->binder_mmap_lock);
#ifdef CONFIG_CPU_CACHE_VIPT
if (cache_is_vipt_aliasing()) {
@@ -3523,12 +3536,12 @@ err_alloc_small_buf_failed:
kfree(proc->pages);
proc->pages = NULL;
err_alloc_pages_failed:
- mutex_lock(&binder_mmap_lock);
+ mutex_lock(&proc->context->binder_mmap_lock);
vfree(proc->buffer);
proc->buffer = NULL;
err_get_vm_area_failed:
err_already_mapped:
- mutex_unlock(&binder_mmap_lock);
+ mutex_unlock(&proc->context->binder_mmap_lock);
err_bad_arg:
pr_err("binder_mmap: %d %lx-%lx %s failed %d\n",
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
@@ -3555,15 +3568,15 @@ static int binder_open(struct inode *nodp, struct file *filp)
miscdev);
proc->context = &binder_dev->context;
- binder_lock(__func__);
+ binder_lock(proc->context, __func__);
binder_stats_created(BINDER_STAT_PROC);
- hlist_add_head(&proc->proc_node, &binder_procs);
+ hlist_add_head(&proc->proc_node, &proc->context->binder_procs);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
filp->private_data = proc;
- binder_unlock(__func__);
+ binder_unlock(proc->context, __func__);
if (binder_debugfs_dir_entry_proc) {
char strbuf[11];
@@ -3628,6 +3641,7 @@ static int binder_release(struct inode *nodp, struct file *filp)
static int binder_node_release(struct binder_node *node, int refs)
{
struct binder_ref *ref;
+ struct binder_context *context = node->proc->context;
int death = 0;
list_del_init(&node->work.entry);
@@ -3643,7 +3657,7 @@ static int binder_node_release(struct binder_node *node, int refs)
node->proc = NULL;
node->local_strong_refs = 0;
node->local_weak_refs = 0;
- hlist_add_head(&node->dead_node, &binder_dead_nodes);
+ hlist_add_head(&node->dead_node, &context->binder_dead_nodes);
hlist_for_each_entry(ref, &node->refs, node_entry) {
refs++;
@@ -3708,7 +3722,8 @@ static void binder_deferred_release(struct binder_proc *proc)
node = rb_entry(n, struct binder_node, rb_node);
nodes++;
rb_erase(&node->rb_node, &proc->nodes);
- incoming_refs = binder_node_release(node, incoming_refs);
+ incoming_refs = binder_node_release(node,
+ incoming_refs);
}
outgoing_refs = 0;
@@ -3780,18 +3795,20 @@ static void binder_deferred_func(struct work_struct *work)
{
struct binder_proc *proc;
struct files_struct *files;
+ struct binder_context *context =
+ container_of(work, struct binder_context, deferred_work);
int defer;
do {
trace_binder_lock(__func__);
- mutex_lock(&binder_main_lock);
+ mutex_lock(&context->binder_main_lock);
trace_binder_locked(__func__);
- mutex_lock(&binder_deferred_lock);
+ mutex_lock(&context->binder_deferred_lock);
preempt_disable();
- if (!hlist_empty(&binder_deferred_list)) {
- proc = hlist_entry(binder_deferred_list.first,
+ if (!hlist_empty(&context->binder_deferred_list)) {
+ proc = hlist_entry(context->binder_deferred_list.first,
struct binder_proc, deferred_work_node);
hlist_del_init(&proc->deferred_work_node);
defer = proc->deferred_work;
@@ -3800,7 +3817,7 @@ static void binder_deferred_func(struct work_struct *work)
proc = NULL;
defer = 0;
}
- mutex_unlock(&binder_deferred_lock);
+ mutex_unlock(&context->binder_deferred_lock);
files = NULL;
if (defer & BINDER_DEFERRED_PUT_FILES) {
@@ -3816,25 +3833,25 @@ static void binder_deferred_func(struct work_struct *work)
binder_deferred_release(proc); /* frees proc */
trace_binder_unlock(__func__);
- mutex_unlock(&binder_main_lock);
+ mutex_unlock(&context->binder_main_lock);
preempt_enable_no_resched();
if (files)
put_files_struct(files);
} while (proc);
}
-static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
static void
binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
{
- mutex_lock(&binder_deferred_lock);
+ mutex_lock(&proc->context->binder_deferred_lock);
proc->deferred_work |= defer;
if (hlist_unhashed(&proc->deferred_work_node)) {
hlist_add_head(&proc->deferred_work_node,
- &binder_deferred_list);
- queue_work(binder_deferred_workqueue, &binder_deferred_work);
+ &proc->context->binder_deferred_list);
+ queue_work(proc->context->binder_deferred_workqueue,
+ &proc->context->deferred_work);
}
- mutex_unlock(&binder_deferred_lock);
+ mutex_unlock(&proc->context->binder_deferred_lock);
}
static void print_binder_transaction(struct seq_file *m, const char *prefix,
@@ -4065,8 +4082,20 @@ static const char * const binder_objstat_strings[] = {
"transaction_complete"
};
+static void add_binder_stats(struct binder_stats *from, struct binder_stats *to)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(to->bc); i++)
+ to->bc[i] += from->bc[i];
+
+ for (i = 0; i < ARRAY_SIZE(to->br); i++)
+ to->br[i] += from->br[i];
+}
+
static void print_binder_stats(struct seq_file *m, const char *prefix,
- struct binder_stats *stats)
+ struct binder_stats *stats,
+ struct binder_obj_stats *obj_stats)
{
int i;
@@ -4086,16 +4115,21 @@ static void print_binder_stats(struct seq_file *m, const char *prefix,
binder_return_strings[i], stats->br[i]);
}
- BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
+ if (!obj_stats)
+ return;
+
+ BUILD_BUG_ON(ARRAY_SIZE(obj_stats->obj_created) !=
ARRAY_SIZE(binder_objstat_strings));
- BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
- ARRAY_SIZE(stats->obj_deleted));
- for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
- if (stats->obj_created[i] || stats->obj_deleted[i])
+ BUILD_BUG_ON(ARRAY_SIZE(obj_stats->obj_created) !=
+ ARRAY_SIZE(obj_stats->obj_deleted));
+ for (i = 0; i < ARRAY_SIZE(obj_stats->obj_created); i++) {
+ int obj_created = atomic_read(&obj_stats->obj_created[i]);
+ int obj_deleted = atomic_read(&obj_stats->obj_deleted[i]);
+
+ if (obj_created || obj_deleted)
seq_printf(m, "%s%s: active %d total %d\n", prefix,
- binder_objstat_strings[i],
- stats->obj_created[i] - stats->obj_deleted[i],
- stats->obj_created[i]);
+ binder_objstat_strings[i],
+ obj_created - obj_deleted, obj_created);
}
}
@@ -4150,85 +4184,131 @@ static void print_binder_proc_stats(struct seq_file *m,
}
seq_printf(m, " pending transactions: %d\n", count);
- print_binder_stats(m, " ", &proc->stats);
+ print_binder_stats(m, " ", &proc->stats, NULL);
}
static int binder_state_show(struct seq_file *m, void *unused)
{
+ struct binder_device *device;
+ struct binder_context *context;
struct binder_proc *proc;
struct binder_node *node;
int do_lock = !binder_debug_no_lock;
-
- if (do_lock)
- binder_lock(__func__);
+ bool wrote_dead_nodes_header = false;
seq_puts(m, "binder state:\n");
- if (!hlist_empty(&binder_dead_nodes))
- seq_puts(m, "dead nodes:\n");
- hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
- print_binder_node(m, node);
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
+ if (!wrote_dead_nodes_header &&
+ !hlist_empty(&context->binder_dead_nodes)) {
+ seq_puts(m, "dead nodes:\n");
+ wrote_dead_nodes_header = true;
+ }
+ hlist_for_each_entry(node, &context->binder_dead_nodes,
+ dead_node)
+ print_binder_node(m, node);
+
+ if (do_lock)
+ binder_unlock(context, __func__);
+ }
- hlist_for_each_entry(proc, &binder_procs, proc_node)
- print_binder_proc(m, proc, 1);
- if (do_lock)
- binder_unlock(__func__);
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
+
+ hlist_for_each_entry(proc, &context->binder_procs, proc_node)
+ print_binder_proc(m, proc, 1);
+ if (do_lock)
+ binder_unlock(context, __func__);
+ }
return 0;
}
static int binder_stats_show(struct seq_file *m, void *unused)
{
+ struct binder_device *device;
+ struct binder_context *context;
struct binder_proc *proc;
+ struct binder_stats total_binder_stats;
int do_lock = !binder_debug_no_lock;
- if (do_lock)
- binder_lock(__func__);
+ memset(&total_binder_stats, 0, sizeof(struct binder_stats));
+
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
+
+ add_binder_stats(&context->binder_stats, &total_binder_stats);
+
+ if (do_lock)
+ binder_unlock(context, __func__);
+ }
seq_puts(m, "binder stats:\n");
+ print_binder_stats(m, "", &total_binder_stats, &binder_obj_stats);
- print_binder_stats(m, "", &binder_stats);
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
- hlist_for_each_entry(proc, &binder_procs, proc_node)
- print_binder_proc_stats(m, proc);
- if (do_lock)
- binder_unlock(__func__);
+ hlist_for_each_entry(proc, &context->binder_procs, proc_node)
+ print_binder_proc_stats(m, proc);
+ if (do_lock)
+ binder_unlock(context, __func__);
+ }
return 0;
}
static int binder_transactions_show(struct seq_file *m, void *unused)
{
+ struct binder_device *device;
+ struct binder_context *context;
struct binder_proc *proc;
int do_lock = !binder_debug_no_lock;
- if (do_lock)
- binder_lock(__func__);
-
seq_puts(m, "binder transactions:\n");
- hlist_for_each_entry(proc, &binder_procs, proc_node)
- print_binder_proc(m, proc, 0);
- if (do_lock)
- binder_unlock(__func__);
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
+
+ hlist_for_each_entry(proc, &context->binder_procs, proc_node)
+ print_binder_proc(m, proc, 0);
+ if (do_lock)
+ binder_unlock(context, __func__);
+ }
return 0;
}
static int binder_proc_show(struct seq_file *m, void *unused)
{
+ struct binder_device *device;
+ struct binder_context *context;
struct binder_proc *itr;
int pid = (unsigned long)m->private;
int do_lock = !binder_debug_no_lock;
- if (do_lock)
- binder_lock(__func__);
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ if (do_lock)
+ binder_lock(context, __func__);
- hlist_for_each_entry(itr, &binder_procs, proc_node) {
- if (itr->pid == pid) {
- seq_puts(m, "binder proc state:\n");
- print_binder_proc(m, itr, 1);
+ hlist_for_each_entry(itr, &context->binder_procs, proc_node) {
+ if (itr->pid == pid) {
+ seq_puts(m, "binder proc state:\n");
+ print_binder_proc(m, itr, 1);
+ }
}
+ if (do_lock)
+ binder_unlock(context, __func__);
}
- if (do_lock)
- binder_unlock(__func__);
return 0;
}
@@ -4243,11 +4323,10 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
e->to_node, e->target_handle, e->data_size, e->offsets_size);
}
-static int binder_transaction_log_show(struct seq_file *m, void *unused)
+static int print_binder_transaction_log(struct seq_file *m,
+ struct binder_transaction_log *log)
{
- struct binder_transaction_log *log = m->private;
int i;
-
if (log->full) {
for (i = log->next; i < ARRAY_SIZE(log->entry); i++)
print_binder_transaction_log_entry(m, &log->entry[i]);
@@ -4257,6 +4336,31 @@ static int binder_transaction_log_show(struct seq_file *m, void *unused)
return 0;
}
+static int binder_transaction_log_show(struct seq_file *m, void *unused)
+{
+ struct binder_device *device;
+ struct binder_context *context;
+
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ print_binder_transaction_log(m, &context->transaction_log);
+ }
+ return 0;
+}
+
+static int binder_failed_transaction_log_show(struct seq_file *m, void *unused)
+{
+ struct binder_device *device;
+ struct binder_context *context;
+
+ hlist_for_each_entry(device, &binder_devices, hlist) {
+ context = &device->context;
+ print_binder_transaction_log(m,
+ &context->transaction_log_failed);
+ }
+ return 0;
+}
+
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
@@ -4272,11 +4376,20 @@ BINDER_DEBUG_ENTRY(state);
BINDER_DEBUG_ENTRY(stats);
BINDER_DEBUG_ENTRY(transactions);
BINDER_DEBUG_ENTRY(transaction_log);
+BINDER_DEBUG_ENTRY(failed_transaction_log);
+
+static void __init free_binder_device(struct binder_device *device)
+{
+ if (device->context.binder_deferred_workqueue)
+ destroy_workqueue(device->context.binder_deferred_workqueue);
+ kfree(device);
+}
static int __init init_binder_device(const char *name)
{
int ret;
struct binder_device *binder_device;
+ struct binder_context *context;
binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
if (!binder_device)
@@ -4286,31 +4399,65 @@ static int __init init_binder_device(const char *name)
binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
binder_device->miscdev.name = name;
- binder_device->context.binder_context_mgr_uid = INVALID_UID;
- binder_device->context.name = name;
+ context = &binder_device->context;
+ context->binder_context_mgr_uid = INVALID_UID;
+ context->name = name;
+
+ mutex_init(&context->binder_main_lock);
+ mutex_init(&context->binder_deferred_lock);
+ mutex_init(&context->binder_mmap_lock);
+
+ context->binder_deferred_workqueue =
+ create_singlethread_workqueue(name);
+
+ if (!context->binder_deferred_workqueue) {
+ ret = -ENOMEM;
+ goto err_create_singlethread_workqueue_failed;
+ }
+
+ INIT_HLIST_HEAD(&context->binder_procs);
+ INIT_HLIST_HEAD(&context->binder_dead_nodes);
+ INIT_HLIST_HEAD(&context->binder_deferred_list);
+ INIT_WORK(&context->deferred_work, binder_deferred_func);
ret = misc_register(&binder_device->miscdev);
if (ret < 0) {
- kfree(binder_device);
- return ret;
+ goto err_misc_register_failed;
}
hlist_add_head(&binder_device->hlist, &binder_devices);
+ return ret;
+
+err_create_singlethread_workqueue_failed:
+err_misc_register_failed:
+ free_binder_device(binder_device);
return ret;
}
static int __init binder_init(void)
{
- int ret;
+ int ret = 0;
char *device_name, *device_names;
struct binder_device *device;
struct hlist_node *tmp;
- binder_deferred_workqueue = create_singlethread_workqueue("binder");
- if (!binder_deferred_workqueue)
+ /*
+ * Copy the module_parameter string, because we don't want to
+ * tokenize it in-place.
+ */
+ device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
+ if (!device_names)
return -ENOMEM;
+ strcpy(device_names, binder_devices_param);
+
+ while ((device_name = strsep(&device_names, ","))) {
+ ret = init_binder_device(device_name);
+ if (ret)
+ goto err_init_binder_device_failed;
+ }
+
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
if (binder_debugfs_dir_entry_root)
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
@@ -4335,30 +4482,13 @@ static int __init binder_init(void)
debugfs_create_file("transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
- &binder_transaction_log,
+ NULL,
&binder_transaction_log_fops);
debugfs_create_file("failed_transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
- &binder_transaction_log_failed,
- &binder_transaction_log_fops);
- }
-
- /*
- * Copy the module_parameter string, because we don't want to
- * tokenize it in-place.
- */
- device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
- if (!device_names) {
- ret = -ENOMEM;
- goto err_alloc_device_names_failed;
- }
- strcpy(device_names, binder_devices_param);
-
- while ((device_name = strsep(&device_names, ","))) {
- ret = init_binder_device(device_name);
- if (ret)
- goto err_init_binder_device_failed;
+ NULL,
+ &binder_failed_transaction_log_fops);
}
return ret;
@@ -4367,12 +4497,8 @@ err_init_binder_device_failed:
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
misc_deregister(&device->miscdev);
hlist_del(&device->hlist);
- kfree(device);
+ free_binder_device(device);
}
-err_alloc_device_names_failed:
- debugfs_remove_recursive(binder_debugfs_dir_entry_root);
-
- destroy_workqueue(binder_deferred_workqueue);
return ret;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ebbe31fee7ae..8e3bff9c7fe9 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -607,7 +607,7 @@ source "drivers/char/xillybus/Kconfig"
config MSM_ADSPRPC
tristate "QTI ADSP RPC driver"
- depends on MSM_GLINK
+ depends on MSM_SMD
help
Provides a communication mechanism that allows for clients to
make remote method invocations across processor boundary to
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 479599473381..10c4d8ce2410 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -25,6 +25,7 @@
#include <linux/hash.h>
#include <linux/msm_ion.h>
#include <soc/qcom/secure_buffer.h>
+#include <soc/qcom/smd.h>
#include <soc/qcom/glink.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
@@ -213,6 +214,7 @@ struct fastrpc_channel_ctx {
struct completion work;
struct notifier_block nb;
struct kref kref;
+ int channel;
int sesscount;
int ssrcount;
void *handle;
@@ -238,6 +240,7 @@ struct fastrpc_apps {
spinlock_t hlock;
struct ion_client *client;
struct device *dev;
+ bool glink;
};
struct fastrpc_mmap {
@@ -298,18 +301,21 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
{
.name = "adsprpc-smd",
.subsys = "adsp",
+ .channel = SMD_APPS_QDSP,
.link.link_info.edge = "lpass",
.link.link_info.transport = "smem",
},
{
.name = "mdsprpc-smd",
.subsys = "modem",
+ .channel = SMD_APPS_MODEM,
.link.link_info.edge = "mpss",
.link.link_info.transport = "smem",
},
{
.name = "sdsprpc-smd",
.subsys = "slpi",
+ .channel = SMD_APPS_DSPS,
.link.link_info.edge = "dsps",
.link.link_info.transport = "smem",
.vmid = VMID_SSC_Q6,
@@ -1382,7 +1388,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
struct smq_msg *msg = &ctx->msg;
struct fastrpc_file *fl = ctx->fl;
struct fastrpc_channel_ctx *channel_ctx = &fl->apps->channel[fl->cid];
- int err = 0;
+ int err = 0, len;
VERIFY(err, 0 != channel_ctx->chan);
if (err)
@@ -1397,21 +1403,64 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0;
msg->invoke.page.size = buf_page_size(ctx->used);
- if (fl->ssrcount != channel_ctx->ssrcount) {
- err = -ECONNRESET;
- goto bail;
+ if (fl->apps->glink) {
+ if (fl->ssrcount != channel_ctx->ssrcount) {
+ err = -ECONNRESET;
+ goto bail;
+ }
+ VERIFY(err, channel_ctx->link.port_state ==
+ FASTRPC_LINK_CONNECTED);
+ if (err)
+ goto bail;
+ err = glink_tx(channel_ctx->chan,
+ (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg),
+ GLINK_TX_REQ_INTENT);
+ } else {
+ spin_lock(&fl->apps->hlock);
+ len = smd_write((smd_channel_t *)
+ channel_ctx->chan,
+ msg, sizeof(*msg));
+ spin_unlock(&fl->apps->hlock);
+ VERIFY(err, len == sizeof(*msg));
}
- VERIFY(err, channel_ctx->link.port_state ==
- FASTRPC_LINK_CONNECTED);
- if (err)
- goto bail;
- err = glink_tx(channel_ctx->chan,
- (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg),
- GLINK_TX_REQ_INTENT);
bail:
return err;
}
+static void fastrpc_smd_read_handler(int cid)
+{
+ struct fastrpc_apps *me = &gfa;
+ struct smq_invoke_rsp rsp = {0};
+ int ret = 0;
+
+ do {
+ ret = smd_read_from_cb(me->channel[cid].chan, &rsp,
+ sizeof(rsp));
+ if (ret != sizeof(rsp))
+ break;
+ rsp.ctx = rsp.ctx & ~1;
+ context_notify_user(uint64_to_ptr(rsp.ctx), rsp.retval);
+ } while (ret == sizeof(rsp));
+}
+
+static void smd_event_handler(void *priv, unsigned event)
+{
+ struct fastrpc_apps *me = &gfa;
+ int cid = (int)(uintptr_t)priv;
+
+ switch (event) {
+ case SMD_EVENT_OPEN:
+ complete(&me->channel[cid].work);
+ break;
+ case SMD_EVENT_CLOSE:
+ fastrpc_notify_drivers(me, cid);
+ break;
+ case SMD_EVENT_DATA:
+ fastrpc_smd_read_handler(cid);
+ break;
+ }
+}
+
static void fastrpc_init(struct fastrpc_apps *me)
{
int i;
@@ -1987,10 +2036,12 @@ static void fastrpc_channel_close(struct kref *kref)
ctx = container_of(kref, struct fastrpc_channel_ctx, kref);
cid = ctx - &gcinfo[0];
- fastrpc_glink_close(ctx->chan, cid);
+ if (!me->glink)
+ smd_close(ctx->chan);
+ else
+ fastrpc_glink_close(ctx->chan, cid);
+
ctx->chan = 0;
- glink_unregister_link_state_cb(ctx->link.link_notify_handle);
- ctx->link.link_notify_handle = 0;
mutex_unlock(&me->smd_mutex);
pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
MAJOR(me->dev_no), cid);
@@ -2405,8 +2456,16 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
fl->ssrcount = me->channel[cid].ssrcount;
if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
(me->channel[cid].chan == 0)) {
- fastrpc_glink_register(cid, me);
- VERIFY(err, 0 == fastrpc_glink_open(cid));
+ if (me->glink) {
+ fastrpc_glink_register(cid, me);
+ VERIFY(err, 0 == fastrpc_glink_open(cid));
+ } else {
+ VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID,
+ gcinfo[cid].channel,
+ (smd_channel_t **)&me->channel[cid].chan,
+ (void *)(uintptr_t)cid,
+ smd_event_handler));
+ }
if (err)
goto bail;
@@ -2635,7 +2694,11 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
ctx->ssrcount++;
ctx->issubsystemup = 0;
if (ctx->chan) {
- fastrpc_glink_close(ctx->chan, cid);
+ if (me->glink)
+ fastrpc_glink_close(ctx->chan, cid);
+ else
+ smd_close(ctx->chan);
+
ctx->chan = 0;
pr_info("'restart notifier: closed /dev/%s c %d %d'\n",
gcinfo[cid].name, MAJOR(me->dev_no), cid);
@@ -2859,7 +2922,7 @@ static int fastrpc_probe(struct platform_device *pdev)
}
return 0;
}
-
+ me->glink = of_property_read_bool(dev->of_node, "qcom,fastrpc-glink");
VERIFY(err, !of_platform_populate(pdev->dev.of_node,
fastrpc_match_table,
NULL, &pdev->dev));
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 4b5db01dbdf3..aaa587975469 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -991,6 +991,21 @@ static void __diag_fwd_open(struct diagfwd_info *fwd_info)
if (!fwd_info->inited)
return;
+ /*
+ * Logging mode here is reflecting previous mode
+ * status and will be updated to new mode later.
+ *
+ * Keeping the buffers busy for Memory Device Mode.
+ */
+
+ if ((driver->logging_mode != DIAG_USB_MODE) ||
+ driver->usb_connected) {
+ if (fwd_info->buf_1)
+ atomic_set(&fwd_info->buf_1->in_busy, 0);
+ if (fwd_info->buf_2)
+ atomic_set(&fwd_info->buf_2->in_busy, 0);
+ }
+
if (fwd_info->p_ops && fwd_info->p_ops->open)
fwd_info->p_ops->open(fwd_info->ctxt);
@@ -1151,11 +1166,13 @@ void diagfwd_write_done(uint8_t peripheral, uint8_t type, int ctxt)
return;
fwd_info = &peripheral_info[type][peripheral];
- if (ctxt == 1 && fwd_info->buf_1)
+ if (ctxt == 1 && fwd_info->buf_1) {
atomic_set(&fwd_info->buf_1->in_busy, 0);
- else if (ctxt == 2 && fwd_info->buf_2)
+ driver->cpd_len_1 = 0;
+ } else if (ctxt == 2 && fwd_info->buf_2) {
atomic_set(&fwd_info->buf_2->in_busy, 0);
- else if (ctxt == 3 && fwd_info->buf_upd_1_a) {
+ driver->cpd_len_2 = 0;
+ } else if (ctxt == 3 && fwd_info->buf_upd_1_a) {
atomic_set(&fwd_info->buf_upd_1_a->in_busy, 0);
if (driver->cpd_len_1 == 0)
atomic_set(&fwd_info->buf_1->in_busy, 0);
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index ce67145bb142..37535a72e066 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -72,6 +72,8 @@ enum debug_event {
CLUSTER_ENTER,
CLUSTER_EXIT,
PRE_PC_CB,
+ CPU_HP_STARTING,
+ CPU_HP_DYING,
};
struct lpm_debug {
@@ -341,10 +343,16 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb,
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_DYING:
+ update_debug_pc_event(CPU_HP_DYING, cpu,
+ cluster->num_children_in_sync.bits[0],
+ cluster->child_cpus.bits[0], false);
cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu),
NR_LPM_LEVELS, false, 0);
break;
case CPU_STARTING:
+ update_debug_pc_event(CPU_HP_STARTING, cpu,
+ cluster->num_children_in_sync.bits[0],
+ cluster->child_cpus.bits[0], false);
cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu),
NR_LPM_LEVELS, false, 0);
break;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1de8e212a703..986026aa1b66 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -260,9 +260,12 @@ kgsl_mem_entry_create(void)
{
struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (entry != NULL)
+ if (entry != NULL) {
kref_init(&entry->refcount);
+ /* put this ref in the caller functions after init */
+ kref_get(&entry->refcount);
+ }
return entry;
}
#ifdef CONFIG_DMA_SHARED_BUFFER
@@ -1764,9 +1767,9 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv,
/* Commit the pointer to the context in context_idr */
write_lock(&device->context_lock);
idr_replace(&device->context_idr, context, context->id);
+ param->drawctxt_id = context->id;
write_unlock(&device->context_lock);
- param->drawctxt_id = context->id;
done:
return result;
}
@@ -2399,6 +2402,9 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
trace_kgsl_mem_map(entry, fd);
kgsl_mem_entry_commit_process(entry);
+
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
return 0;
unmap:
@@ -2705,6 +2711,9 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
trace_kgsl_mem_map(entry, param->fd);
kgsl_mem_entry_commit_process(entry);
+
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
return result;
error_attach:
@@ -3143,6 +3152,9 @@ long kgsl_ioctl_gpuobj_alloc(struct kgsl_device_private *dev_priv,
param->mmapsize = kgsl_memdesc_footprint(&entry->memdesc);
param->id = entry->id;
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+
return 0;
}
@@ -3166,6 +3178,9 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
param->size = (size_t) entry->memdesc.size;
param->flags = (unsigned int) entry->memdesc.flags;
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+
return 0;
}
@@ -3189,6 +3204,9 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
param->mmapsize = (size_t) kgsl_memdesc_footprint(&entry->memdesc);
param->gpuaddr = (unsigned long) entry->memdesc.gpuaddr;
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+
return 0;
}
@@ -3306,6 +3324,9 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
trace_sparse_phys_alloc(entry->id, param->size, param->pagesize);
kgsl_mem_entry_commit_process(entry);
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+
return 0;
err_invalid_pages:
@@ -3385,6 +3406,9 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
trace_sparse_virt_alloc(entry->id, param->size, param->pagesize);
kgsl_mem_entry_commit_process(entry);
+ /* put the extra refcount for kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+
return 0;
}
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 1df5d8812991..6d2e7a569044 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -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
@@ -47,6 +47,8 @@ struct hbtp_data {
struct input_dev *input_dev;
s32 count;
struct mutex mutex;
+ struct mutex sensormutex;
+ struct hbtp_sensor_data *sensor_data;
bool touch_status[HBTP_MAX_FINGER];
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
@@ -87,10 +89,14 @@ struct hbtp_data {
u32 power_on_delay;
u32 power_off_delay;
bool manage_pin_ctrl;
+ s16 ROI[MAX_ROI_SIZE];
+ s16 accelBuffer[MAX_ACCEL_SIZE];
};
static struct hbtp_data *hbtp;
+static struct kobject *sensor_kobject;
+
#if defined(CONFIG_FB)
static int hbtp_fb_suspend(struct hbtp_data *ts);
static int hbtp_fb_early_resume(struct hbtp_data *ts);
@@ -150,6 +156,46 @@ static int fb_notifier_callback(struct notifier_block *self,
}
#endif
+static ssize_t hbtp_sensor_roi_show(struct file *dev, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t pos,
+ size_t size) {
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(buf, hbtp->ROI, size);
+ mutex_unlock(&hbtp->sensormutex);
+
+ return size;
+}
+
+static ssize_t hbtp_sensor_vib_show(struct file *dev, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t pos,
+ size_t size) {
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(buf, hbtp->accelBuffer, size);
+ mutex_unlock(&hbtp->sensormutex);
+
+ return size;
+}
+
+static struct bin_attribute capdata_attr = {
+ .attr = {
+ .name = "capdata",
+ .mode = S_IRUGO,
+ },
+ .size = 1024,
+ .read = hbtp_sensor_roi_show,
+ .write = NULL,
+};
+
+static struct bin_attribute vibdata_attr = {
+ .attr = {
+ .name = "vib_data",
+ .mode = S_IRUGO,
+ },
+ .size = MAX_ACCEL_SIZE*sizeof(int16_t),
+ .read = hbtp_sensor_vib_show,
+ .write = NULL,
+};
+
static int hbtp_input_open(struct inode *inode, struct file *file)
{
mutex_lock(&hbtp->mutex);
@@ -748,6 +794,22 @@ static long hbtp_input_ioctl_handler(struct file *file, unsigned int cmd,
return -EINVAL;
}
break;
+
+ case HBTP_SET_SENSORDATA:
+ if (copy_from_user(hbtp->sensor_data, (void *)arg,
+ sizeof(struct hbtp_sensor_data))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(hbtp->ROI, hbtp->sensor_data->ROI, sizeof(hbtp->ROI));
+ memcpy(hbtp->accelBuffer, hbtp->sensor_data->accelBuffer,
+ sizeof(hbtp->accelBuffer));
+ mutex_unlock(&hbtp->sensormutex);
+
+ error = 0;
+ break;
+
default:
pr_err("%s: Unsupported ioctl command %u\n", __func__, cmd);
error = -EINVAL;
@@ -1358,7 +1420,13 @@ static int __init hbtp_init(void)
if (!hbtp)
return -ENOMEM;
+ hbtp->sensor_data = kzalloc(sizeof(struct hbtp_sensor_data),
+ GFP_KERNEL);
+ if (!hbtp->sensor_data)
+ goto err_sensordata;
+
mutex_init(&hbtp->mutex);
+ mutex_init(&hbtp->sensormutex);
error = misc_register(&hbtp_input_misc);
if (error) {
@@ -1376,6 +1444,28 @@ static int __init hbtp_init(void)
}
#endif
+ sensor_kobject = kobject_create_and_add("hbtpsensor", kernel_kobj);
+ if (!sensor_kobject) {
+ pr_err("%s: Could not create hbtpsensor kobject\n", __func__);
+ goto err_kobject_create;
+ }
+
+ error = sysfs_create_bin_file(sensor_kobject, &capdata_attr);
+ if (error < 0) {
+ pr_err("%s: hbtp capdata sysfs creation failed: %d\n", __func__,
+ error);
+ goto err_sysfs_create_capdata;
+ }
+ pr_debug("capdata sysfs creation success\n");
+
+ error = sysfs_create_bin_file(sensor_kobject, &vibdata_attr);
+ if (error < 0) {
+ pr_err("%s: vibdata sysfs creation failed: %d\n", __func__,
+ error);
+ goto err_sysfs_create_vibdata;
+ }
+ pr_debug("vibdata sysfs creation success\n");
+
error = platform_driver_register(&hbtp_pdev_driver);
if (error) {
pr_err("Failed to register platform driver: %d\n", error);
@@ -1385,12 +1475,20 @@ static int __init hbtp_init(void)
return 0;
err_platform_drv_reg:
+ sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+err_sysfs_create_vibdata:
+ sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+err_sysfs_create_capdata:
+ kobject_put(sensor_kobject);
+err_kobject_create:
#if defined(CONFIG_FB)
fb_unregister_client(&hbtp->fb_notif);
err_fb_reg:
#endif
misc_deregister(&hbtp_input_misc);
err_misc_reg:
+ kfree(hbtp->sensor_data);
+err_sensordata:
kfree(hbtp);
return error;
@@ -1398,6 +1496,9 @@ err_misc_reg:
static void __exit hbtp_exit(void)
{
+ sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+ sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+ kobject_put(sensor_kobject);
misc_deregister(&hbtp_input_misc);
if (hbtp->input_dev)
input_unregister_device(hbtp->input_dev);
@@ -1408,6 +1509,7 @@ static void __exit hbtp_exit(void)
platform_driver_unregister(&hbtp_pdev_driver);
+ kfree(hbtp->sensor_data);
kfree(hbtp);
}
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 139a4c9b49ee..b283f6277b87 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -497,6 +497,7 @@ struct msm_vfe_src_info {
enum msm_vfe_dual_hw_type dual_hw_type;
struct msm_vfe_dual_hw_ms_info dual_hw_ms_info;
bool accept_frame;
+ uint32_t lpm;
};
struct msm_vfe_fetch_engine_info {
@@ -599,7 +600,7 @@ struct msm_vfe_tasklet_queue_cmd {
struct vfe_device *vfe_dev;
};
-#define MSM_VFE_TASKLETQ_SIZE 200
+#define MSM_VFE_TASKLETQ_SIZE 400
enum msm_vfe_overflow_state {
NO_OVERFLOW,
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 ebd3a32281d7..dce474e40470 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
@@ -2421,6 +2421,7 @@ 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;
+ uint32_t intf;
unsigned long flags;
struct msm_vfe_axi_stream *stream_info;
struct msm_vfe_dual_lpm_mode *ab_ib_vote = NULL;
@@ -2436,7 +2437,13 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
stream_info =
msm_isp_get_stream_common_data(vfe_dev,
ab_ib_vote->stream_src[i]);
+ if (stream_info == NULL)
+ continue;
+ /* loop all stream on current session */
spin_lock_irqsave(&stream_info->lock, flags);
+ intf = SRC_TO_INTF(stream_info->stream_src);
+ vfe_dev->axi_data.src_info[intf].lpm =
+ ab_ib_vote->lpm_mode;
if (stream_info->state == ACTIVE) {
vfe_idx =
msm_isp_get_vfe_idx_for_stream(vfe_dev,
@@ -2457,7 +2464,12 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
stream_info =
msm_isp_get_stream_common_data(vfe_dev,
ab_ib_vote->stream_src[i]);
+ if (stream_info == NULL)
+ continue;
spin_lock_irqsave(&stream_info->lock, flags);
+ intf = SRC_TO_INTF(stream_info->stream_src);
+ vfe_dev->axi_data.src_info[intf].lpm =
+ ab_ib_vote->lpm_mode;
if (stream_info->state == PAUSED) {
vfe_idx =
msm_isp_get_vfe_idx_for_stream(vfe_dev,
@@ -2883,7 +2895,9 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
* those state transitions instead of directly forcing stream to
* be INACTIVE
*/
- if (stream_info->state != PAUSED) {
+ intf = SRC_TO_INTF(stream_info->stream_src);
+ if ((!vfe_dev->axi_data.src_info[intf].lpm) ||
+ stream_info->state != PAUSED) {
while (stream_info->state != ACTIVE)
__msm_isp_axi_stream_update(stream_info,
&timestamp);
@@ -2900,10 +2914,12 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.axi_ops.
clear_wm_irq_mask(vfe_dev, stream_info);
}
- if (stream_info->state == ACTIVE) {
+ if (stream_info->state == ACTIVE &&
+ !vfe_dev->axi_data.src_info[intf].lpm) {
init_completion(&stream_info->inactive_comp);
stream_info->state = STOP_PENDING;
- } else if (stream_info->state == PAUSED) {
+ } else if (vfe_dev->axi_data.src_info[intf].lpm ||
+ stream_info->state == PAUSED) {
/* don't wait for reg update */
stream_info->state = STOP_PENDING;
msm_isp_axi_stream_enable_cfg(stream_info);
@@ -3018,6 +3034,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
int k;
struct vfe_device *vfe_dev;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev_ioctl->axi_data;
+ uint32_t intf;
if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM)
return -EINVAL;
@@ -3081,7 +3098,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
cfg_wm_irq_mask(vfe_dev, stream_info);
}
}
-
+ intf = SRC_TO_INTF(stream_info->stream_src);
init_completion(&stream_info->active_comp);
stream_info->state = START_PENDING;
msm_isp_update_intf_stream_cnt(stream_info, 1);
@@ -3091,6 +3108,11 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
vfe_dev_ioctl->pdev->id);
if (src_state) {
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
+ if (vfe_dev_ioctl->axi_data.src_info[intf].lpm) {
+ while (stream_info->state != ACTIVE)
+ __msm_isp_axi_stream_update(
+ stream_info, &timestamp);
+ }
} else {
for (k = 0; k < stream_info->num_isp; k++) {
vfe_dev = stream_info->vfe_dev[k];
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 765bf6521759..e7be914ca267 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
@@ -2070,6 +2070,7 @@ static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
if (queue_cmd->cmd_used) {
pr_err("%s: Tasklet queue overflow: %d\n",
__func__, vfe_dev->pdev->id);
+ spin_unlock_irqrestore(&tasklet->tasklet_lock, flags);
return;
} else {
atomic_add(1, &vfe_dev->irq_cnt);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 41d8ef577a27..caf6639f5151 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -49,17 +49,31 @@
#define ISPIF_TIMEOUT_ALL_US 1000000
#define ISPIF_SOF_DEBUG_COUNT 5
+/* 3D Threshold value according guidelines for line width 1280 */
+#define STEREO_DEFAULT_3D_THRESHOLD 0x36
+
+/*
+ * Overflows before restarting interface during stereo usecase
+ * to give some tolerance for cases when the two sensors sync fails
+ * this value is chosen by experiment
+ */
+#define MAX_PIX_OVERFLOW_ERROR_COUNT 10
+static int pix_overflow_error_count[VFE_MAX] = { 0 };
+
#undef CDBG
#ifdef CONFIG_MSMB_CAMERA_DEBUG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#else
-#define CDBG(fmt, args...) do { } while (0)
+#define CDBG(fmt, args...)
#endif
static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable);
static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
static long msm_ispif_subdev_ioctl_unlocked(struct v4l2_subdev *sd,
unsigned int cmd, void *arg);
+static long msm_ispif_dispatch_cmd(enum ispif_cfg_type_t cmd,
+ struct ispif_device *ispif,
+ struct msm_ispif_param_data_ext *params);
int msm_ispif_get_clk_info(struct ispif_device *ispif_dev,
struct platform_device *pdev);
@@ -249,16 +263,7 @@ static long msm_ispif_cmd_ext(struct v4l2_subdev *sd,
}
mutex_lock(&ispif->mutex);
- switch (pcdata.cfg_type) {
- case ISPIF_CFG2:
- rc = msm_ispif_config2(ispif, params);
- msm_ispif_io_dump_reg(ispif);
- break;
- default:
- pr_err("%s: invalid cfg_type\n", __func__);
- rc = -EINVAL;
- break;
- }
+ rc = msm_ispif_dispatch_cmd(pcdata.cfg_type, ispif, params);
mutex_unlock(&ispif->mutex);
kfree(params);
return rc;
@@ -855,15 +860,34 @@ static uint16_t msm_ispif_get_cids_mask_from_cfg(
return cids_mask;
}
+
+static uint16_t msm_ispif_get_right_cids_mask_from_cfg(
+ struct msm_ispif_right_param_entry *entry, int num_cids)
+{
+ int i;
+ uint16_t cids_mask = 0;
+
+ if (WARN_ON(!entry))
+ return cids_mask;
+
+ for (i = 0; i < num_cids && i < MAX_CID_CH_PARAM_ENTRY; i++) {
+ if (entry->cids[i] < CID_MAX)
+ cids_mask |= (1 << entry->cids[i]);
+ }
+
+ return cids_mask;
+}
+
static int msm_ispif_config(struct ispif_device *ispif,
void *data)
{
int rc = 0, i = 0;
- uint16_t cid_mask;
+ uint16_t cid_mask = 0;
+ uint16_t cid_right_mask = 0;
enum msm_ispif_intftype intftype;
enum msm_ispif_vfe_intf vfe_intf;
- struct msm_ispif_param_data *params =
- (struct msm_ispif_param_data *)data;
+ struct msm_ispif_param_data_ext *params =
+ (struct msm_ispif_param_data_ext *)data;
BUG_ON(!ispif);
BUG_ON(!params);
@@ -913,9 +937,15 @@ static int msm_ispif_config(struct ispif_device *ispif,
return -EINVAL;
}
- if (ispif->csid_version >= CSID_VERSION_V30)
+ if (ispif->csid_version >= CSID_VERSION_V30) {
msm_ispif_select_clk_mux(ispif, intftype,
params->entries[i].csid, vfe_intf);
+ if (intftype == PIX0 && params->stereo_enable &&
+ params->right_entries[i].csid < CSID_MAX)
+ msm_ispif_select_clk_mux(ispif, PIX1,
+ params->right_entries[i].csid,
+ vfe_intf);
+ }
rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf);
if (rc) {
@@ -926,10 +956,26 @@ static int msm_ispif_config(struct ispif_device *ispif,
msm_ispif_sel_csid_core(ispif, intftype,
params->entries[i].csid, vfe_intf);
+ if (intftype == PIX0 && params->stereo_enable &&
+ params->right_entries[i].csid < CSID_MAX)
+ /* configure right stereo csid */
+ msm_ispif_sel_csid_core(ispif, PIX1,
+ params->right_entries[i].csid, vfe_intf);
+
cid_mask = msm_ispif_get_cids_mask_from_cfg(
&params->entries[i]);
msm_ispif_enable_intf_cids(ispif, intftype,
cid_mask, vfe_intf, 1);
+ if (params->stereo_enable)
+ cid_right_mask = msm_ispif_get_right_cids_mask_from_cfg(
+ &params->right_entries[i],
+ params->entries[i].num_cids);
+ else
+ cid_right_mask = 0;
+ if (cid_right_mask && params->stereo_enable)
+ /* configure right stereo cids */
+ msm_ispif_enable_intf_cids(ispif, PIX1,
+ cid_right_mask, vfe_intf, 1);
if (params->entries[i].crop_enable)
msm_ispif_enable_crop(ispif, intftype, vfe_intf,
params->entries[i].crop_start_pixel,
@@ -962,8 +1008,28 @@ static int msm_ispif_config(struct ispif_device *ispif,
return rc;
}
+static void msm_ispif_config_stereo(struct ispif_device *ispif,
+ struct msm_ispif_param_data_ext *params) {
+
+ int i;
+ enum msm_ispif_vfe_intf vfe_intf;
+
+ for (i = 0; i < params->num; i++) {
+ if (params->entries[i].intftype == PIX0 &&
+ params->stereo_enable &&
+ params->right_entries[i].csid < CSID_MAX) {
+ vfe_intf = params->entries[i].vfe_intf;
+ msm_camera_io_w_mb(0x3,
+ ispif->base + ISPIF_VFE_m_OUTPUT_SEL(vfe_intf));
+ msm_camera_io_w_mb(STEREO_DEFAULT_3D_THRESHOLD,
+ ispif->base +
+ ISPIF_VFE_m_3D_THRESHOLD(vfe_intf));
+ }
+ }
+}
+
static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits,
- struct msm_ispif_param_data *params)
+ struct msm_ispif_param_data_ext *params)
{
uint8_t vc;
int i, k;
@@ -1008,6 +1074,19 @@ static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits,
ispif->applied_intf_cmd[vfe_intf].intf_cmd |=
(cmd_bits << (vc * 2 + intf_type * 8));
}
+ if (intf_type == PIX0 && params->stereo_enable &&
+ params->right_entries[i].cids[k] < CID_MAX) {
+ cid = params->right_entries[i].cids[k];
+ vc = cid / 4;
+
+ /* fill right stereo command */
+ /* zero 2 bits */
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd &=
+ ~(0x3 << (vc * 2 + PIX1 * 8));
+ /* set cmd bits */
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd |=
+ (cmd_bits << (vc * 2 + PIX1 * 8));
+ }
}
/* cmd for PIX0, PIX1, RDI0, RDI1 */
if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF)
@@ -1024,7 +1103,7 @@ static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits,
}
static int msm_ispif_stop_immediately(struct ispif_device *ispif,
- struct msm_ispif_param_data *params)
+ struct msm_ispif_param_data_ext *params)
{
int i, rc = 0;
uint16_t cid_mask = 0;
@@ -1052,13 +1131,22 @@ static int msm_ispif_stop_immediately(struct ispif_device *ispif,
&params->entries[i]);
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
cid_mask, params->entries[i].vfe_intf, 0);
+ if (params->stereo_enable) {
+ cid_mask = msm_ispif_get_right_cids_mask_from_cfg(
+ &params->right_entries[i],
+ params->entries[i].num_cids);
+ if (cid_mask)
+ msm_ispif_enable_intf_cids(ispif,
+ params->entries[i].intftype, cid_mask,
+ params->entries[i].vfe_intf, 0);
+ }
}
return rc;
}
static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
- struct msm_ispif_param_data *params)
+ struct msm_ispif_param_data_ext *params)
{
int rc = 0;
@@ -1074,13 +1162,14 @@ static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
rc = -EINVAL;
return rc;
}
+ msm_ispif_config_stereo(ispif, params);
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
return rc;
}
static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
- struct msm_ispif_param_data *params)
+ struct msm_ispif_param_data_ext *params)
{
int rc = 0, i;
long timeout = 0;
@@ -1222,10 +1311,11 @@ end:
}
static int msm_ispif_stop_frame_boundary(struct ispif_device *ispif,
- struct msm_ispif_param_data *params)
+ struct msm_ispif_param_data_ext *params)
{
int i, rc = 0;
uint16_t cid_mask = 0;
+ uint16_t cid_right_mask = 0;
uint32_t intf_addr;
enum msm_ispif_vfe_intf vfe_intf;
uint32_t stop_flag = 0;
@@ -1263,6 +1353,13 @@ static int msm_ispif_stop_frame_boundary(struct ispif_device *ispif,
for (i = 0; i < params->num; i++) {
cid_mask =
msm_ispif_get_cids_mask_from_cfg(&params->entries[i]);
+ if (params->stereo_enable)
+ cid_right_mask =
+ msm_ispif_get_right_cids_mask_from_cfg(
+ &params->right_entries[i],
+ params->entries[i].num_cids);
+ else
+ cid_right_mask = 0;
vfe_intf = params->entries[i].vfe_intf;
switch (params->entries[i].intftype) {
@@ -1294,10 +1391,24 @@ static int msm_ispif_stop_frame_boundary(struct ispif_device *ispif,
ISPIF_TIMEOUT_ALL_US);
if (rc < 0)
goto end;
+ if (cid_right_mask) {
+ intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1);
+ rc = readl_poll_timeout(ispif->base + intf_addr,
+ stop_flag,
+ (stop_flag & 0xF) == 0xF,
+ ISPIF_TIMEOUT_SLEEP_US,
+ ISPIF_TIMEOUT_ALL_US);
+ if (rc < 0)
+ goto end;
+ }
/* disable CIDs in CID_MASK register */
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
cid_mask, vfe_intf, 0);
+ if (cid_right_mask)
+ msm_ispif_enable_intf_cids(ispif,
+ params->entries[i].intftype, cid_right_mask,
+ params->entries[i].vfe_intf, 0);
}
end:
@@ -1318,6 +1429,14 @@ static void ispif_process_irq(struct ispif_device *ispif,
ispif->sof_count[vfe_id].sof_cnt[PIX0]++;
ispif->ispif_sof_debug++;
}
+ if (out[vfe_id].ispifIrqStatus1 &
+ ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
+ if (ispif->ispif_sof_debug < ISPIF_SOF_DEBUG_COUNT*2)
+ pr_err("%s: PIX1 frame id: %u\n", __func__,
+ ispif->sof_count[vfe_id].sof_cnt[PIX1]);
+ ispif->sof_count[vfe_id].sof_cnt[PIX1]++;
+ ispif->ispif_sof_debug++;
+ }
if (out[vfe_id].ispifIrqStatus0 &
ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
if (ispif->ispif_rdi0_debug < ISPIF_SOF_DEBUG_COUNT)
@@ -1344,12 +1463,55 @@ static void ispif_process_irq(struct ispif_device *ispif,
}
}
+static int msm_ispif_reconfig_3d_output(struct ispif_device *ispif,
+ enum msm_ispif_vfe_intf vfe_id)
+{
+ uint32_t reg_data;
+
+ if (WARN_ON(!ispif))
+ return -EINVAL;
+
+ if (!((vfe_id == VFE0) || (vfe_id == VFE1))) {
+ pr_err("%s;%d Cannot reconfigure 3D mode for VFE%d", __func__,
+ __LINE__, vfe_id);
+ return -EINVAL;
+ }
+ pr_info("%s;%d Reconfiguring 3D mode for VFE%d", __func__, __LINE__,
+ vfe_id);
+ reg_data = 0xFFFCFFFC;
+ msm_camera_io_w_mb(reg_data, ispif->base +
+ ISPIF_VFE_m_INTF_CMD_0(vfe_id));
+ msm_camera_io_w_mb(reg_data, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+
+ if (vfe_id == VFE0) {
+ reg_data = 0;
+ reg_data |= (PIX_0_VFE_RST_STB | PIX_1_VFE_RST_STB |
+ STROBED_RST_EN | PIX_0_CSID_RST_STB |
+ PIX_1_CSID_RST_STB | PIX_OUTPUT_0_MISR_RST_STB);
+ msm_camera_io_w_mb(reg_data, ispif->base + ISPIF_RST_CMD_ADDR);
+ } else {
+ reg_data = 0;
+ reg_data |= (PIX_0_VFE_RST_STB | PIX_1_VFE_RST_STB |
+ STROBED_RST_EN | PIX_0_CSID_RST_STB |
+ PIX_1_CSID_RST_STB | PIX_OUTPUT_0_MISR_RST_STB);
+ msm_camera_io_w_mb(reg_data, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
+ }
+
+ reg_data = 0xFFFDFFFD;
+ msm_camera_io_w_mb(reg_data, ispif->base +
+ ISPIF_VFE_m_INTF_CMD_0(vfe_id));
+ return 0;
+}
+
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
void *data)
{
struct ispif_device *ispif = (struct ispif_device *)data;
bool fatal_err = false;
int i = 0;
+ uint32_t reg_data;
BUG_ON(!ispif);
BUG_ON(!out);
@@ -1400,6 +1562,12 @@ static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
fatal_err = true;
}
+ if (out[VFE0].ispifIrqStatus1 & PIX_INTF_1_OVERFLOW_IRQ) {
+ pr_err_ratelimited("%s: VFE0 pix1 overflow.\n",
+ __func__);
+ fatal_err = true;
+ }
+
if (out[VFE0].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ) {
pr_err_ratelimited("%s: VFE0 rdi0 overflow.\n",
__func__);
@@ -1432,6 +1600,12 @@ static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
fatal_err = true;
}
+ if (out[VFE1].ispifIrqStatus1 & PIX_INTF_1_OVERFLOW_IRQ) {
+ pr_err_ratelimited("%s: VFE1 pix1 overflow.\n",
+ __func__);
+ fatal_err = true;
+ }
+
if (out[VFE1].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ) {
pr_err_ratelimited("%s: VFE1 rdi0 overflow.\n",
__func__);
@@ -1453,6 +1627,43 @@ static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
ispif_process_irq(ispif, out, VFE1);
}
+ if ((out[VFE0].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ) ||
+ (out[VFE0].ispifIrqStatus1 & PIX_INTF_0_OVERFLOW_IRQ) ||
+ (out[VFE0].ispifIrqStatus2 & (L_R_SOF_MISMATCH_ERR_IRQ |
+ L_R_EOF_MISMATCH_ERR_IRQ | L_R_SOL_MISMATCH_ERR_IRQ))) {
+ reg_data = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_OUTPUT_SEL(VFE0));
+ if ((reg_data & 0x03) == VFE_PIX_INTF_SEL_3D) {
+ pix_overflow_error_count[VFE0]++;
+ if (pix_overflow_error_count[VFE0] >=
+ MAX_PIX_OVERFLOW_ERROR_COUNT) {
+ msm_ispif_reconfig_3d_output(ispif, VFE0);
+ pix_overflow_error_count[VFE0] = 0;
+ }
+ fatal_err = false;
+ }
+ }
+
+ if (ispif->vfe_info.num_vfe > 1) {
+ if ((out[VFE1].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ) ||
+ (out[VFE1].ispifIrqStatus1 & PIX_INTF_0_OVERFLOW_IRQ) ||
+ (out[VFE1].ispifIrqStatus2 & (L_R_SOF_MISMATCH_ERR_IRQ |
+ L_R_EOF_MISMATCH_ERR_IRQ | L_R_SOL_MISMATCH_ERR_IRQ))) {
+ reg_data = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_OUTPUT_SEL(VFE1));
+ if ((reg_data & 0x03) == VFE_PIX_INTF_SEL_3D) {
+ pix_overflow_error_count[VFE1]++;
+ if (pix_overflow_error_count[VFE1] >=
+ MAX_PIX_OVERFLOW_ERROR_COUNT) {
+ msm_ispif_reconfig_3d_output(ispif,
+ VFE1);
+ pix_overflow_error_count[VFE1] = 0;
+ }
+ }
+ fatal_err = false;
+ }
+ }
+
if (fatal_err == true) {
pr_err_ratelimited("%s: fatal error, stop ispif immediately\n",
__func__);
@@ -1561,61 +1772,97 @@ static void msm_ispif_release(struct ispif_device *ispif)
pr_err("%s: failed to remove vote for AHB\n", __func__);
}
-static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
+static long msm_ispif_dispatch_cmd(enum ispif_cfg_type_t cmd,
+ struct ispif_device *ispif,
+ struct msm_ispif_param_data_ext *params)
{
long rc = 0;
- struct ispif_cfg_data *pcdata = (struct ispif_cfg_data *)arg;
- struct ispif_device *ispif =
- (struct ispif_device *)v4l2_get_subdevdata(sd);
-
- BUG_ON(!sd);
- BUG_ON(!pcdata);
- mutex_lock(&ispif->mutex);
- switch (pcdata->cfg_type) {
- case ISPIF_ENABLE_REG_DUMP:
- ispif->enb_dump_reg = pcdata->reg_dump; /* save dump config */
- break;
- case ISPIF_INIT:
- rc = msm_ispif_init(ispif, pcdata->csid_version);
- msm_ispif_io_dump_reg(ispif);
- break;
+ switch (cmd) {
case ISPIF_CFG:
- rc = msm_ispif_config(ispif, &pcdata->params);
+ rc = msm_ispif_config(ispif, params);
msm_ispif_io_dump_reg(ispif);
break;
case ISPIF_START_FRAME_BOUNDARY:
- rc = msm_ispif_start_frame_boundary(ispif, &pcdata->params);
+ rc = msm_ispif_start_frame_boundary(ispif, params);
msm_ispif_io_dump_reg(ispif);
break;
case ISPIF_RESTART_FRAME_BOUNDARY:
- rc = msm_ispif_restart_frame_boundary(ispif, &pcdata->params);
+ rc = msm_ispif_restart_frame_boundary(ispif, params);
msm_ispif_io_dump_reg(ispif);
break;
-
case ISPIF_STOP_FRAME_BOUNDARY:
- rc = msm_ispif_stop_frame_boundary(ispif, &pcdata->params);
+ rc = msm_ispif_stop_frame_boundary(ispif, params);
msm_ispif_io_dump_reg(ispif);
break;
case ISPIF_STOP_IMMEDIATELY:
- rc = msm_ispif_stop_immediately(ispif, &pcdata->params);
+ rc = msm_ispif_stop_immediately(ispif, params);
msm_ispif_io_dump_reg(ispif);
break;
case ISPIF_RELEASE:
msm_ispif_reset(ispif);
msm_ispif_reset_hw(ispif);
break;
- case ISPIF_SET_VFE_INFO:
- rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info);
+ case ISPIF_CFG2:
+ rc = msm_ispif_config2(ispif, params);
+ msm_ispif_io_dump_reg(ispif);
break;
default:
pr_err("%s: invalid cfg_type\n", __func__);
rc = -EINVAL;
break;
}
+ return rc;
+}
+
+static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
+{
+ long rc = 0;
+ struct ispif_cfg_data *pcdata = (struct ispif_cfg_data *)arg;
+ struct ispif_device *ispif =
+ (struct ispif_device *)v4l2_get_subdevdata(sd);
+ int i;
+ struct msm_ispif_param_data_ext params;
+
+ if (WARN_ON(!sd) || WARN_ON(!pcdata))
+ return -EINVAL;
+
+ mutex_lock(&ispif->mutex);
+ switch (pcdata->cfg_type) {
+ case ISPIF_ENABLE_REG_DUMP:
+ /* save dump config */
+ ispif->enb_dump_reg = pcdata->reg_dump;
+ break;
+ case ISPIF_INIT:
+ rc = msm_ispif_init(ispif, pcdata->csid_version);
+ msm_ispif_io_dump_reg(ispif);
+ break;
+ case ISPIF_SET_VFE_INFO:
+ rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info);
+ break;
+ default:
+ memset(&params, 0, sizeof(params));
+ if (pcdata->params.num > MAX_PARAM_ENTRIES) {
+ pr_err("%s: invalid num entries %u\n", __func__,
+ pcdata->params.num);
+ rc = -EINVAL;
+ } else {
+ params.num = pcdata->params.num;
+ for (i = 0; i < pcdata->params.num; i++)
+ memcpy(&params.entries[i],
+ &pcdata->params.entries[i],
+ sizeof(struct msm_ispif_params_entry));
+ params.stereo_enable = 0;
+ rc = msm_ispif_dispatch_cmd(pcdata->cfg_type, ispif,
+ &params);
+ }
+ break;
+ }
mutex_unlock(&ispif->mutex);
+
return rc;
}
+
static struct v4l2_file_operations msm_ispif_v4l2_subdev_fops;
static long msm_ispif_subdev_ioctl_unlocked(struct v4l2_subdev *sd,
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index d488ca618537..49d7d0f7624e 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -87,6 +87,12 @@
#define MISC_LOGIC_RST_STB BIT(1)
#define STROBED_RST_EN BIT(0)
+#define VFE_PIX_INTF_SEL_3D 0x3
+#define PIX_OUTPUT_0_MISR_RST_STB BIT(16)
+#define L_R_SOF_MISMATCH_ERR_IRQ BIT(16)
+#define L_R_EOF_MISMATCH_ERR_IRQ BIT(17)
+#define L_R_SOL_MISMATCH_ERR_IRQ BIT(18)
+
#define ISPIF_RST_CMD_MASK 0xFE1C77FF
#define ISPIF_RST_CMD_1_MASK 0xFFFFFFFF /* undefined */
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 8ae61dc2d4f6..9abf55efc46c 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -22,6 +22,7 @@
#define ISPIF_VFE(m) ((m) * 0x200)
#define ISPIF_VFE_m_CTRL_0(m) (0x200 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_CTRL_1(m) (0x204 + ISPIF_VFE(m))
#define ISPIF_VFE_m_IRQ_MASK_0(m) (0x208 + ISPIF_VFE(m))
#define ISPIF_VFE_m_IRQ_MASK_1(m) (0x20C + ISPIF_VFE(m))
#define ISPIF_VFE_m_IRQ_MASK_2(m) (0x210 + ISPIF_VFE(m))
@@ -71,6 +72,12 @@
#define MISC_LOGIC_RST_STB BIT(1)
#define STROBED_RST_EN BIT(0)
+#define VFE_PIX_INTF_SEL_3D 0x3
+#define PIX_OUTPUT_0_MISR_RST_STB BIT(16)
+#define L_R_SOF_MISMATCH_ERR_IRQ BIT(16)
+#define L_R_EOF_MISMATCH_ERR_IRQ BIT(17)
+#define L_R_SOL_MISMATCH_ERR_IRQ BIT(18)
+
#define ISPIF_RST_CMD_MASK 0xFE0F1FFF
#define ISPIF_RST_CMD_1_MASK 0xFC0F1FF9
@@ -78,6 +85,7 @@
#define ISPIF_RST_CMD_1_MASK_RESTART 0x00001FF9
#define PIX_INTF_0_OVERFLOW_IRQ BIT(12)
+#define PIX_INTF_1_OVERFLOW_IRQ BIT(12)
#define RAW_INTF_0_OVERFLOW_IRQ BIT(25)
#define RAW_INTF_1_OVERFLOW_IRQ BIT(25)
#define RAW_INTF_2_OVERFLOW_IRQ BIT(12)
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v3.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v3.h
index 94cc974441ee..5f2aa06f3e13 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v3.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v3.h
@@ -74,6 +74,12 @@
#define MISC_LOGIC_RST_STB BIT(1)
#define STROBED_RST_EN BIT(0)
+#define VFE_PIX_INTF_SEL_3D 0x3
+#define PIX_OUTPUT_0_MISR_RST_STB BIT(16)
+#define L_R_SOF_MISMATCH_ERR_IRQ BIT(16)
+#define L_R_EOF_MISMATCH_ERR_IRQ BIT(17)
+#define L_R_SOL_MISMATCH_ERR_IRQ BIT(18)
+
#define ISPIF_RST_CMD_MASK 0xFE7F1FFF
#define ISPIF_RST_CMD_1_MASK 0xFC7F1FF9
@@ -81,6 +87,7 @@
#define ISPIF_RST_CMD_1_MASK_RESTART 0x7F1FF9
#define PIX_INTF_0_OVERFLOW_IRQ BIT(12)
+#define PIX_INTF_1_OVERFLOW_IRQ BIT(12)
#define RAW_INTF_0_OVERFLOW_IRQ BIT(25)
#define RAW_INTF_1_OVERFLOW_IRQ BIT(25)
#define RAW_INTF_2_OVERFLOW_IRQ BIT(12)
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 55a743737c59..7ae071176ef4 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -227,16 +227,34 @@ static void msm_csid_set_sof_freeze_debug_reg(
static int msm_csid_reset(struct csid_device *csid_dev)
{
int32_t rc = 0;
+ uint32_t irq = 0, irq_bitshift;
+
+ irq_bitshift = csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift;
msm_camera_io_w(csid_dev->ctrl_reg->csid_reg.csid_rst_stb_all,
csid_dev->base +
csid_dev->ctrl_reg->csid_reg.csid_rst_cmd_addr);
rc = wait_for_completion_timeout(&csid_dev->reset_complete,
CSID_TIMEOUT);
- if (rc <= 0) {
+ if (rc < 0) {
pr_err("wait_for_completion in msm_csid_reset fail rc = %d\n",
rc);
+ } else if (rc == 0) {
+ irq = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
+ pr_err_ratelimited("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
+ __func__, csid_dev->pdev->id, irq);
+ if (irq & (0x1 << irq_bitshift)) {
+ rc = 1;
+ CDBG("%s succeeded", __func__);
+ } else {
+ rc = 0;
+ pr_err("%s reset csid_irq_status failed = 0x%x\n",
+ __func__, irq);
+ }
if (rc == 0)
rc = -ETIMEDOUT;
+ } else {
+ CDBG("%s succeeded", __func__);
}
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
index 5d57ec8c28ff..8f55f453bf03 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
@@ -89,6 +89,7 @@ struct msm_sensor_ctrl_t {
uint32_t set_mclk_23880000;
uint8_t is_csid_tg_mode;
uint32_t is_secure;
+ uint8_t bypass_video_node_creation;
};
int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index 1dd2b0d26007..344f1a6f8d92 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -86,11 +86,14 @@ static int32_t msm_sensor_driver_create_i2c_v4l_subdev
struct i2c_client *client = s_ctrl->sensor_i2c_client->client;
CDBG("%s %s I2c probe succeeded\n", __func__, client->name);
- rc = camera_init_v4l2(&client->dev, &session_id);
- if (rc < 0) {
- pr_err("failed: camera_init_i2c_v4l2 rc %d", rc);
- return rc;
+ if (s_ctrl->bypass_video_node_creation == 0) {
+ rc = camera_init_v4l2(&client->dev, &session_id);
+ if (rc < 0) {
+ pr_err("failed: camera_init_i2c_v4l2 rc %d", rc);
+ return rc;
+ }
}
+
CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
snprintf(s_ctrl->msm_sd.sd.name,
sizeof(s_ctrl->msm_sd.sd.name), "%s",
@@ -123,11 +126,14 @@ static int32_t msm_sensor_driver_create_v4l_subdev
int32_t rc = 0;
uint32_t session_id = 0;
- rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
- if (rc < 0) {
- pr_err("failed: camera_init_v4l2 rc %d", rc);
- return rc;
+ if (s_ctrl->bypass_video_node_creation == 0) {
+ rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
+ if (rc < 0) {
+ pr_err("failed: camera_init_v4l2 rc %d", rc);
+ return rc;
+ }
}
+
CDBG("rc %d session_id %d", rc, session_id);
s_ctrl->sensordata->sensor_info->session_id = session_id;
@@ -773,6 +779,8 @@ int32_t msm_sensor_driver_probe(void *setting,
slave_info32->sensor_init_params;
slave_info->output_format =
slave_info32->output_format;
+ slave_info->bypass_video_node_creation =
+ !!slave_info32->bypass_video_node_creation;
kfree(slave_info32);
} else
#endif
@@ -800,7 +808,8 @@ int32_t msm_sensor_driver_probe(void *setting,
slave_info->sensor_init_params.position);
CDBG("mount %d",
slave_info->sensor_init_params.sensor_mount_angle);
-
+ CDBG("bypass video node creation %d",
+ slave_info->bypass_video_node_creation);
/* Validate camera id */
if (slave_info->camera_id >= MAX_CAMERAS) {
pr_err("failed: invalid camera id %d max %d",
@@ -980,6 +989,9 @@ CSID_TG:
*/
s_ctrl->is_probe_succeed = 1;
+ s_ctrl->bypass_video_node_creation =
+ slave_info->bypass_video_node_creation;
+
/*
* Create /dev/videoX node, comment for now until dummy /dev/videoX
* node is created and used by HAL
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index c3a0cfb390c4..34ec6529d8ae 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1245,6 +1245,33 @@ static int sde_hw_rotator_swts_create(struct sde_hw_rotator *rot)
goto err_detach;
}
+ ion_free(rot->iclient, handle);
+
+ sde_smmu_ctrl(0);
+
+ return rc;
+err_detach:
+ dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment);
+err_put:
+ dma_buf_put(data->srcp_dma_buf);
+ data->srcp_dma_buf = NULL;
+imap_err:
+ ion_free(rot->iclient, handle);
+
+ return rc;
+}
+
+/*
+ * sde_hw_rotator_swts_map - map software timestamp buffer
+ * @rot: Pointer to rotator hw
+ *
+ */
+static int sde_hw_rotator_swts_map(struct sde_hw_rotator *rot)
+{
+ int rc = 0;
+ struct sde_mdp_img_data *data = &rot->swts_buf;
+
+ sde_smmu_ctrl(1);
rc = sde_smmu_map_dma_buf(data->srcp_dma_buf, data->srcp_table,
SDE_IOMMU_DOMAIN_ROT_UNSECURE, &data->addr,
&data->len, DMA_BIDIRECTIONAL);
@@ -1264,35 +1291,25 @@ static int sde_hw_rotator_swts_create(struct sde_hw_rotator *rot)
data->mapped = true;
SDEROT_DBG("swts buffer mapped: %pad/%lx va:%p\n", &data->addr,
- data->len, rot->swts_buffer);
-
- ion_free(rot->iclient, handle);
-
+ data->len, rot->swts_buffer);
sde_smmu_ctrl(0);
-
return rc;
+
kmap_err:
sde_smmu_unmap_dma_buf(data->srcp_table, SDE_IOMMU_DOMAIN_ROT_UNSECURE,
DMA_FROM_DEVICE, data->srcp_dma_buf);
err_unmap:
dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table,
DMA_FROM_DEVICE);
-err_detach:
- dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment);
-err_put:
- dma_buf_put(data->srcp_dma_buf);
- data->srcp_dma_buf = NULL;
-imap_err:
- ion_free(rot->iclient, handle);
return rc;
}
/*
- * sde_hw_rotator_swtc_destroy - destroy software timestamp buffer
+ * sde_hw_rotator_swtc_unmap - unmap software timestamp buffer
* @rot: Pointer to rotator hw
*/
-static void sde_hw_rotator_swtc_destroy(struct sde_hw_rotator *rot)
+static void sde_hw_rotator_swtc_unmap(struct sde_hw_rotator *rot)
{
struct sde_mdp_img_data *data;
@@ -1301,9 +1318,29 @@ static void sde_hw_rotator_swtc_destroy(struct sde_hw_rotator *rot)
dma_buf_end_cpu_access(data->srcp_dma_buf, 0, data->len,
DMA_FROM_DEVICE);
dma_buf_kunmap(data->srcp_dma_buf, 0, rot->swts_buffer);
+ rot->swts_buffer = NULL;
sde_smmu_unmap_dma_buf(data->srcp_table, SDE_IOMMU_DOMAIN_ROT_UNSECURE,
DMA_FROM_DEVICE, data->srcp_dma_buf);
+ data->addr = 0x0;
+ data->len = 0;
+
+ data->mapped = false;
+}
+
+/*
+ * sde_hw_rotator_swtc_destroy - destroy software timestamp buffer
+ * @rot: Pointer to rotator hw
+ */
+static void sde_hw_rotator_swtc_destroy(struct sde_hw_rotator *rot)
+{
+ struct sde_mdp_img_data *data;
+
+ data = &rot->swts_buf;
+
+ if (data->mapped)
+ sde_hw_rotator_swtc_unmap(rot);
+
dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table,
DMA_FROM_DEVICE);
dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment);
@@ -1436,6 +1473,7 @@ static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext(
struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id)
{
struct sde_hw_rotator_resource_info *resinfo;
+ int ret = 0;
if (!mgr || !mgr->hw_data) {
SDEROT_ERR("null parameters\n");
@@ -1463,8 +1501,21 @@ static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext(
else {
resinfo->hw.max_active = SDE_HW_ROT_REGDMA_TOTAL_CTX - 1;
- if (resinfo->rot->iclient == NULL)
- sde_hw_rotator_swts_create(resinfo->rot);
+ if (resinfo->rot->iclient == NULL) {
+ ret = sde_hw_rotator_swts_create(resinfo->rot);
+ if (ret) {
+ SDEROT_ERR("swts buffer create failed\n");
+ goto swts_fail;
+ }
+ }
+
+ if (resinfo->rot->swts_buf.mapped == false) {
+ ret = sde_hw_rotator_swts_map(resinfo->rot);
+ if (ret) {
+ SDEROT_ERR("swts buffer map failed\n");
+ goto swts_fail;
+ }
+ }
}
if (resinfo->rot->irq_num >= 0)
@@ -1474,6 +1525,10 @@ static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext(
resinfo, wb_id);
return &resinfo->hw;
+
+swts_fail:
+ devm_kfree(&mgr->pdev->dev, resinfo);
+ return NULL;
}
/*
@@ -1485,6 +1540,7 @@ static void sde_hw_rotator_free_ext(struct sde_rot_mgr *mgr,
struct sde_rot_hw_resource *hw)
{
struct sde_hw_rotator_resource_info *resinfo;
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
if (!mgr || !mgr->hw_data)
return;
@@ -1499,6 +1555,18 @@ static void sde_hw_rotator_free_ext(struct sde_rot_mgr *mgr,
if (resinfo->rot->irq_num >= 0)
sde_hw_rotator_disable_irq(resinfo->rot);
+ /*
+ * For SDM660 and SDM630, the IOMMU is shared between MDP and rotator.
+ * If IOMMU is detached from MDP driver, the timestamp buffer will be
+ * invalidated. It is safer to unmap the timestamp buffer when the
+ * rotator session ends, so that it will be mapped again when a fresh
+ * session starts.
+ */
+ if (((mdata->mdss_version == MDSS_MDP_HW_REV_320) ||
+ (mdata->mdss_version == MDSS_MDP_HW_REV_330)) &&
+ resinfo->rot->swts_buf.mapped)
+ sde_hw_rotator_swtc_unmap(resinfo->rot);
+
devm_kfree(&mgr->pdev->dev, resinfo);
}
diff --git a/drivers/mfd/wcd934x-regmap.c b/drivers/mfd/wcd934x-regmap.c
index e8ba1495de2b..27249eeec013 100644
--- a/drivers/mfd/wcd934x-regmap.c
+++ b/drivers/mfd/wcd934x-regmap.c
@@ -1937,7 +1937,6 @@ static bool wcd934x_is_volatile_register(struct device *dev, unsigned int reg)
case WCD934X_BIAS_VBG_FINE_ADJ:
case WCD934X_CODEC_CPR_SVS_CX_VDD:
case WCD934X_CODEC_CPR_SVS2_CX_VDD:
- case WCD934X_CDC_TOP_TOP_CFG1:
case WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL:
return true;
}
diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c
index 3bb95f50bc13..52f7d3d2f268 100644
--- a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c
+++ b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -179,7 +179,7 @@ static const int s_button_map[] = {
};
/* The opened devices container */
-static int s_opened_devs[MAX_DEVS_NUMBER];
+static atomic_t s_opened_devs[MAX_DEVS_NUMBER];
static struct wakeup_source usf_wakeup_source;
@@ -2338,14 +2338,11 @@ static uint16_t add_opened_dev(int minor)
uint16_t ind = 0;
for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
- if (minor == s_opened_devs[ind]) {
+ if (minor == atomic_cmpxchg(&s_opened_devs[ind], 0, minor)) {
pr_err("%s: device %d is already opened\n",
__func__, minor);
return USF_UNDEF_DEV_ID;
- }
-
- if (s_opened_devs[ind] == 0) {
- s_opened_devs[ind] = minor;
+ } else {
pr_debug("%s: device %d is added; ind=%d\n",
__func__, minor, ind);
return ind;
@@ -2401,7 +2398,7 @@ static int usf_release(struct inode *inode, struct file *file)
usf_disable(&usf->usf_tx);
usf_disable(&usf->usf_rx);
- s_opened_devs[usf->dev_ind] = 0;
+ atomic_set(&s_opened_devs[usf->dev_ind], 0);
wakeup_source_trash(&usf_wakeup_source);
mutex_unlock(&usf->mutex);
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index f172671cb00f..84a9b1a9577c 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -854,7 +854,6 @@ int ath10k_snoc_start_qmi_service(struct ath10k *ar)
goto out_destroy_wq;
}
- atomic_set(&qmi_cfg->fw_ready, 1);
ath10k_dbg(ar, ATH10K_DBG_SNOC, "QMI service started successfully\n");
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h
index c8bc26bb96b2..29ad5acdf414 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.h
+++ b/drivers/net/wireless/ath/ath10k/qmi.h
@@ -18,7 +18,7 @@
#define ATH10K_SNOC_WLAN_FW_READY_TIMEOUT 8000
#define WLFW_SERVICE_INS_ID_V01 0
-#define WLFW_CLIENT_ID 0x4b4e454c
+#define WLFW_CLIENT_ID 0x41544851
#define WLFW_TIMEOUT_MS 20000
enum ath10k_snoc_driver_event_type {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index add0a7cd9edb..2cbc8ee9abf9 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -650,6 +650,9 @@ static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
if (!ar_snoc)
return -EINVAL;
+ if (atomic_read(&ar_snoc->fw_crashed))
+ return -ESHUTDOWN;
+
snoc_pipe = &ar_snoc->pipe_info[pipe_id];
ce_pipe = snoc_pipe->ce_hdl;
src_ring = ce_pipe->src_ring;
diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
index e93416ebd343..09c37c2383c6 100644
--- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
+++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
@@ -181,7 +181,6 @@ void *wcnss_prealloc_get(unsigned int size)
pr_err("wcnss: %s: prealloc not available for size: %d\n",
__func__, size);
- WARN_ON(1);
return NULL;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index c8ff06ddda87..14735787cb9c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -3430,6 +3430,7 @@ static void ipa3_gsi_poll_after_suspend(struct ipa3_ep_context *ep)
/* queue a work to start polling if don't have one */
atomic_set(&ipa3_ctx->transport_pm.eot_activity, 1);
if (!atomic_read(&ep->sys->curr_polling_state)) {
+ ipa3_inc_acquire_wakelock();
atomic_set(&ep->sys->curr_polling_state, 1);
queue_work(ep->sys->wq, &ep->sys->work);
}
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 81e656c06da0..c7d6937bcc49 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -244,6 +244,8 @@ struct smb_dt_props {
int boost_threshold_ua;
int fv_uv;
int wipower_max_uw;
+ int min_freq_khz;
+ int max_freq_khz;
u32 step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
struct device_node *revid_dev_node;
@@ -338,6 +340,18 @@ static int smb2_parse_dt(struct smb2 *chip)
if (rc < 0)
chip->dt.boost_threshold_ua = MICRO_P1A;
+ rc = of_property_read_u32(node,
+ "qcom,min-freq-khz",
+ &chip->dt.min_freq_khz);
+ if (rc < 0)
+ chip->dt.min_freq_khz = -EINVAL;
+
+ rc = of_property_read_u32(node,
+ "qcom,max-freq-khz",
+ &chip->dt.max_freq_khz);
+ if (rc < 0)
+ chip->dt.max_freq_khz = -EINVAL;
+
rc = of_property_read_u32(node, "qcom,wipower-max-uw",
&chip->dt.wipower_max_uw);
if (rc < 0)
@@ -1438,6 +1452,16 @@ static int smb2_init_hw(struct smb2 *chip)
smblib_get_charge_param(chg, &chg->param.dc_icl,
&chip->dt.dc_icl_ua);
+ if (chip->dt.min_freq_khz > 0) {
+ chg->param.freq_buck.min_u = chip->dt.min_freq_khz;
+ chg->param.freq_boost.min_u = chip->dt.min_freq_khz;
+ }
+
+ if (chip->dt.max_freq_khz > 0) {
+ chg->param.freq_buck.max_u = chip->dt.max_freq_khz;
+ chg->param.freq_boost.max_u = chip->dt.max_freq_khz;
+ }
+
/* set a slower soft start setting for OTG */
rc = smblib_masked_write(chg, DC_ENG_SSUPPLY_CFG2_REG,
ENG_SSUPPLY_IVREF_OTG_SS_MASK, OTG_SS_SLOW);
@@ -2022,6 +2046,16 @@ static int smb2_request_interrupts(struct smb2 *chip)
return rc;
}
+static void smb2_disable_interrupts(struct smb_charger *chg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
+ if (smb2_irqs[i].irq > 0)
+ disable_irq(smb2_irqs[i].irq);
+ }
+}
+
#if defined(CONFIG_DEBUG_FS)
static int force_batt_psy_update_write(void *data, u64 val)
@@ -2284,6 +2318,9 @@ static void smb2_shutdown(struct platform_device *pdev)
struct smb2 *chip = platform_get_drvdata(pdev);
struct smb_charger *chg = &chip->chg;
+ /* disable all interrupts */
+ smb2_disable_interrupts(chg);
+
/* configure power role for UFP */
smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 14e9c3a2254d..e4ab41b1f16a 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -685,6 +685,7 @@ static void smblib_uusb_removal(struct smb_charger *chg)
chg->voltage_max_uv = MICRO_5V;
chg->usb_icl_delta_ua = 0;
chg->pulse_cnt = 0;
+ chg->uusb_apsd_rerun_done = false;
/* clear USB ICL vote for USB_PSY_VOTER */
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
@@ -752,6 +753,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg)
rc);
}
+ chg->uusb_apsd_rerun_done = true;
smblib_rerun_apsd(chg);
return 0;
@@ -3482,6 +3484,17 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
}
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
+ if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
+ && !chg->uusb_apsd_rerun_done) {
+ /*
+ * Force re-run APSD to handle slow insertion related
+ * charger-mis-detection.
+ */
+ chg->uusb_apsd_rerun_done = true;
+ smblib_rerun_apsd(chg);
+ return IRQ_HANDLED;
+ }
+
smblib_handle_apsd_done(chg,
(bool)(stat & APSD_DTC_STATUS_DONE_BIT));
@@ -3578,6 +3591,8 @@ static void typec_source_insertion(struct smb_charger *chg)
&& !is_client_vote_enabled(chg->usb_icl_votable, PD_VOTER)
&& !is_client_vote_enabled(chg->usb_icl_votable, USB_PSY_VOTER))
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
+
+ smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_5V);
}
static void typec_sink_insertion(struct smb_charger *chg)
@@ -3653,8 +3668,8 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg,
typec_source_removal(chg);
typec_sink_insertion(chg);
} else {
- typec_source_insertion(chg);
typec_sink_removal(chg);
+ typec_source_insertion(chg);
}
rp = smblib_get_prop_ufp_mode(chg);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 49b9d3da783c..4b277c4282cf 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -312,6 +312,7 @@ struct smb_charger {
int vconn_attempts;
int default_icl_ua;
int otg_cl_ua;
+ bool uusb_apsd_rerun_done;
/* workaround flag */
u32 wa_flags;
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index 3a6d84140bc9..8a2be787b70e 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -114,7 +114,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
{
int rc = 0, retries = 0;
void *pkt_data = NULL;
- struct apr_tx_buf *tx_buf;
+ struct apr_tx_buf *tx_buf = NULL;
struct apr_pkt_priv *pkt_priv_ptr = pkt_priv;
if (!apr_ch->handle || !pkt_priv)
diff --git a/drivers/soc/qcom/qdsp6v2/audio_notifier.c b/drivers/soc/qcom/qdsp6v2/audio_notifier.c
index a59b436234c7..b46cd2067441 100644
--- a/drivers/soc/qcom/qdsp6v2/audio_notifier.c
+++ b/drivers/soc/qcom/qdsp6v2/audio_notifier.c
@@ -510,7 +510,7 @@ int audio_notifier_deregister(char *client_name)
int ret = 0;
int ret2;
struct list_head *ptr, *next;
- struct client_data *client_data;
+ struct client_data *client_data = NULL;
if (client_name == NULL) {
pr_err("%s: client_name is NULL\n", __func__);
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index f2784dedbc7a..e792c953f31f 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -108,9 +108,7 @@ static struct glink_apps_rpm_data *glink_data;
#define RPM_DATA_LEN_SIZE 16
#define RPM_HDR_SIZE ((rpm_msg_fmt_ver == RPM_MSG_V0_FMT) ?\
sizeof(struct rpm_v0_hdr) : sizeof(struct rpm_v1_hdr))
-#define GET_FIELD(offset, size) (((1U << (offset + size)) - 1) - \
- ((1U << offset) - 1))
-#define CLEAR_FIELD(offset, size) (~GET_FIELD(offset, size))
+#define CLEAR_FIELD(offset, size) (~GENMASK(offset + size - 1, offset))
static ATOMIC_NOTIFIER_HEAD(msm_rpm_sleep_notifier);
static bool standalone;
@@ -223,7 +221,7 @@ static uint32_t msm_rpm_get_next_msg_id(void);
static inline uint32_t get_offset_value(uint32_t val, uint32_t offset,
uint32_t size)
{
- return (((val) & GET_FIELD(offset, size))
+ return (((val) & GENMASK(offset + size - 1, offset))
>> offset);
}
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 0625f75de373..97cd11201262 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -24,7 +24,6 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
-#include <linux/debugfs.h>
#include <soc/qcom/msm_qmi_interface.h>
#include <soc/qcom/service-locator.h>
@@ -440,140 +439,3 @@ int find_subsys(const char *pd_path, char *subsys)
return 0;
}
EXPORT_SYMBOL(find_subsys);
-
-static struct pd_qmi_client_data test_data;
-
-static int servloc_test_pdr_cb(struct notifier_block *this,
- unsigned long opcode, void *ptr)
-{
- int i, rc = 0;
- char subsys[QMI_SERVREG_LOC_NAME_LENGTH_V01];
- struct pd_qmi_client_data *return_data;
-
- return_data = (struct pd_qmi_client_data *)ptr;
-
- if (opcode) {
- pr_err("%s: Failed to get process domain!, opcode = %lu\n",
- __func__, opcode);
- return -EIO;
- }
-
- pr_err("Service Name: %s\tTotal Domains: %d\n",
- return_data->service_name, return_data->total_domains);
-
- for (i = 0; i < return_data->total_domains; i++) {
- pr_err("Instance ID: %d\t ",
- return_data->domain_list[i].instance_id);
- pr_err("Domain Name: %s\n",
- return_data->domain_list[i].name);
- rc = find_subsys(return_data->domain_list[i].name,
- subsys);
- if (rc < 0)
- pr_err("No valid subsys found for %s!\n",
- return_data->domain_list[i].name);
- else
- pr_err("Subsys: %s\n", subsys);
- }
- return 0;
-}
-
-static struct notifier_block pdr_service_nb = {
- .notifier_call = servloc_test_pdr_cb,
-};
-
-static ssize_t servloc_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
-{
- int rc = 0;
- char *node_name = filp->private_data;
-
- if (!strcmp(node_name, "test_servloc_get"))
- rc = get_service_location(test_data.client_name,
- test_data.service_name, &pdr_service_nb);
-
- return rc;
-}
-
-static ssize_t servloc_write(struct file *fp, const char __user *buf,
- size_t count, loff_t *unused)
-{
- char *node_name = fp->private_data;
-
- if (!buf)
- return -EIO;
- if (!strcmp(node_name, "service_name")) {
- snprintf(test_data.service_name, sizeof(test_data.service_name),
- "%.*s", (int) min((size_t)count - 1,
- (sizeof(test_data.service_name) - 1)), buf);
- } else {
- snprintf(test_data.client_name, sizeof(test_data.client_name),
- "%.*s", (int) min((size_t)count - 1,
- (sizeof(test_data.client_name) - 1)), buf);
- }
- return count;
-}
-
-static const struct file_operations servloc_fops = {
- .open = simple_open,
- .read = servloc_read,
- .write = servloc_write,
-};
-
-static struct dentry *servloc_base_dir;
-static struct dentry *test_servloc_file;
-
-static int __init servloc_debugfs_init(void)
-{
- servloc_base_dir = debugfs_create_dir("test_servloc", NULL);
- return !servloc_base_dir ? -ENOMEM : 0;
-}
-
-static void servloc_debugfs_exit(void)
-{
- debugfs_remove_recursive(servloc_base_dir);
-}
-
-static int servloc_debugfs_add(void)
-{
- int rc;
-
- if (!servloc_base_dir)
- return -ENOMEM;
-
- test_servloc_file = debugfs_create_file("client_name",
- S_IRUGO | S_IWUSR, servloc_base_dir,
- "client_name", &servloc_fops);
- rc = !test_servloc_file ? -ENOMEM : 0;
-
- if (rc == 0) {
- test_servloc_file = debugfs_create_file("service_name",
- S_IRUGO | S_IWUSR, servloc_base_dir,
- "service_name", &servloc_fops);
- rc = !test_servloc_file ? -ENOMEM : 0;
- }
-
- if (rc == 0) {
- test_servloc_file = debugfs_create_file("test_servloc_get",
- S_IRUGO | S_IWUSR, servloc_base_dir,
- "test_servloc_get", &servloc_fops);
- rc = !test_servloc_file ? -ENOMEM : 0;
- }
- return rc;
-}
-
-static int __init service_locator_init(void)
-{
- pr_debug("service_locator_status = %d\n", locator_status);
- if (servloc_debugfs_init())
- pr_err("Could not create test_servloc base directory!");
- if (servloc_debugfs_add())
- pr_err("Could not create test_servloc node entries!");
- return 0;
-}
-
-static void __exit service_locator_exit(void)
-{
- servloc_debugfs_exit();
-}
-module_init(service_locator_init);
-module_exit(service_locator_exit);
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index fa916ac5ade4..68592feccb33 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -21,7 +21,6 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/err.h>
-#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <soc/qcom/subsystem_restart.h>
@@ -752,179 +751,3 @@ int service_notif_unregister_notifier(void *service_notif_handle,
&service_notif->service_notif_rcvr_list, nb);
}
EXPORT_SYMBOL(service_notif_unregister_notifier);
-
-struct service_notifier_test_data {
- char service_path[MAX_STRING_LEN];
- int instance_id;
- struct notifier_block nb;
- void *service_notif_handle;
-};
-
-static struct service_notifier_test_data test_data;
-
-static void print_service_provider_state(int notification, char *type)
-{
- if (notification == SERVREG_NOTIF_SERVICE_STATE_DOWN_V01)
- pr_info("%s: Service %s down!\n", type, test_data.service_path);
- else if (notification == SERVREG_NOTIF_SERVICE_STATE_UP_V01)
- pr_info("%s: Service %s up!\n", type, test_data.service_path);
- else if (notification == SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01)
- pr_info("%s: Service %s state uninit!\n", type,
- test_data.service_path);
- else
- pr_info("%s: Service %s state Unknown 0x%x!\n", type,
- test_data.service_path, notification);
-}
-
-static int nb_callback(struct notifier_block *nb,
- unsigned long notification,
- void *data)
-{
- print_service_provider_state((int)notification, "Notification:");
- return 0;
-}
-
-static ssize_t show_service_path(struct seq_file *f, void *unused)
-{
- if (test_data.service_notif_handle)
- seq_printf(f, "Service Path: %s\n", test_data.service_path);
- else
- seq_puts(f, "No existing notifier\n");
- return 0;
-}
-
-
-static ssize_t set_service_notifier_register(struct file *fp,
- const char __user *buf,
- size_t count, loff_t *ppos)
-{
- int curr_state = INT_MAX, rc;
-
- if (!buf)
- return -EIO;
- if (test_data.service_notif_handle) {
- service_notif_unregister_notifier(
- test_data.service_notif_handle,
- &test_data.nb);
- test_data.service_notif_handle = NULL;
- pr_info("Unregistering existing notifier for %s\n",
- test_data.service_path);
- }
- rc = simple_write_to_buffer(test_data.service_path, MAX_STRING_LEN,
- ppos, buf, count - 1);
- if (rc != count - 1) {
- pr_err("Unable to read data into kernel buffer\n");
- goto err;
- }
- test_data.nb.notifier_call = nb_callback;
- test_data.service_notif_handle = service_notif_register_notifier(
- test_data.service_path,
- test_data.instance_id, &test_data.nb,
- &curr_state);
- if (!IS_ERR(test_data.service_notif_handle)) {
- pr_info("Notifier Registered for service %s\n",
- test_data.service_path);
- print_service_provider_state(curr_state, "Initial State");
- return count;
- }
-err:
- test_data.service_notif_handle = NULL;
- pr_err("Unable to register notifier for %s\n", test_data.service_path);
- return -EIO;
-}
-
-static int open_service_notifier_register(struct inode *inode, struct file *f)
-{
- return single_open(f, (void *) show_service_path,
- inode->i_private);
-}
-
-static const struct file_operations service_notifier_register_fops = {
- .open = open_service_notifier_register,
- .read = seq_read,
- .write = set_service_notifier_register,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static ssize_t show_service_notifier_id(struct seq_file *f, void *unused)
-{
- seq_printf(f, "Service instance ID: %d\n", test_data.instance_id);
- return 0;
-}
-
-static ssize_t set_service_notifier_id(struct file *fp,
- const char __user *buf,
- size_t count, loff_t *unused)
-{
- int val, rc;
- char kbuf[MAX_STRING_LEN];
-
- if (count > MAX_STRING_LEN) {
- rc = -EIO;
- goto err;
- }
- rc = copy_from_user(kbuf, buf, count);
- if (rc != 0) {
- rc = -EFAULT;
- goto err;
- }
-
- kbuf[count - 1] = '\0';
- rc = kstrtoint(kbuf, 0, &val);
- if (rc < 0)
- goto err;
-
- test_data.instance_id = val;
- return count;
-err:
- pr_err("Invalid input parameters: rc = %d\n", rc);
- return rc;
-}
-
-static int open_service_notifier_id(struct inode *inode, struct file *f)
-{
- return single_open(f, (void *) show_service_notifier_id,
- inode->i_private);
-}
-
-static const struct file_operations service_notifier_id_fops = {
- .open = open_service_notifier_id,
- .read = seq_read,
- .write = set_service_notifier_id,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static struct dentry *service_notifier_dir;
-static struct dentry *service_path_file;
-static struct dentry *service_id_file;
-
-static int __init service_notifier_init(void)
-{
- service_notifier_dir = debugfs_create_dir("service_notifier", NULL);
- if (service_notifier_dir) {
- service_path_file = debugfs_create_file("service_path",
- S_IRUGO | S_IWUSR, service_notifier_dir, NULL,
- &service_notifier_register_fops);
- if (!service_path_file)
- goto err;
- service_id_file = debugfs_create_file("service_id",
- S_IRUGO | S_IWUSR, service_notifier_dir, NULL,
- &service_notifier_id_fops);
- if (!service_id_file)
- goto err;
- }
- return 0;
-err:
- debugfs_remove_recursive(service_notifier_dir);
- return 0;
-}
-
-static void __exit service_notifier_exit(void)
-{
- debugfs_remove_recursive(service_notifier_dir);
- test_data.nb.notifier_call = nb_callback;
-}
-module_init(service_notifier_init);
-module_exit(service_notifier_exit);
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index c35ec26fefa2..d3d0b8594c9f 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.c
@@ -28,7 +28,6 @@
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/idr.h>
-#include <linux/debugfs.h>
#include <linux/interrupt.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
@@ -149,7 +148,6 @@ struct restart_log {
* @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
* @restart_order: order of other devices this devices restarts with
* @crash_count: number of times the device has crashed
- * @dentry: debugfs directory for this device
* @do_ramdump_on_put: ramdump on subsystem_put() if true
* @err_ready: completion variable to record error ready from subsystem
* @crashed: indicates if subsystem has crashed
@@ -171,9 +169,6 @@ struct subsys_device {
int restart_level;
int crash_count;
struct subsys_soc_restart_order *restart_order;
-#ifdef CONFIG_DEBUG_FS
- struct dentry *dentry;
-#endif
bool do_ramdump_on_put;
struct cdev char_dev;
dev_t dev_no;
@@ -352,10 +347,11 @@ static struct device_attribute subsys_attrs[] = {
__ATTR_NULL,
};
-static struct bus_type subsys_bus_type = {
+struct bus_type subsys_bus_type = {
.name = "msm_subsys",
.dev_attrs = subsys_attrs,
};
+EXPORT_SYMBOL(subsys_bus_type);
static DEFINE_IDA(subsys_ida);
@@ -1169,87 +1165,6 @@ void notify_proxy_unvote(struct device *device)
notify_each_subsys_device(&dev, 1, SUBSYS_PROXY_UNVOTE, NULL);
}
-#ifdef CONFIG_DEBUG_FS
-static ssize_t subsys_debugfs_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
-{
- int r;
- char buf[40];
- struct subsys_device *subsys = filp->private_data;
-
- r = snprintf(buf, sizeof(buf), "%d\n", subsys->count);
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-}
-
-static ssize_t subsys_debugfs_write(struct file *filp,
- const char __user *ubuf, size_t cnt, loff_t *ppos)
-{
- struct subsys_device *subsys = filp->private_data;
- char buf[10];
- char *cmp;
-
- cnt = min(cnt, sizeof(buf) - 1);
- if (copy_from_user(&buf, ubuf, cnt))
- return -EFAULT;
- buf[cnt] = '\0';
- cmp = strstrip(buf);
-
- if (!strcmp(cmp, "restart")) {
- if (subsystem_restart_dev(subsys))
- return -EIO;
- } else if (!strcmp(cmp, "get")) {
- if (subsystem_get(subsys->desc->name))
- return -EIO;
- } else if (!strcmp(cmp, "put")) {
- subsystem_put(subsys);
- } else {
- return -EINVAL;
- }
-
- return cnt;
-}
-
-static const struct file_operations subsys_debugfs_fops = {
- .open = simple_open,
- .read = subsys_debugfs_read,
- .write = subsys_debugfs_write,
-};
-
-static struct dentry *subsys_base_dir;
-
-static int __init subsys_debugfs_init(void)
-{
- subsys_base_dir = debugfs_create_dir("msm_subsys", NULL);
- return !subsys_base_dir ? -ENOMEM : 0;
-}
-
-static void subsys_debugfs_exit(void)
-{
- debugfs_remove_recursive(subsys_base_dir);
-}
-
-static int subsys_debugfs_add(struct subsys_device *subsys)
-{
- if (!subsys_base_dir)
- return -ENOMEM;
-
- subsys->dentry = debugfs_create_file(subsys->desc->name,
- S_IRUGO | S_IWUSR, subsys_base_dir,
- subsys, &subsys_debugfs_fops);
- return !subsys->dentry ? -ENOMEM : 0;
-}
-
-static void subsys_debugfs_remove(struct subsys_device *subsys)
-{
- debugfs_remove(subsys->dentry);
-}
-#else
-static int __init subsys_debugfs_init(void) { return 0; };
-static void subsys_debugfs_exit(void) { }
-static int subsys_debugfs_add(struct subsys_device *subsys) { return 0; }
-static void subsys_debugfs_remove(struct subsys_device *subsys) { }
-#endif
-
static int subsys_device_open(struct inode *inode, struct file *file)
{
struct subsys_device *device, *subsys_dev = 0;
@@ -1686,17 +1601,8 @@ struct subsys_device *subsys_register(struct subsys_desc *desc)
mutex_init(&subsys->track.lock);
- ret = subsys_debugfs_add(subsys);
- if (ret) {
- ida_simple_remove(&subsys_ida, subsys->id);
- wakeup_source_trash(&subsys->ssr_wlock);
- kfree(subsys);
- return ERR_PTR(ret);
- }
-
ret = device_register(&subsys->dev);
if (ret) {
- subsys_debugfs_remove(subsys);
put_device(&subsys->dev);
return ERR_PTR(ret);
}
@@ -1758,7 +1664,6 @@ err_setup_irqs:
if (ofnode)
subsys_remove_restart_order(ofnode);
err_register:
- subsys_debugfs_remove(subsys);
device_unregister(&subsys->dev);
return ERR_PTR(ret);
}
@@ -1787,7 +1692,6 @@ void subsys_unregister(struct subsys_device *subsys)
WARN_ON(subsys->count);
device_unregister(&subsys->dev);
mutex_unlock(&subsys->track.lock);
- subsys_debugfs_remove(subsys);
subsys_char_device_remove(subsys);
sysmon_notifier_unregister(subsys->desc);
if (subsys->desc->edge)
@@ -1827,9 +1731,6 @@ static int __init subsys_restart_init(void)
ret = bus_register(&subsys_bus_type);
if (ret)
goto err_bus;
- ret = subsys_debugfs_init();
- if (ret)
- goto err_debugfs;
char_class = class_create(THIS_MODULE, "subsys");
if (IS_ERR(char_class)) {
@@ -1848,8 +1749,6 @@ static int __init subsys_restart_init(void)
err_soc:
class_destroy(char_class);
err_class:
- subsys_debugfs_exit();
-err_debugfs:
bus_unregister(&subsys_bus_type);
err_bus:
destroy_workqueue(ssr_wq);
diff --git a/drivers/usb/gadget/function/f_ccid.h b/drivers/usb/gadget/function/f_ccid.h
index 42a7ebbbccfc..935308cff0bc 100644
--- a/drivers/usb/gadget/function/f_ccid.h
+++ b/drivers/usb/gadget/function/f_ccid.h
@@ -55,29 +55,29 @@
#define CCID_READ_DTR _IOR('C', 3, int)
struct usb_ccid_notification {
- unsigned char buf[4];
+ __u8 buf[4];
} __packed;
struct ccid_bulk_in_header {
- unsigned char bMessageType;
- unsigned long wLength;
- unsigned char bSlot;
- unsigned char bSeq;
- unsigned char bStatus;
- unsigned char bError;
- unsigned char bSpecific;
- unsigned char abData[ABDATA_SIZE];
- unsigned char bSizeToSend;
+ __u8 bMessageType;
+ __u32 wLength;
+ __u8 bSlot;
+ __u8 bSeq;
+ __u8 bStatus;
+ __u8 bError;
+ __u8 bSpecific;
+ __u8 abData[ABDATA_SIZE];
+ __u8 bSizeToSend;
} __packed;
struct ccid_bulk_out_header {
- unsigned char bMessageType;
- unsigned long wLength;
- unsigned char bSlot;
- unsigned char bSeq;
- unsigned char bSpecific_0;
- unsigned char bSpecific_1;
- unsigned char bSpecific_2;
- unsigned char APDU[ABDATA_SIZE];
+ __u8 bMessageType;
+ __u32 wLength;
+ __u8 bSlot;
+ __u8 bSeq;
+ __u8 bSpecific_0;
+ __u8 bSpecific_1;
+ __u8 bSpecific_2;
+ __u8 APDU[ABDATA_SIZE];
} __packed;
#endif
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index d794d3b3b48e..7c35241a487a 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1189,7 +1189,7 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
*to = p->data;
}
- ffs_log("enter");
+ ffs_log("exit");
return res;
}
@@ -3384,6 +3384,8 @@ static int ffs_func_set_alt(struct usb_function *f,
if (ffs->func) {
ffs_func_eps_disable(ffs->func);
ffs->func = NULL;
+ /* matching put to allow LPM on disconnect */
+ usb_gadget_autopm_put_async(ffs->gadget);
}
if (ffs->state == FFS_DEACTIVATED) {
@@ -3417,14 +3419,9 @@ static int ffs_func_set_alt(struct usb_function *f,
static void ffs_func_disable(struct usb_function *f)
{
- struct ffs_function *func = ffs_func_from_usb(f);
- struct ffs_data *ffs = func->ffs;
-
ffs_log("enter");
ffs_func_set_alt(f, 0, (unsigned)-1);
- /* matching put to allow LPM on disconnect */
- usb_gadget_autopm_put_async(ffs->gadget);
ffs_log("exit");
}
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 226198efbeec..7a1b563fbb6c 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -1434,6 +1434,13 @@ static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train)
if (ret)
goto end;
+ /*
+ * Skip the transfer unit setup and the routine to wait for the
+ * video ready interrupt as link training tests do not require
+ * video frames to be sent.
+ */
+ if (mdss_dp_is_link_training_requested(dp))
+ goto end;
send_video:
/*
* Set up transfer unit values and set controller state to send
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 9f4b7eb52492..37f3929a3a2c 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -778,6 +778,12 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
u32 loop = 10, u_dly = 200;
pr_debug("%s: MDSS DSI CTRL and PHY reset. ctrl-num = %d\n",
__func__, ctrl->ndx);
+
+ if (ctrl->panel_mode == DSI_CMD_MODE) {
+ pr_warn("ctl_phy_reset not applicable for cmd mode\n");
+ return;
+ }
+
if (event == DSI_EV_DLNx_FIFO_OVERFLOW) {
mask = BIT(20); /* clock lane only for overflow recovery */
} else if (event == DSI_EV_LP_RX_TIMEOUT) {
@@ -792,15 +798,6 @@ 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) {
- 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.
@@ -874,6 +871,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 & ~mask);
MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 & ~mask);
+ 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;
+ }
+ }
/* Enable Video mode for DSI controller */
MIPI_OUTP(ctrl0->ctrl_base + 0x004, data0);
MIPI_OUTP(ctrl1->ctrl_base + 0x004, data1);
@@ -890,15 +896,6 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
*/
udelay(200);
} else {
- 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);
@@ -951,6 +948,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
__func__, ln0);
MIPI_OUTP(ctrl->ctrl_base + 0x0ac, ln_ctrl0 & ~mask);
+ 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;
+ }
+ }
/* Enable Video mode for DSI controller */
MIPI_OUTP(ctrl->ctrl_base + 0x004, data0);
/* Enable PHY contention detection and receiver */
@@ -1311,6 +1317,31 @@ void mdss_dsi_set_burst_mode(struct mdss_dsi_ctrl_pdata *ctrl)
}
+static void mdss_dsi_split_link_setup(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ u32 data = 0;
+ struct mdss_panel_info *pinfo;
+
+ if (!ctrl_pdata)
+ return;
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
+ if (!pinfo->split_link_enabled)
+ return;
+
+ pr_debug("%s: enable split link\n", __func__);
+
+ data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x330);
+ /* DMA_LINK_SEL */
+ data |= 0x3 << 12;
+ /* MDP0_LINK_SEL */
+ data |= 0x5 << 20;
+ /* EN */
+ data |= 0x1;
+ /* DSI_SPLIT_LINK_CTRL */
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x330, data);
+}
+
static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
@@ -1429,6 +1460,8 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
}
mdss_dsi_dsc_config(ctrl_pdata, dsc);
+
+ mdss_dsi_split_link_setup(ctrl_pdata);
}
void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl)
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 6f20c0ed0455..9faa1531c256 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -1350,6 +1350,44 @@ static int mdss_dsi_parse_hdr_settings(struct device_node *np,
return 0;
}
+static int mdss_dsi_parse_split_link_settings(struct device_node *np,
+ struct mdss_panel_info *pinfo)
+{
+ u32 tmp;
+ int rc = 0;
+
+ if (!np) {
+ pr_err("%s: device node pointer is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!pinfo) {
+ pr_err("%s: panel info is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo->split_link_enabled = of_property_read_bool(np,
+ "qcom,split-link-enabled");
+
+ if (pinfo->split_link_enabled) {
+ rc = of_property_read_u32(np,
+ "qcom,sublinks-count", &tmp);
+ /* default num of sublink is 1*/
+ pinfo->mipi.num_of_sublinks = (!rc ? tmp : 1);
+
+ rc = of_property_read_u32(np,
+ "qcom,lanes-per-sublink", &tmp);
+ /* default num of lanes per sublink is 1 */
+ pinfo->mipi.lanes_per_sublink = (!rc ? tmp : 1);
+ }
+
+ pr_info("%s: enable %d sublinks-count %d lanes per sublink %d\n",
+ __func__, pinfo->split_link_enabled,
+ pinfo->mipi.num_of_sublinks,
+ pinfo->mipi.lanes_per_sublink);
+ return 0;
+}
+
static int mdss_dsi_parse_dsc_version(struct device_node *np,
struct mdss_panel_timing *timing)
{
@@ -2734,9 +2772,15 @@ static int mdss_panel_parse_dt(struct device_node *np,
pinfo->mipi.data_lane3 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-3-state");
+ /* parse split link properties */
+ rc = mdss_dsi_parse_split_link_settings(np, pinfo);
+ if (rc)
+ return rc;
+
rc = mdss_panel_parse_display_timings(np, &ctrl_pdata->panel_data);
if (rc)
return rc;
+
rc = mdss_dsi_parse_hdr_settings(np, pinfo);
if (rc)
return rc;
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index fc47de7692e7..93643246935e 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -374,7 +374,8 @@ static int mdss_fb_get_panel_xres(struct mdss_panel_info *pinfo)
xres = pinfo->xres;
if (pdata->next && pdata->next->active)
xres += mdss_fb_get_panel_xres(&pdata->next->panel_info);
-
+ if (pinfo->split_link_enabled)
+ xres = xres * pinfo->mipi.num_of_sublinks;
return xres;
}
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index f046ff08cbf7..8e5fc5949770 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -392,6 +392,12 @@ static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd)
}
}
+/* Function returns true for split link */
+static inline bool is_panel_split_link(struct msm_fb_data_type *mfd)
+{
+ return mfd && mfd->panel_info && mfd->panel_info->split_link_enabled;
+}
+
/* Function returns true for either any kind of dual display */
static inline bool is_panel_split(struct msm_fb_data_type *mfd)
{
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 2fd047edd3e8..56af021e8cfc 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1267,6 +1267,8 @@ static inline u32 get_panel_width(struct mdss_mdp_ctl *ctl)
width = get_panel_xres(&ctl->panel_data->panel_info);
if (ctl->panel_data->next && is_pingpong_split(ctl->mfd))
width += get_panel_xres(&ctl->panel_data->next->panel_info);
+ else if (is_panel_split_link(ctl->mfd))
+ width *= (ctl->panel_data->panel_info.mipi.num_of_sublinks);
return width;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 0495b6e19cc2..a66ecb7a57b7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -709,6 +709,8 @@ int mdss_mdp_get_panel_params(struct mdss_mdp_pipe *pipe,
*h_total += mdss_panel_get_htotal(
&mixer->ctl->panel_data->next->panel_info,
false);
+ else if (is_panel_split_link(mixer->ctl->mfd))
+ *h_total *= pinfo->mipi.num_of_sublinks;
} else {
*v_total = mixer->height;
*xres = mixer->width;
@@ -4108,6 +4110,9 @@ static void mdss_mdp_ctl_split_display_enable(int enable,
}
}
}
+
+ if (is_panel_split_link(main_ctl->mfd))
+ upper = lower = 0;
writel_relaxed(upper, main_ctl->mdata->mdp_base +
MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL);
writel_relaxed(lower, main_ctl->mdata->mdp_base +
@@ -4276,7 +4281,8 @@ void mdss_mdp_ctl_restore(bool locked)
if (sctl) {
mdss_mdp_ctl_restore_sub(sctl);
mdss_mdp_ctl_split_display_enable(1, ctl, sctl);
- } else if (is_pingpong_split(ctl->mfd)) {
+ } else if (is_pingpong_split(ctl->mfd) ||
+ is_panel_split_link(ctl->mfd)) {
mdss_mdp_ctl_pp_split_display_enable(1, ctl);
}
@@ -4403,6 +4409,8 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
} else if (is_pingpong_split(ctl->mfd)) {
ctl->slave_intf_num = (ctl->intf_num + 1);
mdss_mdp_ctl_pp_split_display_enable(true, ctl);
+ } else if (is_panel_split_link(ctl->mfd)) {
+ mdss_mdp_ctl_pp_split_display_enable(true, ctl);
}
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index 7d495232c198..d9e2b042bfc3 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -850,4 +850,8 @@ enum mdss_mdp_pingpong_index {
#define MDSS_MDP_REG_TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4))
#define MDSS_MDP_REG_TRAFFIC_SHAPER_FIXPOINT_FACTOR 4
+#define MDSS_MDP_REG_SPLIT_LINK 0x00060
+#define MDSS_MDP_REG_SPLIT_LINK_LEFT_LINK_EN BIT(1)
+#define MDSS_MDP_REG_SPLIT_LINK_RIGHT_LINK_EN BIT(2)
+
#endif
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index a3511a1a07ef..ea55203afc51 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -1682,6 +1682,16 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
mdss_bus_bandwidth_ctrl(true);
+ /* configure the split link to both sublinks */
+ if (is_panel_split_link(ctl->mfd)) {
+ mdp_video_write(ctx, MDSS_MDP_REG_SPLIT_LINK, 0x3);
+ /*
+ * ensure split link register is written before
+ * enabling timegen
+ */
+ wmb();
+ }
+
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
wmb();
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 8d7bd60318ad..724913f376a7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2292,6 +2292,9 @@ static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, addr[2]);
}
+ MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
+ pipe->play_cnt, addr[0], addr[1], addr[2], addr[3]);
+
return 0;
}
@@ -2734,9 +2737,6 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
goto update_nobuf;
}
- MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
- pipe->play_cnt, 0x222);
-
if (params_changed) {
pipe->params_changed = 0;
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 92413e078244..fa1df94976f9 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -533,6 +533,8 @@ struct mipi_panel_info {
char lp11_init;
u32 init_delay;
u32 post_init_delay;
+ u32 num_of_sublinks;
+ u32 lanes_per_sublink;
};
struct edp_panel_info {
@@ -847,6 +849,7 @@ struct mdss_panel_info {
bool is_lpm_mode;
bool is_split_display; /* two DSIs in one display, pp split or not */
bool use_pingpong_split;
+ bool split_link_enabled;
/*
* index[0] = left layer mixer, value of 0 not valid
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 62e25500060e..f56158446c0d 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -600,24 +600,30 @@ int mdss_smmu_fault_handler(struct iommu_domain *domain, struct device *dev,
(struct mdss_smmu_client *)user_data;
u32 fsynr1, mid, i;
- if (!mdss_smmu || !mdss_smmu->mmu_base)
+ if (!mdss_smmu)
goto end;
- fsynr1 = readl_relaxed(mdss_smmu->mmu_base + SMMU_CBN_FSYNR1);
- mid = fsynr1 & 0xff;
- pr_err("mdss_smmu: iova:0x%lx flags:0x%x fsynr1: 0x%x mid: 0x%x\n",
- iova, flags, fsynr1, mid);
+ if (mdss_smmu->mmu_base) {
+ fsynr1 = readl_relaxed(mdss_smmu->mmu_base + SMMU_CBN_FSYNR1);
+ mid = fsynr1 & 0xff;
+ pr_err("mdss_smmu: iova:0x%lx flags:0x%x fsynr1: 0x%x mid: 0x%x\n",
+ iova, flags, fsynr1, mid);
- /* get domain id information */
- for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
- if (mdss_smmu == mdss_smmu_get_cb(i))
- break;
- }
+ /* get domain id information */
+ for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
+ if (mdss_smmu == mdss_smmu_get_cb(i))
+ break;
+ }
- if (i == MDSS_IOMMU_MAX_DOMAIN)
- goto end;
+ if (i == MDSS_IOMMU_MAX_DOMAIN)
+ goto end;
- mdss_mdp_debug_mid(mid);
+ mdss_mdp_debug_mid(mid);
+ } else {
+ pr_err("mdss_smmu: iova:0x%lx flags:0x%x\n",
+ iova, flags);
+ MDSS_XLOG_TOUT_HANDLER("mdp");
+ }
end:
return -ENOSYS;
}
@@ -844,14 +850,13 @@ int mdss_smmu_probe(struct platform_device *pdev)
mdss_smmu->base.dev = dev;
+ iommu_set_fault_handler(mdss_smmu->mmu_mapping->domain,
+ mdss_smmu_fault_handler, mdss_smmu);
address = of_get_address_by_name(pdev->dev.of_node, "mmu_cb", 0, 0);
if (address) {
size = address + 1;
mdss_smmu->mmu_base = ioremap(be32_to_cpu(*address),
be32_to_cpu(*size));
- if (mdss_smmu->mmu_base)
- iommu_set_fault_handler(mdss_smmu->mmu_mapping->domain,
- mdss_smmu_fault_handler, mdss_smmu);
} else {
pr_debug("unable to map context bank base\n");
}
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index 03e78733d168..9c156af6b63c 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -38,16 +38,23 @@
#define MDSS_DSI_DSIPHY_GLBL_TEST_CTRL 0x1d4
#define MDSS_DSI_DSIPHY_CTRL_0 0x170
#define MDSS_DSI_DSIPHY_CTRL_1 0x174
+#define MDSS_DSI_DSIPHY_CMN_CLK_CFG0 0x0010
+#define MDSS_DSI_DSIPHY_CMN_CLK_CFG1 0x0014
+
+#define MDSS_DSI_NUM_DATA_LANES 0x04
+#define MDSS_DSI_NUM_CLK_LANES 0x01
#define SW_RESET BIT(2)
#define SW_RESET_PLL BIT(0)
#define PWRDN_B BIT(7)
/* 8996 */
-#define DATALANE_OFFSET_FROM_BASE_8996 0x100
-#define DSIPHY_CMN_PLL_CNTRL 0x0048
+#define DATALANE_OFFSET_FROM_BASE_8996 0x100
+#define CLKLANE_OFFSET_FROM_BASE_8996 0x300
#define DATALANE_SIZE_8996 0x80
+#define CLKLANE_SIZE_8996 0x80
+#define DSIPHY_CMN_PLL_CNTRL 0x0048
#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018
#define DSIPHY_CMN_CTRL_0 0x001c
#define DSIPHY_CMN_CTRL_1 0x0020
@@ -55,6 +62,24 @@
#define DSIPHY_PLL_CLKBUFLR_EN 0x041c
#define DSIPHY_PLL_PLL_BANDGAP 0x0508
+#define DSIPHY_LANE_STRENGTH_CTRL_NUM 0x0002
+#define DSIPHY_LANE_STRENGTH_CTRL_OFFSET 0x0004
+#define DSIPHY_LANE_STRENGTH_CTRL_BASE 0x0038
+
+#define DSIPHY_LANE_CFG_NUM 0x0004
+#define DSIPHY_LANE_CFG_OFFSET 0x0004
+#define DSIPHY_LANE_CFG_BASE 0x0000
+
+#define DSIPHY_LANE_VREG_NUM 0x0001
+#define DSIPHY_LANE_VREG_OFFSET 0x0004
+#define DSIPHY_LANE_VREG_BASE 0x0064
+
+#define DSIPHY_LANE_TIMING_CTRL_NUM 0x0008
+#define DSIPHY_LANE_TIMING_CTRL_OFFSET 0x0004
+#define DSIPHY_LANE_TIMING_CTRL_BASE 0x0018
+
+#define DSIPHY_LANE_TEST_STR 0x0014
+
#define DSIPHY_LANE_STRENGTH_CTRL_1 0x003c
#define DSIPHY_LANE_VREG_CNTRL 0x0064
@@ -131,6 +156,8 @@
#define DSIPHY_PLL_RESETSM_CNTRL5 0x043c
+#define DSIPHY_CMN_CLK_CFG1_SPLIT_LINK 0x1
+
#define PLL_CALC_DATA(addr0, addr1, data0, data1) \
(((data1) << 24) | ((((addr1)/4) & 0xFF) << 16) | \
((data0) << 8) | (((addr0)/4) & 0xFF))
@@ -911,35 +938,59 @@ static void mdss_dsi_8996_phy_regulator_enable(
int j, off, ln, cnt, ln_off;
char *ip;
void __iomem *base;
+ struct mdss_panel_info *panel_info;
+
+ if (!ctrl) {
+ pr_warn("%s: null ctrl pdata\n", __func__);
+ return;
+ }
+ panel_info = &((ctrl->panel_data).panel_info);
pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
- if (pd->regulator_len != 5) {
+ if (pd->regulator_len != (MDSS_DSI_NUM_DATA_LANES +
+ MDSS_DSI_NUM_CLK_LANES)) {
pr_warn("%s: invalid regulator settings\n", __func__);
return;
}
- /* 4 lanes + clk lane configuration */
- for (ln = 0; ln < 5; ln++) {
- /*
- * data lane offset frome base: 0x100
- * data lane size: 0x80
- */
- base = ctrl->phy_io.base +
- DATALANE_OFFSET_FROM_BASE_8996;
- base += (ln * DATALANE_SIZE_8996); /* lane base */
-
- /* vreg ctrl, 1 * 5 */
- cnt = 1;
+ /*
+ * data lane offset from base: 0x100
+ * data lane size: 0x80
+ */
+ base = ctrl->phy_io.base + DATALANE_OFFSET_FROM_BASE_8996;
+ /* data lanes configuration */
+ for (ln = 0; ln < MDSS_DSI_NUM_DATA_LANES; ln++) {
+ /* vreg ctrl, 1 * MDSS_DSI_NUM_DATA_LANES */
+ cnt = DSIPHY_LANE_VREG_NUM;
+ off = DSIPHY_LANE_VREG_BASE;
ln_off = cnt * ln;
ip = &pd->regulator[ln_off];
- off = 0x64;
- for (j = 0; j < cnt; j++, off += 4)
+ for (j = 0; j < cnt; j++) {
MIPI_OUTP(base + off, *ip++);
+ off += DSIPHY_LANE_VREG_OFFSET;
+ }
+ base += DATALANE_SIZE_8996; /* next lane */
}
- wmb(); /* make sure registers committed */
+ /*
+ * clk lane offset from base: 0x300
+ * clk lane size: 0x80
+ */
+ base = ctrl->phy_io.base + CLKLANE_OFFSET_FROM_BASE_8996;
+ /*
+ * clk lane configuration for vreg ctrl
+ * for split link there are two clock lanes, one
+ * clock lane per sublink needs to be configured
+ */
+ off = DSIPHY_LANE_VREG_BASE;
+ ln_off = MDSS_DSI_NUM_DATA_LANES;
+ ip = &pd->regulator[ln_off];
+ MIPI_OUTP(base + off, *ip);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, *ip);
+ wmb(); /* make sure registers committed */
}
static void mdss_dsi_8996_phy_power_off(
@@ -948,31 +999,51 @@ static void mdss_dsi_8996_phy_power_off(
int ln;
void __iomem *base;
u32 data;
+ struct mdss_panel_info *panel_info;
+
+ if (ctrl) {
+ panel_info = &((ctrl->panel_data).panel_info);
+ } else {
+ pr_warn("%s: null ctrl pdata\n", __func__);
+ return;
+ }
/* Turn off PLL power */
data = MIPI_INP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0);
MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, data & ~BIT(7));
- /* 4 lanes + clk lane configuration */
- for (ln = 0; ln < 5; ln++) {
- base = ctrl->phy_io.base +
- DATALANE_OFFSET_FROM_BASE_8996;
- base += (ln * DATALANE_SIZE_8996); /* lane base */
-
+ /* data lanes configuration */
+ base = ctrl->phy_io.base + DATALANE_OFFSET_FROM_BASE_8996;
+ for (ln = 0; ln < MDSS_DSI_NUM_DATA_LANES; ln++) {
/* turn off phy ldo */
- MIPI_OUTP(base + DSIPHY_LANE_VREG_CNTRL, 0x1c);
+ MIPI_OUTP(base + DSIPHY_LANE_VREG_BASE, 0x1c);
+ base += DATALANE_SIZE_8996; /* next lane */
}
- MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c);
- /* 4 lanes + clk lane configuration */
- for (ln = 0; ln < 5; ln++) {
- base = ctrl->phy_io.base +
- DATALANE_OFFSET_FROM_BASE_8996;
- base += (ln * DATALANE_SIZE_8996); /* lane base */
+ /* clk lane configuration */
+ base = ctrl->phy_io.base + CLKLANE_OFFSET_FROM_BASE_8996;
+ /* turn off phy ldo */
+ MIPI_OUTP(base + DSIPHY_LANE_VREG_BASE, 0x1c);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 +
+ DSIPHY_LANE_VREG_BASE, 0x1c);
+
+ MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c);
+ /* data lanes configuration */
+ base = ctrl->phy_io.base + DATALANE_OFFSET_FROM_BASE_8996;
+ for (ln = 0; ln < MDSS_DSI_NUM_DATA_LANES; ln++) {
MIPI_OUTP(base + DSIPHY_LANE_STRENGTH_CTRL_1, 0x0);
+ base += DATALANE_SIZE_8996; /* next lane */
}
+ /* clk lane configuration */
+ base = ctrl->phy_io.base + CLKLANE_OFFSET_FROM_BASE_8996;
+ MIPI_OUTP(base + DSIPHY_LANE_STRENGTH_CTRL_1, 0x0);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 +
+ DSIPHY_LANE_STRENGTH_CTRL_1, 0x0);
+
wmb(); /* make sure registers committed */
}
@@ -1008,22 +1079,46 @@ static void mdss_dsi_8996_phy_power_on(
struct mdss_dsi_phy_ctrl *pd;
char *ip;
u32 data;
+ struct mdss_panel_info *panel_info;
- pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
+ if (ctrl) {
+ panel_info = &((ctrl->panel_data).panel_info);
+ } else {
+ pr_warn("%s: null ctrl pdata\n", __func__);
+ return;
+ }
- /* 4 lanes + clk lane configuration */
- for (ln = 0; ln < 5; ln++) {
- base = ctrl->phy_io.base +
- DATALANE_OFFSET_FROM_BASE_8996;
- base += (ln * DATALANE_SIZE_8996); /* lane base */
+ pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
- /* strength, 2 * 5 */
- cnt = 2;
+ /* data lanes configuration */
+ base = ctrl->phy_io.base + DATALANE_OFFSET_FROM_BASE_8996;
+ for (ln = 0; ln < MDSS_DSI_NUM_DATA_LANES; ln++) {
+ /* strength, 2 * MDSS_DSI_NUM_DATA_LANES */
+ cnt = DSIPHY_LANE_STRENGTH_CTRL_NUM;
ln_off = cnt * ln;
ip = &pd->strength[ln_off];
- off = 0x38;
- for (j = 0; j < cnt; j++, off += 4)
+ off = DSIPHY_LANE_STRENGTH_CTRL_BASE;
+ for (j = 0; j < cnt; j++,
+ off += DSIPHY_LANE_STRENGTH_CTRL_OFFSET)
MIPI_OUTP(base + off, *ip++);
+ base += DATALANE_SIZE_8996; /* next lane */
+ }
+
+ /*
+ * clk lane configuration for strength ctrl
+ * for split link there are two clock lanes, one
+ * clock lane per sublink needs to be configured
+ */
+ base = ctrl->phy_io.base + CLKLANE_OFFSET_FROM_BASE_8996;
+ cnt = DSIPHY_LANE_STRENGTH_CTRL_NUM;
+ ln_off = MDSS_DSI_NUM_DATA_LANES;
+ ip = &pd->strength[ln_off];
+ off = DSIPHY_LANE_STRENGTH_CTRL_BASE;
+ for (j = 0; j < cnt; j++,
+ off += DSIPHY_LANE_STRENGTH_CTRL_OFFSET) {
+ MIPI_OUTP(base + off, *ip);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, *ip);
}
mdss_dsi_8996_phy_regulator_enable(ctrl);
@@ -1051,67 +1146,126 @@ static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
int j, off, ln, cnt, ln_off;
char *ip;
void __iomem *base;
+ struct mdss_panel_info *panel_info;
+ int num_of_lanes = 0;
+
+ if (ctrl) {
+ panel_info = &((ctrl->panel_data).panel_info);
+ } else {
+ pr_warn("%s: null ctrl pdata\n", __func__);
+ return;
+ }
pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
+ num_of_lanes = MDSS_DSI_NUM_DATA_LANES + MDSS_DSI_NUM_CLK_LANES;
MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c);
/* clk_en */
MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, 0x1);
- if (pd->lanecfg_len != 20) {
+ if (pd->lanecfg_len != (num_of_lanes * DSIPHY_LANE_CFG_NUM)) {
pr_err("%s: wrong lane cfg\n", __func__);
return;
}
- if (pd->strength_len != 10) {
+ if (pd->strength_len != (num_of_lanes *
+ DSIPHY_LANE_STRENGTH_CTRL_NUM)) {
pr_err("%s: wrong strength ctrl\n", __func__);
return;
}
- if (pd->regulator_len != 5) {
+ if (pd->regulator_len != (num_of_lanes * DSIPHY_LANE_VREG_NUM)) {
pr_err("%s: wrong regulator setting\n", __func__);
return;
}
- /* 4 lanes + clk lane configuration */
- for (ln = 0; ln < 5; ln++) {
- /*
- * data lane offset frome base: 0x100
- * data lane size: 0x80
- */
- base = ctrl->phy_io.base +
- DATALANE_OFFSET_FROM_BASE_8996;
- base += (ln * DATALANE_SIZE_8996); /* lane base */
-
- /* lane cfg, 4 * 5 */
- cnt = 4;
+ /* data lanes configuration */
+ base = ctrl->phy_io.base + DATALANE_OFFSET_FROM_BASE_8996;
+ for (ln = 0; ln < MDSS_DSI_NUM_DATA_LANES; ln++) {
+ /* lane cfg, 4 * MDSS_DSI_NUM_DATA_LANES */
+ cnt = DSIPHY_LANE_CFG_NUM;
+ off = DSIPHY_LANE_CFG_BASE;
ln_off = cnt * ln;
ip = &pd->lanecfg[ln_off];
- off = 0x0;
for (j = 0; j < cnt; j++) {
MIPI_OUTP(base + off, *ip++);
- off += 4;
+ off += DSIPHY_LANE_CFG_OFFSET;
}
/* test str */
- MIPI_OUTP(base + 0x14, 0x0088); /* fixed */
+ MIPI_OUTP(base + DSIPHY_LANE_TEST_STR, 0x88); /* fixed */
- /* phy timing, 8 * 5 */
- cnt = 8;
+ /* phy timing, 8 * MDSS_DSI_NUM_DATA_LANES */
+ cnt = DSIPHY_LANE_TIMING_CTRL_NUM;
+ off = DSIPHY_LANE_TIMING_CTRL_BASE;
ln_off = cnt * ln;
ip = &pd->timing_8996[ln_off];
- off = 0x18;
- for (j = 0; j < cnt; j++, off += 4)
+ for (j = 0; j < cnt; j++) {
MIPI_OUTP(base + off, *ip++);
+ off += DSIPHY_LANE_TIMING_CTRL_OFFSET;
+ }
- /* strength, 2 * 5 */
- cnt = 2;
+ /* strength, 2 * MDSS_DSI_NUM_DATA_LANES */
+ cnt = DSIPHY_LANE_STRENGTH_CTRL_NUM;
+ off = DSIPHY_LANE_STRENGTH_CTRL_BASE;
ln_off = cnt * ln;
ip = &pd->strength[ln_off];
- off = 0x38;
- for (j = 0; j < cnt; j++, off += 4)
+ for (j = 0; j < cnt; j++) {
MIPI_OUTP(base + off, *ip++);
+ off += DSIPHY_LANE_STRENGTH_CTRL_OFFSET;
+ }
+
+ base += DATALANE_SIZE_8996; /* next lane */
+ }
+
+ /*
+ * clk lane configuration
+ * for split link there are two clock lanes, one
+ * clock lane per sublink needs to be configured
+ */
+ base = ctrl->phy_io.base + CLKLANE_OFFSET_FROM_BASE_8996;
+ cnt = DSIPHY_LANE_CFG_NUM;
+ off = DSIPHY_LANE_CFG_BASE;
+ ln_off = cnt * MDSS_DSI_NUM_DATA_LANES;
+ ip = &pd->lanecfg[ln_off];
+ for (j = 0; j < cnt; j++, *ip++) {
+ MIPI_OUTP(base + off, *ip);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, *ip);
+ off += DSIPHY_LANE_CFG_OFFSET;
+ }
+
+ /* test str */
+ MIPI_OUTP(base + DSIPHY_LANE_TEST_STR, 0x88); /* fixed */
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, 0x88);
+
+ cnt = DSIPHY_LANE_TIMING_CTRL_NUM;
+ off = DSIPHY_LANE_TIMING_CTRL_BASE;
+ ln_off = cnt * MDSS_DSI_NUM_DATA_LANES;
+ ip = &pd->timing_8996[ln_off];
+ for (j = 0; j < cnt; j++, *ip++) {
+ MIPI_OUTP(base + off, *ip);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, *ip);
+ off += DSIPHY_LANE_TIMING_CTRL_OFFSET;
+ }
+
+ /*
+ * clk lane configuration for timing
+ * for split link there are two clock lanes, one
+ * clock lane per sublink needs to be configured
+ */
+ cnt = DSIPHY_LANE_STRENGTH_CTRL_NUM;
+ off = DSIPHY_LANE_STRENGTH_CTRL_BASE;
+ ln_off = cnt * MDSS_DSI_NUM_DATA_LANES;
+ ip = &pd->strength[ln_off];
+ for (j = 0; j < cnt; j++, *ip++) {
+ MIPI_OUTP(base + off, *ip);
+ if (panel_info->split_link_enabled)
+ MIPI_OUTP(base + CLKLANE_SIZE_8996 + off, *ip);
+ off += DSIPHY_LANE_STRENGTH_CTRL_OFFSET;
}
wmb(); /* make sure registers committed */
@@ -1665,6 +1819,9 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
u32 dsi_pclk_rate;
u8 lanes = 0, bpp;
+ if (!panel_info)
+ return -EINVAL;
+
if (panel_info->mipi.data_lane3)
lanes += 1;
if (panel_info->mipi.data_lane2)
@@ -1690,6 +1847,8 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
}
h_period = mdss_panel_get_htotal(panel_info, true);
+ if (panel_info->split_link_enabled)
+ h_period *= panel_info->mipi.num_of_sublinks;
v_period = mdss_panel_get_vtotal(panel_info);
if (ctrl_pdata->refresh_clk_rate || is_diff_frame_rate(panel_info,
@@ -1710,7 +1869,12 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
clk_rate = panel_info->clk_rate;
do_div(clk_rate, 8 * bpp);
- dsi_pclk_rate = (u32) clk_rate * lanes;
+
+ if (panel_info->split_link_enabled)
+ dsi_pclk_rate = (u32) clk_rate *
+ panel_info->mipi.lanes_per_sublink;
+ else
+ dsi_pclk_rate = (u32) clk_rate * lanes;
if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 250000000))
dsi_pclk_rate = 35000000;
@@ -2320,6 +2484,32 @@ int mdss_dsi_pre_clkoff_cb(void *priv,
return rc;
}
+static void mdss_dsi_split_link_clk_cfg(struct mdss_dsi_ctrl_pdata *ctrl,
+ int enable)
+{
+ struct mdss_panel_data *pdata = NULL;
+ void __iomem *base;
+ u32 data = 0;
+
+ if (ctrl)
+ pdata = &ctrl->panel_data;
+ else {
+ pr_err("%s: ctrl pdata is NULL\n", __func__);
+ return;
+ }
+
+ /*
+ * for split link there are two clock lanes, and
+ * both clock lanes needs to be enabled
+ */
+ if (pdata->panel_info.split_link_enabled) {
+ base = ctrl->phy_io.base;
+ data = MIPI_INP(base + MDSS_DSI_DSIPHY_CMN_CLK_CFG1);
+ data |= (enable << DSIPHY_CMN_CLK_CFG1_SPLIT_LINK);
+ MIPI_OUTP(base + MDSS_DSI_DSIPHY_CMN_CLK_CFG1, data);
+ }
+}
+
int mdss_dsi_post_clkon_cb(void *priv,
enum mdss_dsi_clk_type clk,
enum mdss_dsi_clk_state curr_state)
@@ -2393,6 +2583,9 @@ int mdss_dsi_post_clkon_cb(void *priv,
}
if (pdata->panel_info.mipi.force_clk_lane_hs)
mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 1);
+
+ /* enable split link for cmn clk cfg1 */
+ mdss_dsi_split_link_clk_cfg(ctrl, 1);
}
error:
return rc;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 186d2ab9cd13..3c10d4638646 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2146,6 +2146,17 @@ static inline void vm_stat_account(struct mm_struct *mm,
}
#endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_PAGE_POISONING
+extern bool page_poisoning_enabled(void);
+extern void kernel_poison_pages(struct page *page, int numpages, int enable);
+extern bool page_is_poisoned(struct page *page);
+#else
+static inline bool page_poisoning_enabled(void) { return false; }
+static inline void kernel_poison_pages(struct page *page, int numpages,
+ int enable) { }
+static inline bool page_is_poisoned(struct page *page) { return false; }
+#endif
+
#ifdef CONFIG_DEBUG_PAGEALLOC
extern bool _debug_pagealloc_enabled;
extern void __kernel_map_pages(struct page *page, int numpages, int enable);
@@ -2295,7 +2306,6 @@ extern void copy_user_huge_page(struct page *dst, struct page *src,
#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
extern struct page_ext_operations debug_guardpage_ops;
-extern struct page_ext_operations page_poisoning_ops;
#ifdef CONFIG_DEBUG_PAGEALLOC
extern unsigned int _debug_guardpage_minorder;
diff --git a/include/linux/poison.h b/include/linux/poison.h
index 317e16de09e5..199ffec4bdf3 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -30,7 +30,11 @@
#define TIMER_ENTRY_STATIC ((void *) 0x74737461)
/********** mm/debug-pagealloc.c **********/
+#ifdef CONFIG_PAGE_POISONING_ZERO
+#define PAGE_POISON 0x00
+#else
#define PAGE_POISON 0xaa
+#endif
/********** mm/slab.c **********/
/*
diff --git a/include/linux/usb/ccid_desc.h b/include/linux/usb/ccid_desc.h
index 9a0c72650cd2..2e6dbb5afe71 100644
--- a/include/linux/usb/ccid_desc.h
+++ b/include/linux/usb/ccid_desc.h
@@ -86,27 +86,27 @@
* Table 5.1-1 Smart Card Device Class descriptors
*/
struct usb_ccid_class_descriptor {
- unsigned char bLength;
- unsigned char bDescriptorType;
- unsigned short bcdCCID;
- unsigned char bMaxSlotIndex;
- unsigned char bVoltageSupport;
- unsigned long dwProtocols;
- unsigned long dwDefaultClock;
- unsigned long dwMaximumClock;
- unsigned char bNumClockSupported;
- unsigned long dwDataRate;
- unsigned long dwMaxDataRate;
- unsigned char bNumDataRatesSupported;
- unsigned long dwMaxIFSD;
- unsigned long dwSynchProtocols;
- unsigned long dwMechanical;
- unsigned long dwFeatures;
- unsigned long dwMaxCCIDMessageLength;
- unsigned char bClassGetResponse;
- unsigned char bClassEnvelope;
- unsigned short wLcdLayout;
- unsigned char bPINSupport;
- unsigned char bMaxCCIDBusySlots;
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 bcdCCID;
+ __u8 bMaxSlotIndex;
+ __u8 bVoltageSupport;
+ __u32 dwProtocols;
+ __u32 dwDefaultClock;
+ __u32 dwMaximumClock;
+ __u8 bNumClockSupported;
+ __u32 dwDataRate;
+ __u32 dwMaxDataRate;
+ __u8 bNumDataRatesSupported;
+ __u32 dwMaxIFSD;
+ __u32 dwSynchProtocols;
+ __u32 dwMechanical;
+ __u32 dwFeatures;
+ __u32 dwMaxCCIDMessageLength;
+ __u8 bClassGetResponse;
+ __u8 bClassEnvelope;
+ __u16 wLcdLayout;
+ __u8 bPINSupport;
+ __u8 bMaxCCIDBusySlots;
} __packed;
#endif
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 75d0912aa459..762f1c51620c 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -41,6 +41,7 @@ struct msm_camera_sensor_slave_info32 {
uint8_t is_init_params_valid;
struct msm_sensor_init_params sensor_init_params;
enum msm_sensor_output_format_t output_format;
+ uint8_t bypass_video_node_creation;
};
struct msm_camera_csid_lut_params32 {
diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h
index 763eaa9ad918..59749210001a 100644
--- a/include/soc/qcom/subsystem_restart.h
+++ b/include/soc/qcom/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
struct subsys_device;
+extern struct bus_type subsys_bus_type;
enum {
RESET_SOC = 0,
diff --git a/include/uapi/linux/hbtp_input.h b/include/uapi/linux/hbtp_input.h
index 9173c2ab72ed..3b124ffcdcf3 100644
--- a/include/uapi/linux/hbtp_input.h
+++ b/include/uapi/linux/hbtp_input.h
@@ -6,6 +6,8 @@
#define HBTP_MAX_FINGER 20
#define HBTP_ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
#define HBTP_ABS_MT_LAST ABS_MT_TOOL_Y
+#define MAX_ROI_SIZE 144
+#define MAX_ACCEL_SIZE 128
#define HBTP_EVENT_TYPE_DISPLAY "EVENT_TYPE=HBTP_DISPLAY"
@@ -20,6 +22,11 @@ struct hbtp_input_touch {
__s32 orientation;
};
+struct hbtp_sensor_data {
+ __s16 accelBuffer[MAX_ACCEL_SIZE];
+ __s16 ROI[MAX_ROI_SIZE];
+};
+
struct hbtp_input_mt {
__s32 num_touches;
struct hbtp_input_touch touches[HBTP_MAX_FINGER];
@@ -68,6 +75,8 @@ enum hbtp_afe_power_ctrl {
enum hbtp_afe_signal)
#define HBTP_SET_POWER_CTRL _IOW(HBTP_INPUT_IOCTL_BASE, 206, \
enum hbtp_afe_power_ctrl)
+#define HBTP_SET_SENSORDATA _IOW(HBTP_INPUT_IOCTL_BASE, 207, \
+ struct hbtp_sensor_data)
#endif /* _UAPI_HBTP_INPUT_H */
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index ad0825e33217..83927c614e91 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -48,6 +48,8 @@
#define MSM_EEPROM_MEMORY_MAP_MAX_SIZE 80
#define MSM_EEPROM_MAX_MEM_MAP_CNT 8
+#define MSM_SENSOR_BYPASS_VIDEO_NODE 1
+
enum msm_sensor_camera_id_t {
CAMERA_0,
CAMERA_1,
@@ -300,6 +302,7 @@ struct msm_camera_sensor_slave_info {
unsigned char is_init_params_valid;
struct msm_sensor_init_params sensor_init_params;
enum msm_sensor_output_format_t output_format;
+ uint8_t bypass_video_node_creation;
};
struct msm_camera_i2c_reg_array {
diff --git a/include/uapi/media/msmb_ispif.h b/include/uapi/media/msmb_ispif.h
index 3720056aa28d..c3a6e006b2ff 100644
--- a/include/uapi/media/msmb_ispif.h
+++ b/include/uapi/media/msmb_ispif.h
@@ -36,7 +36,6 @@ enum msm_ispif_intftype {
#define RDI1_MASK (1 << RDI1)
#define RDI2_MASK (1 << RDI2)
-
enum msm_ispif_vc {
VC0,
VC1,
@@ -102,10 +101,17 @@ struct msm_ispif_params_entry {
uint16_t crop_end_pixel;
};
+struct msm_ispif_right_param_entry {
+ enum msm_ispif_cid cids[MAX_CID_CH_PARAM_ENTRY];
+ enum msm_ispif_csid csid;
+};
+
struct msm_ispif_param_data_ext {
uint32_t num;
struct msm_ispif_params_entry entries[MAX_PARAM_ENTRIES];
struct msm_ispif_pack_cfg pack_cfg[CID_MAX];
+ struct msm_ispif_right_param_entry right_entries[MAX_PARAM_ENTRIES];
+ uint32_t stereo_enable;
};
struct msm_ispif_param_data {
@@ -157,6 +163,8 @@ struct ispif_cfg_data_ext {
#define ISPIF_RDI_PACK_MODE_SUPPORT 1
+#define ISPIF_3D_SUPPORT 1
+
#define VIDIOC_MSM_ISPIF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE, struct ispif_cfg_data)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 0ca3599cee1f..e822cb0e18d5 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -593,8 +593,9 @@ out:
if (!switch_err) {
switch_err = switch_to_fair_policy();
- pr_err("Hotplug policy switch err. Task %s pid=%d\n",
- current->comm, current->pid);
+ if (switch_err)
+ pr_err("Hotplug policy switch err=%d Task %s pid=%d\n",
+ switch_err, current->comm, current->pid);
}
return err;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 3124cebaec31..2fc1177383a0 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -1159,6 +1159,22 @@ static int __init kaslr_nohibernate_setup(char *str)
return nohibernate_setup(str);
}
+static int __init page_poison_nohibernate_setup(char *str)
+{
+#ifdef CONFIG_PAGE_POISONING_ZERO
+ /*
+ * The zeroing option for page poison skips the checks on alloc.
+ * since hibernation doesn't save free pages there's no way to
+ * guarantee the pages will still be zeroed.
+ */
+ if (!strcmp(str, "on")) {
+ pr_info("Disabling hibernation due to page poisoning\n");
+ return nohibernate_setup(str);
+ }
+#endif
+ return 1;
+}
+
__setup("noresume", noresume_setup);
__setup("resume_offset=", resume_offset_setup);
__setup("resume=", resume_setup);
@@ -1167,3 +1183,4 @@ __setup("resumewait", resumewait_setup);
__setup("resumedelay=", resumedelay_setup);
__setup("nohibernate", nohibernate_setup);
__setup("kaslr", kaslr_nohibernate_setup);
+__setup("page_poison=", page_poison_nohibernate_setup);
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index 9e55d6b141aa..7470fd60fc59 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -40,9 +40,6 @@ config DEBUG_PAGEALLOC_ENABLE_DEFAULT
Enable debug page memory allocations by default? This value
can be overridden by debug_pagealloc=off|on.
-config PAGE_POISONING
- bool
-
config SLUB_DEBUG_PANIC_ON
bool "Enable to Panic on SLUB corruption detection"
depends on SLUB_DEBUG
@@ -52,3 +49,53 @@ config SLUB_DEBUG_PANIC_ON
debug options this may not be desirable as it prevents from
investigating the root cause which may be rooted within cache
or memory.
+
+config PAGE_POISONING
+ bool "Poison pages after freeing"
+ select PAGE_EXTENSION
+ select PAGE_POISONING_NO_SANITY if HIBERNATION
+ ---help---
+ Fill the pages with poison patterns after free_pages() and verify
+ the patterns before alloc_pages. The filling of the memory helps
+ reduce the risk of information leaks from freed data. This does
+ have a potential performance impact.
+
+ Note that "poison" here is not the same thing as the "HWPoison"
+ for CONFIG_MEMORY_FAILURE. This is software poisoning only.
+
+ If unsure, say N
+
+config PAGE_POISONING_ENABLE_DEFAULT
+ bool "Enable page poisoning by default?"
+ default n
+ depends on PAGE_POISONING
+ ---help---
+ Enable page poisoning of free pages by default? This value
+ can be overridden by page_poison=off|on. This can be used
+ to avoid passing the kernel parameter and let page poisoning
+ feature enabled by default.
+
+config PAGE_POISONING_NO_SANITY
+ depends on PAGE_POISONING
+ bool "Only poison, don't sanity check"
+ ---help---
+ Skip the sanity checking on alloc, only fill the pages with
+ poison on free. This reduces some of the overhead of the
+ poisoning feature.
+
+ If you are only interested in sanitization, say Y. Otherwise
+ say N.
+
+config PAGE_POISONING_ZERO
+ bool "Use zero for poisoning instead of random data"
+ depends on PAGE_POISONING
+ ---help---
+ Instead of using the existing poison value, fill the pages with
+ zeros. This makes it harder to detect when errors are occurring
+ due to sanitization but the zeroing at free means that it is
+ no longer necessary to write zeros when GFP_ZERO is used on
+ allocation.
+
+ Enabling page poisoning with this option will disable hibernation
+
+ If unsure, say N
diff --git a/mm/Makefile b/mm/Makefile
index 4b1a69abce7a..130d06ac56e0 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -52,7 +52,7 @@ obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
obj-$(CONFIG_SLOB) += slob.o
obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
obj-$(CONFIG_KSM) += ksm.o
-obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
+obj-$(CONFIG_PAGE_POISONING) += page_poison.o
obj-$(CONFIG_SLAB) += slab.o
obj-$(CONFIG_SLUB) += slub.o
obj-$(CONFIG_KMEMCHECK) += kmemcheck.o
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 28f60d9ea074..170c1486e5c9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1012,6 +1012,7 @@ static bool free_pages_prepare(struct page *page, unsigned int order)
PAGE_SIZE << order);
}
arch_free_page(page, order);
+ kernel_poison_pages(page, 1 << order, 0);
kernel_map_pages(page, 1 << order, 0);
kasan_free_pages(page, order);
@@ -1396,6 +1397,12 @@ static inline int check_new_page(struct page *page)
return 0;
}
+static inline bool free_pages_prezeroed(void)
+{
+ return IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) &&
+ page_poisoning_enabled();
+}
+
static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
int alloc_flags)
{
@@ -1413,8 +1420,9 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
kasan_alloc_pages(page, order);
arch_alloc_page(page, order);
kernel_map_pages(page, 1 << order, 1);
+ kernel_poison_pages(page, 1 << order, 1);
- if (gfp_flags & __GFP_ZERO)
+ if (!free_pages_prezeroed() && (gfp_flags & __GFP_ZERO))
for (i = 0; i < (1 << order); i++)
clear_highpage(page + i);
diff --git a/mm/page_ext.c b/mm/page_ext.c
index 292ca7b8debd..916accfec86a 100644
--- a/mm/page_ext.c
+++ b/mm/page_ext.c
@@ -54,9 +54,6 @@
static struct page_ext_operations *page_ext_ops[] = {
&debug_guardpage_ops,
-#ifdef CONFIG_PAGE_POISONING
- &page_poisoning_ops,
-#endif
#ifdef CONFIG_PAGE_OWNER
&page_owner_ops,
#endif
@@ -106,12 +103,15 @@ struct page_ext *lookup_page_ext(struct page *page)
struct page_ext *base;
base = NODE_DATA(page_to_nid(page))->node_page_ext;
-#ifdef CONFIG_DEBUG_VM
+#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAGE_POISONING)
/*
* The sanity checks the page allocator does upon freeing a
* page can reach here before the page_ext arrays are
* allocated when feeding a range of pages to the allocator
* for the first time during bootup or memory hotplug.
+ *
+ * This check is also necessary for ensuring page poisoning
+ * works as expected when enabled
*/
if (unlikely(!base))
return NULL;
@@ -180,12 +180,15 @@ struct page_ext *lookup_page_ext(struct page *page)
{
unsigned long pfn = page_to_pfn(page);
struct mem_section *section = __pfn_to_section(pfn);
-#ifdef CONFIG_DEBUG_VM
+#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAGE_POISONING)
/*
* The sanity checks the page allocator does upon freeing a
* page can reach here before the page_ext arrays are
* allocated when feeding a range of pages to the allocator
* for the first time during bootup or memory hotplug.
+ *
+ * This check is also necessary for ensuring page poisoning
+ * works as expected when enabled
*/
if (!section->page_ext)
return NULL;
diff --git a/mm/debug-pagealloc.c b/mm/page_poison.c
index 100963091cc6..c8cf230dbfcb 100644
--- a/mm/debug-pagealloc.c
+++ b/mm/page_poison.c
@@ -6,68 +6,41 @@
#include <linux/poison.h>
#include <linux/ratelimit.h>
-#ifndef mark_addr_rdonly
-#define mark_addr_rdonly(a)
-#endif
-
-#ifndef mark_addr_rdwrite
-#define mark_addr_rdwrite(a)
-#endif
-
-static bool page_poisoning_enabled __read_mostly;
-
-static bool need_page_poisoning(void)
-{
- if (!debug_pagealloc_enabled())
- return false;
-
- return true;
-}
-
-static void init_page_poisoning(void)
-{
- if (!debug_pagealloc_enabled())
- return;
-
- page_poisoning_enabled = true;
-}
-
-struct page_ext_operations page_poisoning_ops = {
- .need = need_page_poisoning,
- .init = init_page_poisoning,
-};
+static bool want_page_poisoning __read_mostly
+ = IS_ENABLED(CONFIG_PAGE_POISONING_ENABLE_DEFAULT);
-static inline void set_page_poison(struct page *page)
+static int early_page_poison_param(char *buf)
{
- struct page_ext *page_ext;
+ if (!buf)
+ return -EINVAL;
- page_ext = lookup_page_ext(page);
- __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
-}
-
-static inline void clear_page_poison(struct page *page)
-{
- struct page_ext *page_ext;
+ if (strcmp(buf, "on") == 0)
+ want_page_poisoning = true;
+ else if (strcmp(buf, "off") == 0)
+ want_page_poisoning = false;
- page_ext = lookup_page_ext(page);
- __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
+ return 0;
}
+early_param("page_poison", early_page_poison_param);
-static inline bool page_poison(struct page *page)
+bool page_poisoning_enabled(void)
{
- struct page_ext *page_ext;
-
- page_ext = lookup_page_ext(page);
- return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
+ /*
+ * Assumes that debug_pagealloc_enabled is set before
+ * free_all_bootmem.
+ * Page poisoning is debug page alloc for some arches. If
+ * either of those options are enabled, enable poisoning.
+ */
+ return (want_page_poisoning ||
+ (!IS_ENABLED(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) &&
+ debug_pagealloc_enabled()));
}
static void poison_page(struct page *page)
{
void *addr = kmap_atomic(page);
- set_page_poison(page);
memset(addr, PAGE_POISON, PAGE_SIZE);
- mark_addr_rdonly(addr);
kunmap_atomic(addr);
}
@@ -93,6 +66,9 @@ static void check_poison_mem(struct page *page,
unsigned char *start;
unsigned char *end;
+ if (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY))
+ return;
+
start = memchr_inv(mem, PAGE_POISON, bytes);
if (!start)
return;
@@ -121,13 +97,13 @@ static void unpoison_page(struct page *page)
{
void *addr;
- if (!page_poison(page))
- return;
-
addr = kmap_atomic(page);
+ /*
+ * Page poisoning when enabled poisons each and every page
+ * that is freed to buddy. Thus no extra check is done to
+ * see if a page was posioned.
+ */
check_poison_mem(page, addr, PAGE_SIZE);
- mark_addr_rdwrite(addr);
- clear_page_poison(page);
kunmap_atomic(addr);
}
@@ -139,9 +115,9 @@ static void unpoison_pages(struct page *page, int n)
unpoison_page(page + i);
}
-void __kernel_map_pages(struct page *page, int numpages, int enable)
+void kernel_poison_pages(struct page *page, int numpages, int enable)
{
- if (!page_poisoning_enabled)
+ if (!page_poisoning_enabled())
return;
if (enable)
@@ -149,3 +125,10 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
else
poison_pages(page, numpages);
}
+
+#ifndef CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC
+void __kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ /* This function does nothing, all work is done via poison pages */
+}
+#endif
diff --git a/sound/soc/codecs/wcd-spi.c b/sound/soc/codecs/wcd-spi.c
index 3d2fe2c6bed9..fde1d3e815d3 100644
--- a/sound/soc/codecs/wcd-spi.c
+++ b/sound/soc/codecs/wcd-spi.c
@@ -553,7 +553,7 @@ static int wcd_spi_clk_enable(struct spi_device *spi)
{
struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi);
int ret;
- u32 rd_status;
+ u32 rd_status = 0;
ret = wcd_spi_cmd_nop(spi);
if (IS_ERR_VALUE(ret)) {
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index a2b7fb7a3bca..7ad3aeaa8fb7 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -4945,7 +4945,7 @@ static int tasha_codec_enable_spline_src(struct snd_soc_codec *codec,
int src_num,
int event)
{
- u16 src_paired_reg;
+ u16 src_paired_reg = 0;
struct tasha_priv *tasha;
u16 rx_path_cfg_reg = WCD9335_CDC_RX1_RX_PATH_CFG0;
u16 rx_path_ctl_reg = WCD9335_CDC_RX1_RX_PATH_CTL;
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index e502d6340ffb..a0514c8a1ee5 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -5476,7 +5476,7 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
u32 adc, i, mic_bias_found = 0;
int ret = 0;
char *mad_input;
- bool is_adc2_input = false;
+ bool is_adc_input = false;
tavil_mad_input = ucontrol->value.integer.value[0];
@@ -5524,8 +5524,7 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
mad_input_widget = mad_amic_input_widget;
- if (adc == 2)
- is_adc2_input = true;
+ is_adc_input = true;
} else {
/* DMIC type input widget*/
mad_input_widget = tavil_conn_mad_text[tavil_mad_input];
@@ -5533,7 +5532,7 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
dev_dbg(codec->dev,
"%s: tavil input widget = %s, adc_input = %s\n", __func__,
- mad_input_widget, is_adc2_input ? "true" : "false");
+ mad_input_widget, is_adc_input ? "true" : "false");
for (i = 0; i < card->num_of_dapm_routes; i++) {
if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) {
@@ -5578,8 +5577,8 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
0x0F, tavil_mad_input);
snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
0x07, mic_bias_found);
- /* for adc2 input, mad should be in micbias mode with BG enabled */
- if (is_adc2_input)
+ /* for all adc inputs, mad should be in micbias mode with BG enabled */
+ if (is_adc_input)
snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
0x88, 0x88);
else
diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c
index 2082c356203d..3b681f53b17a 100644
--- a/sound/soc/codecs/wcd_cpe_core.c
+++ b/sound/soc/codecs/wcd_cpe_core.c
@@ -3556,6 +3556,8 @@ static int wcd_cpe_lsm_lab_control(
pr_debug("%s: enter payload_size = %d Enable %d\n",
__func__, pld_size, enable);
+ memset(&cpe_lab_enable, 0, sizeof(cpe_lab_enable));
+
if (fill_lsm_cmd_header_v0_inband(&cpe_lab_enable.hdr, session->id,
(u8) pld_size, CPE_LSM_SESSION_CMD_SET_PARAMS_V2)) {
return -EINVAL;
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index ec02cdf3ca3c..0f09c68ab344 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -4155,9 +4155,6 @@ static void update_mi2s_clk_val(int dai_id, int stream)
mi2s_clk[dai_id].clk_freq_in_hz =
mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
}
-
- if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master)
- mi2s_clk[dai_id].clk_freq_in_hz = 0;
}
static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-slim.c b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
index 43a27eb35a44..64ecd7e031f0 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-slim.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-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
@@ -314,7 +314,7 @@ static int msm_dai_slim_prepare(struct snd_pcm_substream *substream,
struct msm_slim_dai_data *dai_data = NULL;
struct slim_ch prop;
int rc;
- u8 i;
+ u8 i, j;
dai_data = msm_slim_get_dai_data(drv_data, dai);
if (!dai_data) {
@@ -351,10 +351,6 @@ static int msm_dai_slim_prepare(struct snd_pcm_substream *substream,
}
}
- /* To decrement the channel ref count*/
- for (i = 0; i < dai_data->ch_cnt; i++)
- slim_dealloc_ch(drv_data->sdev, dai_data->chan_h[i]);
-
prop.prot = SLIM_AUTO_ISO;
prop.baser = SLIM_RATE_4000HZ;
prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
@@ -378,6 +374,8 @@ static int msm_dai_slim_prepare(struct snd_pcm_substream *substream,
error_define_chan:
error_chan_query:
+ for (j = 0; j < i; j++)
+ slim_dealloc_ch(drv_data->sdev, dai_data->chan_h[j]);
return rc;
}
@@ -387,6 +385,7 @@ static void msm_dai_slim_shutdown(struct snd_pcm_substream *stream,
struct msm_dai_slim_drv_data *drv_data = dev_get_drvdata(dai->dev);
struct msm_slim_dma_data *dma_data = NULL;
struct msm_slim_dai_data *dai_data;
+ int i, rc = 0;
dai_data = msm_slim_get_dai_data(drv_data, dai);
dma_data = snd_soc_dai_get_dma_data(dai, stream);
@@ -405,6 +404,15 @@ static void msm_dai_slim_shutdown(struct snd_pcm_substream *stream,
return;
}
+ for (i = 0; i < dai_data->ch_cnt; i++) {
+ rc = slim_dealloc_ch(drv_data->sdev, dai_data->chan_h[i]);
+ if (rc) {
+ dev_err(dai->dev,
+ "%s: dealloc_ch failed, err = %d\n",
+ __func__, rc);
+ }
+ }
+
snd_soc_dai_set_dma_data(dai, stream, NULL);
/* clear prepared state for the dai */
CLR_DAI_STATE(dai_data->status, DAI_STATE_PREPARED);
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index edf5719fbf3e..90b661dff7ec 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -2412,9 +2412,6 @@ static void update_mi2s_clk_val(int dai_id, int stream)
mi2s_clk[dai_id].clk_freq_in_hz =
mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
}
-
- if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master)
- mi2s_clk[dai_id].clk_freq_in_hz = 0;
}
static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)