diff options
109 files changed, 2584 insertions, 662 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index f9b9ad7894f5..02431aeca15f 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -136,6 +136,7 @@ !Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result +!Finclude/net/cfg80211.h cfg80211_connect_bss !Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_disconnected !Finclude/net/cfg80211.h cfg80211_ready_on_channel diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 42daa8a61e4c..7b1c081ef586 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -92,6 +92,9 @@ SoCs: - MSMFALCON compatible = "qcom,msmfalcon" +- MSMTRITON + compatible = "qcom,msmtriton" + - MSM8952 compatible = "qcom,msm8952" @@ -259,6 +262,7 @@ compatible = "qcom,msmhamster-cdp" compatible = "qcom,msmhamster-mtp" compatible = "qcom,msmfalcon-sim" compatible = "qcom,msmfalcon-rumi" +compatible = "qcom,msmtriton-rumi" compatible = "qcom,msm8952-rumi" compatible = "qcom,msm8952-sim" compatible = "qcom,msm8952-qrd" diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt index cee9b942a9e3..e6593251b4fd 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt @@ -16,12 +16,14 @@ Properties: Value type: <prop-encoded-array> Definition: Addresses and sizes for the memory of the OSM controller, cluster PLL management, and APCS common register regions. - + Optionally, the address of the efuse registers used to + determine the pwrcl or perfcl speed-bins. - reg-names Usage: required Value type: <stringlist> Definition: Address names. Must be "osm", "pwrcl_pll", "perfcl_pll", - and "apcs_common". + "apcs_common" and "debug". Optionally, "pwrcl_efuse" or + "perfcl_efuse". Must be specified in the same order as the corresponding addresses are specified in the reg property. @@ -301,9 +303,10 @@ Example: reg = <0x179C0000 0x4000>, <0x17916000 0x1000>, <0x17816000 0x1000>, - <0x179D1000 0x1000>; + <0x179D1000 0x1000>, + <0x1791101c 0x8>; reg-names = "osm", "pwrcl_pll", "perfcl_pll", - "apcs_common"; + "apcs_common", "debug"; vdd-pwrcl-supply = <&apc0_pwrcl_vreg>; vdd-perfcl-supply = <&apc1_perfcl_vreg>; diff --git a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt index da4cdf253b2c..628b4df9fd7d 100644 --- a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt +++ b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt @@ -53,23 +53,29 @@ Optional properties: - "secondary" - "tertiary" -[Optional child nodes]: These nodes are for devices which are -dependent on HDMI Tx controller. If HDMI Tx controller is disabled then -these devices will be disabled as well. Ex. HDMI Audio Codec device. - -- qcom,msm-hdmi-audio-rx: Node for HDMI audio codec. -Required properties: -- compatible : "msm-hdmi-audio-codec-rx"; - msm_ext_disp is a device which manages the interaction between external displays (HDMI and Display Port) and the audio and display frameworks. Required properties: - compatible: Must be "qcom,msm-ext-disp" +[Required child nodes]: These nodes are for devices which are +dependent on msm_ext_disp. If msm_ext_disp is disabled then +these devices will be disabled as well. Ex. Audio Codec device. + +- ext_disp_audio_codec: Node for Audio Codec. + +Required properties: +- compatible : "qcom,msm-ext-disp-audio-codec-rx"; + Example: msm_ext_disp: qcom,msm_ext_disp { compatible = "qcom,msm-ext-disp"; + + ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { + compatible = "qcom,msm-ext-disp-audio-codec-rx"; + qcom,msm_ext_disp = <&msm_ext_disp>; + }; }; mdss_hdmi_tx: qcom,hdmi_tx@fd922100 { @@ -109,9 +115,6 @@ Example: qcom,pluggable; qcom,display-id = "secondary"; - qcom,msm-hdmi-audio-rx { - compatible = "qcom,msm-hdmi-audio-codec-rx"; - }; pinctrl-names = "hdmi_hpd_active", "hdmi_ddc_active", "hdmi_cec_active", "hdmi_active", "hdmi_sleep"; diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt index ec8b08ad60e4..f7494c4c6e2b 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt @@ -72,6 +72,9 @@ Optional properties: - focaltech,psensor-support : specify whether support the proximity sensor - focaltech,gesture-support : specify whether support gesture feature - focaltech,resume-in-workqueue : specifiy whether to defer the resume to workqueue + - clock-names: : Clock names used for secure touch. They are: "iface_clk", "core_clk" + - clocks : Defined if 'clock-names' DT property is defined. These clocks + are associated with the underlying I2C bus. Example: i2c@f9923000{ @@ -109,5 +112,9 @@ Example: focaltech,fw-auto-cal; focaltech,psensor-support; focaltech,gesture-support; + /* Underlying clocks used by secure touch */ + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>; }; }; diff --git a/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt b/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt index 7d88e9fbd9c6..af53e59cd87f 100644 --- a/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt @@ -35,13 +35,15 @@ Platform independent properties: - reg Usage: required Value type: <prop-encoded-array> - Definition: Addresses and sizes for the memory of the CPR3 controller - and the first fuse row + Definition: Addresses and sizes for the memory of the CPR3 controller, + the first fuse row, and optionally a register used to check + if aging measurements are possible. - reg-names Usage: required Value type: <stringlist> - Definition: Address names. Must be "cpr_ctrl" and "fuse_base". Must be + Definition: Address names. Must include "cpr_ctrl" and "fuse_base". + "aging_allowed" may also be specified. The strings must be specified in the same order as the corresponding addresses are specified in the reg property. @@ -183,6 +185,17 @@ Platform independent properties: This is the voltage that vdd-supply must be set to when performing an aging measurement. +- qcom,cpr-aging-allowed-reg-mask + Usage: required if "aging_allowed" register is specified + Value type: <u32> + Definition: Bitmask used to mask off the "aging_allowed" register. + +- qcom,cpr-aging-allowed-reg-value + Usage: required if "aging_allowed" register is specified + Value type: <u32> + Definition: Value required in the masked off "aging_allowed" register + bits in order for a CPR aging measurement to be possible. + - qcom,cpr-panic-reg-addr-list Usage: optional Value type: <prop-encoded-array> diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index f6dadb738175..a01bd451c577 100755 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -470,6 +470,11 @@ Example: qcom,msm-dai-q6-dev-id = <8>; }; + dai_dp: qcom,msm-dai-q6-dp { + compatible = "qcom,msm-dai-q6-hdmi"; + qcom,msm-dai-q6-dev-id = <24608>; + }; + qcom,msm-dai-q6 { compatible = "qcom,msm-dai-q6"; qcom,msm-dai-q6-sb-0-rx { @@ -784,7 +789,7 @@ Example: "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback", "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa"; - asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>, + asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>, <&dai_dp>, <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>, @@ -793,6 +798,7 @@ Example: <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, <&incall_music_2_rx>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8", + "msm-dai-q6-dp.24608", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", @@ -1157,7 +1163,7 @@ Example: <&bt_sco_tx>,<&int_fm_rx>,<&int_fm_tx>,<&afe_pcm_rx>, <&afe_pcm_tx>,<&afe_proxy_rx>,<&afe_proxy_tx>, <&incall_record_rx>,<&incall_record_tx>,<&incall_music_rx>, - <&incall_music2_rx>; + <&incall_music2_rx>,<&dai_dp>; asoc-cpu-names = "msm-dai-q6-auxpcm.1","msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8","msm-dai-q6-mi2s.0", "msm-dai-q6-dev.16384","msm-dai-q6-dev.16385", @@ -1171,7 +1177,7 @@ Example: "msm-dai-q6-dev.225","msm-dai-q6-dev.241", "msm-dai-q6-dev.240","msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772","msm-dai-q6-dev.32773", - "msm-dai-q6-dev.32770"; + "msm-dai-q6-dev.32770","msm-dai-q6-dp.24608"; asoc-codec = <&stub>; asoc-codec-names = "msm-stub-codec.1"; }; diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt index 0af26ca1f380..b45ee910258e 100644 --- a/Documentation/devicetree/bindings/usb/msm-phy.txt +++ b/Documentation/devicetree/bindings/usb/msm-phy.txt @@ -118,6 +118,10 @@ Required properties: USB3_PHY_POWER_DOWN_CONTROL, USB3_PHY_SW_RESET, USB3_PHY_START +- resets: reset specifier pair consists of phandle for the reset controller + and reset lines used by this controller. +- reset-names: reset signal name strings sorted in the same order as the resets + property. Optional properties: - reg: Additional register set of address and length to control QMP PHY are: @@ -126,7 +130,7 @@ Optional properties: - clocks: a list of phandles to the PHY clocks. Use as per Documentation/devicetree/bindings/clock/clock-bindings.txt - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" - property. Required clocks are "cfg_ahb_clk", "phy_reset" and "phy_phy_reset". + property. "cfg_ahb_clk" is an optional clock. - qcom,vbus-valid-override: If present, indicates VBUS pin is not connected to the USB PHY and the controller must rely on external VBUS notification in order to manually relay the notification to the SSPHY. @@ -150,13 +154,17 @@ Example: clocks = <&clock_gcc clk_gcc_usb3_phy_aux_clk>, <&clock_gcc clk_gcc_usb3_phy_pipe_clk>, <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>, - <&clock_gcc clk_gcc_usb3_phy_reset>, - <&clock_gcc clk_gcc_usb3phy_phy_reset>, <&clock_gcc clk_ln_bb_clk1>, <&clock_gcc clk_gcc_usb3_clkref_clk>; - clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", "phy_reset", - "phy_phy_reset", "ref_clk_src", "ref_clk"; + clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", + "ref_clk_src", "ref_clk"; + + resets = <&clock_gcc GCC_USB3_PHY_BCR>, + <&clock_gcc GCC_USB3PHY_PHY_BCR>; + reset-names = "phy_reset", + "phy_phy_reset"; + }; QUSB2 High-Speed PHY @@ -173,11 +181,11 @@ Required properties: - qcom,vdd-voltage-level: This property must be a list of three integer values (no, min, max) where each value represents either a voltage in microvolts or a value corresponding to voltage corner - - clocks: a list of phandles to the PHY clocks. Use as per - Documentation/devicetree/bindings/clock/clock-bindings.txt - - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" - property. Required clock is "phy_reset". - phy_type: Should be one of "ulpi" or "utmi". ChipIdea core uses "ulpi" mode. + - resets: reset specifier pair consists of phandle for the reset controller + and reset lines used by this controller. + - reset-names: reset signal name strings sorted in the same order as the resets + property. Optional properties: - reg-names: Additional registers corresponding with the following: @@ -218,7 +226,8 @@ Example: clocks = <&clock_rpm clk_ln_bb_clk>, <&clock_gcc clk_gcc_rx2_usb1_clkref_clk>, - <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>, - <&clock_gcc clk_gcc_qusb2_phy_reset>; - clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk", "phy_reset"; + <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>; + clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk"; + resets = <&clock_gcc GCC_QUSB2PHY_PRIM_BCR>; + reset-names = "phy_reset"; }; diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt index c5e5f1851fc2..f4d10908f4ff 100644 --- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt @@ -15,6 +15,10 @@ Required properties : - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" property. Required clocks are "xo", "iface_clk", "core_clk", "sleep_clk" and "utmi_clk". +- resets: reset specifier pair consists of phandle for the reset provider + and reset lines used by this controller. +- reset-names: reset signal name strings sorted in the same order as the resets + property. Optional properties : - reg: Additional registers @@ -99,6 +103,9 @@ Example MSM USB3.0 controller device node : clock-names = "core_clk", "iface_clk", "bus_aggr_clk", "utmi_clk", "sleep_clk", "cfg_ahb_clk", "xo"; + resets = <&clock_gcc GCC_USB_30_BCR>; + reset-names = "core_reset"; + dwc3@f9200000 { compatible = "synopsys,dwc3"; reg = <0xf9200000 0xfc000>; diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 073490062971..bffa21a06462 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -121,13 +121,18 @@ dtb-$(CONFIG_ARCH_MSMCOBALT) += msmcobalt-sim.dtb \ apqcobalt-v2-qrd.dtb \ msmcobalt-v2.1-mtp.dtb \ msmcobalt-v2.1-cdp.dtb \ - msmcobalt-v2.1-qrd.dtb + msmcobalt-v2.1-qrd.dtb \ + apqcobalt-v2.1-mtp.dtb \ + apqcobalt-v2.1-cdp.dtb \ + apqcobalt-v2.1-qrd.dtb dtb-$(CONFIG_ARCH_MSMHAMSTER) += msmhamster-rumi.dtb dtb-$(CONFIG_ARCH_MSMFALCON) += msmfalcon-sim.dtb \ msmfalcon-rumi.dtb +dtb-$(CONFIG_ARCH_MSMTRITON) += msmtriton-rumi.dtb + ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm/boot/dts/qcom/apqcobalt-v2.1-cdp.dts b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-cdp.dts new file mode 100644 index 000000000000..f0ab8e0afc78 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-cdp.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apqcobalt-v2.1.dtsi" +#include "msmcobalt-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ COBALT V2.1 CDP"; + compatible = "qcom,apqcobalt-cdp", "qcom,apqcobalt", "qcom,cdp"; + qcom,board-id = <1 0>; +}; diff --git a/arch/arm/boot/dts/qcom/apqcobalt-v2.1-mtp.dts b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-mtp.dts new file mode 100644 index 000000000000..e23134f8897b --- /dev/null +++ b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-mtp.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apqcobalt-v2.1.dtsi" +#include "msmcobalt-mtp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ COBALT V2.1 MTP"; + compatible = "qcom,apqcobalt-mtp", "qcom,apqcobalt", "qcom,mtp"; + qcom,board-id = <8 0>; +}; diff --git a/arch/arm/boot/dts/qcom/apqcobalt-v2.1-qrd.dts b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-qrd.dts new file mode 100644 index 000000000000..8da6f90958d2 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apqcobalt-v2.1-qrd.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apqcobalt-v2.1.dtsi" +#include "msmcobalt-qrd.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ COBALT V2.1 QRD"; + compatible = "qcom,apqcobalt-qrd", "qcom,apqcobalt", "qcom,qrd"; + qcom,board-id = <11 0>; +}; diff --git a/arch/arm/boot/dts/qcom/apqcobalt-v2.1.dtsi b/arch/arm/boot/dts/qcom/apqcobalt-v2.1.dtsi new file mode 100644 index 000000000000..5a49afecd60b --- /dev/null +++ b/arch/arm/boot/dts/qcom/apqcobalt-v2.1.dtsi @@ -0,0 +1,18 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msmcobalt-v2.1.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ COBALT V2.1"; + qcom,msm-id = <319 0x20001>; +}; diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi index f3233948d457..41b6f50c520b 100644 --- a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi @@ -76,6 +76,11 @@ qcom,msm-dai-q6-dev-id = <8>; }; + dai_dp: qcom,msm-dai-q6-dp { + compatible = "qcom,msm-dai-q6-hdmi"; + qcom,msm-dai-q6-dev-id = <24608>; + }; + loopback: qcom,msm-pcm-loopback { compatible = "qcom,msm-pcm-loopback"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index aa973e4ee3d6..e0d84e423e88 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -1934,6 +1934,9 @@ clock-names = "core_clk", "iface_clk", "bus_aggr_clk", "utmi_clk", "sleep_clk", "xo", "cfg_ahb_clk"; + resets = <&clock_gcc USB_30_BCR>; + reset-names = "core_reset"; + dwc3@6a00000 { compatible = "snps,dwc3"; reg = <0x06a00000 0xc8d0>; @@ -2039,6 +2042,8 @@ <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>; clock-names = "core_clk", "iface_clk", "utmi_clk", "sleep_clk", "xo", "cfg_ahb_clk"; + resets = <&clock_gcc USB_20_BCR>; + reset-names = "core_reset"; dwc3@7600000 { compatible = "snps,dwc3"; @@ -2088,10 +2093,11 @@ qcom,major-rev = <1>; clocks = <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>, - <&clock_gcc clk_gcc_qusb2phy_prim_reset>, <&clock_gcc clk_ln_bb_clk>; + clock-names = "cfg_ahb_clk", "ref_clk_src"; - clock-names = "cfg_ahb_clk", "phy_reset", "ref_clk_src"; + resets = <&clock_gcc QUSB2PHY_PRIM_BCR>; + reset-names = "phy_reset"; }; qusb_phy1: qusb@7412000 { @@ -2124,10 +2130,11 @@ qcom,hold-reset; clocks = <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>, - <&clock_gcc clk_gcc_qusb2phy_sec_reset>, - <&clock_gcc clk_ln_bb_clk>; + <&clock_gcc clk_ln_bb_clk>; + clock-names = "cfg_ahb_clk", "ref_clk_src"; - clock-names = "cfg_ahb_clk", "phy_reset", "ref_clk_src"; + resets = <&clock_gcc QUSB2PHY_SEC_BCR>; + reset-names = "phy_reset"; }; ssphy: ssphy@7410000 { @@ -2209,13 +2216,15 @@ clocks = <&clock_gcc clk_gcc_usb3_phy_aux_clk>, <&clock_gcc clk_gcc_usb3_phy_pipe_clk>, <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>, - <&clock_gcc clk_gcc_usb3_phy_reset>, - <&clock_gcc clk_gcc_usb3phy_phy_reset>, <&clock_gcc clk_ln_bb_clk>, <&clock_gcc clk_gcc_usb3_clkref_clk>; - clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", "phy_reset", - "phy_phy_reset", "ref_clk_src", "ref_clk"; + clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", + "ref_clk_src", "ref_clk"; + + resets = <&clock_gcc USB3_PHY_BCR>, + <&clock_gcc USB3PHY_PHY_BCR>; + reset-names = "phy_reset", "phy_phy_reset"; }; usb_nop_phy: usb_nop_phy { diff --git a/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi index 05328a0f29dc..ec69d7ac895d 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi @@ -34,7 +34,7 @@ sound-9335 { compatible = "qcom,msmcobalt-asoc-snd-tasha"; qcom,model = "msmcobalt-tasha-snd-card"; - qcom,hdmi-audio-rx; + qcom,ext-disp-audio-rx; qcom,audio-routing = "AIF4 VI", "MCLK", @@ -80,7 +80,7 @@ "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", "msm-cpe-lsm", "msm-compr-dsp", "msm-pcm-dsp-noirq"; - asoc-cpu = <&dai_hdmi>, + asoc-cpu = <&dai_hdmi>, <&dai_dp>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, @@ -90,7 +90,7 @@ <&incall_music_2_rx>, <&sb_5_rx>, <&sb_6_rx>, <&sb_7_rx>, <&sb_7_tx>, <&sb_8_tx>, <&usb_audio_rx>, <&usb_audio_tx>; - asoc-cpu-names = "msm-dai-q6-hdmi.8", + asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608", "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", @@ -104,9 +104,9 @@ "msm-dai-q6-dev.16396", "msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399", "msm-dai-q6-dev.16401", "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673"; - asoc-codec = <&stub_codec>, <&hdmi_audio>; + asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>; asoc-codec-names = "msm-stub-codec.1", - "msm-hdmi-audio-codec-rx"; + "msm-ext-disp-audio-codec-rx"; qcom,wsa-max-devs = <2>; qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>, <&wsa881x_213>, <&wsa881x_214>; @@ -117,6 +117,7 @@ sound-tavil { compatible = "qcom,msmcobalt-asoc-snd-tavil"; qcom,model = "msmcobalt-tavil-snd-card"; + qcom,ext-disp-audio-rx; qcom,audio-routing = "RX_BIAS", "MCLK", @@ -160,7 +161,7 @@ "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", "msm-cpe-lsm", "msm-compr-dsp", "msm-pcm-dsp-noirq"; - asoc-cpu = <&dai_hdmi>, + asoc-cpu = <&dai_hdmi>, <&dai_dp>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, @@ -169,7 +170,7 @@ <&incall_record_tx>, <&incall_music_rx>, <&incall_music_2_rx>, <&sb_5_rx>, <&usb_audio_rx>, <&usb_audio_tx>, <&sb_6_rx>; - asoc-cpu-names = "msm-dai-q6-hdmi.8", + asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608", "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", @@ -182,8 +183,9 @@ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", "msm-dai-q6-dev.16396"; - asoc-codec = <&stub_codec>; - asoc-codec-names = "msm-stub-codec.1"; + asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>; + asoc-codec-names = "msm-stub-codec.1", + "msm-ext-disp-audio-codec-rx"; qcom,wsa-max-devs = <2>; qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>, <&wsa881x_0213>, <&wsa881x_0214>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi index 85d6b1d5fba3..fd930d3d1644 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi @@ -451,8 +451,9 @@ msm_ext_disp: qcom,msm_ext_disp { compatible = "qcom,msm-ext-disp"; - hdmi_audio: qcom,msm-hdmi-audio-rx { - compatible = "qcom,msm-hdmi-audio-codec-rx"; + ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { + compatible = "qcom,msm-ext-disp-audio-codec-rx"; + qcom,msm_ext_disp = <&msm_ext_disp>; }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi index 256c404bb972..86bc048adeb5 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi @@ -900,8 +900,10 @@ gfx_cpr: cpr4-ctrl@5061000 { compatible = "qcom,cpr4-msmcobalt-v1-mmss-regulator"; - reg = <0x05061000 0x4000>, <0x00784000 0x1000>; - reg-names = "cpr_ctrl", "fuse_base"; + reg = <0x05061000 0x4000>, + <0x00784000 0x1000>, + <0x05065204 0x4>; + reg-names = "cpr_ctrl", "fuse_base", "aging_allowed"; clocks = <&clock_gpu clk_gpucc_rbcpr_clk>, <&clock_gcc clk_cnoc_clk>; clock-names = "core_clk", "bus_clk"; @@ -912,14 +914,16 @@ qcom,cpr-sensor-time = <1000>; qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; - qcom,cpr-step-quot-init-min = <10>; - qcom,cpr-step-quot-init-max = <13>; + qcom,cpr-step-quot-init-min = <8>; + qcom,cpr-step-quot-init-max = <12>; qcom,cpr-count-mode = <0>; /* All-at-once min */ vdd-supply = <&pm8005_s1>; qcom,voltage-step = <4000>; mem-acc-supply = <&gfx_mem_acc_vreg>; qcom,cpr-aging-ref-voltage = <1032000>; + qcom,cpr-aging-allowed-reg-mask = <0x00000003>; + qcom,cpr-aging-allowed-reg-value = <0x00000003>; qcom,cpr-enable; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi index 38cfd58f7f2d..7e1b47ddf17a 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi @@ -79,6 +79,34 @@ < 2342400000 0x0404007a 0x0a620062 0x3 >, < 2419200000 0x0404007e 0x0a650065 0x3 >, < 2496000000 0x04040082 0x0a680068 0x3 >; + + qcom,perfcl-speedbin1-v0 = + < 300000000 0x0004000f 0x01200020 0x1 >, + < 345600000 0x05040012 0x01200020 0x1 >, + < 422400000 0x05040016 0x02200020 0x1 >, + < 499200000 0x0504001a 0x02200020 0x1 >, + < 576000000 0x0504001e 0x02200020 0x1 >, + < 652800000 0x05040022 0x03200020 0x1 >, + < 729600000 0x05040026 0x03200020 0x1 >, + < 806400000 0x0504002a 0x03220022 0x1 >, + < 902400000 0x0404002f 0x04260026 0x1 >, + < 979200000 0x04040033 0x04290029 0x1 >, + < 1056000000 0x04040037 0x052c002c 0x1 >, + < 1132800000 0x0404003b 0x052f002f 0x1 >, + < 1190400000 0x0404003e 0x05320032 0x2 >, + < 1267200000 0x04040042 0x06350035 0x2 >, + < 1344000000 0x04040046 0x06380038 0x2 >, + < 1420800000 0x0404004a 0x063b003b 0x2 >, + < 1497600000 0x0404004e 0x073e003e 0x2 >, + < 1574400000 0x04040052 0x07420042 0x2 >, + < 1651200000 0x04040056 0x07450045 0x2 >, + < 1728000000 0x0404005a 0x08480048 0x2 >, + < 1804800000 0x0404005e 0x084b004b 0x2 >, + < 1881600000 0x04040062 0x094e004e 0x2 >, + < 1958400000 0x04040066 0x09520052 0x2 >, + < 2035200000 0x0404006a 0x09550055 0x3 >, + < 2112000000 0x0404006e 0x0a580058 0x3 >, + < 2208000000 0x04040073 0x0a5c005c 0x3 >; }; &msm_cpufreq { @@ -198,24 +226,59 @@ &apc0_pwrcl_vreg { regulator-max-microvolt = <23>; - qcom,cpr-corners = <22>; - qcom,cpr-corner-fmax-map = <8 11 18 22>; + + qcom,cpr-fuse-combos = <16>; + qcom,cpr-speed-bins = <2>; + qcom,cpr-speed-bin-corners = <22 22>; + qcom,cpr-corners = + /* Speed bin 0 */ + <22 22 22 22 22 22 22 22>, + /* Speed bin 1 */ + <22 22 22 22 22 22 22 22>; + + qcom,cpr-corner-fmax-map = + /* Speed bin 0 */ + <8 11 18 22>, + /* Speed bin 1 */ + <8 11 18 22>; qcom,cpr-voltage-ceiling = - <688000 688000 688000 688000 688000 - 688000 688000 688000 756000 756000 - 756000 828000 828000 828000 828000 + /* Speed bin 0 */ + <828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 828000 828000 828000 952000 952000 - 1024000 1024000>; + 1056000 1056000>, + /* Speed bin 1 */ + <828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 828000 828000 828000 952000 952000 + 1056000 1056000>; qcom,cpr-voltage-floor = + /* Speed bin 0 */ <568000 568000 568000 568000 568000 568000 568000 568000 568000 568000 568000 632000 632000 632000 632000 632000 632000 632000 712000 712000 - 756000 756000>; + 772000 772000>, + /* Speed bin 1 */ + <568000 568000 568000 568000 568000 + 568000 568000 568000 568000 568000 + 568000 632000 632000 632000 632000 + 632000 632000 632000 712000 712000 + 772000 772000>; qcom,cpr-floor-to-ceiling-max-range = + /* Speed bin 0 */ + <55000 55000 55000 55000 + 55000 55000 55000 55000 + 55000 55000 55000 65000 + 65000 65000 65000 65000 + 65000 65000 65000 65000 + 65000 65000>, + /* Speed bin 1 */ <55000 55000 55000 55000 55000 55000 55000 55000 55000 55000 55000 65000 @@ -224,6 +287,16 @@ 65000 65000>; qcom,corner-frequencies = + /* Speed bin 0 */ + <300000000 364800000 441600000 + 518400000 595200000 672000000 + 748800000 825600000 883200000 + 960000000 1036800000 1094400000 + 1171200000 1248000000 1324800000 + 1401600000 1478400000 1555200000 + 1670400000 1747200000 1824000000 + 1900800000>, + /* Speed bin 1 */ <300000000 364800000 441600000 518400000 595200000 672000000 748800000 825600000 883200000 @@ -248,6 +321,16 @@ 1559 1392>; qcom,cpr-open-loop-voltage-fuse-adjustment = + /* Speed bin 0 */ + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + <40000 24000 0 0>, + /* Speed bin 1 */ <40000 24000 0 0>, <40000 24000 0 0>, <40000 24000 0 0>, @@ -258,6 +341,16 @@ <40000 24000 0 0>; qcom,cpr-closed-loop-voltage-fuse-adjustment = + /* Speed bin 0 */ + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + <20000 26000 0 0>, + /* Speed bin 1 */ <20000 26000 0 0>, <20000 26000 0 0>, <20000 26000 0 0>, @@ -278,26 +371,56 @@ &apc1_perfcl_vreg { regulator-max-microvolt = <31>; - qcom,cpr-corners = <30>; - qcom,cpr-corner-fmax-map = <8 12 20 30>; + + qcom,cpr-fuse-combos = <16>; + qcom,cpr-speed-bins = <2>; + qcom,cpr-speed-bin-corners = <30 26>; + qcom,cpr-corners = + /* Speed bin 0 */ + <30 30 30 30 30 30 30 30>, + /* Speed bin 1 */ + <26 26 26 26 26 26 26 26>; + + qcom,cpr-corner-fmax-map = + /* Speed bin 0 */ + <8 12 20 30>, + /* Speed bin 1 */ + <8 12 20 26>; qcom,cpr-voltage-ceiling = - <688000 688000 688000 688000 688000 - 688000 688000 688000 756000 756000 - 756000 756000 828000 828000 828000 + /* Speed bin 0 */ + <828000 828000 828000 828000 828000 828000 828000 828000 828000 828000 - 952000 952000 952000 1024000 1024000 - 1024000 1024000 1024000 1024000 1024000>; + 828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 952000 952000 952000 1056000 1056000 + 1056000 1056000 1056000 1056000 1056000>, + /* Speed bin 1 */ + <828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 828000 828000 828000 828000 828000 + 952000 952000 952000 1056000 1056000 + 1056000>; qcom,cpr-voltage-floor = + /* Speed bin 0 */ <568000 568000 568000 568000 568000 568000 568000 568000 568000 568000 568000 568000 632000 632000 632000 632000 632000 632000 632000 632000 - 712000 712000 712000 756000 756000 - 756000 756000 756000 756000 756000>; + 712000 712000 712000 772000 772000 + 772000 772000 772000 772000 772000>, + /* Speed bin 1 */ + <568000 568000 568000 568000 568000 + 568000 568000 568000 568000 568000 + 568000 568000 632000 632000 632000 + 632000 632000 632000 632000 632000 + 712000 712000 712000 772000 772000 + 772000>; qcom,cpr-floor-to-ceiling-max-range = + /* Speed bin 0 */ <55000 55000 55000 55000 55000 55000 55000 55000 55000 55000 55000 55000 @@ -305,9 +428,18 @@ 65000 65000 65000 65000 65000 65000 65000 65000 65000 65000 65000 65000 + 65000 65000>, + /* Speed bin 1 */ + <55000 55000 55000 55000 + 55000 55000 55000 55000 + 55000 55000 55000 55000 + 65000 65000 65000 65000 + 65000 65000 65000 65000 + 65000 65000 65000 65000 65000 65000>; qcom,corner-frequencies = + /* Speed bin 0 */ <300000000 345600000 422400000 499200000 576000000 652800000 729600000 806400000 902400000 @@ -317,7 +449,17 @@ 1651200000 1728000000 1804800000 1881600000 1958400000 2035200000 2112000000 2188800000 2265600000 - 2342400000 2419200000 2496000000>; + 2342400000 2419200000 2496000000>, + /* Speed bin 1 */ + <300000000 345600000 422400000 + 499200000 576000000 652800000 + 729600000 806400000 902400000 + 979200000 1056000000 1132800000 + 1190400000 1267200000 1344000000 + 1420800000 1497600000 1574400000 + 1651200000 1728000000 1804800000 + 1881600000 1958400000 2035200000 + 2112000000 2208000000>; qcom,cpr-ro-scaling-factor = <4001 4019 3747 3758 3564 3480 2336 @@ -334,6 +476,16 @@ 1559 1392>; qcom,cpr-open-loop-voltage-fuse-adjustment = + /* Speed bin 0 */ + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + <8000 0 0 52000>, + /* Speed bin 1 */ <8000 0 0 52000>, <8000 0 0 52000>, <8000 0 0 52000>, @@ -344,6 +496,16 @@ <8000 0 0 52000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = + /* Speed bin 0 */ + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + <0 0 0 50000>, + /* Speed bin 1 */ <0 0 0 50000>, <0 0 0 50000>, <0 0 0 50000>, @@ -373,8 +535,8 @@ qcom,cpr-corner-fmax-map = <1 3 5 8>; qcom,cpr-voltage-ceiling = - <616000 676000 740000 800000 828000 - 884000 952000 1024000>; + <656000 716000 772000 880000 908000 + 948000 1016000 1088000>; qcom,cpr-voltage-floor = <516000 516000 532000 584000 632000 diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 4ea1cf31c4dc..820e70a6d9a6 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -804,12 +804,14 @@ clock_cpu: qcom,cpu-clock-cobalt@179c0000 { compatible = "qcom,cpu-clock-osm"; - reg = <0x179C0000 0x4000>, + reg = <0x179c0000 0x4000>, <0x17916000 0x1000>, <0x17816000 0x1000>, - <0x179D1000 0x1000>; + <0x179d1000 0x1000>, + <0x00784130 0x8>, + <0x1791101c 0x8>; reg-names = "osm", "pwrcl_pll", "perfcl_pll", - "apcs_common"; + "apcs_common", "perfcl_efuse", "debug"; vdd-pwrcl-supply = <&apc0_pwrcl_vreg>; vdd-perfcl-supply = <&apc1_perfcl_vreg>; @@ -942,10 +944,11 @@ reg = <0x162000 0x4>; reg-names = "cc_base"; clock-names = "debug_gpu_clk", "debug_gfx_clk", - "debug_mmss_clk"; + "debug_mmss_clk", "debug_cpu_clk"; clocks = <&clock_gpu clk_gpucc_gcc_dbg_clk>, <&clock_gfx clk_gfxcc_dbg_clk>, - <&clock_mmss clk_mmss_debug_mux>; + <&clock_mmss clk_mmss_debug_mux>, + <&clock_cpu clk_cpu_debug_mux>; #clock-cells = <1>; }; @@ -1804,6 +1807,10 @@ "utmi_clk", "sleep_clk", "xo"; qcom,core-clk-rate = <120000000>; + + resets = <&clock_gcc USB_30_BCR>; + reset-names = "core_reset"; + dwc3@a800000 { compatible = "snps,dwc3"; reg = <0x0a800000 0xcd00>; @@ -1870,10 +1877,11 @@ phy_type= "utmi"; clocks = <&clock_gcc clk_ln_bb_clk1>, - <&clock_gcc clk_gcc_rx1_usb2_clkref_clk>, - <&clock_gcc clk_gcc_qusb2phy_prim_reset>; + <&clock_gcc clk_gcc_rx1_usb2_clkref_clk>; + clock-names = "ref_clk_src", "ref_clk"; - clock-names = "ref_clk_src", "ref_clk", "phy_reset"; + resets = <&clock_gcc QUSB2PHY_PRIM_BCR>; + reset-names = "phy_reset"; }; ssphy: ssphy@c010000 { @@ -2021,13 +2029,15 @@ clocks = <&clock_gcc clk_gcc_usb3_phy_aux_clk>, <&clock_gcc clk_gcc_usb3_phy_pipe_clk>, - <&clock_gcc clk_gcc_usb3_phy_reset>, - <&clock_gcc clk_gcc_usb3phy_phy_reset>, <&clock_gcc clk_ln_bb_clk1>, <&clock_gcc clk_gcc_usb3_clkref_clk>; - clock-names = "aux_clk", "pipe_clk", "phy_reset", - "phy_phy_reset", "ref_clk_src", "ref_clk"; + clock-names = "aux_clk", "pipe_clk", "ref_clk_src", + "ref_clk"; + + resets = <&clock_gcc USB3_PHY_BCR>, + <&clock_gcc USB3PHY_PHY_BCR>; + reset-names = "phy_reset", "phy_phy_reset"; }; usb_audio_qmi_dev { diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index 549274d52791..44d8e089837c 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -482,6 +482,27 @@ qcom,glinkpkt-ch-name = "DATA40_CNTL"; qcom,glinkpkt-dev-name = "smdcntl8"; }; + + qcom,glinkpkt-data1 { + qcom,glinkpkt-transport = "smem"; + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA1"; + qcom,glinkpkt-dev-name = "smd7"; + }; + + qcom,glinkpkt-data4 { + qcom,glinkpkt-transport = "smem"; + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA4"; + qcom,glinkpkt-dev-name = "smd8"; + }; + + qcom,glinkpkt-data11 { + qcom,glinkpkt-transport = "smem"; + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA11"; + qcom,glinkpkt-dev-name = "smd11"; + }; }; qcom,ipc_router { diff --git a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts new file mode 100644 index 000000000000..d3c62dbf99f2 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts @@ -0,0 +1,29 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "msmtriton.dtsi" +#include "msmfalcon-pinctrl.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM TRITON RUMI"; + compatible = "qcom,msmtriton-rumi", "qcom,msmtriton", "qcom,rumi"; + qcom,board-id = <15 0>; +}; + +&uartblsp1dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi new file mode 100644 index 000000000000..7b7501dceff3 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -0,0 +1,263 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "skeleton64.dtsi" +#include <dt-bindings/clock/qcom,gcc-msmfalcon.h> +#include <dt-bindings/clock/qcom,gpu-msmfalcon.h> +#include <dt-bindings/clock/qcom,mmcc-msmfalcon.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + model = "Qualcomm Technologies, Inc. MSMTRITON"; + compatible = "qcom,msmtriton"; + qcom,msm-id = <318 0x0>; + interrupt-parent = <&intc>; + + aliases { + serial0 = &uartblsp1dm1; + }; + + chosen { + stdout-path = "serial0"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + }; + + CPU2: cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + }; + + CPU3: cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + }; + + CPU4: cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + + CPU5: cpu@101 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + }; + + CPU6: cpu@102 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + }; + + CPU7: cpu@103 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU4>; + }; + + core1 { + cpu = <&CPU5>; + }; + + core2 { + cpu = <&CPU6>; + }; + + core3 { + cpu = <&CPU7>; + }; + }; + + cluster1 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + }; + }; + }; + + soc: soc { }; + +}; + +&soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + intc: interrupt-controller@17a00000 { + compatible = "arm,gic-v3"; + reg = <0x17a00000 0x10000>, /* GICD */ + <0x17b00000 0x100000>; /* GICR * 8 */ + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-controller; + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x20000>; + interrupts = <1 9 4>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 1 0xf08>, + <1 2 0xf08>, + <1 3 0xf08>, + <1 0 0xf08>; + clock-frequency = <19200000>; + }; + + uartblsp1dm1: serial@0c170000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xc170000 0x1000>; + interrupts = <0 108 0>; + status = "disabled"; + clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>, + <&clock_gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + }; + + uartblsp2dm1: serial@0c1b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xc1b0000 0x1000>; + interrupts = <0 114 0>; + status = "disabled"; + clocks = <&clock_gcc GCC_BLSP2_UART2_APPS_CLK>, + <&clock_gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + }; + + timer@17920000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x17920000 0x1000>; + clock-frequency = <19200000>; + + frame@17921000 { + frame-number = <0>; + interrupts = <0 8 0x4>, + <0 7 0x4>; + reg = <0x17921000 0x1000>, + <0x17922000 0x1000>; + }; + + frame@17923000 { + frame-number = <1>; + interrupts = <0 9 0x4>; + reg = <0x17923000 0x1000>; + status = "disabled"; + }; + + frame@17924000 { + frame-number = <2>; + interrupts = <0 10 0x4>; + reg = <0x17924000 0x1000>; + status = "disabled"; + }; + + frame@17925000 { + frame-number = <3>; + interrupts = <0 11 0x4>; + reg = <0x17925000 0x1000>; + status = "disabled"; + }; + + frame@17926000 { + frame-number = <4>; + interrupts = <0 12 0x4>; + reg = <0x17926000 0x1000>; + status = "disabled"; + }; + + frame@17927000 { + frame-number = <5>; + interrupts = <0 13 0x4>; + reg = <0x17927000 0x1000>; + status = "disabled"; + }; + + frame@17928000 { + frame-number = <6>; + interrupts = <0 14 0x4>; + reg = <0x17928000 0x1000>; + status = "disabled"; + }; + }; + + clock_gcc: qcom,dummycc { + compatible = "qcom,dummycc"; + #clock-cells = <1>; + }; + + clock_mmss: qcom,dummycc { + compatible = "qcom,dummycc"; + #clock-cells = <1>; + }; + + clock_gfx: qcom,dummycc { + compatible = "qcom,dummycc"; + #clock-cells = <1>; + }; +}; diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 1e6a1c66ed82..0a20c52bd3b2 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -460,6 +460,7 @@ CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_MPM_OF=y CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_CORE_CTL_HELPER=y +CONFIG_QCOM_REMOTEQDSS=y CONFIG_MSM_SERVICE_NOTIFIER=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_QCOM_BIMC_BWMON=y diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index 1e6a1c66ed82..0a20c52bd3b2 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -460,6 +460,7 @@ CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_MPM_OF=y CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_CORE_CTL_HELPER=y +CONFIG_QCOM_REMOTEQDSS=y CONFIG_MSM_SERVICE_NOTIFIER=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_QCOM_BIMC_BWMON=y diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index eb02bc09b63d..ee4efe58d0c8 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -95,6 +95,15 @@ config ARCH_MSMFALCON If you do not wish to build a kernel that runs on this chipset,say 'N' here. +config ARCH_MSMTRITON + bool "Enable Support for Qualcomm Technologies Inc MSMTRITON" + depends on ARCH_QCOM + select COMMON_CLK_MSM + help + This enables support for the MSMTRITON chipset. + If you do not wish to build a kernel that runs + on this chipset,say 'N' here. + config ARCH_ROCKCHIP bool "Rockchip Platforms" select ARCH_HAS_RESET_CONTROLLER diff --git a/arch/arm64/configs/msmfalcon-perf_defconfig b/arch/arm64/configs/msmfalcon-perf_defconfig index f2eafd610cac..39c2d3f71c5a 100644 --- a/arch/arm64/configs/msmfalcon-perf_defconfig +++ b/arch/arm64/configs/msmfalcon-perf_defconfig @@ -44,6 +44,7 @@ CONFIG_ARCH_QCOM=y CONFIG_ARCH_MSMCOBALT=y CONFIG_ARCH_MSMHAMSTER=y CONFIG_ARCH_MSMFALCON=y +CONFIG_ARCH_MSMTRITON=y CONFIG_PCI=y CONFIG_PCI_MSM=y CONFIG_SCHED_MC=y diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig index 3742fe210dc2..a277038b3fc3 100644 --- a/arch/arm64/configs/msmfalcon_defconfig +++ b/arch/arm64/configs/msmfalcon_defconfig @@ -45,6 +45,7 @@ CONFIG_ARCH_QCOM=y CONFIG_ARCH_MSMCOBALT=y CONFIG_ARCH_MSMHAMSTER=y CONFIG_ARCH_MSMFALCON=y +CONFIG_ARCH_MSMTRITON=y CONFIG_PCI=y CONFIG_PCI_MSM=y CONFIG_SCHED_MC=y diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c index aeb0f25c9289..471fb3cb8c5f 100644 --- a/arch/arm64/kernel/io.c +++ b/arch/arm64/kernel/io.c @@ -28,21 +28,21 @@ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { while (count && (!IS_ALIGNED((unsigned long)from, 8) || !IS_ALIGNED((unsigned long)to, 8))) { - *(u8 *)to = __raw_readb(from); + *(u8 *)to = __raw_readb_no_log(from); from++; to++; count--; } while (count >= 8) { - *(u64 *)to = __raw_readq(from); + *(u64 *)to = __raw_readq_no_log(from); from += 8; to += 8; count -= 8; } while (count) { - *(u8 *)to = __raw_readb(from); + *(u8 *)to = __raw_readb_no_log(from); from++; to++; count--; @@ -57,21 +57,21 @@ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { while (count && (!IS_ALIGNED((unsigned long)to, 8) || !IS_ALIGNED((unsigned long)from, 8))) { - __raw_writeb(*(volatile u8 *)from, to); + __raw_writeb_no_log(*(volatile u8 *)from, to); from++; to++; count--; } while (count >= 8) { - __raw_writeq(*(volatile u64 *)from, to); + __raw_writeq_no_log(*(volatile u64 *)from, to); from += 8; to += 8; count -= 8; } while (count) { - __raw_writeb(*(volatile u8 *)from, to); + __raw_writeb_no_log(*(volatile u8 *)from, to); from++; to++; count--; @@ -91,19 +91,19 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count) qc |= qc << 32; while (count && !IS_ALIGNED((unsigned long)dst, 8)) { - __raw_writeb(c, dst); + __raw_writeb_no_log(c, dst); dst++; count--; } while (count >= 8) { - __raw_writeq(qc, dst); + __raw_writeq_no_log(qc, dst); dst += 8; count -= 8; } while (count) { - __raw_writeb(c, dst); + __raw_writeb_no_log(c, dst); dst++; count--; } diff --git a/drivers/clk/msm/clock-gcc-cobalt.c b/drivers/clk/msm/clock-gcc-cobalt.c index e469c61cc3db..71c5541d0c0d 100644 --- a/drivers/clk/msm/clock-gcc-cobalt.c +++ b/drivers/clk/msm/clock-gcc-cobalt.c @@ -2354,11 +2354,13 @@ static struct mux_clk gcc_debug_mux = { &gpu_gcc_debug_clk.c, &gfx_gcc_debug_clk.c, &debug_mmss_clk.c, + &debug_cpu_clk.c, ), MUX_SRC_LIST( { &gpu_gcc_debug_clk.c, 0x013d }, { &gfx_gcc_debug_clk.c, 0x013d }, { &debug_mmss_clk.c, 0x0022 }, + { &debug_cpu_clk.c, 0x00c0 }, { &snoc_clk.c, 0x0000 }, { &cnoc_clk.c, 0x000e }, { &bimc_clk.c, 0x00a9 }, @@ -2853,6 +2855,7 @@ static struct clk_lookup msm_clocks_measure_cobalt[] = { CLK_LIST(gpu_gcc_debug_clk), CLK_LIST(gfx_gcc_debug_clk), CLK_LIST(debug_mmss_clk), + CLK_LIST(debug_cpu_clk), CLK_LOOKUP_OF("measure", gcc_debug_mux, "debug"), }; @@ -2889,6 +2892,9 @@ static int msm_clock_debug_cobalt_probe(struct platform_device *pdev) debug_mmss_clk.dev = &pdev->dev; debug_mmss_clk.clk_id = "debug_mmss_clk"; + debug_cpu_clk.dev = &pdev->dev; + debug_cpu_clk.clk_id = "debug_cpu_clk"; + ret = of_msm_clock_register(pdev->dev.of_node, msm_clocks_measure_cobalt, ARRAY_SIZE(msm_clocks_measure_cobalt)); diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c index 9d605503520f..be4b866bc122 100644 --- a/drivers/clk/msm/clock-osm.c +++ b/drivers/clk/msm/clock-osm.c @@ -48,6 +48,7 @@ enum clk_osm_bases { OSM_BASE, PLL_BASE, + EFUSE_BASE, NUM_BASES, }; @@ -208,7 +209,13 @@ enum clk_osm_trace_packet_id { #define PLL_DD_D0_USER_CTL_LO 0x17916208 #define PLL_DD_D1_USER_CTL_LO 0x17816208 +#define PWRCL_EFUSE_SHIFT 0 +#define PWRCL_EFUSE_MASK 0 +#define PERFCL_EFUSE_SHIFT 29 +#define PERFCL_EFUSE_MASK 0x7 + static void __iomem *virt_base; +static void __iomem *debug_base; #define lmh_lite_clk_src_source_val 1 @@ -525,14 +532,45 @@ static struct clk_osm perfcl_clk = { }, }; +static struct clk_ops clk_ops_cpu_dbg_mux; + +static struct mux_clk cpu_debug_mux = { + .offset = 0x0, + .mask = 0x3, + .shift = 8, + .ops = &mux_reg_ops, + MUX_SRC_LIST( + { &pwrcl_clk.c, 0x00 }, + { &perfcl_clk.c, 0x01 }, + ), + .base = &debug_base, + .c = { + .dbg_name = "cpu_debug_mux", + .ops = &clk_ops_cpu_dbg_mux, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(cpu_debug_mux.c), + }, +}; + static struct clk_lookup cpu_clocks_osm[] = { CLK_LIST(pwrcl_clk), CLK_LIST(perfcl_clk), CLK_LIST(sys_apcsaux_clk_gcc), CLK_LIST(xo_ao), CLK_LIST(osm_clk_src), + CLK_LIST(cpu_debug_mux), }; +static unsigned long cpu_dbg_mux_get_rate(struct clk *clk) +{ + /* Account for the divider between the clock and the debug mux */ + if (!strcmp(clk->parent->dbg_name, "pwrcl_clk")) + return clk->rate/4; + else if (!strcmp(clk->parent->dbg_name, "perfcl_clk")) + return clk->rate/8; + return clk->rate; +} + static void clk_osm_print_osm_table(struct clk_osm *c) { int i; @@ -901,6 +939,22 @@ static int clk_osm_resources_init(struct platform_device *pdev) } } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "debug"); + if (!res) { + dev_err(&pdev->dev, "Failed to get debug mux base\n"); + return -EINVAL; + } + + debug_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!debug_base) { + dev_err(&pdev->dev, "Unable to map in debug mux base\n"); + return -ENOMEM; + } + + clk_ops_cpu_dbg_mux = clk_ops_gen_mux; + clk_ops_cpu_dbg_mux.get_rate = cpu_dbg_mux_get_rate; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_common"); if (!res) { dev_err(&pdev->dev, "Failed to get apcs common base\n"); @@ -913,6 +967,35 @@ static int clk_osm_resources_init(struct platform_device *pdev) return -ENOMEM; } + /* efuse speed bin fuses are optional */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "pwrcl_efuse"); + if (res) { + pbase = (unsigned long)res->start; + vbase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!vbase) { + dev_err(&pdev->dev, "Unable to map in pwrcl_efuse base\n"); + return -ENOMEM; + } + pwrcl_clk.pbases[EFUSE_BASE] = pbase; + pwrcl_clk.vbases[EFUSE_BASE] = vbase; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "perfcl_efuse"); + if (res) { + pbase = (unsigned long)res->start; + vbase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!vbase) { + dev_err(&pdev->dev, "Unable to map in perfcl_efuse base\n"); + return -ENOMEM; + } + perfcl_clk.pbases[EFUSE_BASE] = pbase; + perfcl_clk.vbases[EFUSE_BASE] = vbase; + } + vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl"); if (IS_ERR(vdd_pwrcl)) { rc = PTR_ERR(vdd_pwrcl); @@ -2441,9 +2524,11 @@ static unsigned long osm_clk_init_rate = 200000000; static int cpu_clock_osm_driver_probe(struct platform_device *pdev) { - char perfclspeedbinstr[] = "qcom,perfcl-speedbin0-v0"; - char pwrclspeedbinstr[] = "qcom,pwrcl-speedbin0-v0"; int rc, cpu; + int speedbin = 0, pvs_ver = 0; + u32 pte_efuse; + char pwrclspeedbinstr[] = "qcom,pwrcl-speedbin0-v0"; + char perfclspeedbinstr[] = "qcom,perfcl-speedbin0-v0"; struct cpu_cycle_counter_cb cb = { .get_cpu_cycle_counter = clk_osm_get_cpu_cycle_counter, }; @@ -2462,6 +2547,18 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev) return rc; } + if (pwrcl_clk.vbases[EFUSE_BASE]) { + /* Multiple speed-bins are supported */ + pte_efuse = readl_relaxed(pwrcl_clk.vbases[EFUSE_BASE]); + speedbin = ((pte_efuse >> PWRCL_EFUSE_SHIFT) & + PWRCL_EFUSE_MASK); + snprintf(pwrclspeedbinstr, ARRAY_SIZE(pwrclspeedbinstr), + "qcom,pwrcl-speedbin%d-v%d", speedbin, pvs_ver); + } + + dev_info(&pdev->dev, "using pwrcl speed bin %u and pvs_ver %d\n", + speedbin, pvs_ver); + rc = clk_osm_get_lut(pdev, &pwrcl_clk, pwrclspeedbinstr); if (rc) { @@ -2470,6 +2567,18 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev) return rc; } + if (perfcl_clk.vbases[EFUSE_BASE]) { + /* Multiple speed-bins are supported */ + pte_efuse = readl_relaxed(perfcl_clk.vbases[EFUSE_BASE]); + speedbin = ((pte_efuse >> PERFCL_EFUSE_SHIFT) & + PERFCL_EFUSE_MASK); + snprintf(perfclspeedbinstr, ARRAY_SIZE(perfclspeedbinstr), + "qcom,perfcl-speedbin%d-v%d", speedbin, pvs_ver); + } + + dev_info(&pdev->dev, "using perfcl speed bin %u and pvs_ver %d\n", + speedbin, pvs_ver); + rc = clk_osm_get_lut(pdev, &perfcl_clk, perfclspeedbinstr); if (rc) { dev_err(&pdev->dev, "Unable to get OSM LUT for perf cluster, rc=%d\n", diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 2675a8cab51f..362493118670 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1193,7 +1193,8 @@ static int adreno_init(struct kgsl_device *device) if (!adreno_is_a3xx(adreno_dev)) { int r = kgsl_allocate_global(device, - &adreno_dev->cmdbatch_profile_buffer, PAGE_SIZE, 0, 0); + &adreno_dev->cmdbatch_profile_buffer, PAGE_SIZE, + 0, 0, "alwayson"); adreno_dev->cmdbatch_profile_index = 0; diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 2accbe5c5764..97e71464c2df 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -174,7 +174,7 @@ static int _a3xx_pwron_fixup(struct adreno_device *adreno_dev) ret = kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &adreno_dev->pwron_fixup, PAGE_SIZE, - KGSL_MEMFLAGS_GPUREADONLY, 0); + KGSL_MEMFLAGS_GPUREADONLY, 0, "pwron_fixup"); if (ret) return ret; diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c index b15d23cfbe0a..7a691667e59f 100644 --- a/drivers/gpu/msm/adreno_a4xx.c +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -1360,7 +1360,7 @@ static int _a4xx_pwron_fixup(struct adreno_device *adreno_dev) ret = kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &adreno_dev->pwron_fixup, PAGE_SIZE, - KGSL_MEMFLAGS_GPUREADONLY, 0); + KGSL_MEMFLAGS_GPUREADONLY, 0, "pwron_fixup"); if (ret) return ret; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 3252bfb764f2..583de85678fc 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -244,7 +244,8 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev) ret = kgsl_allocate_global(&adreno_dev->dev, &crit_pkts, PAGE_SIZE, - KGSL_MEMFLAGS_GPUREADONLY, 0); + KGSL_MEMFLAGS_GPUREADONLY, + 0, "crit_pkts"); if (ret) return ret; @@ -258,19 +259,19 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev) ret = kgsl_allocate_global(&adreno_dev->dev, &crit_pkts_refbuf1, - PAGE_SIZE, 0, 0); + PAGE_SIZE, 0, 0, "crit_pkts_refbuf1"); if (ret) return ret; ret = kgsl_allocate_global(&adreno_dev->dev, &crit_pkts_refbuf2, - PAGE_SIZE, 0, 0); + PAGE_SIZE, 0, 0, "crit_pkts_refbuf2"); if (ret) return ret; ret = kgsl_allocate_global(&adreno_dev->dev, &crit_pkts_refbuf3, - PAGE_SIZE, 0, 0); + PAGE_SIZE, 0, 0, "crit_pkts_refbuf3"); if (ret) return ret; @@ -2366,7 +2367,7 @@ static int _load_firmware(struct kgsl_device *device, const char *fwfile, } ret = kgsl_allocate_global(device, ucode, fw->size - 4, - KGSL_MEMFLAGS_GPUREADONLY, 0); + KGSL_MEMFLAGS_GPUREADONLY, 0, "ucode"); if (ret) goto done; diff --git a/drivers/gpu/msm/adreno_a5xx_preempt.c b/drivers/gpu/msm/adreno_a5xx_preempt.c index c1463b824c67..ffd7acbbe1f9 100644 --- a/drivers/gpu/msm/adreno_a5xx_preempt.c +++ b/drivers/gpu/msm/adreno_a5xx_preempt.c @@ -490,7 +490,8 @@ static int a5xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, int ret; ret = kgsl_allocate_global(device, &rb->preemption_desc, - A5XX_CP_CTXRECORD_SIZE_IN_BYTES, 0, KGSL_MEMDESC_PRIVILEGED); + A5XX_CP_CTXRECORD_SIZE_IN_BYTES, 0, KGSL_MEMDESC_PRIVILEGED, + "preemption_desc"); if (ret) return ret; @@ -525,7 +526,8 @@ static int a5xx_preemption_iommu_init(struct adreno_device *adreno_dev) /* Allocate mem for storing preemption smmu record */ return kgsl_allocate_global(device, &iommu->smmu_info, PAGE_SIZE, - KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED); + KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED, + "smmu_info"); } #else static int a5xx_preemption_iommu_init(struct adreno_device *adreno_dev) @@ -555,7 +557,8 @@ int a5xx_preemption_init(struct adreno_device *adreno_dev) /* Allocate mem for storing preemption counters */ ret = kgsl_allocate_global(device, &preempt->counters, adreno_dev->num_ringbuffers * - A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0); + A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0, + "preemption_counters"); if (ret) return ret; diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c index 04d82844a5e9..aeffeab2f6dc 100644 --- a/drivers/gpu/msm/adreno_a5xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c @@ -1033,11 +1033,11 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) /* The script buffers needs 2 extra qwords on the end */ if (kgsl_allocate_global(device, &capturescript, script_size + 16, KGSL_MEMFLAGS_GPUREADONLY, - KGSL_MEMDESC_PRIVILEGED)) + KGSL_MEMDESC_PRIVILEGED, "capturescript")) return; if (kgsl_allocate_global(device, ®isters, data_size, 0, - KGSL_MEMDESC_PRIVILEGED)) { + KGSL_MEMDESC_PRIVILEGED, "capturescript_regs")) { kgsl_free_global(KGSL_DEVICE(adreno_dev), &capturescript); return; } diff --git a/drivers/gpu/msm/adreno_profile.c b/drivers/gpu/msm/adreno_profile.c index c4fab8a5528a..d8af520b2fe6 100644 --- a/drivers/gpu/msm/adreno_profile.c +++ b/drivers/gpu/msm/adreno_profile.c @@ -1071,7 +1071,8 @@ void adreno_profile_init(struct adreno_device *adreno_dev) /* allocate shared_buffer, which includes pre_ib and post_ib */ profile->shared_size = ADRENO_PROFILE_SHARED_BUF_SIZE_DWORDS; ret = kgsl_allocate_global(device, &profile->shared_buffer, - profile->shared_size * sizeof(unsigned int), 0, 0); + profile->shared_size * sizeof(unsigned int), + 0, 0, "profile"); if (ret) { profile->shared_size = 0; diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 5ffb0b2513f3..07ef09034d7c 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -250,12 +250,12 @@ static int _adreno_ringbuffer_probe(struct adreno_device *adreno_dev, * switch pagetable */ ret = kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc, - PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED); + PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, "pagetable_desc"); if (ret) return ret; - return kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->buffer_desc, - KGSL_RB_SIZE, KGSL_MEMFLAGS_GPUREADONLY, 0); + KGSL_RB_SIZE, KGSL_MEMFLAGS_GPUREADONLY, + 0, "ringbuffer"); } int adreno_ringbuffer_probe(struct adreno_device *adreno_dev, bool nopreempt) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 691f687cd839..f9eb080d903b 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4474,13 +4474,13 @@ int kgsl_device_platform_probe(struct kgsl_device *device) goto error_close_mmu; status = kgsl_allocate_global(device, &device->memstore, - KGSL_MEMSTORE_SIZE, 0, KGSL_MEMDESC_CONTIG); + KGSL_MEMSTORE_SIZE, 0, KGSL_MEMDESC_CONTIG, "memstore"); if (status != 0) goto error_close_mmu; status = kgsl_allocate_global(device, &device->scratch, - PAGE_SIZE, 0, 0); + PAGE_SIZE, 0, 0, "scratch"); if (status != 0) goto error_free_memstore; diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index df9eb9ebd779..2f293e4da398 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -280,6 +280,29 @@ static const struct file_operations process_sparse_mem_fops = { .release = process_mem_release, }; +static int globals_print(struct seq_file *s, void *unused) +{ + kgsl_print_global_pt_entries(s); + return 0; +} + +static int globals_open(struct inode *inode, struct file *file) +{ + return single_open(file, globals_print, NULL); +} + +static int globals_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations global_fops = { + .open = globals_open, + .read = seq_read, + .llseek = seq_lseek, + .release = globals_release, +}; + /** * kgsl_process_init_debugfs() - Initialize debugfs for a process * @private: Pointer to process private structure created for the process @@ -336,6 +359,9 @@ void kgsl_core_debugfs_init(void) kgsl_debugfs_dir = debugfs_create_dir("kgsl", NULL); + debugfs_create_file("globals", 0444, kgsl_debugfs_dir, NULL, + &global_fops); + debug_dir = debugfs_create_dir("debug", kgsl_debugfs_dir); debugfs_create_file("strict_memory", 0644, debug_dir, NULL, diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 166bb68e64a1..71b6086423d6 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -38,6 +38,10 @@ #define _IOMMU_PRIV(_mmu) (&((_mmu)->priv.iommu)) +#define ADDR_IN_GLOBAL(_a) \ + (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \ + ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE))) + static struct kgsl_mmu_pt_ops iommu_pt_ops; static bool need_iommu_sync; @@ -92,19 +96,41 @@ static struct kmem_cache *addr_entry_cache; #define GLOBAL_PT_ENTRIES 32 -static struct kgsl_memdesc *global_pt_entries[GLOBAL_PT_ENTRIES]; +struct global_pt_entry { + struct kgsl_memdesc *memdesc; + char name[32]; +}; + +static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES]; static struct kgsl_memdesc *kgsl_global_secure_pt_entry; static int global_pt_count; uint64_t global_pt_alloc; static struct kgsl_memdesc gpu_qdss_desc; +void kgsl_print_global_pt_entries(struct seq_file *s) +{ + int i; + + for (i = 0; i < global_pt_count; i++) { + struct kgsl_memdesc *memdesc = global_pt_entries[i].memdesc; + + if (memdesc == NULL) + continue; + + seq_printf(s, "0x%16.16llX-0x%16.16llX %16llu %s\n", + memdesc->gpuaddr, memdesc->gpuaddr + memdesc->size - 1, + memdesc->size, global_pt_entries[i].name); + } +} + static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable) { unsigned int i; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] != NULL) - kgsl_mmu_unmap(pagetable, global_pt_entries[i]); + if (global_pt_entries[i].memdesc != NULL) + kgsl_mmu_unmap(pagetable, + global_pt_entries[i].memdesc); } } @@ -113,8 +139,9 @@ static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable) unsigned int i; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] != NULL) { - int ret = kgsl_mmu_map(pagetable, global_pt_entries[i]); + if (global_pt_entries[i].memdesc != NULL) { + int ret = kgsl_mmu_map(pagetable, + global_pt_entries[i].memdesc); BUG_ON(ret); } @@ -152,17 +179,17 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, return; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] == memdesc) { + if (global_pt_entries[i].memdesc == memdesc) { memdesc->gpuaddr = 0; memdesc->priv &= ~KGSL_MEMDESC_GLOBAL; - global_pt_entries[i] = NULL; + global_pt_entries[i].memdesc = NULL; return; } } } static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, - struct kgsl_memdesc *memdesc) + struct kgsl_memdesc *memdesc, const char *name) { if (memdesc->gpuaddr != 0) return; @@ -174,7 +201,10 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, memdesc->priv |= KGSL_MEMDESC_GLOBAL; global_pt_alloc += memdesc->size; - global_pt_entries[global_pt_count++] = memdesc; + global_pt_entries[global_pt_count].memdesc = memdesc; + strlcpy(global_pt_entries[global_pt_count].name, name, + sizeof(global_pt_entries[global_pt_count].name)); + global_pt_count++; } void kgsl_add_global_secure_entry(struct kgsl_device *device, @@ -220,7 +250,7 @@ static void kgsl_setup_qdss_desc(struct kgsl_device *device) return; } - kgsl_mmu_add_global(device, &gpu_qdss_desc); + kgsl_mmu_add_global(device, &gpu_qdss_desc, "gpu-qdss"); } static inline void kgsl_cleanup_qdss_desc(struct kgsl_mmu *mmu) @@ -493,8 +523,62 @@ struct _mem_entry { unsigned int priv; int pending_free; pid_t pid; + char name[32]; }; +static void _get_global_entries(uint64_t faultaddr, + struct _mem_entry *prev, + struct _mem_entry *next) +{ + int i; + uint64_t prevaddr = 0; + struct global_pt_entry *p = NULL; + + uint64_t nextaddr = (uint64_t) -1; + struct global_pt_entry *n = NULL; + + for (i = 0; i < global_pt_count; i++) { + uint64_t addr; + + if (global_pt_entries[i].memdesc == NULL) + continue; + + addr = global_pt_entries[i].memdesc->gpuaddr; + if ((addr < faultaddr) && (addr > prevaddr)) { + prevaddr = addr; + p = &global_pt_entries[i]; + } + + if ((addr > faultaddr) && (addr < nextaddr)) { + nextaddr = addr; + n = &global_pt_entries[i]; + } + } + + if (p != NULL) { + prev->gpuaddr = p->memdesc->gpuaddr; + prev->size = p->memdesc->size; + prev->flags = p->memdesc->flags; + prev->priv = p->memdesc->priv; + prev->pid = 0; + strlcpy(prev->name, p->name, sizeof(prev->name)); + } + + if (n != NULL) { + next->gpuaddr = n->memdesc->gpuaddr; + next->size = n->memdesc->size; + next->flags = n->memdesc->flags; + next->priv = n->memdesc->priv; + next->pid = 0; + strlcpy(next->name, n->name, sizeof(next->name)); + } +} + +void __kgsl_get_memory_usage(struct _mem_entry *entry) +{ + kgsl_get_memory_usage(entry->name, sizeof(entry->name), entry->flags); +} + static void _get_entries(struct kgsl_process_private *private, uint64_t faultaddr, struct _mem_entry *prev, struct _mem_entry *next) @@ -529,6 +613,7 @@ static void _get_entries(struct kgsl_process_private *private, prev->priv = p->memdesc.priv; prev->pending_free = p->pending_free; prev->pid = private->pid; + __kgsl_get_memory_usage(prev); } if (n != NULL) { @@ -538,6 +623,7 @@ static void _get_entries(struct kgsl_process_private *private, next->priv = n->memdesc.priv; next->pending_free = n->pending_free; next->pid = private->pid; + __kgsl_get_memory_usage(next); } } @@ -553,7 +639,9 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, /* Set the maximum possible size as an initial value */ nextentry->gpuaddr = (uint64_t) -1; - if (context) { + if (ADDR_IN_GLOBAL(faultaddr)) { + _get_global_entries(faultaddr, preventry, nextentry); + } else if (context) { private = context->proc_priv; spin_lock(&private->mem_lock); _get_entries(private, faultaddr, preventry, nextentry); @@ -563,18 +651,13 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, static void _print_entry(struct kgsl_device *device, struct _mem_entry *entry) { - char name[32]; - memset(name, 0, sizeof(name)); - - kgsl_get_memory_usage(name, sizeof(name) - 1, entry->flags); - KGSL_LOG_DUMP(device, "[%016llX - %016llX] %s %s (pid = %d) (%s)\n", entry->gpuaddr, entry->gpuaddr + entry->size, entry->priv & KGSL_MEMDESC_GUARD_PAGE ? "(+guard)" : "", entry->pending_free ? "(pending free)" : "", - entry->pid, name); + entry->pid, entry->name); } static void _check_if_freed(struct kgsl_iommu_context *ctx, @@ -1395,7 +1478,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) } } - kgsl_iommu_add_global(mmu, &iommu->setstate); + kgsl_iommu_add_global(mmu, &iommu->setstate, "setstate"); kgsl_setup_qdss_desc(device); done: @@ -2220,10 +2303,6 @@ static uint64_t kgsl_iommu_find_svm_region(struct kgsl_pagetable *pagetable, return addr; } -#define ADDR_IN_GLOBAL(_a) \ - (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \ - ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE))) - static int kgsl_iommu_set_svm_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size) { diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 10f6b8049d36..4371c9a1b87e 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -543,12 +543,12 @@ void kgsl_mmu_remove_global(struct kgsl_device *device, EXPORT_SYMBOL(kgsl_mmu_remove_global); void kgsl_mmu_add_global(struct kgsl_device *device, - struct kgsl_memdesc *memdesc) + struct kgsl_memdesc *memdesc, const char *name) { struct kgsl_mmu *mmu = &device->mmu; if (MMU_OP_VALID(mmu, mmu_add_global)) - mmu->mmu_ops->mmu_add_global(mmu, memdesc); + mmu->mmu_ops->mmu_add_global(mmu, memdesc, name); } EXPORT_SYMBOL(kgsl_mmu_add_global); @@ -620,7 +620,7 @@ static struct kgsl_mmu_pt_ops nommu_pt_ops = { }; static void nommu_add_global(struct kgsl_mmu *mmu, - struct kgsl_memdesc *memdesc) + struct kgsl_memdesc *memdesc, const char *name) { memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl); } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index 53645cc1741c..acbc0e784cf2 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -75,7 +75,7 @@ struct kgsl_mmu_ops { (struct kgsl_mmu *mmu); int (*mmu_init_pt)(struct kgsl_mmu *mmu, struct kgsl_pagetable *); void (*mmu_add_global)(struct kgsl_mmu *mmu, - struct kgsl_memdesc *memdesc); + struct kgsl_memdesc *memdesc, const char *name); void (*mmu_remove_global)(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc); struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu, @@ -174,6 +174,7 @@ struct kgsl_pagetable *kgsl_mmu_getpagetable_ptbase(struct kgsl_mmu *, void kgsl_add_global_secure_entry(struct kgsl_device *device, struct kgsl_memdesc *memdesc); +void kgsl_print_global_pt_entries(struct seq_file *s); void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable); int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable, @@ -198,7 +199,7 @@ int kgsl_mmu_find_region(struct kgsl_pagetable *pagetable, uint64_t *gpuaddr, uint64_t size, unsigned int align); void kgsl_mmu_add_global(struct kgsl_device *device, - struct kgsl_memdesc *memdesc); + struct kgsl_memdesc *memdesc, const char *name); void kgsl_mmu_remove_global(struct kgsl_device *device, struct kgsl_memdesc *memdesc); diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index 565ae4c39fdd..9e6817c76df8 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -279,7 +279,7 @@ kgsl_memdesc_footprint(const struct kgsl_memdesc *memdesc) */ static inline int kgsl_allocate_global(struct kgsl_device *device, struct kgsl_memdesc *memdesc, uint64_t size, uint64_t flags, - unsigned int priv) + unsigned int priv, const char *name) { int ret; @@ -297,7 +297,7 @@ static inline int kgsl_allocate_global(struct kgsl_device *device, } if (ret == 0) - kgsl_mmu_add_global(device, memdesc); + kgsl_mmu_add_global(device, memdesc, name); return ret; } diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index bc5126a08ecb..b02abfc58aea 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1195,4 +1195,14 @@ config TOUCHSCREEN_FT5X06 To compile this driver as a module, choose M here: the module will be called ft5x06_ts. +config FT_SECURE_TOUCH + bool "Secure Touch support for Focaltech Touchscreen" + depends on TOUCHSCREEN_FT5X06 + help + Say Y here + -Focaltech touch driver is connected + -To enable secure touch for Focaltech touch driver + + If unsure, say N. + endif diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c index 17bce3d18d2f..499ba692d53c 100644 --- a/drivers/input/touchscreen/ft5x06_ts.c +++ b/drivers/input/touchscreen/ft5x06_ts.c @@ -47,6 +47,14 @@ #define FT_SUSPEND_LEVEL 1 #endif +#if defined(CONFIG_FT_SECURE_TOUCH) +#include <linux/completion.h> +#include <linux/atomic.h> +#include <linux/clk.h> +#include <linux/pm_runtime.h> +static irqreturn_t ft5x06_ts_interrupt(int irq, void *data); +#endif + #define FT_DRIVER_VERSION 0x02 #define FT_META_REGS 3 @@ -148,9 +156,6 @@ #define FT_FW_FILE_MAJ_VER_FT6X36(x) ((x)->data[0x10a]) #define FT_FW_FILE_VENDOR_ID_FT6X36(x) ((x)->data[0x108]) -#define FT_SYSFS_TS_INFO "ts_info" - - /** * Application data verification will be run before upgrade flow. * Firmware image stores some flags with negative and positive value @@ -202,6 +207,8 @@ #define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" #define PINCTRL_STATE_RELEASE "pmx_ts_release" +static irqreturn_t ft5x06_ts_interrupt(int irq, void *data); + enum { FT_BLOADER_VERSION_LZ4 = 0, FT_BLOADER_VERSION_Z7 = 1, @@ -215,8 +222,17 @@ enum { FT_FT5336_FAMILY_ID_0x14 = 0x14, }; -#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \ - fw_name, fw_maj, fw_min, fw_sub_min) \ +#define FT_STORE_TS_INFO(buf, id, fw_maj, fw_min, fw_sub_min) \ + snprintf(buf, FT_INFO_MAX_LEN, \ + "vendor name = Focaltech\n" \ + "model = 0x%x\n" \ + "fw_version = %d.%d.%d\n", \ + id, fw_maj, fw_min, fw_sub_min) +#define FT_TS_INFO_SYSFS_DIR_NAME "ts_info" +static char *ts_info_buff; + +#define FT_STORE_TS_DBG_INFO(buf, id, name, max_tch, group_id, \ + fw_vkey_support, fw_name, fw_maj, fw_min, fw_sub_min) \ snprintf(buf, FT_INFO_MAX_LEN, \ "controller\t= focaltech\n" \ "model\t\t= 0x%x\n" \ @@ -240,6 +256,7 @@ struct ft5x06_ts_data { struct ft5x06_gesture_platform_data *gesture_pdata; struct regulator *vdd; struct regulator *vcc_i2c; + struct mutex ft_clk_io_ctrl_mutex; char fw_name[FT_FW_NAME_MAX_LEN]; bool loading_fw; u8 family_id; @@ -251,7 +268,7 @@ struct ft5x06_ts_data { u32 tch_data_len; u8 fw_ver[3]; u8 fw_vendor_id; - struct kobject ts_info_kobj; + struct kobject *ts_info_kobj; #if defined(CONFIG_FB) struct work_struct fb_notify_work; struct notifier_block fb_notif; @@ -262,11 +279,255 @@ struct ft5x06_ts_data { struct pinctrl_state *pinctrl_state_active; struct pinctrl_state *pinctrl_state_suspend; struct pinctrl_state *pinctrl_state_release; +#if defined(CONFIG_FT_SECURE_TOUCH) + atomic_t st_enabled; + atomic_t st_pending_irqs; + struct completion st_powerdown; + struct completion st_irq_processed; + bool st_initialized; + struct clk *core_clk; + struct clk *iface_clk; +#endif }; static int ft5x06_ts_start(struct device *dev); static int ft5x06_ts_stop(struct device *dev); +#if defined(CONFIG_FT_SECURE_TOUCH) +static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data) +{ + data->st_initialized = 0; + + init_completion(&data->st_powerdown); + init_completion(&data->st_irq_processed); + + /* Get clocks */ + data->core_clk = devm_clk_get(&data->client->dev, "core_clk"); + if (IS_ERR(data->core_clk)) { + data->core_clk = NULL; + dev_warn(&data->client->dev, + "%s: core_clk is not defined\n", __func__); + } + + data->iface_clk = devm_clk_get(&data->client->dev, "iface_clk"); + if (IS_ERR(data->iface_clk)) { + data->iface_clk = NULL; + dev_warn(&data->client->dev, + "%s: iface_clk is not defined", __func__); + } + data->st_initialized = 1; +} + +static void ft5x06_secure_touch_notify(struct ft5x06_ts_data *data) +{ + sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch"); +} + +static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data) +{ + if (atomic_read(&data->st_enabled)) { + if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0) { + reinit_completion(&data->st_irq_processed); + ft5x06_secure_touch_notify(data); + wait_for_completion_interruptible( + &data->st_irq_processed); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/* + * 'blocking' variable will have value 'true' when we want to prevent the driver + * from accessing the xPU/SMMU protected HW resources while the session is + * active. + */ +static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking) +{ + if (atomic_read(&data->st_enabled)) { + atomic_set(&data->st_pending_irqs, -1); + ft5x06_secure_touch_notify(data); + if (blocking) + wait_for_completion_interruptible( + &data->st_powerdown); + } +} + +static int ft5x06_clk_prepare_enable(struct ft5x06_ts_data *data) +{ + int ret; + + ret = clk_prepare_enable(data->iface_clk); + if (ret) { + dev_err(&data->client->dev, + "error on clk_prepare_enable(iface_clk):%d\n", ret); + return ret; + } + + ret = clk_prepare_enable(data->core_clk); + if (ret) { + clk_disable_unprepare(data->iface_clk); + dev_err(&data->client->dev, + "error clk_prepare_enable(core_clk):%d\n", ret); + } + return ret; +} + +static void ft5x06_clk_disable_unprepare(struct ft5x06_ts_data *data) +{ + clk_disable_unprepare(data->core_clk); + clk_disable_unprepare(data->iface_clk); +} + +static int ft5x06_bus_get(struct ft5x06_ts_data *data) +{ + int retval; + + mutex_lock(&data->ft_clk_io_ctrl_mutex); + retval = pm_runtime_get_sync(data->client->adapter->dev.parent); + if (retval >= 0 && data->core_clk != NULL && data->iface_clk != NULL) { + retval = ft5x06_clk_prepare_enable(data); + if (retval) + pm_runtime_put_sync(data->client->adapter->dev.parent); + } + mutex_unlock(&data->ft_clk_io_ctrl_mutex); + return retval; +} + +static void ft5x06_bus_put(struct ft5x06_ts_data *data) +{ + mutex_lock(&data->ft_clk_io_ctrl_mutex); + if (data->core_clk != NULL && data->iface_clk != NULL) + ft5x06_clk_disable_unprepare(data); + pm_runtime_put_sync(data->client->adapter->dev.parent); + mutex_unlock(&data->ft_clk_io_ctrl_mutex); +} + +static ssize_t ft5x06_secure_touch_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5x06_ts_data *data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled)); +} + +/* + * Accept only "0" and "1" valid values. + * "0" will reset the st_enabled flag, then wake up the reading process and + * the interrupt handler. + * The bus driver is notified via pm_runtime that it is not required to stay + * awake anymore. + * It will also make sure the queue of events is emptied in the controller, + * in case a touch happened in between the secure touch being disabled and + * the local ISR being ungated. + * "1" will set the st_enabled flag and clear the st_pending_irqs flag. + * The bus driver is requested via pm_runtime to stay awake. + */ +static ssize_t ft5x06_secure_touch_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct ft5x06_ts_data *data = dev_get_drvdata(dev); + unsigned long value; + int err = 0; + + if (count > 2) + return -EINVAL; + err = kstrtoul(buf, 10, &value); + if (err != 0) + return err; + + if (!data->st_initialized) + return -EIO; + + err = count; + switch (value) { + case 0: + if (atomic_read(&data->st_enabled) == 0) + break; + ft5x06_bus_put(data); + atomic_set(&data->st_enabled, 0); + ft5x06_secure_touch_notify(data); + complete(&data->st_irq_processed); + ft5x06_ts_interrupt(data->client->irq, data); + complete(&data->st_powerdown); + break; + + case 1: + if (atomic_read(&data->st_enabled)) { + err = -EBUSY; + break; + } + synchronize_irq(data->client->irq); + if (ft5x06_bus_get(data) < 0) { + dev_err(&data->client->dev, "ft5x06_bus_get failed\n"); + err = -EIO; + break; + } + reinit_completion(&data->st_powerdown); + reinit_completion(&data->st_irq_processed); + atomic_set(&data->st_enabled, 1); + atomic_set(&data->st_pending_irqs, 0); + break; + + default: + dev_err(&data->client->dev, "unsupported value: %lu\n", value); + err = -EINVAL; + break; + } + return err; +} + +/* + * This function returns whether there are pending interrupts, or + * other error conditions that need to be signaled to the userspace library, + * according tot he following logic: + * - st_enabled is 0 if secure touch is not enabled, returning -EBADF + * - st_pending_irqs is -1 to signal that secure touch is in being stopped, + * returning -EINVAL + * - st_pending_irqs is 1 to signal that there is a pending irq, returning + * the value "1" to the sysfs read operation + * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt + * has been processed, so the interrupt handler can be allowed to continue. + */ +static ssize_t ft5x06_secure_touch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5x06_ts_data *data = dev_get_drvdata(dev); + int val = 0; + + if (atomic_read(&data->st_enabled) == 0) + return -EBADF; + if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1) + return -EINVAL; + if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1) + val = 1; + else + complete(&data->st_irq_processed); + return scnprintf(buf, PAGE_SIZE, "%u", val); +} +#else +static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data) +{ +} +static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data) +{ + return IRQ_NONE; +} +static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking) +{ +} +#endif + +static struct device_attribute attrs[] = { +#if defined(CONFIG_FT_SECURE_TOUCH) + __ATTR(secure_touch_enable, (S_IRUGO | S_IWUSR | S_IWGRP), + ft5x06_secure_touch_enable_show, + ft5x06_secure_touch_enable_store), + __ATTR(secure_touch, S_IRUGO, + ft5x06_secure_touch_show, NULL), +#endif +}; + static inline bool ft5x06_gesture_support_enabled(void) { return config_enabled(CONFIG_TOUCHSCREEN_FT5X06_GESTURE); @@ -593,6 +854,9 @@ static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } + if (ft5x06_filter_interrupt(data) == IRQ_HANDLED) + return IRQ_HANDLED; + ip_dev = data->input_dev; buf = data->tch_data; @@ -620,6 +884,10 @@ static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id) } for (i = 0; i < data->pdata->num_max_touches; i++) { + /* + * Getting the finger ID of the touch event incase of + * multiple touch events + */ id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4; if (id >= FT_MAX_ID) break; @@ -1057,6 +1325,8 @@ static int ft5x06_ts_suspend(struct device *dev) return 0; } + ft5x06_secure_touch_stop(data, true); + if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support && device_may_wakeup(dev) && data->gesture_pdata->gesture_enable_to_set) { @@ -1083,6 +1353,8 @@ static int ft5x06_ts_resume(struct device *dev) return 0; } + ft5x06_secure_touch_stop(data, true); + if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support && device_may_wakeup(dev) && !(data->gesture_pdata->in_pocket) && @@ -1185,6 +1457,13 @@ static void ft5x06_ts_early_suspend(struct early_suspend *handler) struct ft5x06_ts_data, early_suspend); + /* + * During early suspend/late resume, the driver doesn't access xPU/SMMU + * protected HW resources. So, there is no compelling need to block, + * but notifying the userspace that a power event has occurred is + * enough. Hence 'blocking' variable can be set to false. + */ + ft5x06_secure_touch_stop(data, false); ft5x06_ts_suspend(&data->client->dev); } @@ -1194,6 +1473,7 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler) struct ft5x06_ts_data, early_suspend); + ft5x06_secure_touch_stop(data, false); ft5x06_ts_resume(&data->client->dev); } #endif @@ -1510,11 +1790,13 @@ static int ft5x06_fw_upgrade(struct device *dev, bool force) ft5x06_update_fw_ver(data); - FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name, data->pdata->num_max_touches, data->pdata->group_id, data->pdata->fw_vkey_support ? "yes" : "no", data->pdata->fw_name, data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); + FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); rel_fw: release_firmware(fw); return rc; @@ -1617,22 +1899,13 @@ static ssize_t ft5x06_fw_name_store(struct device *dev, static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store); - -static ssize_t ft5x06_ts_info_show(struct kobject *kobj, +static ssize_t ts_info_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - struct ft5x06_ts_data *data = container_of(kobj, - struct ft5x06_ts_data, ts_info_kobj); - return snprintf(buf, FT_INFO_MAX_LEN, - "vendor name = Focaltech\n" - "model = 0x%x\n" - "fw_verion = %d.%d.%d\n", - data->family_id, data->fw_ver[0], - data->fw_ver[1], data->fw_ver[2]); + strlcpy(buf, ts_info_buff, FT_INFO_MAX_LEN); + return strnlen(buf, FT_INFO_MAX_LEN); } - -static struct kobj_attribute ts_info_attribute = __ATTR(ts_info, - 0664, ft5x06_ts_info_show, NULL); +static struct kobj_attribute ts_info_attr = __ATTR_RO(ts_info); static bool ft5x06_debug_addr_is_valid(int addr) { @@ -1984,7 +2257,8 @@ static int ft5x06_ts_probe(struct i2c_client *client, struct dentry *temp; u8 reg_value; u8 reg_addr; - int err, len; + int err, len, retval, attr_count; + if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL); @@ -2271,28 +2545,50 @@ static int ft5x06_ts_probe(struct i2c_client *client, dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4); /*creation touch panel info kobj*/ - data->ts_info_kobj = *(kobject_create_and_add(FT_SYSFS_TS_INFO, - kernel_kobj)); - if (!&(data->ts_info_kobj)) { - dev_err(&client->dev, "kob creation failed .\n"); + data->ts_info_kobj = kobject_create_and_add(FT_TS_INFO_SYSFS_DIR_NAME, + kernel_kobj); + if (!data->ts_info_kobj) { + dev_err(&client->dev, "kobject creation failed.\n"); } else { - err = sysfs_create_file(&(data->ts_info_kobj), - &ts_info_attribute.attr); + err = sysfs_create_file(data->ts_info_kobj, &ts_info_attr.attr); if (err) { - kobject_put(&(data->ts_info_kobj)); - dev_err(&client->dev, "sysfs create fail .\n"); + kobject_put(data->ts_info_kobj); + dev_err(&client->dev, "sysfs creation failed.\n"); + } else { + ts_info_buff = devm_kzalloc(&client->dev, + FT_INFO_MAX_LEN, GFP_KERNEL); + if (!ts_info_buff) + goto free_debug_dir; + } + } + + /*Initialize secure touch */ + ft5x06_secure_touch_init(data); + ft5x06_secure_touch_stop(data, true); + mutex_init(&(data->ft_clk_io_ctrl_mutex)); + + /* Creation of secure touch sysfs files */ + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(&client->dev, + "%s: Failed to create sysfs attributes\n", + __func__); + goto free_secure_touch_sysfs; } } ft5x06_update_fw_ver(data); ft5x06_update_fw_vendor_id(data); - FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name, data->pdata->num_max_touches, data->pdata->group_id, data->pdata->fw_vkey_support ? "yes" : "no", data->pdata->fw_name, data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); - + FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); #if defined(CONFIG_FB) INIT_WORK(&data->fb_notify_work, fb_notify_resume_work); data->fb_notif.notifier_call = fb_notifier_callback; @@ -2311,6 +2607,11 @@ static int ft5x06_ts_probe(struct i2c_client *client, #endif return 0; +free_secure_touch_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } free_debug_dir: debugfs_remove_recursive(data->dir); free_force_update_fw_sys: @@ -2371,7 +2672,7 @@ unreg_inputdev: static int ft5x06_ts_remove(struct i2c_client *client) { struct ft5x06_ts_data *data = i2c_get_clientdata(client); - int retval; + int retval, attr_count; if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) { device_init_wakeup(&client->dev, 0); @@ -2414,6 +2715,11 @@ static int ft5x06_ts_remove(struct i2c_client *client) } } + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + if (data->pdata->power_on) data->pdata->power_on(false); else @@ -2425,7 +2731,7 @@ static int ft5x06_ts_remove(struct i2c_client *client) ft5x06_power_init(data, false); input_unregister_device(data->input_dev); - kobject_put(&(data->ts_info_kobj)); + kobject_put(data->ts_info_kobj); return 0; } diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c index 0c5754341991..b6a476cd882d 100644 --- a/drivers/mfd/wcd9xxx-irq.c +++ b/drivers/mfd/wcd9xxx-irq.c @@ -450,10 +450,22 @@ int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res) { int i, ret; u8 irq_level[wcd9xxx_res->num_irq_regs]; + struct irq_domain *domain; + struct device_node *pnode; mutex_init(&wcd9xxx_res->irq_lock); mutex_init(&wcd9xxx_res->nested_irq_lock); + pnode = of_irq_find_parent(wcd9xxx_res->dev->of_node); + if (unlikely(!pnode)) + return -EINVAL; + + domain = irq_find_host(pnode); + if (unlikely(!domain)) + return -EINVAL; + + wcd9xxx_res->domain = domain; + wcd9xxx_res->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx_res); if (!wcd9xxx_res->irq) { pr_warn("%s: irq driver is not yet initialized\n", __func__); @@ -553,7 +565,6 @@ void wcd9xxx_irq_exit(struct wcd9xxx_core_resource *wcd9xxx_res) if (wcd9xxx_res->irq) { disable_irq_wake(wcd9xxx_res->irq); free_irq(wcd9xxx_res->irq, wcd9xxx_res); - /* Release parent's of node */ wcd9xxx_res->irq = 0; wcd9xxx_irq_put_upstream_irq(wcd9xxx_res); } @@ -626,19 +637,14 @@ wcd9xxx_irq_add_domain(struct device_node *node, static struct wcd9xxx_irq_drv_data * wcd9xxx_get_irq_drv_d(const struct wcd9xxx_core_resource *wcd9xxx_res) { - struct device_node *pnode; struct irq_domain *domain; - pnode = of_irq_find_parent(wcd9xxx_res->dev->of_node); - /* Shouldn't happen */ - if (unlikely(!pnode)) - return NULL; + domain = wcd9xxx_res->domain; - domain = irq_find_host(pnode); - if (unlikely(!domain)) + if (domain) + return domain->host_data; + else return NULL; - - return (struct wcd9xxx_irq_drv_data *)domain->host_data; } static int phyirq_to_virq(struct wcd9xxx_core_resource *wcd9xxx_res, int offset) @@ -669,10 +675,6 @@ static unsigned int wcd9xxx_irq_get_upstream_irq( { struct wcd9xxx_irq_drv_data *data; - /* Hold parent's of node */ - if (!of_node_get(of_irq_find_parent(wcd9xxx_res->dev->of_node))) - return -EINVAL; - data = wcd9xxx_get_irq_drv_d(wcd9xxx_res); if (!data) { pr_err("%s: interrupt controller is not registerd\n", __func__); @@ -686,8 +688,7 @@ static unsigned int wcd9xxx_irq_get_upstream_irq( static void wcd9xxx_irq_put_upstream_irq( struct wcd9xxx_core_resource *wcd9xxx_res) { - /* Hold parent's of node */ - of_node_put(of_irq_find_parent(wcd9xxx_res->dev->of_node)); + wcd9xxx_res->domain = NULL; } static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq) diff --git a/drivers/misc/qcom/Kconfig b/drivers/misc/qcom/Kconfig index a62297e913d2..9c73960f01ff 100644 --- a/drivers/misc/qcom/Kconfig +++ b/drivers/misc/qcom/Kconfig @@ -1,6 +1,7 @@ config MSM_QDSP6V2_CODECS bool "Audio QDSP6V2 APR support" depends on MSM_SMD + select SND_SOC_QDSP6V2 help Enable Audio codecs with APR IPC protocol support between application processor and QDSP6 for B-family. APR is @@ -9,6 +10,7 @@ config MSM_QDSP6V2_CODECS config MSM_ULTRASOUND bool "QDSP6V2 HW Ultrasound support" + select SND_SOC_QDSP6V2 help Enable HW Ultrasound support in QDSP6V2. QDSP6V2 can support HW encoder & decoder and diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c index c9d5dbb0b313..7176c114f85b 100644 --- a/drivers/misc/qcom/qdsp6v2/aac_in.c +++ b/drivers/misc/qcom/qdsp6v2/aac_in.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -421,6 +421,8 @@ static long aac_in_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_aac_enc_config cfg; struct msm_audio_aac_enc_config32 cfg_32; + memset(&cfg_32, 0, sizeof(cfg_32)); + cmd = AUDIO_GET_AAC_ENC_CONFIG; rc = aac_in_ioctl_shared(file, cmd, &cfg); if (rc) { diff --git a/drivers/misc/qcom/qdsp6v2/amrnb_in.c b/drivers/misc/qcom/qdsp6v2/amrnb_in.c index eb92137f0671..1bb441bd2ff4 100644 --- a/drivers/misc/qcom/qdsp6v2/amrnb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrnb_in.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2010-2012, 2014 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2012, 2014, 2016 The Linux Foundation. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -221,6 +222,8 @@ static long amrnb_in_compat_ioctl(struct file *file, struct msm_audio_amrnb_enc_config_v2 *amrnb_config; struct msm_audio_amrnb_enc_config_v2_32 amrnb_config_32; + memset(&amrnb_config_32, 0, sizeof(amrnb_config_32)); + amrnb_config = (struct msm_audio_amrnb_enc_config_v2 *)audio->enc_cfg; amrnb_config_32.band_mode = amrnb_config->band_mode; diff --git a/drivers/misc/qcom/qdsp6v2/amrwb_in.c b/drivers/misc/qcom/qdsp6v2/amrwb_in.c index 4cea3dc63389..4f94ed2673e6 100644 --- a/drivers/misc/qcom/qdsp6v2/amrwb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrwb_in.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2012, 2014, 2016 The Linux Foundation. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -216,6 +217,8 @@ static long amrwb_in_compat_ioctl(struct file *file, struct msm_audio_amrwb_enc_config *amrwb_config; struct msm_audio_amrwb_enc_config_32 amrwb_config_32; + memset(&amrwb_config_32, 0, sizeof(amrwb_config_32)); + amrwb_config = (struct msm_audio_amrwb_enc_config *)audio->enc_cfg; amrwb_config_32.band_mode = amrwb_config->band_mode; diff --git a/drivers/misc/qcom/qdsp6v2/audio_alac.c b/drivers/misc/qcom/qdsp6v2/audio_alac.c index 9748db30fac3..3de204c1ebc8 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_alac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_alac.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -196,6 +196,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_alac_config *alac_config; struct msm_audio_alac_config_32 alac_config_32; + memset(&alac_config_32, 0, sizeof(alac_config_32)); + alac_config = (struct msm_audio_alac_config *)audio->codec_cfg; alac_config_32.frameLength = alac_config->frameLength; alac_config_32.compatVersion = diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c index ee5991177687..bfd730017d41 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c +++ b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -205,6 +205,10 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_amrwbplus_config_v2 *amrwbplus_config; struct msm_audio_amrwbplus_config_v2_32 amrwbplus_config_32; + + memset(&amrwbplus_config_32, 0, + sizeof(amrwbplus_config_32)); + amrwbplus_config = (struct msm_audio_amrwbplus_config_v2 *) audio->codec_cfg; diff --git a/drivers/misc/qcom/qdsp6v2/audio_ape.c b/drivers/misc/qcom/qdsp6v2/audio_ape.c index b4c2ddb947de..670ec555b8c6 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_ape.c +++ b/drivers/misc/qcom/qdsp6v2/audio_ape.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -180,6 +180,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_ape_config *ape_config; struct msm_audio_ape_config_32 ape_config_32; + memset(&ape_config_32, 0, sizeof(ape_config_32)); + ape_config = (struct msm_audio_ape_config *)audio->codec_cfg; ape_config_32.compatibleVersion = ape_config->compatibleVersion; ape_config_32.compressionLevel = diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 3a8834446ea4..3632fc2b961b 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -630,6 +630,8 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, case AUDIO_EFFECTS_GET_BUF_AVAIL32: { struct msm_hwacc_buf_avail32 buf_avail; + memset(&buf_avail, 0, sizeof(buf_avail)); + buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", diff --git a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c index a15fd87c7be8..91bbba176dfd 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -302,6 +302,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_aac_config *aac_config; struct msm_audio_aac_config32 aac_config_32; + memset(&aac_config_32, 0, sizeof(aac_config_32)); + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; aac_config_32.format = aac_config->format; aac_config_32.audio_object = aac_config->audio_object; diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index 5c23da7f8857..f7ad8f61f2e7 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -1936,6 +1936,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, case AUDIO_GET_CONFIG_32: { struct msm_audio_config32 cfg_32; mutex_lock(&audio->lock); + memset(&cfg_32, 0, sizeof(cfg_32)); cfg_32.buffer_size = audio->pcm_cfg.buffer_size; cfg_32.buffer_count = audio->pcm_cfg.buffer_count; cfg_32.channel_count = audio->pcm_cfg.channel_count; @@ -2032,6 +2033,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, audio->buf_cfg.frames_per_buf); mutex_lock(&audio->lock); + memset(&cfg_32, 0, sizeof(cfg_32)); cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable; cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf; if (copy_to_user((void *)arg, &cfg_32, diff --git a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c index 8d96b99d8f84..21ad33b7fd5d 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c +++ b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -217,6 +217,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_wmapro_config *wmapro_config; struct msm_audio_wmapro_config32 wmapro_config_32; + memset(&wmapro_config_32, 0, sizeof(wmapro_config_32)); + wmapro_config = (struct msm_audio_wmapro_config *)audio->codec_cfg; wmapro_config_32.armdatareqthr = wmapro_config->armdatareqthr; diff --git a/drivers/misc/qcom/qdsp6v2/evrc_in.c b/drivers/misc/qcom/qdsp6v2/evrc_in.c index 2f931be226c6..aab8e27c0094 100644 --- a/drivers/misc/qcom/qdsp6v2/evrc_in.c +++ b/drivers/misc/qcom/qdsp6v2/evrc_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -224,6 +224,8 @@ static long evrc_in_compat_ioctl(struct file *file, struct msm_audio_evrc_enc_config32 cfg_32; struct msm_audio_evrc_enc_config *enc_cfg; + memset(&cfg_32, 0, sizeof(cfg_32)); + enc_cfg = audio->enc_cfg; cfg_32.cdma_rate = enc_cfg->cdma_rate; cfg_32.min_bit_rate = enc_cfg->min_bit_rate; diff --git a/drivers/misc/qcom/qdsp6v2/qcelp_in.c b/drivers/misc/qcom/qdsp6v2/qcelp_in.c index b5d5ad113722..aabf5d33a507 100644 --- a/drivers/misc/qcom/qdsp6v2/qcelp_in.c +++ b/drivers/misc/qcom/qdsp6v2/qcelp_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -225,6 +225,8 @@ static long qcelp_in_compat_ioctl(struct file *file, struct msm_audio_qcelp_enc_config32 cfg_32; struct msm_audio_qcelp_enc_config *enc_cfg; + memset(&cfg_32, 0, sizeof(cfg_32)); + enc_cfg = (struct msm_audio_qcelp_enc_config *)audio->enc_cfg; cfg_32.cdma_rate = enc_cfg->cdma_rate; cfg_32.min_bit_rate = enc_cfg->min_bit_rate; diff --git a/drivers/power/qcom/debug_core.c b/drivers/power/qcom/debug_core.c index d3620bbbeafa..ccef04ae9eb2 100644 --- a/drivers/power/qcom/debug_core.c +++ b/drivers/power/qcom/debug_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,6 +22,8 @@ #include "soc/qcom/msm-core.h" #define MAX_PSTATES 50 +#define NUM_OF_PENTRY 3 /* number of variables for ptable node */ +#define NUM_OF_EENTRY 2 /* number of variables for enable node */ enum arg_offset { CPU_OFFSET, @@ -82,15 +84,28 @@ static struct debugfs_blob_wrapper help_msg = { }; -static void add_to_ptable(uint64_t *arg) +static void add_to_ptable(unsigned int *arg) { struct core_debug *node; int i, cpu = arg[CPU_OFFSET]; + uint32_t freq = arg[FREQ_OFFSET]; + uint32_t power = arg[POWER_OFFSET]; if (!cpu_possible(cpu)) return; + if ((freq == 0) || (power == 0)) { + pr_warn("Incorrect power data\n"); + return; + } + node = &per_cpu(c_dgfs, cpu); + + if (node->len >= MAX_PSTATES) { + pr_warn("Dropped ptable update - no space left.\n"); + return; + } + if (!node->head) { node->head = kzalloc(sizeof(struct cpu_pstate_pwr) * (MAX_PSTATES + 1), @@ -98,24 +113,18 @@ static void add_to_ptable(uint64_t *arg) if (!node->head) return; } - for (i = 0; i < MAX_PSTATES; i++) { - if (node->head[i].freq == arg[FREQ_OFFSET]) { - node->head[i].power = arg[POWER_OFFSET]; + + for (i = 0; i < node->len; i++) { + if (node->head[i].freq == freq) { + node->head[i].power = power; return; } - if (node->head[i].freq == 0) - break; - } - - if (i == MAX_PSTATES) { - pr_warn("Dropped ptable update - no space left.\n"); - return; } /* Insert a new frequency (may need to move things around to keep in ascending order). */ for (i = MAX_PSTATES - 1; i > 0; i--) { - if (node->head[i-1].freq > arg[FREQ_OFFSET]) { + if (node->head[i-1].freq > freq) { node->head[i].freq = node->head[i-1].freq; node->head[i].power = node->head[i-1].power; } else if (node->head[i-1].freq != 0) { @@ -123,23 +132,29 @@ static void add_to_ptable(uint64_t *arg) } } - node->head[i].freq = arg[FREQ_OFFSET]; - node->head[i].power = arg[POWER_OFFSET]; - node->len++; + if (node->len < MAX_PSTATES) { + node->head[i].freq = freq; + node->head[i].power = power; + node->len++; + } if (node->ptr) node->ptr->len = node->len; } -static int split_ptable_args(char *line, uint64_t *arg) +static int split_ptable_args(char *line, unsigned int *arg, uint32_t n) { char *args; int i; int ret = 0; - for (i = 0; line; i++) { + for (i = 0; i < n; i++) { + if (!line) + break; args = strsep(&line, " "); - ret = kstrtoull(args, 10, &arg[i]); + ret = kstrtouint(args, 10, &arg[i]); + if (ret) + return ret; } return ret; } @@ -149,7 +164,7 @@ static ssize_t msm_core_ptable_write(struct file *file, { char *kbuf; int ret; - uint64_t arg[3]; + unsigned int arg[3]; if (len == 0) return 0; @@ -163,7 +178,7 @@ static ssize_t msm_core_ptable_write(struct file *file, goto done; } kbuf[len] = '\0'; - ret = split_ptable_args(kbuf, arg); + ret = split_ptable_args(kbuf, arg, NUM_OF_PENTRY); if (!ret) { add_to_ptable(arg); ret = len; @@ -201,7 +216,7 @@ static int msm_core_ptable_read(struct seq_file *m, void *data) seq_printf(m, "--- CPU%d - Live numbers at %ldC---\n", cpu, node->ptr->temp); print_table(m, msm_core_data[cpu].ptable, - msm_core_data[cpu].len); + node->driver_len); } } return 0; @@ -212,7 +227,7 @@ static ssize_t msm_core_enable_write(struct file *file, { char *kbuf; int ret; - uint64_t arg[3]; + unsigned int arg[3]; int cpu; if (len == 0) @@ -227,7 +242,7 @@ static ssize_t msm_core_enable_write(struct file *file, goto done; } kbuf[len] = '\0'; - ret = split_ptable_args(kbuf, arg); + ret = split_ptable_args(kbuf, arg, NUM_OF_EENTRY); if (ret) goto done; cpu = arg[CPU_OFFSET]; diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c index fe5dbbeac15e..b0439871c41a 100644 --- a/drivers/regulator/cpr3-mmss-regulator.c +++ b/drivers/regulator/cpr3-mmss-regulator.c @@ -242,8 +242,8 @@ static const int msmcobalt_v2_mmss_fuse_ref_volt[MSM8996_MMSS_FUSE_CORNERS] = { #define MSMCOBALT_MMSS_CPR_SENSOR_COUNT 35 -#define MSMCOBALT_MMSS_AGING_SENSOR_ID 17 -#define MSMCOBALT_MMSS_AGING_BYPASS_MASK0 0 +#define MSMCOBALT_MMSS_AGING_SENSOR_ID 29 +#define MSMCOBALT_MMSS_AGING_BYPASS_MASK0 (GENMASK(23, 0)) #define MSMCOBALT_MMSS_MAX_TEMP_POINTS 3 #define MSMCOBALT_MMSS_TEMP_SENSOR_ID_START 12 diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c index 6e8db03fe16e..232373092746 100644 --- a/drivers/regulator/cpr3-regulator.c +++ b/drivers/regulator/cpr3-regulator.c @@ -3523,7 +3523,7 @@ cleanup: if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { rc2 = cpr3_ctrl_clear_cpr4_config(ctrl); - if (rc) { + if (rc2) { cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", rc2); rc = rc2; @@ -3725,6 +3725,17 @@ static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl) return 0; } + /* + * Verify that the aging possible register (if specified) has an + * acceptable value. + */ + if (ctrl->aging_possible_reg) { + reg = readl_relaxed(ctrl->aging_possible_reg); + reg &= ctrl->aging_possible_mask; + if (reg != ctrl->aging_possible_val) + return 0; + } + restore_current_corner = kcalloc(vreg_count, sizeof(*restore_current_corner), GFP_KERNEL); restore_vreg_enabled = kcalloc(vreg_count, @@ -3798,7 +3809,7 @@ static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl) max_aging_volt = max(max_aging_volt, aging_volt); } else { cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n", - rc, CPR3_AGING_RETRY_COUNT); + j, rc); ctrl->aging_failed = true; ctrl->aging_required = false; goto cleanup; @@ -5992,6 +6003,21 @@ int cpr3_regulator_register(struct platform_device *pdev, } ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res)); + if (ctrl->aging_possible_mask) { + /* + * Aging possible register address is required if an aging + * possible mask has been specified. + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "aging_allowed"); + if (!res || !res->start) { + cpr3_err(ctrl, "CPR aging allowed address is missing\n"); + return -ENXIO; + } + ctrl->aging_possible_reg = devm_ioremap(dev, res->start, + resource_size(res)); + } + if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) { ctrl->irq = platform_get_irq_byname(pdev, "cpr"); if (ctrl->irq < 0) { diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h index 0907518722df..8897def3ef76 100644 --- a/drivers/regulator/cpr3-regulator.h +++ b/drivers/regulator/cpr3-regulator.h @@ -532,6 +532,9 @@ struct cpr3_panic_regs_info { * that this CPR3 controller manages. * @cpr_ctrl_base: Virtual address of the CPR3 controller base register * @fuse_base: Virtual address of fuse row 0 + * @aging_possible_reg: Virtual address of an optional platform-specific + * register that must be ready to determine if it is + * possible to perform an aging measurement. * @list: list head used in a global cpr3-regulator list so that * cpr3-regulator structs can be found easily in RAM dumps * @thread: Array of CPR3 threads managed by the CPR3 controller @@ -671,6 +674,11 @@ struct cpr3_panic_regs_info { * @aging_sensor: Array of CPR3 aging sensors which are used to perform * aging measurements at a runtime. * @aging_sensor_count: Number of elements in the aging_sensor array + * @aging_possible_mask: Optional bitmask used to mask off the + * aging_possible_reg register. + * @aging_possible_val: Optional value that the masked aging_possible_reg + * register must have in order for a CPR aging measurement + * to be possible. * @step_quot_fixed: Fixed step quotient value used for target quotient * adjustment if use_dynamic_step_quot is not set. * This parameter is only relevant for CPR4 controllers @@ -721,6 +729,7 @@ struct cpr3_controller { int ctrl_id; void __iomem *cpr_ctrl_base; void __iomem *fuse_base; + void __iomem *aging_possible_reg; struct list_head list; struct cpr3_thread *thread; int thread_count; @@ -784,6 +793,8 @@ struct cpr3_controller { bool aging_failed; struct cpr3_aging_sensor_info *aging_sensor; int aging_sensor_count; + u32 aging_possible_mask; + u32 aging_possible_val; u32 step_quot_fixed; u32 initial_temp_band; diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c index 9d55e9af2e7c..51179f28fcf5 100644 --- a/drivers/regulator/cpr3-util.c +++ b/drivers/regulator/cpr3-util.c @@ -1169,6 +1169,24 @@ int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage", &ctrl->aging_ref_volt); + /* Aging possible bitmask is optional */ + ctrl->aging_possible_mask = 0; + of_property_read_u32(ctrl->dev->of_node, + "qcom,cpr-aging-allowed-reg-mask", + &ctrl->aging_possible_mask); + + if (ctrl->aging_possible_mask) { + /* + * Aging possible register value required if bitmask is + * specified + */ + rc = cpr3_parse_ctrl_u32(ctrl, + "qcom,cpr-aging-allowed-reg-value", + &ctrl->aging_possible_val, 0, UINT_MAX); + if (rc) + return rc; + } + if (of_find_property(ctrl->dev->of_node, "clock-names", NULL)) { ctrl->core_clk = devm_clk_get(ctrl->dev, "core_clk"); if (IS_ERR(ctrl->core_clk)) { diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c index 083459f96ac4..284180b0e72f 100644 --- a/drivers/regulator/cprh-kbss-regulator.c +++ b/drivers/regulator/cprh-kbss-regulator.c @@ -69,8 +69,9 @@ struct cprh_msmcobalt_kbss_fuses { /* * Fuse combos 0 - 7 map to CPR fusing revision 0 - 7 with speed bin fuse = 0. + * Fuse combos 8 - 15 map to CPR fusing revision 0 - 7 with speed bin fuse = 1. */ -#define CPRH_MSMCOBALT_KBSS_FUSE_COMBO_COUNT 8 +#define CPRH_MSMCOBALT_KBSS_FUSE_COMBO_COUNT 16 /* * Constants which define the name of each fuse corner. @@ -206,11 +207,19 @@ msmcobalt_v1_kbss_fuse_ref_volt[MSMCOBALT_KBSS_FUSE_CORNERS] = { * Open loop voltage fuse reference voltages in microvolts for MSMCOBALT v2 */ static const int -msmcobalt_v2_kbss_fuse_ref_volt[MSMCOBALT_KBSS_FUSE_CORNERS] = { - 688000, - 756000, - 828000, - 1056000, +msmcobalt_v2_kbss_fuse_ref_volt[2][MSMCOBALT_KBSS_FUSE_CORNERS] = { + [MSMCOBALT_KBSS_POWER_CLUSTER_ID] = { + 688000, + 756000, + 828000, + 1056000, + }, + [MSMCOBALT_KBSS_PERFORMANCE_CLUSTER_ID] = { + 756000, + 756000, + 828000, + 1056000, + }, }; #define MSMCOBALT_KBSS_FUSE_STEP_VOLT 10000 @@ -391,7 +400,7 @@ static int cprh_msmcobalt_kbss_calculate_open_loop_voltages( { struct device_node *node = vreg->of_node; struct cprh_msmcobalt_kbss_fuses *fuse = vreg->platform_fuses; - int i, j, soc_revision, rc = 0; + int i, j, soc_revision, id, rc = 0; bool allow_interpolation; u64 freq_low, volt_low, freq_high, volt_high; const int *ref_volt; @@ -407,13 +416,12 @@ static int cprh_msmcobalt_kbss_calculate_open_loop_voltages( goto done; } + id = vreg->thread->ctrl->ctrl_id; soc_revision = vreg->thread->ctrl->soc_revision; if (soc_revision == 1) ref_volt = msmcobalt_v1_kbss_fuse_ref_volt; - else if (soc_revision == 2) - ref_volt = msmcobalt_v2_kbss_fuse_ref_volt; else - ref_volt = msmcobalt_v2_kbss_fuse_ref_volt; + ref_volt = msmcobalt_v2_kbss_fuse_ref_volt[id]; for (i = 0; i < vreg->fuse_corner_count; i++) { fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse( diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index bfa82ca64499..a3bcfb42ca6a 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -996,7 +996,7 @@ static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) } } -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) +static int __ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) { int err = 0; @@ -1027,7 +1027,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) vote = ufs_qcom_get_bus_vote(host, mode); if (vote >= 0) - err = ufs_qcom_set_bus_vote(host, vote); + err = __ufs_qcom_set_bus_vote(host, vote); else err = vote; @@ -1038,6 +1038,35 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return err; } +static int ufs_qcom_set_bus_vote(struct ufs_hba *hba, bool on) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + int vote, err; + + /* + * In case ufs_qcom_init() is not yet done, simply ignore. + * This ufs_qcom_set_bus_vote() shall be called from + * ufs_qcom_init() after init is done. + */ + if (!host) + return 0; + + if (on) { + vote = host->bus_vote.saved_vote; + if (vote == host->bus_vote.min_bw_vote) + ufs_qcom_update_bus_bw_vote(host); + } else { + vote = host->bus_vote.min_bw_vote; + } + + err = __ufs_qcom_set_bus_vote(host, vote); + if (err) + dev_err(hba->dev, "%s: set bus vote failed %d\n", + __func__, err); + + return err; +} + static ssize_t show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, char *buf) @@ -1403,7 +1432,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, { struct ufs_qcom_host *host = ufshcd_get_variant(hba); int err; - int vote = 0; /* * In case ufs_qcom_init() is not yet done, simply ignore. @@ -1428,9 +1456,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); - vote = host->bus_vote.saved_vote; - if (vote == host->bus_vote.min_bw_vote) - ufs_qcom_update_bus_bw_vote(host); err = ufs_qcom_ice_resume(host); if (err) @@ -1449,14 +1474,8 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); } - vote = host->bus_vote.min_bw_vote; } - err = ufs_qcom_set_bus_vote(host, vote); - if (err) - dev_err(hba->dev, "%s: set bus vote failed %d\n", - __func__, err); - out: return err; } @@ -2011,6 +2030,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); + ufs_qcom_set_bus_vote(hba, true); ufs_qcom_setup_clocks(hba, true, false); if (hba->dev->id < MAX_UFS_QCOM_HOSTS) @@ -2521,6 +2541,7 @@ static struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .full_reset = ufs_qcom_full_reset, .update_sec_cfg = ufs_qcom_update_sec_cfg, .get_scale_down_gear = ufs_qcom_get_scale_down_gear, + .set_bus_vote = ufs_qcom_set_bus_vote, .dbg_register_dump = ufs_qcom_dump_dbg_regs, #ifdef CONFIG_DEBUG_FS .add_debugfs = ufs_qcom_dbg_add_debugfs, diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ce779d760c69..a49b3c7bc4ef 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7555,6 +7555,13 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on, if (!head || list_empty(head)) goto out; + /* call vendor specific bus vote before enabling the clocks */ + if (on) { + ret = ufshcd_vops_set_bus_vote(hba, on); + if (ret) + return ret; + } + /* * vendor specific setup_clocks ops may depend on clocks managed by * this standard driver hence call the vendor specific setup_clocks @@ -7593,11 +7600,24 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on, * this standard driver hence call the vendor specific setup_clocks * after enabling the clocks managed here. */ - if (on) + if (on) { ret = ufshcd_vops_setup_clocks(hba, on, is_gating_context); + if (ret) + goto out; + } + + /* + * call vendor specific bus vote to remove the vote after + * disabling the clocks. + */ + if (!on) + ret = ufshcd_vops_set_bus_vote(hba, on); out: if (ret) { + if (on) + /* Can't do much if this fails */ + (void) ufshcd_vops_set_bus_vote(hba, false); list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) clk_disable_unprepare(clki->clk); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 552d50081e3f..b79bebb58dcd 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -309,6 +309,7 @@ struct ufs_pwr_mode_info { * @update_sec_cfg: called to restore host controller secure configuration * @get_scale_down_gear: called to get the minimum supported gear to * scale down + * @set_bus_vote: called to vote for the required bus bandwidth * @add_debugfs: used to add debugfs entries * @remove_debugfs: used to remove debugfs entries */ @@ -335,6 +336,7 @@ struct ufs_hba_variant_ops { void (*dbg_register_dump)(struct ufs_hba *hba); int (*update_sec_cfg)(struct ufs_hba *hba, bool restore_sec_cfg); u32 (*get_scale_down_gear)(struct ufs_hba *); + int (*set_bus_vote)(struct ufs_hba *, bool); #ifdef CONFIG_DEBUG_FS void (*add_debugfs)(struct ufs_hba *hba, struct dentry *root); void (*remove_debugfs)(struct ufs_hba *hba); @@ -1259,6 +1261,13 @@ static inline u32 ufshcd_vops_get_scale_down_gear(struct ufs_hba *hba) return UFS_HS_G1; } +static inline int ufshcd_vops_set_bus_vote(struct ufs_hba *hba, bool on) +{ + if (hba->var && hba->var->vops && hba->var->vops->set_bus_vote) + return hba->var->vops->set_bus_vote(hba, on); + return 0; +} + #ifdef CONFIG_DEBUG_FS static inline void ufshcd_vops_add_debugfs(struct ufs_hba *hba, struct dentry *root) diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 20a4a3c7fdf0..f00570aa5fe8 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -4113,6 +4113,37 @@ static struct glink_core_xprt_ctx *glink_create_dummy_xprt_ctx( return xprt_ptr; } +static struct channel_ctx *get_first_ch_ctx( + struct glink_core_xprt_ctx *xprt_ctx) +{ + unsigned long flags; + struct channel_ctx *ctx; + + spin_lock_irqsave(&xprt_ctx->xprt_ctx_lock_lhb1, flags); + if (!list_empty(&xprt_ctx->channels)) { + ctx = list_first_entry(&xprt_ctx->channels, + struct channel_ctx, port_list_node); + rwref_get(&ctx->ch_state_lhb2); + } else { + ctx = NULL; + } + spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags); + return ctx; +} + +static void glink_core_move_ch_node(struct glink_core_xprt_ctx *xprt_ptr, + struct glink_core_xprt_ctx *dummy_xprt_ctx, struct channel_ctx *ctx) +{ + unsigned long flags, d_flags; + + spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags); + spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags); + rwref_get(&dummy_xprt_ctx->xprt_state_lhb0); + list_move_tail(&ctx->port_list_node, &dummy_xprt_ctx->channels); + spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags); + spin_unlock_irqrestore(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags); +} + /** * glink_core_channel_cleanup() - cleanup all channels for the transport * @@ -4123,7 +4154,7 @@ static struct glink_core_xprt_ctx *glink_create_dummy_xprt_ctx( static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr) { unsigned long flags, d_flags; - struct channel_ctx *ctx, *tmp_ctx; + struct channel_ctx *ctx; struct channel_lcid *temp_lcid, *temp_lcid1; struct glink_core_xprt_ctx *dummy_xprt_ctx; @@ -4132,29 +4163,18 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr) GLINK_ERR("%s: Dummy Transport creation failed\n", __func__); return; } - rwref_read_get(&dummy_xprt_ctx->xprt_state_lhb0); rwref_read_get(&xprt_ptr->xprt_state_lhb0); - spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags); - spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags); - - list_for_each_entry_safe(ctx, tmp_ctx, &xprt_ptr->channels, - port_list_node) { + ctx = get_first_ch_ctx(xprt_ptr); + while (ctx) { rwref_write_get_atomic(&ctx->ch_state_lhb2, true); if (ctx->local_open_state == GLINK_CHANNEL_OPENED || ctx->local_open_state == GLINK_CHANNEL_OPENING) { - rwref_get(&dummy_xprt_ctx->xprt_state_lhb0); - list_move_tail(&ctx->port_list_node, - &dummy_xprt_ctx->channels); ctx->transport_ptr = dummy_xprt_ctx; rwref_write_put(&ctx->ch_state_lhb2); + glink_core_move_ch_node(xprt_ptr, dummy_xprt_ctx, ctx); } else { /* local state is in either CLOSED or CLOSING */ - spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, - flags); - spin_unlock_irqrestore( - &dummy_xprt_ctx->xprt_ctx_lock_lhb1, - d_flags); glink_core_remote_close_common(ctx, true); if (ctx->local_open_state == GLINK_CHANNEL_CLOSING) glink_core_ch_close_ack_common(ctx, true); @@ -4162,22 +4182,21 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr) if (ch_is_fully_closed(ctx)) glink_delete_ch_from_list(ctx, false); rwref_write_put(&ctx->ch_state_lhb2); - spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, - d_flags); - spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags); } + rwref_put(&ctx->ch_state_lhb2); + ctx = get_first_ch_ctx(xprt_ptr); } + spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags); list_for_each_entry_safe(temp_lcid, temp_lcid1, &xprt_ptr->free_lcid_list, list_node) { list_del(&temp_lcid->list_node); kfree(&temp_lcid->list_node); } - dummy_xprt_ctx->dummy_in_use = false; spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags); - spin_unlock_irqrestore(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags); rwref_read_put(&xprt_ptr->xprt_state_lhb0); spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags); + dummy_xprt_ctx->dummy_in_use = false; while (!list_empty(&dummy_xprt_ctx->channels)) { ctx = list_first_entry(&dummy_xprt_ctx->channels, struct channel_ctx, port_list_node); diff --git a/drivers/soc/qcom/irq-helper.c b/drivers/soc/qcom/irq-helper.c index 7bb371f7991e..370801291230 100644 --- a/drivers/soc/qcom/irq-helper.c +++ b/drivers/soc/qcom/irq-helper.c @@ -78,10 +78,12 @@ IRQ_HELPER_ATTR(irq_blacklist_on, 0444, show_deploy, NULL); static struct irq_helper *irq_h; +/* Do not call this API in an atomic context */ int irq_blacklist_on(void) { bool flag = false; + might_sleep(); if (!irq_h) { pr_err("%s: init function is not called", __func__); return -EPERM; @@ -103,10 +105,12 @@ int irq_blacklist_on(void) } EXPORT_SYMBOL(irq_blacklist_on); +/* Do not call this API in an atomic context */ int irq_blacklist_off(void) { bool flag = false; + might_sleep(); if (!irq_h) { pr_err("%s: init function is not called", __func__); return -EPERM; diff --git a/drivers/soc/qcom/remoteqdss.c b/drivers/soc/qcom/remoteqdss.c index e66ca587adca..5e2a5babdcc8 100644 --- a/drivers/soc/qcom/remoteqdss.c +++ b/drivers/soc/qcom/remoteqdss.c @@ -28,8 +28,8 @@ static struct dentry *remoteqdss_dir; #define REMOTEQDSS_ERR(fmt, ...) \ pr_debug("%s: " fmt, __func__, ## __VA_ARGS__) -#define REMOTEQDSS_ERR_CALLER(fmt, ...) \ - pr_debug("%pf: " fmt, __builtin_return_address(1), ## __VA_ARGS__) +#define REMOTEQDSS_ERR_CALLER(fmt, caller, ...) \ + pr_debug("%pf: " fmt, caller, ## __VA_ARGS__) struct qdss_msg_translation { u64 val; @@ -97,7 +97,7 @@ struct remoteqdss_query_swentity_fmt { /* msgs is a null terminated array */ static void remoteqdss_err_translation(struct qdss_msg_translation *msgs, - u64 err) + u64 err, const void *caller) { static DEFINE_RATELIMIT_STATE(rl, 5 * HZ, 2); struct qdss_msg_translation *msg; @@ -110,12 +110,13 @@ static void remoteqdss_err_translation(struct qdss_msg_translation *msgs, for (msg = msgs; msg->msg; msg++) { if (err == msg->val && __ratelimit(&rl)) { - REMOTEQDSS_ERR_CALLER("0x%llx: %s\n", err, msg->msg); + REMOTEQDSS_ERR_CALLER("0x%llx: %s\n", caller, err, + msg->msg); return; } } - REMOTEQDSS_ERR_CALLER("Error 0x%llx\n", err); + REMOTEQDSS_ERR_CALLER("Error 0x%llx\n", caller, err); } /* Shared across all remoteqdss scm functions */ @@ -160,7 +161,7 @@ static void free_remoteqdss_data(struct remoteqdss_data *data) } static int remoteqdss_do_scm_call(struct scm_desc *desc, - dma_addr_t addr, size_t size) + dma_addr_t addr, size_t size, const void *caller) { int ret; @@ -175,7 +176,7 @@ static int remoteqdss_do_scm_call(struct scm_desc *desc, if (ret) return ret; - remoteqdss_err_translation(remoteqdss_scm_msgs, desc->ret[0]); + remoteqdss_err_translation(remoteqdss_scm_msgs, desc->ret[0], caller); ret = desc->ret[0] ? -EINVAL : 0; return ret; } @@ -194,7 +195,8 @@ static int remoteqdss_scm_query_swtrace(void *priv, u64 *val) fmt->subsys_id = data->id; fmt->cmd_id = CMD_ID_QUERY_SWTRACE_STATE; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); *val = desc.ret[1]; dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); @@ -216,7 +218,8 @@ static int remoteqdss_scm_filter_swtrace(void *priv, u64 val) fmt->h.cmd_id = CMD_ID_FILTER_SWTRACE_STATE; fmt->state = (uint32_t)val; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); return ret; @@ -241,7 +244,8 @@ static int remoteqdss_scm_query_tag(void *priv, u64 *val) fmt->subsys_id = data->id; fmt->cmd_id = CMD_ID_QUERY_SWEVENT_TAG; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); *val = desc.ret[1]; dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); @@ -268,7 +272,8 @@ static int remoteqdss_scm_query_swevent(void *priv, u64 *val) fmt->h.cmd_id = CMD_ID_QUERY_SWEVENT; fmt->event_group = data->sw_event_group; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); *val = desc.ret[1]; dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); @@ -291,7 +296,8 @@ static int remoteqdss_scm_filter_swevent(void *priv, u64 val) fmt->event_group = data->sw_event_group; fmt->event_mask = (uint32_t)val; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); return ret; @@ -317,7 +323,8 @@ static int remoteqdss_scm_query_swentity(void *priv, u64 *val) fmt->h.cmd_id = CMD_ID_QUERY_SWENTITY; fmt->entity_group = data->sw_entity_group; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); *val = desc.ret[1]; dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); @@ -340,7 +347,8 @@ static int remoteqdss_scm_filter_swentity(void *priv, u64 val) fmt->entity_group = data->sw_entity_group; fmt->entity_mask = (uint32_t)val; - ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt)); + ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt), + __builtin_return_address(0)); dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr); return ret; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 23e32214756a..ea4f557fcd70 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -538,6 +538,9 @@ static struct msm_soc_info cpu_of_id[] = { /* falcon ID */ [317] = {MSM_CPU_FALCON, "MSMFALCON"}, + /* triton ID */ + [318] = {MSM_CPU_TRITON, "MSMTRITON"}, + /* Uninitialized IDs are not known to run Linux. MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are considered as unknown CPU. */ @@ -1207,6 +1210,10 @@ static void * __init setup_dummy_socinfo(void) dummy_socinfo.id = 317; strlcpy(dummy_socinfo.build_id, "msmfalcon - ", sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msmtriton()) { + dummy_socinfo.id = 318; + strlcpy(dummy_socinfo.build_id, "msmtriton - ", + sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_apqcobalt()) { dummy_socinfo.id = 319; strlcpy(dummy_socinfo.build_id, "apqcobalt - ", diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 0bdb3d76cc8d..9fdb06e08d4b 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -198,13 +198,13 @@ struct msm_port { static void msm_write(struct uart_port *port, unsigned int val, unsigned int off) { - writel_relaxed(val, port->membase + off); + writel_relaxed_no_log(val, port->membase + off); } static unsigned int msm_read(struct uart_port *port, unsigned int off) { - return readl_relaxed(port->membase + off); + return readl_relaxed_no_log(port->membase + off); } /* diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 8189096f95c2..f24816f06a5b 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -45,6 +45,7 @@ #include <linux/msm-bus.h> #include <linux/irq.h> #include <linux/extcon.h> +#include <linux/reset.h> #include "power.h" #include "core.h" @@ -159,6 +160,7 @@ struct dwc3_msm { struct clk *utmi_clk_src; struct clk *bus_aggr_clk; struct clk *cfg_ahb_clk; + struct reset_control *core_reset; struct regulator *dwc3_gdsc; struct usb_phy *hs_phy, *ss_phy; @@ -1517,19 +1519,19 @@ static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert) clk_disable_unprepare(mdwc->sleep_clk); clk_disable_unprepare(mdwc->core_clk); clk_disable_unprepare(mdwc->iface_clk); - ret = clk_reset(mdwc->core_clk, CLK_RESET_ASSERT); + ret = reset_control_assert(mdwc->core_reset); if (ret) - dev_err(mdwc->dev, "dwc3 core_clk assert failed\n"); + dev_err(mdwc->dev, "dwc3 core_reset assert failed\n"); } else { dev_dbg(mdwc->dev, "block_reset DEASSERT\n"); - ret = clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); + ret = reset_control_deassert(mdwc->core_reset); + if (ret) + dev_err(mdwc->dev, "dwc3 core_reset deassert failed\n"); ndelay(200); clk_prepare_enable(mdwc->iface_clk); clk_prepare_enable(mdwc->core_clk); clk_prepare_enable(mdwc->sleep_clk); clk_prepare_enable(mdwc->utmi_clk); - if (ret) - dev_err(mdwc->dev, "dwc3 core_clk deassert failed\n"); enable_irq(mdwc->pwr_event_irq); } @@ -2041,11 +2043,16 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { dev_dbg(mdwc->dev, "%s: exit power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 1); - - clk_reset(mdwc->core_clk, CLK_RESET_ASSERT); + ret = reset_control_assert(mdwc->core_reset); + if (ret) + dev_err(mdwc->dev, "%s:core_reset assert failed\n", + __func__); /* HW requires a short delay for reset to take place properly */ usleep_range(1000, 1200); - clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); + ret = reset_control_deassert(mdwc->core_reset); + if (ret) + dev_err(mdwc->dev, "%s:core_reset deassert failed\n", + __func__); clk_prepare_enable(mdwc->sleep_clk); } @@ -2366,6 +2373,17 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX); } + mdwc->core_reset = devm_reset_control_get(mdwc->dev, "core_reset"); + if (IS_ERR(mdwc->core_reset)) { + dev_err(mdwc->dev, "failed to get core_reset\n"); + return PTR_ERR(mdwc->core_reset); + } + + /* + * Get Max supported clk frequency for USB Core CLK and request + * to set the same. + */ + mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX); if (IS_ERR_VALUE(mdwc->core_clk_rate)) { dev_err(mdwc->dev, "fail to get core clk max freq.\n"); } else { diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 206192ff99bb..80c9928e948e 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -36,6 +36,7 @@ MODULE_PARM_DESC(num_out_bufs, static struct workqueue_struct *ipa_usb_wq; +static void gsi_rndis_ipa_reset_trigger(struct f_gsi *rndis); static void ipa_disconnect_handler(struct gsi_data_port *d_port); static int gsi_ctrl_send_notification(struct f_gsi *gsi, enum gsi_ctrl_notify_state); @@ -553,6 +554,7 @@ static void ipa_work_handler(struct work_struct *w) struct device *dev; struct device *gad_dev; struct f_gsi *gsi; + bool block_db; event = read_event(d_port); @@ -665,7 +667,27 @@ static void ipa_work_handler(struct work_struct *w) } break; case STATE_CONNECTED: - if (event == EVT_DISCONNECTED) { + if (event == EVT_DISCONNECTED || event == EVT_HOST_NRDY) { + if (peek_event(d_port) == EVT_HOST_READY) { + read_event(d_port); + log_event_dbg("%s: NO_OP NRDY_RDY", __func__); + break; + } + + if (event == EVT_HOST_NRDY) { + log_event_dbg("%s: ST_CON_HOST_NRDY\n", + __func__); + block_db = true; + /* stop USB ringing doorbell to GSI(OUT_EP) */ + usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, + GSI_EP_OP_SET_CLR_BLOCK_DBL); + gsi_rndis_ipa_reset_trigger(gsi); + usb_gsi_ep_op(d_port->in_ep, NULL, + GSI_EP_OP_ENDXFER); + usb_gsi_ep_op(d_port->out_ep, NULL, + GSI_EP_OP_ENDXFER); + } + ipa_disconnect_work_handler(d_port); d_port->sm_state = STATE_INITIALIZED; usb_gadget_autopm_put_async(d_port->gadget); @@ -1269,7 +1291,7 @@ static void gsi_rndis_open(struct f_gsi *rndis) rndis_signal_connect(rndis->params); } -void gsi_rndis_ipa_reset_trigger(struct f_gsi *rndis) +static void gsi_rndis_ipa_reset_trigger(struct f_gsi *rndis) { unsigned long flags; @@ -1301,12 +1323,11 @@ void gsi_rndis_flow_ctrl_enable(bool enable, struct rndis_params *param) d_port = &rndis->d_port; - if (enable) { - gsi_rndis_ipa_reset_trigger(rndis); - usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_ENDXFER); - usb_gsi_ep_op(d_port->out_ep, NULL, GSI_EP_OP_ENDXFER); - post_event(d_port, EVT_DISCONNECTED); + if (enable) { + log_event_dbg("%s: posting HOST_NRDY\n", __func__); + post_event(d_port, EVT_HOST_NRDY); } else { + log_event_dbg("%s: posting HOST_READY\n", __func__); post_event(d_port, EVT_HOST_READY); } diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index b222c3c5f7b4..4ecdc350fbd4 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -27,6 +27,7 @@ #include <linux/regulator/machine.h> #include <linux/usb/phy.h> #include <linux/usb/msm_hsusb.h> +#include <linux/reset.h> #define QUSB2PHY_PWR_CTRL1 0x210 #define PWR_CTRL1_POWR_DOWN BIT(0) @@ -76,7 +77,7 @@ struct qusb_phy { struct clk *ref_clk_src; struct clk *ref_clk; struct clk *cfg_ahb_clk; - struct clk *phy_reset; + struct reset_control *phy_reset; struct regulator *vdd; struct regulator *vdda33; @@ -370,14 +371,19 @@ static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, static void qusb_phy_host_init(struct usb_phy *phy) { u8 reg; + int ret; struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); dev_dbg(phy->dev, "%s\n", __func__); /* Perform phy reset */ - clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset assert failed\n", __func__); usleep_range(100, 150); - clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", __func__); qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq, qphy->host_init_seq_len, 0); @@ -411,9 +417,13 @@ static int qusb_phy_init(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, true); /* Perform phy reset */ - clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset assert failed\n", __func__); usleep_range(100, 150); - clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", __func__); if (qphy->emulation) { if (qphy->emu_init_seq) @@ -531,6 +541,7 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); u32 linestate = 0, intr_mask = 0; + int ret; if (qphy->suspended && suspend) { dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", @@ -578,9 +589,15 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) qusb_phy_enable_clocks(qphy, false); } else { /* Cable disconnect case */ - clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset assert failed\n", + __func__); usleep_range(100, 150); - clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", + __func__); /* enable clock bypass */ writel_relaxed(0x90, @@ -622,7 +639,10 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) */ wmb(); - clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", + __func__); qusb_phy_enable_power(qphy, true, true); qusb_phy_enable_clocks(qphy, true); @@ -802,7 +822,7 @@ static int qusb_phy_probe(struct platform_device *pdev) } } - qphy->phy_reset = devm_clk_get(dev, "phy_reset"); + qphy->phy_reset = devm_reset_control_get(dev, "phy_reset"); if (IS_ERR(qphy->phy_reset)) return PTR_ERR(qphy->phy_reset); diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c index af7ec03314f5..5456b9e8733b 100644 --- a/drivers/usb/phy/phy-msm-qusb.c +++ b/drivers/usb/phy/phy-msm-qusb.c @@ -27,6 +27,7 @@ #include <linux/regulator/machine.h> #include <linux/usb/phy.h> #include <linux/usb/msm_hsusb.h> +#include <linux/reset.h> #define QUSB2PHY_PLL_STATUS 0x38 #define QUSB2PHY_PLL_LOCK BIT(5) @@ -112,7 +113,7 @@ struct qusb_phy { struct clk *ref_clk_src; struct clk *ref_clk; struct clk *cfg_ahb_clk; - struct clk *phy_reset; + struct reset_control *phy_reset; struct regulator *vdd; struct regulator *vdda33; @@ -443,9 +444,13 @@ static int qusb_phy_init(struct usb_phy *phy) } /* Perform phy reset */ - clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset assert failed\n", __func__); usleep_range(100, 150); - clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", __func__); if (qphy->emulation) { if (qphy->emu_init_seq) @@ -858,7 +863,7 @@ static int qusb_phy_probe(struct platform_device *pdev) if (IS_ERR(qphy->cfg_ahb_clk)) return PTR_ERR(qphy->cfg_ahb_clk); - qphy->phy_reset = devm_clk_get(dev, "phy_reset"); + qphy->phy_reset = devm_reset_control_get(dev, "phy_reset"); if (IS_ERR(qphy->phy_reset)) return PTR_ERR(qphy->phy_reset); @@ -1011,8 +1016,11 @@ static int qusb_phy_probe(struct platform_device *pdev) * not used, there is leakage current seen with QUSB PHY related voltage * rail. Hence keep QUSB PHY into reset state explicitly here. */ - if (hold_phy_reset) - clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + if (hold_phy_reset) { + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(dev, "%s:phy_reset assert failed\n", __func__); + } ret = usb_add_phy_dev(&qphy->phy); if (ret) diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index 87235a5a4f99..fc61e3172d0b 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -25,6 +25,7 @@ #include <linux/usb/msm_hsusb.h> #include <linux/clk.h> #include <linux/clk/msm-clk.h> +#include <linux/reset.h> enum core_ldo_levels { CORE_LEVEL_NONE = 0, @@ -87,9 +88,10 @@ struct msm_ssphy_qmp { struct clk *aux_clk; struct clk *cfg_ahb_clk; struct clk *pipe_clk; - struct clk *phy_reset; - struct clk *phy_phy_reset; bool power_enabled; + struct reset_control *phy_reset; + struct reset_control *phy_phy_reset; + bool clk_enabled; bool cable_connected; bool in_suspend; @@ -371,56 +373,39 @@ static int msm_ssphy_qmp_reset(struct usb_phy *uphy) dev_dbg(uphy->dev, "Resetting QMP phy\n"); /* Assert USB3 PHY reset */ - if (phy->phy_phy_reset) { - ret = clk_reset(phy->phy_phy_reset, CLK_RESET_ASSERT); - if (ret) { - dev_err(uphy->dev, "phy_phy reset assert failed\n"); - goto exit; - } - } else { - ret = clk_reset(phy->pipe_clk, CLK_RESET_ASSERT); - if (ret) { - dev_err(uphy->dev, "pipe_clk reset assert failed\n"); - goto exit; - } + ret = reset_control_assert(phy->phy_phy_reset); + if (ret) { + dev_err(uphy->dev, "phy_phy_reset assert failed\n"); + goto exit; } /* Assert USB3 PHY CSR reset */ - ret = clk_reset(phy->phy_reset, CLK_RESET_ASSERT); + ret = reset_control_assert(phy->phy_reset); if (ret) { - dev_err(uphy->dev, "phy_reset clk assert failed\n"); + dev_err(uphy->dev, "phy_reset assert failed\n"); goto deassert_phy_phy_reset; } /* Deassert USB3 PHY CSR reset */ - ret = clk_reset(phy->phy_reset, CLK_RESET_DEASSERT); + ret = reset_control_deassert(phy->phy_reset); if (ret) { - dev_err(uphy->dev, "phy_reset clk deassert failed\n"); + dev_err(uphy->dev, "phy_reset deassert failed\n"); goto deassert_phy_phy_reset; } /* Deassert USB3 PHY reset */ - if (phy->phy_phy_reset) { - ret = clk_reset(phy->phy_phy_reset, CLK_RESET_DEASSERT); - if (ret) { - dev_err(uphy->dev, "phy_phy reset deassert failed\n"); - goto exit; - } - } else { - ret = clk_reset(phy->pipe_clk, CLK_RESET_DEASSERT); - if (ret) { - dev_err(uphy->dev, "pipe_clk reset deassert failed\n"); - goto exit; - } + ret = reset_control_deassert(phy->phy_phy_reset); + if (ret) { + dev_err(uphy->dev, "phy_phy_reset deassert failed\n"); + goto exit; } return 0; deassert_phy_phy_reset: - if (phy->phy_phy_reset) - clk_reset(phy->phy_phy_reset, CLK_RESET_DEASSERT); - else - clk_reset(phy->pipe_clk, CLK_RESET_DEASSERT); + ret = reset_control_deassert(phy->phy_phy_reset); + if (ret) + dev_err(uphy->dev, "phy_phy_reset deassert failed\n"); exit: phy->in_suspend = false; @@ -594,26 +579,18 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev) goto err; } - if (of_property_match_string(pdev->dev.of_node, - "clock-names", "phy_reset") >= 0) { - phy->phy_reset = clk_get(&pdev->dev, "phy_reset"); - if (IS_ERR(phy->phy_reset)) { - ret = PTR_ERR(phy->phy_reset); - phy->phy_reset = NULL; - dev_dbg(dev, "failed to get phy_reset\n"); - goto err; - } + phy->phy_reset = devm_reset_control_get(dev, "phy_reset"); + if (IS_ERR(phy->phy_reset)) { + ret = PTR_ERR(phy->phy_reset); + dev_dbg(dev, "failed to get phy_reset\n"); + goto err; } - if (of_property_match_string(pdev->dev.of_node, - "clock-names", "phy_phy_reset") >= 0) { - phy->phy_phy_reset = clk_get(dev, "phy_phy_reset"); - if (IS_ERR(phy->phy_phy_reset)) { - ret = PTR_ERR(phy->phy_phy_reset); - phy->phy_phy_reset = NULL; - dev_dbg(dev, "phy_phy_reset unavailable\n"); - goto err; - } + phy->phy_phy_reset = devm_reset_control_get(dev, "phy_phy_reset"); + if (IS_ERR(phy->phy_phy_reset)) { + ret = PTR_ERR(phy->phy_phy_reset); + dev_dbg(dev, "failed to get phy_phy_reset\n"); + goto err; } of_get_property(dev->of_node, "qcom,qmp-phy-reg-offset", &size); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index fe6ce30d0c89..e8d68059581f 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -27,7 +27,6 @@ #include "mdss_dba_utils.h" #define DT_CMD_HDR 6 -#define MIN_REFRESH_RATE 48 #define DEFAULT_MDP_TRANSFER_TIME 14000 #define VSYNC_DELAY msecs_to_jiffies(17) @@ -1907,10 +1906,10 @@ static int mdss_dsi_set_refresh_rate_range(struct device_node *pan_node, __func__, __LINE__); /* - * Since min refresh rate is not specified when dynamic - * fps is enabled, using minimum as 30 + * If min refresh rate is not specified, set it to the + * default panel refresh rate. */ - pinfo->min_fps = MIN_REFRESH_RATE; + pinfo->min_fps = pinfo->mipi.frame_rate; rc = 0; } diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index f35156a2cfcb..cd842cecc945 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1364,6 +1364,7 @@ static void mdss_mdp_memory_retention_enter(void) } } + __mdss_mdp_reg_access_clk_enable(mdata, true); if (mdss_mdp_clk) { clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM); clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET); @@ -1375,6 +1376,7 @@ static void mdss_mdp_memory_retention_enter(void) clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET); clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_PERIPH); } + __mdss_mdp_reg_access_clk_enable(mdata, false); } static void mdss_mdp_memory_retention_exit(void) @@ -1396,7 +1398,7 @@ static void mdss_mdp_memory_retention_exit(void) } } - + __mdss_mdp_reg_access_clk_enable(mdata, true); if (mdss_mdp_clk) { clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM); clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH); @@ -1408,6 +1410,7 @@ static void mdss_mdp_memory_retention_exit(void) clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH); clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_CLEAR); } + __mdss_mdp_reg_access_clk_enable(mdata, false); } /** diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h index f366d526c138..31c4537ea964 100644 --- a/include/dt-bindings/clock/msm-clocks-cobalt.h +++ b/include/dt-bindings/clock/msm-clocks-cobalt.h @@ -494,6 +494,7 @@ #define clk_sys_apcsaux_clk_gcc 0xf905e862 #define clk_xo_ao 0x428c856d #define clk_osm_clk_src 0xaabe68c3 +#define clk_cpu_debug_mux 0x3ae8bcb2 /* Audio External Clocks */ #define clk_audio_ap_clk 0x9b5727cb diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h index 75908dfa8d64..f595275e9d42 100644 --- a/include/linux/mfd/wcd9xxx/core.h +++ b/include/linux/mfd/wcd9xxx/core.h @@ -204,6 +204,7 @@ struct wcd9xxx_core_resource { void *parent; struct device *dev; + struct irq_domain *domain; }; /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 74b2a11b1d1c..4701e0403167 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -336,8 +336,6 @@ enum migrate_types { GROUP_TO_GROUP, }; -extern const char *migrate_type_names[]; - #include <linux/spinlock.h> /* diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 73b0fbe034fb..2e03ed0e56d3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -65,6 +65,7 @@ struct wiphy; #define CFG80211_SCAN_BSSID 1 #define CFG80211_CONNECT_PREV_BSSID 1 +#define CFG80211_CONNECT_BSS 1 /* * wireless hardware capability structures @@ -4668,6 +4669,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) #endif /** + * cfg80211_connect_bss - notify cfg80211 of connection result + * + * @dev: network device + * @bssid: the BSSID of the AP + * @bss: entry of bss to which STA got connected to, can be obtained + * through cfg80211_get_bss (may be %NULL) + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @resp_ie: association response IEs (may be %NULL) + * @resp_ie_len: assoc response IEs length + * @status: status code, 0 for successful connection, use + * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you + * the real status code for failures. + * @gfp: allocation flags + * + * It should be called by the underlying driver whenever connect() has + * succeeded. This is similar to cfg80211_connect_result(), but with the + * option of identifying the exact bss entry for the connection. Only one of + * these functions should be called. + */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp); + +/** * cfg80211_connect_result - notify cfg80211 of connection result * * @dev: network device @@ -4684,10 +4711,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) * It should be called by the underlying driver whenever connect() has * succeeded. */ -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp); +static inline void +cfg80211_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, + u16 status, gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie, + resp_ie_len, status, gfp); +} /** * cfg80211_roamed - notify cfg80211 of roaming diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 82672bba7c17..76555ce53d97 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -96,6 +96,8 @@ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmhamster") #define early_machine_is_msmfalcon() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmfalcon") +#define early_machine_is_msmtriton() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmtriton") #else #define of_board_is_sim() 0 #define of_board_is_rumi() 0 @@ -133,6 +135,7 @@ #define early_machine_is_apqcobalt() 0 #define early_machine_is_msmhamster() 0 #define early_machine_is_msmfalcon() 0 +#define early_machine_is_msmtriton() 0 #endif #define PLATFORM_SUBTYPE_MDM 1 @@ -192,6 +195,7 @@ enum msm_cpu { MSM_CPU_COBALT, MSM_CPU_HAMSTER, MSM_CPU_FALCON, + MSM_CPU_TRITON, }; struct msm_soc_info { diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 695e33f4d1cf..636ae899c304 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -804,6 +804,7 @@ struct adm_cmd_connect_afe_port_v5 { #define INT_FM_TX 0x3005 #define RT_PROXY_PORT_001_RX 0x2000 #define RT_PROXY_PORT_001_TX 0x2001 +#define DISPLAY_PORT_RX 0x6020 #define AFE_PORT_INVALID 0xFFFF #define SLIMBUS_INVALID AFE_PORT_INVALID @@ -953,6 +954,8 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_8_RX 0x4010 /* SLIMbus Tx port on channel 8. */ #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_8_TX 0x4011 +/* AFE Rx port for audio over Display port */ +#define AFE_PORT_ID_HDMI_OVER_DP_RX 0x6020 /*USB AFE port */ #define AFE_PORT_ID_USB_RX 0x7000 #define AFE_PORT_ID_USB_TX 0x7001 diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index 6be903a4c8d0..b252463b72a2 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -173,14 +173,16 @@ enum { IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_6, IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7, IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7, - /* IDX 118->122 */ + /* IDX 118->121 */ IDX_SLIMBUS_7_RX, IDX_SLIMBUS_7_TX, IDX_SLIMBUS_8_RX, IDX_SLIMBUS_8_TX, - /* IDX 123-> 124 */ + /* IDX 122-> 123 */ IDX_AFE_PORT_ID_USB_RX, IDX_AFE_PORT_ID_USB_TX, + /* IDX 124 */ + IDX_DISPLAY_PORT_RX, AFE_MAX_PORTS }; diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index f35630045c2f..1ef5ec3eaf70 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -9,9 +9,6 @@ #include <linux/binfmts.h> struct rq; -struct group_cpu_time; -struct migration_sum_data; -extern const char *task_event_names[]; /* * Tracepoint for calling kthread_stop, performed to end a kthread: @@ -113,6 +110,11 @@ TRACE_EVENT(sched_enq_deq_task, #ifdef CONFIG_SCHED_HMP +struct group_cpu_time; +struct migration_sum_data; +extern const char *task_event_names[]; +extern const char *migrate_type_names[]; + TRACE_EVENT(sched_task_load, TP_PROTO(struct task_struct *p, bool boost, int reason, diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ae54c5bfac1d..7474463b9835 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -90,13 +90,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/sched.h> -const char *task_event_names[] = {"PUT_PREV_TASK", "PICK_NEXT_TASK", - "TASK_WAKE", "TASK_MIGRATE", "TASK_UPDATE", - "IRQ_UPDATE"}; - -const char *migrate_type_names[] = {"GROUP_TO_RQ", "RQ_TO_GROUP", - "RQ_TO_RQ", "GROUP_TO_GROUP"}; - ATOMIC_NOTIFIER_HEAD(load_alert_notifier_head); DEFINE_MUTEX(sched_domains_mutex); diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index 447f3880f645..837025353db0 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -22,6 +22,13 @@ #include <trace/events/sched.h> +const char *task_event_names[] = {"PUT_PREV_TASK", "PICK_NEXT_TASK", + "TASK_WAKE", "TASK_MIGRATE", "TASK_UPDATE", + "IRQ_UPDATE"}; + +const char *migrate_type_names[] = {"GROUP_TO_RQ", "RQ_TO_GROUP", + "RQ_TO_RQ", "GROUP_TO_GROUP"}; + static ktime_t ktime_last; static bool sched_ktime_suspended; diff --git a/net/wireless/core.h b/net/wireless/core.h index a918fc303d51..05125d092b18 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -213,6 +213,7 @@ struct cfg80211_event { const u8 *resp_ie; size_t req_ie_len; size_t resp_ie_len; + struct cfg80211_bss *bss; u16 status; } cr; struct { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 44f420dfa8e3..37d8ab3a71be 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -767,19 +767,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(country_ie); } -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp) +/* Consumes bss object one way or another */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_event *ev; unsigned long flags; + if (bss) { + /* Make sure the bss entry provided by the driver is valid. */ + struct cfg80211_internal_bss *ibss = bss_from_pub(bss); + + if (WARN_ON(list_empty(&ibss->list))) { + cfg80211_put_bss(wdev->wiphy, bss); + return; + } + } + ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); - if (!ev) + if (!ev) { + cfg80211_put_bss(wdev->wiphy, bss); return; + } ev->type = EVENT_CONNECT_RESULT; if (bssid) @@ -794,6 +807,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ev->cr.resp_ie_len = resp_ie_len; memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); } + if (bss) + cfg80211_hold_bss(bss_from_pub(bss)); + ev->cr.bss = bss; ev->cr.status = status; spin_lock_irqsave(&wdev->event_lock, flags); @@ -801,7 +817,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, spin_unlock_irqrestore(&wdev->event_lock, flags); queue_work(cfg80211_wq, &rdev->event_work); } -EXPORT_SYMBOL(cfg80211_connect_result); +EXPORT_SYMBOL(cfg80211_connect_bss); /* Consumes bss object one way or another */ void __cfg80211_roamed(struct wireless_dev *wdev, diff --git a/net/wireless/util.c b/net/wireless/util.c index a2532f46169d..a5b20d75017e 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -877,7 +877,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.status, ev->cr.status == WLAN_STATUS_SUCCESS, - NULL); + ev->cr.bss); break; case EVENT_ROAMED: __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, diff --git a/sound/core/timer.c b/sound/core/timer.c index b982d1b089bd..f420cd8583da 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1121,7 +1121,11 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, mutex_lock(®ister_mutex); list_for_each_entry(timer, &snd_timer_list, device_list) { - if (timer->card && timer->card->shutdown) + if (timer->card == NULL) { + pr_debug("%s: timer->card is NULL\n", __func__); + continue; + } + if (timer->card->shutdown) continue; switch (timer->tmr_class) { case SNDRV_TIMER_CLASS_GLOBAL: @@ -1247,6 +1251,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, tu->tstamp = *tstamp; if ((tu->filter & (1 << event)) == 0 || !tu->tread) return; + memset(&r1, 0, sizeof(r1)); r1.event = event; r1.tstamp = *tstamp; r1.val = resolution; @@ -1281,6 +1286,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, } if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { + memset(&r1, 0, sizeof(r1)); r1.event = SNDRV_TIMER_EVENT_RESOLUTION; r1.tstamp = tstamp; r1.val = resolution; @@ -1746,6 +1752,7 @@ static int snd_timer_user_params(struct file *file, if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { if (tu->tread) { struct snd_timer_tread tread; + memset(&tread, 0, sizeof(tread)); tread.event = SNDRV_TIMER_EVENT_EARLY; tread.tstamp.tv_sec = 0; tread.tstamp.tv_nsec = 0; diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c index 241410c60b97..dee66f231ceb 100755..100644 --- a/sound/soc/codecs/msm_hdmi_codec_rx.c +++ b/sound/soc/codecs/msm_hdmi_codec_rx.c @@ -19,115 +19,208 @@ #include <sound/soc.h> #include <linux/msm_ext_display.h> -#define MSM_HDMI_PCM_RATES SNDRV_PCM_RATE_48000 +#define MSM_EXT_DISP_PCM_RATES SNDRV_PCM_RATE_48000 -static int msm_hdmi_audio_codec_return_value; +static const char *const ext_disp_audio_type_text[] = {"None", "HDMI", "DP"}; -struct msm_hdmi_audio_codec_rx_data { - struct platform_device *hdmi_core_pdev; - struct msm_ext_disp_audio_codec_ops hdmi_ops; +static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_audio_type, ext_disp_audio_type_text); + +struct msm_ext_disp_audio_codec_rx_data { + struct platform_device *ext_disp_core_pdev; + struct msm_ext_disp_audio_codec_ops ext_disp_ops; + int cable_status; }; -static int msm_hdmi_edid_ctl_info(struct snd_kcontrol *kcontrol, +static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct msm_hdmi_audio_codec_rx_data *codec_data; + struct msm_ext_disp_audio_codec_rx_data *codec_data; struct msm_ext_disp_audio_edid_blk edid_blk; int rc; codec_data = snd_soc_codec_get_drvdata(codec); - if (!codec_data->hdmi_ops.get_audio_edid_blk) { - pr_debug("%s: get_audio_edid_blk() is NULL\n", __func__); + if (!codec_data) { + dev_err(codec->dev, "%s: codec_data is NULL\n", __func__); + return -EINVAL; + } + + if (!codec_data->ext_disp_ops.get_audio_edid_blk) { + dev_dbg(codec->dev, "%s: get_audio_edid_blk() is NULL\n", + __func__); uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = 0; return 0; } - rc = codec_data->hdmi_ops.get_audio_edid_blk( - codec_data->hdmi_core_pdev, - &edid_blk); + rc = codec_data->ext_disp_ops.get_audio_edid_blk( + codec_data->ext_disp_core_pdev, &edid_blk); + if (!IS_ERR_VALUE(rc)) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = edid_blk.audio_data_blk_size + edid_blk.spk_alloc_data_blk_size; } + dev_dbg(codec->dev, "%s: count: %d\n", __func__, uinfo->count); + return rc; } -static int msm_hdmi_edid_get(struct snd_kcontrol *kcontrol, +static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct msm_hdmi_audio_codec_rx_data *codec_data; + struct msm_ext_disp_audio_codec_rx_data *codec_data; struct msm_ext_disp_audio_edid_blk edid_blk; int rc; codec_data = snd_soc_codec_get_drvdata(codec); - - if (!codec_data->hdmi_ops.get_audio_edid_blk) + if (!codec_data || !codec_data->ext_disp_ops.get_audio_edid_blk) { + dev_err(codec->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n", + __func__); return -EINVAL; + } - rc = codec_data->hdmi_ops.get_audio_edid_blk( - codec_data->hdmi_core_pdev, &edid_blk); - + rc = codec_data->ext_disp_ops.get_audio_edid_blk( + codec_data->ext_disp_core_pdev, &edid_blk); if (!IS_ERR_VALUE(rc)) { memcpy(ucontrol->value.bytes.data, - edid_blk.audio_data_blk, - edid_blk.audio_data_blk_size); + edid_blk.audio_data_blk, + edid_blk.audio_data_blk_size); memcpy((ucontrol->value.bytes.data + - edid_blk.audio_data_blk_size), - edid_blk.spk_alloc_data_blk, - edid_blk.spk_alloc_data_blk_size); + edid_blk.audio_data_blk_size), + edid_blk.spk_alloc_data_blk, + edid_blk.spk_alloc_data_blk_size); + + dev_dbg(codec->dev, "%s: data_blk_size:%d, spk_alloc_data_blk_size:%d\n", + __func__, edid_blk.audio_data_blk_size, + edid_blk.spk_alloc_data_blk_size); } return rc; } -static const struct snd_kcontrol_new msm_hdmi_codec_rx_controls[] = { +static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct msm_ext_disp_audio_codec_rx_data *codec_data; + enum msm_ext_disp_cable_state cable_state; + enum msm_ext_disp_type disp_type; + int rc; + + codec_data = snd_soc_codec_get_drvdata(codec); + if (!codec_data || + !codec_data->ext_disp_ops.get_audio_edid_blk || + !codec_data->ext_disp_ops.get_intf_id) { + dev_err(codec->dev, "%s: codec_data, get_audio_edid_blk() or get_intf_id is NULL\n", + __func__); + return -EINVAL; + } + + cable_state = codec_data->ext_disp_ops.cable_status( + codec_data->ext_disp_core_pdev, 1); + if (IS_ERR_VALUE(cable_state)) { + dev_err(codec->dev, "%s: Error retrieving cable state from ext_disp, err:%d\n", + __func__, cable_state); + rc = cable_state; + goto done; + } + + codec_data->cable_status = cable_state; + if (cable_state == EXT_DISPLAY_CABLE_DISCONNECT) { + dev_err(codec->dev, "%s: Display cable disconnected\n", + __func__); + ucontrol->value.integer.value[0] = 0; + rc = 0; + goto done; + } + + disp_type = codec_data->ext_disp_ops.get_intf_id( + codec_data->ext_disp_core_pdev); + if (!IS_ERR_VALUE(disp_type)) { + switch (disp_type) { + case EXT_DISPLAY_TYPE_DP: + ucontrol->value.integer.value[0] = 2; + rc = 0; + break; + case EXT_DISPLAY_TYPE_HDMI: + ucontrol->value.integer.value[0] = 1; + rc = 0; + break; + default: + rc = -EINVAL; + dev_err(codec->dev, "%s: Invalid disp_type:%d\n", + __func__, disp_type); + goto done; + } + dev_dbg(codec->dev, "%s: Display type: %d\n", + __func__, disp_type); + } else { + dev_err(codec->dev, "%s: Error retrieving disp_type from ext_disp, err:%d\n", + __func__, disp_type); + rc = disp_type; + } + +done: + return rc; +} + +static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "HDMI EDID", + .info = msm_ext_disp_edid_ctl_info, + .get = msm_ext_disp_edid_get, + }, { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "HDMI EDID", - .info = msm_hdmi_edid_ctl_info, - .get = msm_hdmi_edid_get, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Display Port EDID", + .info = msm_ext_disp_edid_ctl_info, + .get = msm_ext_disp_edid_get, }, + SOC_ENUM_EXT("External Display Type", ext_disp_audio_type, + msm_ext_disp_audio_type_get, NULL), }; -static int msm_hdmi_audio_codec_rx_dai_startup( +static int msm_ext_disp_audio_codec_rx_dai_startup( struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int ret = 0; - struct msm_hdmi_audio_codec_rx_data *codec_data = + struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); - if (!codec_data->hdmi_ops.cable_status) { - dev_err(dai->dev, "%s() cable_status is null\n", __func__); + if (!codec_data || !codec_data->ext_disp_ops.cable_status) { + dev_err(dai->dev, "%s() codec_data or cable_status is null\n", + __func__); return -EINVAL; } - msm_hdmi_audio_codec_return_value = - codec_data->hdmi_ops.cable_status( - codec_data->hdmi_core_pdev, 1); - if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) { + codec_data->cable_status = + codec_data->ext_disp_ops.cable_status( + codec_data->ext_disp_core_pdev, 1); + if (IS_ERR_VALUE(codec_data->cable_status)) { dev_err(dai->dev, - "%s() HDMI core is not ready (ret val = %d)\n", - __func__, msm_hdmi_audio_codec_return_value); - ret = msm_hdmi_audio_codec_return_value; - } else if (!msm_hdmi_audio_codec_return_value) { + "%s() ext disp core is not ready (ret val = %d)\n", + __func__, codec_data->cable_status); + ret = codec_data->cable_status; + } else if (!codec_data->cable_status) { dev_err(dai->dev, - "%s() HDMI cable is not connected (ret val = %d)\n", - __func__, msm_hdmi_audio_codec_return_value); + "%s() ext disp cable is not connected (ret val = %d)\n", + __func__, codec_data->cable_status); ret = -ENODEV; } return ret; } -static int msm_hdmi_audio_codec_rx_dai_hw_params( +static int msm_ext_disp_audio_codec_rx_dai_hw_params( struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -139,23 +232,24 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params( int rc = 0; struct msm_ext_disp_audio_setup_params audio_setup_params = {0}; - struct msm_hdmi_audio_codec_rx_data *codec_data = + struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); - if (!codec_data->hdmi_ops.audio_info_setup) { - dev_err(dai->dev, "%s() audio_info_setup is null\n", __func__); + if (!codec_data || !codec_data->ext_disp_ops.audio_info_setup) { + dev_err(dai->dev, "%s: codec_data or audio_info_setup is null\n", + __func__); return -EINVAL; } - if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) { + if (IS_ERR_VALUE(codec_data->cable_status)) { dev_err_ratelimited(dai->dev, - "%s() HDMI core is not ready (ret val = %d)\n", - __func__, msm_hdmi_audio_codec_return_value); - return msm_hdmi_audio_codec_return_value; - } else if (!msm_hdmi_audio_codec_return_value) { + "%s() ext disp core is not ready (ret val = %d)\n", + __func__, codec_data->cable_status); + return codec_data->cable_status; + } else if (!codec_data->cable_status) { dev_err_ratelimited(dai->dev, - "%s() HDMI cable is not connected (ret val = %d)\n", - __func__, msm_hdmi_audio_codec_return_value); + "%s() ext disp cable is not connected (ret val = %d)\n", + __func__, codec_data->cable_status); return -ENODEV; } @@ -204,54 +298,49 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params( audio_setup_params.level_shift = level_shift; audio_setup_params.down_mix = down_mix; - rc = codec_data->hdmi_ops.audio_info_setup( - codec_data->hdmi_core_pdev, &audio_setup_params); + rc = codec_data->ext_disp_ops.audio_info_setup( + codec_data->ext_disp_core_pdev, &audio_setup_params); if (IS_ERR_VALUE(rc)) { dev_err_ratelimited(dai->dev, - "%s() HDMI core is not ready, rc: %d\n", + "%s() ext disp core is not ready, rc: %d\n", __func__, rc); } return rc; } -static void msm_hdmi_audio_codec_rx_dai_shutdown( +static void msm_ext_disp_audio_codec_rx_dai_shutdown( struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int rc; - struct msm_hdmi_audio_codec_rx_data *codec_data = + struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); - if (!codec_data->hdmi_ops.cable_status) { - dev_err(dai->dev, "%s() cable_status is null\n", __func__); + if (!codec_data || !codec_data->ext_disp_ops.cable_status) { + dev_err(dai->dev, "%s: codec data or cable_status is null\n", + __func__); return; } - rc = codec_data->hdmi_ops.cable_status( - codec_data->hdmi_core_pdev, 0); + rc = codec_data->ext_disp_ops.cable_status( + codec_data->ext_disp_core_pdev, 0); if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, - "%s() HDMI core had problems releasing HDMI audio flag\n", + "%s: ext disp core had problems releasing audio flag\n", __func__); } return; } -static struct snd_soc_dai_ops msm_hdmi_audio_codec_rx_dai_ops = { - .startup = msm_hdmi_audio_codec_rx_dai_startup, - .hw_params = msm_hdmi_audio_codec_rx_dai_hw_params, - .shutdown = msm_hdmi_audio_codec_rx_dai_shutdown -}; - -static int msm_hdmi_audio_codec_rx_probe(struct snd_soc_codec *codec) +static int msm_ext_disp_audio_codec_rx_probe(struct snd_soc_codec *codec) { - struct msm_hdmi_audio_codec_rx_data *codec_data; + struct msm_ext_disp_audio_codec_rx_data *codec_data; struct device_node *of_node_parent = NULL; - codec_data = kzalloc(sizeof(struct msm_hdmi_audio_codec_rx_data), + codec_data = kzalloc(sizeof(struct msm_ext_disp_audio_codec_rx_data), GFP_KERNEL); if (!codec_data) { @@ -268,16 +357,16 @@ static int msm_hdmi_audio_codec_rx_probe(struct snd_soc_codec *codec) return -ENODEV; } - codec_data->hdmi_core_pdev = of_find_device_by_node(of_node_parent); - if (!codec_data->hdmi_core_pdev) { + codec_data->ext_disp_core_pdev = of_find_device_by_node(of_node_parent); + if (!codec_data->ext_disp_core_pdev) { dev_err(codec->dev, "%s(): can't get parent pdev\n", __func__); kfree(codec_data); return -ENODEV; } - if (msm_hdmi_register_audio_codec(codec_data->hdmi_core_pdev, - &codec_data->hdmi_ops)) { - dev_err(codec->dev, "%s(): can't register with hdmi core", + if (msm_ext_disp_register_audio_codec(codec_data->ext_disp_core_pdev, + &codec_data->ext_disp_ops)) { + dev_err(codec->dev, "%s(): can't register with ext disp core", __func__); kfree(codec_data); return -ENODEV; @@ -285,15 +374,15 @@ static int msm_hdmi_audio_codec_rx_probe(struct snd_soc_codec *codec) dev_set_drvdata(codec->dev, codec_data); - dev_dbg(codec->dev, "%s(): registerd %s with HDMI core\n", + dev_dbg(codec->dev, "%s(): registered %s with ext disp core\n", __func__, codec->component.name); return 0; } -static int msm_hdmi_audio_codec_rx_remove(struct snd_soc_codec *codec) +static int msm_ext_disp_audio_codec_rx_remove(struct snd_soc_codec *codec) { - struct msm_hdmi_audio_codec_rx_data *codec_data; + struct msm_ext_disp_audio_codec_rx_data *codec_data; codec_data = dev_get_drvdata(codec->dev); kfree(codec_data); @@ -301,7 +390,13 @@ static int msm_hdmi_audio_codec_rx_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_dai_driver msm_hdmi_audio_codec_rx_dais[] = { +static struct snd_soc_dai_ops msm_ext_disp_audio_codec_rx_dai_ops = { + .startup = msm_ext_disp_audio_codec_rx_dai_startup, + .hw_params = msm_ext_disp_audio_codec_rx_dai_hw_params, + .shutdown = msm_ext_disp_audio_codec_rx_dai_shutdown +}; + +static struct snd_soc_dai_driver msm_ext_disp_audio_codec_rx_dais[] = { { .name = "msm_hdmi_audio_codec_rx_dai", .playback = { @@ -310,66 +405,89 @@ static struct snd_soc_dai_driver msm_hdmi_audio_codec_rx_dais[] = { .channels_max = 8, .rate_min = 48000, .rate_max = 48000, - .rates = MSM_HDMI_PCM_RATES, + .rates = MSM_EXT_DISP_PCM_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &msm_hdmi_audio_codec_rx_dai_ops, + .ops = &msm_ext_disp_audio_codec_rx_dai_ops, + }, + { + .name = "msm_dp_audio_codec_rx_dai", + .playback = { + .stream_name = "Display Port Playback", + .channels_min = 1, + .channels_max = 8, + .rate_min = 48000, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + }, + .ops = &msm_ext_disp_audio_codec_rx_dai_ops, }, }; -static struct snd_soc_codec_driver msm_hdmi_audio_codec_rx_soc_driver = { - .probe = msm_hdmi_audio_codec_rx_probe, - .remove = msm_hdmi_audio_codec_rx_remove, - .controls = msm_hdmi_codec_rx_controls, - .num_controls = ARRAY_SIZE(msm_hdmi_codec_rx_controls), +static struct snd_soc_codec_driver msm_ext_disp_audio_codec_rx_soc_driver = { + .probe = msm_ext_disp_audio_codec_rx_probe, + .remove = msm_ext_disp_audio_codec_rx_remove, + .controls = msm_ext_disp_codec_rx_controls, + .num_controls = ARRAY_SIZE(msm_ext_disp_codec_rx_controls), }; -static int msm_hdmi_audio_codec_rx_plat_probe( +static int msm_ext_disp_audio_codec_rx_plat_probe( struct platform_device *pdev) { dev_dbg(&pdev->dev, "%s(): dev name %s\n", __func__, dev_name(&pdev->dev)); return snd_soc_register_codec(&pdev->dev, - &msm_hdmi_audio_codec_rx_soc_driver, - msm_hdmi_audio_codec_rx_dais, - ARRAY_SIZE(msm_hdmi_audio_codec_rx_dais)); + &msm_ext_disp_audio_codec_rx_soc_driver, + msm_ext_disp_audio_codec_rx_dais, + ARRAY_SIZE(msm_ext_disp_audio_codec_rx_dais)); } -static int msm_hdmi_audio_codec_rx_plat_remove( +static int msm_ext_disp_audio_codec_rx_plat_remove( struct platform_device *pdev) { snd_soc_unregister_codec(&pdev->dev); return 0; } -static const struct of_device_id msm_hdmi_audio_codec_rx_dt_match[] = { - { .compatible = "qcom,msm-hdmi-audio-codec-rx", }, +static const struct of_device_id msm_ext_disp_audio_codec_rx_dt_match[] = { + { .compatible = "qcom,msm-ext-disp-audio-codec-rx", }, {} }; -MODULE_DEVICE_TABLE(of, msm_hdmi_codec_dt_match); +MODULE_DEVICE_TABLE(of, msm_ext_disp_audio_codec_rx_dt_match); -static struct platform_driver msm_hdmi_audio_codec_rx_driver = { +static struct platform_driver msm_ext_disp_audio_codec_rx_driver = { .driver = { - .name = "msm-hdmi-audio-codec-rx", + .name = "msm-ext-disp-audio-codec-rx", .owner = THIS_MODULE, - .of_match_table = msm_hdmi_audio_codec_rx_dt_match, + .of_match_table = msm_ext_disp_audio_codec_rx_dt_match, }, - .probe = msm_hdmi_audio_codec_rx_plat_probe, - .remove = msm_hdmi_audio_codec_rx_plat_remove, + .probe = msm_ext_disp_audio_codec_rx_plat_probe, + .remove = msm_ext_disp_audio_codec_rx_plat_remove, }; -static int __init msm_hdmi_audio_codec_rx_init(void) +static int __init msm_ext_disp_audio_codec_rx_init(void) { - return platform_driver_register(&msm_hdmi_audio_codec_rx_driver); + int rc; + + rc = platform_driver_register(&msm_ext_disp_audio_codec_rx_driver); + if (rc) { + pr_err("%s: failed to register ext disp codec driver err:%d\n", + __func__, rc); + } + + return rc; } -module_init(msm_hdmi_audio_codec_rx_init); +module_init(msm_ext_disp_audio_codec_rx_init); -static void __exit msm_hdmi_audio_codec_rx_exit(void) +static void __exit msm_ext_disp_audio_codec_rx_exit(void) { - platform_driver_unregister(&msm_hdmi_audio_codec_rx_driver); + platform_driver_unregister(&msm_ext_disp_audio_codec_rx_driver); } -module_exit(msm_hdmi_audio_codec_rx_exit); +module_exit(msm_ext_disp_audio_codec_rx_exit); -MODULE_DESCRIPTION("MSM HDMI CODEC driver"); +MODULE_DESCRIPTION("MSM External Display Audio CODEC Driver"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 2cdc1a688e93..84e5c09494c6 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -6359,13 +6359,6 @@ static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = { {WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, {WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, {WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01}, - {WCD934X_CDC_RX0_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX1_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX2_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX3_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX4_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX7_RX_PATH_MIX_CFG, 0x01, 0x01}, - {WCD934X_CDC_RX8_RX_PATH_MIX_CFG, 0x01, 0x01}, {WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0x01, 0x01}, {WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01}, {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80}, diff --git a/sound/soc/codecs/wcd9xxx-common-v2.c b/sound/soc/codecs/wcd9xxx-common-v2.c index 615922274690..f1b147aafd84 100644 --- a/sound/soc/codecs/wcd9xxx-common-v2.c +++ b/sound/soc/codecs/wcd9xxx-common-v2.c @@ -198,6 +198,11 @@ void wcd_clsh_imped_config(struct snd_soc_codec *codec, int imped, bool reset) pr_debug("%s, impedance not in range = %d\n", __func__, imped); return; } + if (index >= ARRAY_SIZE(imped_table)) { + pr_debug("%s, impedance index not in range = %d\n", __func__, + index); + return; + } for (i = 0; i < MAX_IMPED_PARAMS; i++) snd_soc_update_bits(codec, imped_table[index][i].reg, imped_table[index][i].mask, diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig index 759716199224..e740a24704b7 100644 --- a/sound/soc/msm/Kconfig +++ b/sound/soc/msm/Kconfig @@ -15,6 +15,7 @@ config SND_SOC_MSM_QDSP6V2_INTF config SND_SOC_QDSP6V2 tristate "SoC ALSA audio driver for QDSP6V2" select SND_SOC_MSM_QDSP6V2_INTF + select SND_SOC_COMPRESS help To add support for MSM QDSP6V2 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c index b0948acf8a71..523cd1ce4140 100644 --- a/sound/soc/msm/msmcobalt.c +++ b/sound/soc/msm/msmcobalt.c @@ -101,6 +101,12 @@ struct dev_config { u32 channels; }; +enum { + HDMI_RX_IDX = 0, + DP_RX_IDX, + EXT_DISP_RX_IDX_MAX, +}; + struct msm_wsa881x_dev_info { struct device_node *of_node; u32 index; @@ -147,6 +153,13 @@ static struct dev_config slim_tx_cfg[] = { [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, }; + +/* Default configuration of external display BE */ +static struct dev_config ext_disp_rx_cfg[] = { + [HDMI_RX_IDX] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [DP_RX_IDX] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; + static struct dev_config usb_rx_cfg = { .sample_rate = SAMPLING_RATE_48KHZ, .bit_format = SNDRV_PCM_FORMAT_S16_LE, @@ -159,12 +172,6 @@ static struct dev_config usb_tx_cfg = { .channels = 1, }; -static struct dev_config hdmi_rx_cfg = { - .sample_rate = SAMPLING_RATE_48KHZ, - .bit_format = SNDRV_PCM_FORMAT_S16_LE, - .channels = 2, -}; - static struct dev_config proxy_rx_cfg = { .sample_rate = SAMPLING_RATE_48KHZ, .bit_format = SNDRV_PCM_FORMAT_S16_LE, @@ -178,6 +185,7 @@ static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four", "Eight"}; static const char *const vi_feed_ch_text[] = {"One", "Two"}; static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"}; +static char const *ext_disp_bit_format_text[] = {"S16_LE", "S24_LE"}; static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_88P2", "KHZ_96", "KHZ_176P4", @@ -190,8 +198,8 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_16", "KHZ_22P05", "KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_96", "KHZ_192"}; -static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96", - "KHZ_192"}; +static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96", + "KHZ_192"}; static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text); @@ -202,7 +210,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text); -static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_chs, ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text); @@ -210,7 +218,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text); -static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_format, ext_disp_bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text); @@ -219,7 +227,8 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text); -static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_sample_rate, hdmi_rx_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_sample_rate, + ext_disp_sample_rate_text); static struct platform_device *spdev; @@ -999,15 +1008,33 @@ static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol, return rc; } -static int hdmi_rx_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_get_port_idx(struct snd_kcontrol *kcontrol) { + int idx; - switch (hdmi_rx_cfg.bit_format) { - case SNDRV_PCM_FORMAT_S24_3LE: - ucontrol->value.integer.value[0] = 2; - break; + if (strnstr(kcontrol->id.name, "HDMI_RX", sizeof("HDMI_RX"))) + idx = HDMI_RX_IDX; + else if (strnstr(kcontrol->id.name, "Display Port RX", + sizeof("Display Port RX"))) + idx = DP_RX_IDX; + else { + pr_err("%s: unsupported BE: %s", + __func__, kcontrol->id.name); + idx = -EINVAL; + } + + return idx; +} +static int ext_disp_rx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_disp_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + switch (ext_disp_rx_cfg[idx].bit_format) { case SNDRV_PCM_FORMAT_S24_LE: ucontrol->value.integer.value[0] = 1; break; @@ -1018,66 +1045,79 @@ static int hdmi_rx_format_get(struct snd_kcontrol *kcontrol, break; } - pr_debug("%s: hdmi_rx_cfg = %d, ucontrol value = %ld\n", - __func__, hdmi_rx_cfg.bit_format, + pr_debug("%s: ext_disp_rx[%d].format = %d, ucontrol value = %ld\n", + __func__, idx, ext_disp_rx_cfg[idx].bit_format, ucontrol->value.integer.value[0]); - return 0; } -static int hdmi_rx_format_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_rx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { + int idx = ext_disp_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + switch (ucontrol->value.integer.value[0]) { - case 2: - hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE; - break; case 1: - hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE; + ext_disp_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE; break; case 0: default: - hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE; + ext_disp_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S16_LE; break; } - pr_debug("%s: hdmi_rx_cfg.bit_format = %d, ucontrol value = %ld\n", - __func__, hdmi_rx_cfg.bit_format, + pr_debug("%s: ext_disp_rx[%d].format = %d, ucontrol value = %ld\n", + __func__, idx, ext_disp_rx_cfg[idx].bit_format, ucontrol->value.integer.value[0]); return 0; } -static int hdmi_rx_ch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - pr_debug("%s: hdmi_rx_cfg.channels = %d\n", __func__, - hdmi_rx_cfg.channels); - ucontrol->value.integer.value[0] = hdmi_rx_cfg.channels - 2; + int idx = ext_disp_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.integer.value[0] = + ext_disp_rx_cfg[idx].channels - 2; + + pr_debug("%s: ext_disp_rx[%d].ch = %d\n", __func__, + idx, ext_disp_rx_cfg[idx].channels); return 0; } -static int hdmi_rx_ch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - hdmi_rx_cfg.channels = ucontrol->value.integer.value[0] + 2; - if (hdmi_rx_cfg.channels > 8) { - pr_err("%s: channels %d exceeded 8.Limiting to max chs-8\n", - __func__, hdmi_rx_cfg.channels); - hdmi_rx_cfg.channels = 8; - } - pr_debug("%s: hdmi_rx_cfg.channels = %d\n", __func__, - hdmi_rx_cfg.channels); + int idx = ext_disp_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ext_disp_rx_cfg[idx].channels = + ucontrol->value.integer.value[0] + 2; + pr_debug("%s: ext_disp_rx[%d].ch = %d\n", __func__, + idx, ext_disp_rx_cfg[idx].channels); return 1; } -static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - int sample_rate_val = 0; + int sample_rate_val; + int idx = ext_disp_get_port_idx(kcontrol); - switch (hdmi_rx_cfg.sample_rate) { + if (idx < 0) + return idx; + + switch (ext_disp_rx_cfg[idx].sample_rate) { case SAMPLING_RATE_192KHZ: sample_rate_val = 2; break; @@ -1093,33 +1133,36 @@ static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol, } ucontrol->value.integer.value[0] = sample_rate_val; - pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__, - hdmi_rx_cfg.sample_rate); + pr_debug("%s: ext_disp_rx[%d].sample_rate = %d\n", __func__, + idx, ext_disp_rx_cfg[idx].sample_rate); return 0; } -static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int ext_disp_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - pr_debug("%s: ucontrol value = %ld\n", __func__, - ucontrol->value.integer.value[0]); + int idx = ext_disp_get_port_idx(kcontrol); + + if (idx < 0) + return idx; switch (ucontrol->value.integer.value[0]) { case 2: - hdmi_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ; + ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ; break; case 1: - hdmi_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ; + ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_96KHZ; break; case 0: default: - hdmi_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ; + ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_48KHZ; + break; } - pr_debug("%s: hdmi_rx_cfg.sample_rate = %d\n", __func__, - hdmi_rx_cfg.sample_rate); - + pr_debug("%s: control value = %ld, ext_disp_rx[%d].sample_rate = %d\n", + __func__, ucontrol->value.integer.value[0], idx, + ext_disp_rx_cfg[idx].sample_rate); return 0; } @@ -1162,8 +1205,10 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { usb_audio_rx_ch_get, usb_audio_rx_ch_put), SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs, usb_audio_tx_ch_get, usb_audio_tx_ch_put), - SOC_ENUM_EXT("HDMI_RX Channels", hdmi_rx_chs, - hdmi_rx_ch_get, hdmi_rx_ch_put), + SOC_ENUM_EXT("HDMI_RX Channels", ext_disp_rx_chs, + ext_disp_rx_ch_get, ext_disp_rx_ch_put), + SOC_ENUM_EXT("Display Port RX Channels", ext_disp_rx_chs, + ext_disp_rx_ch_get, ext_disp_rx_ch_put), SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs, proxy_rx_ch_get, proxy_rx_ch_put), SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format, @@ -1178,8 +1223,10 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { usb_audio_rx_format_get, usb_audio_rx_format_put), SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format, usb_audio_tx_format_get, usb_audio_tx_format_put), - SOC_ENUM_EXT("HDMI_RX Bit Format", hdmi_rx_format, - hdmi_rx_format_get, hdmi_rx_format_put), + SOC_ENUM_EXT("HDMI_RX Bit Format", ext_disp_rx_format, + ext_disp_rx_format_get, ext_disp_rx_format_put), + SOC_ENUM_EXT("Display Port RX Bit Format", ext_disp_rx_format, + ext_disp_rx_format_get, ext_disp_rx_format_put), SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate, slim_rx_sample_rate_get, slim_rx_sample_rate_put), SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate, @@ -1199,9 +1246,12 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate, usb_audio_tx_sample_rate_get, usb_audio_tx_sample_rate_put), - SOC_ENUM_EXT("HDMI_RX SampleRate", hdmi_rx_sample_rate, - hdmi_rx_sample_rate_get, - hdmi_rx_sample_rate_put), + SOC_ENUM_EXT("HDMI_RX SampleRate", ext_disp_rx_sample_rate, + ext_disp_rx_sample_rate_get, + ext_disp_rx_sample_rate_put), + SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate, + ext_disp_rx_sample_rate_get, + ext_disp_rx_sample_rate_put), }; static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, @@ -1324,6 +1374,26 @@ static int msm_slim_get_ch_from_beid(int32_t be_id) return ch_id; } +static int msm_ext_disp_get_idx_from_beid(int32_t be_id) +{ + int idx; + + switch (be_id) { + case MSM_BACKEND_DAI_HDMI_RX: + idx = HDMI_RX_IDX; + break; + case MSM_BACKEND_DAI_DISPLAY_PORT_RX: + idx = DP_RX_IDX; + break; + default: + pr_err("%s: Incorrect ext_disp be_id %d\n", __func__, be_id); + idx = -EINVAL; + break; + } + + return idx; +} + static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -1333,9 +1403,9 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); int rc = 0; + int idx; void *config = NULL; struct snd_soc_codec *codec = NULL; - int ch_num; pr_debug("%s: format = %d, rate = %d\n", __func__, params_format(params), params_rate(params)); @@ -1347,20 +1417,20 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, case MSM_BACKEND_DAI_SLIMBUS_3_RX: case MSM_BACKEND_DAI_SLIMBUS_4_RX: case MSM_BACKEND_DAI_SLIMBUS_6_RX: - ch_num = msm_slim_get_ch_from_beid(dai_link->be_id); + idx = msm_slim_get_ch_from_beid(dai_link->be_id); param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - slim_rx_cfg[ch_num].bit_format); - rate->min = rate->max = slim_rx_cfg[ch_num].sample_rate; - channels->min = channels->max = slim_rx_cfg[ch_num].channels; + slim_rx_cfg[idx].bit_format); + rate->min = rate->max = slim_rx_cfg[idx].sample_rate; + channels->min = channels->max = slim_rx_cfg[idx].channels; break; case MSM_BACKEND_DAI_SLIMBUS_0_TX: case MSM_BACKEND_DAI_SLIMBUS_3_TX: - ch_num = msm_slim_get_ch_from_beid(dai_link->be_id); + idx = msm_slim_get_ch_from_beid(dai_link->be_id); param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - slim_tx_cfg[ch_num].bit_format); - rate->min = rate->max = slim_tx_cfg[ch_num].sample_rate; - channels->min = channels->max = slim_tx_cfg[ch_num].channels; + slim_tx_cfg[idx].bit_format); + rate->min = rate->max = slim_tx_cfg[idx].sample_rate; + channels->min = channels->max = slim_tx_cfg[idx].channels; break; case MSM_BACKEND_DAI_SLIMBUS_1_TX: @@ -1435,10 +1505,19 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, break; case MSM_BACKEND_DAI_HDMI_RX: + case MSM_BACKEND_DAI_DISPLAY_PORT_RX: + idx = msm_ext_disp_get_idx_from_beid(dai_link->be_id); + if (IS_ERR_VALUE(idx)) { + pr_err("%s: Incorrect ext disp idx %d\n", + __func__, idx); + rc = idx; + goto done; + } + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - hdmi_rx_cfg.bit_format); - rate->min = rate->max = hdmi_rx_cfg.sample_rate; - channels->min = channels->max = hdmi_rx_cfg.channels; + ext_disp_rx_cfg[idx].bit_format); + rate->min = rate->max = ext_disp_rx_cfg[idx].sample_rate; + channels->min = channels->max = ext_disp_rx_cfg[idx].channels; break; case MSM_BACKEND_DAI_AFE_PCM_RX: @@ -1450,7 +1529,9 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, rate->min = rate->max = SAMPLING_RATE_48KHZ; break; } - return 0; + +done: + return rc; } static bool msm_swap_gnd_mic(struct snd_soc_codec *codec) @@ -3293,14 +3374,14 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = { }, }; -static struct snd_soc_dai_link hdmi_be_dai_link[] = { +static struct snd_soc_dai_link ext_disp_be_dai_link[] = { /* HDMI BACK END DAI Link */ { .name = LPASS_BE_HDMI, .stream_name = "HDMI Playback", .cpu_dai_name = "msm-dai-q6-hdmi.8", .platform_name = "msm-pcm-routing", - .codec_name = "msm-hdmi-audio-codec-rx", + .codec_name = "msm-ext-disp-audio-codec-rx", .codec_dai_name = "msm_hdmi_audio_codec_rx_dai", .no_pcm = 1, .dpcm_playback = 1, @@ -3309,6 +3390,21 @@ static struct snd_soc_dai_link hdmi_be_dai_link[] = { .ignore_pmdown_time = 1, .ignore_suspend = 1, }, + /* DISP PORT BACK END DAI Link */ + { + .name = LPASS_BE_DISPLAY_PORT, + .stream_name = "Display Port Playback", + .cpu_dai_name = "msm-dai-q6-dp.24608", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-ext-disp-audio-codec-rx", + .codec_dai_name = "msm_dp_audio_codec_rx_dai", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_DISPLAY_PORT_RX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, }; static struct snd_soc_dai_link msm_tasha_dai_links[ @@ -3317,7 +3413,7 @@ static struct snd_soc_dai_link msm_tasha_dai_links[ ARRAY_SIZE(msm_common_be_dai_links) + ARRAY_SIZE(msm_tasha_be_dai_links) + ARRAY_SIZE(msm_wcn_be_dai_links) + - ARRAY_SIZE(hdmi_be_dai_link)]; + ARRAY_SIZE(ext_disp_be_dai_link)]; static struct snd_soc_dai_link msm_tavil_dai_links[ ARRAY_SIZE(msm_common_dai_links) + @@ -3325,7 +3421,7 @@ static struct snd_soc_dai_link msm_tavil_dai_links[ ARRAY_SIZE(msm_common_be_dai_links) + ARRAY_SIZE(msm_tavil_be_dai_links) + ARRAY_SIZE(msm_wcn_be_dai_links) + - ARRAY_SIZE(hdmi_be_dai_link)]; + ARRAY_SIZE(ext_disp_be_dai_link)]; static int msm_snd_card_late_probe(struct snd_soc_card *card) { @@ -3725,14 +3821,15 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) total_links += ARRAY_SIZE(msm_wcn_be_dai_links); } - if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) { - dev_dbg(dev, "%s(): HDMI support present\n", __func__); + if (of_property_read_bool(dev->of_node, + "qcom,ext-disp-audio-rx")) { + dev_dbg(dev, "%s(): External display audio support present\n", + __func__); memcpy(msm_tasha_dai_links + total_links, - hdmi_be_dai_link, - sizeof(hdmi_be_dai_link)); - total_links += ARRAY_SIZE(hdmi_be_dai_link); + ext_disp_be_dai_link, + sizeof(ext_disp_be_dai_link)); + total_links += ARRAY_SIZE(ext_disp_be_dai_link); } - dailink = msm_tasha_dai_links; } else if (!strcmp(match->data, "tavil_codec")) { card = &snd_soc_card_tavil_msm; @@ -3762,14 +3859,15 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) total_links += ARRAY_SIZE(msm_wcn_be_dai_links); } - if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) { - dev_dbg(dev, "%s(): HDMI support present\n", __func__); + if (of_property_read_bool(dev->of_node, + "qcom,ext-disp-audio-rx")) { + dev_dbg(dev, "%s(): ext disp audio support present\n", + __func__); memcpy(msm_tavil_dai_links + total_links, - hdmi_be_dai_link, - sizeof(hdmi_be_dai_link)); - total_links += ARRAY_SIZE(hdmi_be_dai_link); + ext_disp_be_dai_link, + sizeof(ext_disp_be_dai_link)); + total_links += ARRAY_SIZE(ext_disp_be_dai_link); } - dailink = msm_tavil_dai_links; } else if (!strcmp(match->data, "stub_codec")) { card = &snd_soc_card_stub_msm; @@ -3786,7 +3884,6 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) dailink = msm_stub_dai_links; total_links = len_2; } - dev_dbg(dev, "%s(): No hdmi audio support\n", __func__); if (card) { card->dai_link = dailink; diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c index 9c57adb863d4..69a9e14c47de 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,53 +32,82 @@ enum { STATUS_MAX }; -struct msm_hdmi_ca { +struct msm_ext_disp_ca { bool set_ca; u32 ca; }; -static struct msm_hdmi_ca hdmi_ca = { false, 0x0 }; - struct msm_dai_q6_hdmi_dai_data { DECLARE_BITMAP(status_mask, STATUS_MAX); u32 rate; u32 channels; + struct msm_ext_disp_ca ca; union afe_port_config port_config; }; -static int msm_dai_q6_hdmi_format_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int msm_dai_q6_ext_disp_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data; int value = ucontrol->value.integer.value[0]; + + if (!dai_data) { + pr_err("%s: dai_data is NULL\n", __func__); + return -EINVAL; + } + dai_data->port_config.hdmi_multi_ch.datatype = value; pr_debug("%s: value = %d\n", __func__, value); + return 0; } -static int msm_dai_q6_hdmi_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int msm_dai_q6_ext_disp_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data; + + if (!dai_data) { + pr_err("%s: dai_data is NULL\n", __func__); + return -EINVAL; + } + ucontrol->value.integer.value[0] = dai_data->port_config.hdmi_multi_ch.datatype; + pr_debug("%s: value = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; } -static int msm_dai_q6_hdmi_ca_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int msm_dai_q6_ext_disp_ca_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - hdmi_ca.ca = ucontrol->value.integer.value[0]; - hdmi_ca.set_ca = true; + struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data; + + if (!dai_data) { + pr_err("%s: dai_data is NULL\n", __func__); + return -EINVAL; + } + + dai_data->ca.ca = ucontrol->value.integer.value[0]; + dai_data->ca.set_ca = true; + pr_debug("%s: ca = %d\n", __func__, dai_data->ca.ca); return 0; } -static int msm_dai_q6_hdmi_ca_get(struct snd_kcontrol *kcontrol, +static int msm_dai_q6_ext_disp_ca_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = hdmi_ca.ca; + struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data; + + if (!dai_data) { + pr_err("%s: dai_data is NULL\n", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = dai_data->ca.ca; + pr_debug("%s: ca = %d\n", __func__, dai_data->ca.ca); return 0; } @@ -97,12 +126,22 @@ static const struct soc_enum hdmi_config_enum[] = { static const struct snd_kcontrol_new hdmi_config_controls[] = { SOC_ENUM_EXT("HDMI RX Format", hdmi_config_enum[0], - msm_dai_q6_hdmi_format_get, - msm_dai_q6_hdmi_format_put), + msm_dai_q6_ext_disp_format_get, + msm_dai_q6_ext_disp_format_put), SOC_SINGLE_MULTI_EXT("HDMI RX CA", SND_SOC_NOPM, 0, HDMI_RX_CA_MAX, 0, 1, - msm_dai_q6_hdmi_ca_get, - msm_dai_q6_hdmi_ca_put), + msm_dai_q6_ext_disp_ca_get, + msm_dai_q6_ext_disp_ca_put), +}; + +static const struct snd_kcontrol_new display_port_config_controls[] = { + SOC_ENUM_EXT("Display Port RX Format", hdmi_config_enum[0], + msm_dai_q6_ext_disp_format_get, + msm_dai_q6_ext_disp_format_put), + SOC_SINGLE_MULTI_EXT("Display Port RX CA", SND_SOC_NOPM, 0, + HDMI_RX_CA_MAX, 0, 1, + msm_dai_q6_ext_disp_ca_get, + msm_dai_q6_ext_disp_ca_put), }; /* Current implementation assumes hw_param is called once @@ -200,9 +239,9 @@ static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream, struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; - if (hdmi_ca.set_ca) + if (dai_data->ca.set_ca) dai_data->port_config.hdmi_multi_ch.channel_allocation = - hdmi_ca.ca; + dai_data->ca.ca; if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { rc = afe_port_start(dai->id, &dai_data->port_config, @@ -236,8 +275,8 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai) struct snd_soc_dapm_route intercon; struct snd_soc_dapm_context *dapm; - if (!dai) { - pr_err("%s: dai not found\n", __func__); + if (!dai || !dai->driver) { + pr_err("%s: dai or dai->driver is NULL\n", __func__); return -EINVAL; } dai_data = kzalloc(sizeof(struct msm_dai_q6_hdmi_dai_data), @@ -252,19 +291,33 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai) msm_dai_q6_hdmi_set_dai_id(dai); - kcontrol = &hdmi_config_controls[0]; - - rc = snd_ctl_add(dai->component->card->snd_card, - snd_ctl_new1(kcontrol, dai_data)); - - kcontrol = &hdmi_config_controls[1]; - - rc = snd_ctl_add(dai->component->card->snd_card, - snd_ctl_new1(kcontrol, dai_data)); + if (dai->driver->id == HDMI_RX) { + kcontrol = &hdmi_config_controls[0]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai_data)); + + kcontrol = &hdmi_config_controls[1]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai_data)); + } else if (dai->driver->id == DISPLAY_PORT_RX) { + kcontrol = &display_port_config_controls[0]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai_data)); + + kcontrol = &display_port_config_controls[1]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai_data)); + } else { + dev_err(dai->dev, "%s: Invalid id:%d\n", + __func__, dai->driver->id); + kfree(dai_data); + dev_set_drvdata(dai->dev, NULL); + return -EINVAL; + } dapm = snd_soc_component_get_dapm(dai->component); memset(&intercon, 0 , sizeof(intercon)); - if (!rc && dai && dai->driver) { + if (!rc) { if (dai->driver->playback.stream_name && dai->driver->playback.aif_name) { dev_dbg(dai->dev, "%s add route for widget %s", @@ -325,8 +378,8 @@ static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 2, .channels_max = 8, - .rate_max = 192000, - .rate_min = 48000, + .rate_max = 192000, + .rate_min = 48000, }, .ops = &msm_dai_q6_hdmi_ops, .id = HDMI_RX, @@ -334,6 +387,27 @@ static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = { .remove = msm_dai_q6_hdmi_dai_remove, }; +static struct snd_soc_dai_driver msm_dai_q6_display_port_rx_dai[] = { + { + .playback = { + .stream_name = "Display Port Playback", + .aif_name = "DISPLAY_PORT", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 2, + .channels_max = 8, + .rate_max = 192000, + .rate_min = 48000, + }, + .ops = &msm_dai_q6_hdmi_ops, + .id = DISPLAY_PORT_RX, + .probe = msm_dai_q6_hdmi_dai_probe, + .remove = msm_dai_q6_hdmi_dai_remove, + }, +}; + static const struct snd_soc_component_driver msm_dai_hdmi_q6_component = { .name = "msm-dai-q6-hdmi", }; @@ -362,6 +436,12 @@ static int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev) &msm_dai_hdmi_q6_component, &msm_dai_q6_hdmi_hdmi_rx_dai, 1); break; + case DISPLAY_PORT_RX: + rc = snd_soc_register_component(&pdev->dev, + &msm_dai_hdmi_q6_component, + &msm_dai_q6_display_port_rx_dai[0], + ARRAY_SIZE(msm_dai_q6_display_port_rx_dai)); + break; default: dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id); rc = -ENODEV; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 6e5b4e871fe6..972cacb50f47 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -375,8 +375,12 @@ static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd) q6asm_cmd(prtd->audio_client, CMD_PAUSE); q6asm_cmd(prtd->audio_client, CMD_FLUSH); buf = q6asm_shared_io_buf(prtd->audio_client, dir); - if (buf) - memset(buf->data, 0, buf->actual_size); + if (buf == NULL) { + pr_err("%s: shared IO buffer is null\n", __func__); + ret = -EINVAL; + break; + } + memset(buf->data, 0, buf->actual_size); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 695f57b30322..aea60f1fa044 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -99,7 +99,8 @@ struct msm_pcm_route_bdai_pp_params { static struct msm_pcm_route_bdai_pp_params msm_bedais_pp_params[MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX] = { - {HDMI_RX, 0, 0, 0} + {HDMI_RX, 0, 0, 0}, + {DISPLAY_PORT_RX, 0, 0, 0}, }; static int msm_routing_send_device_pp_params(int port_id, int copp_idx); @@ -448,6 +449,7 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { { SLIMBUS_8_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX}, { AFE_PORT_ID_USB_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX}, { AFE_PORT_ID_USB_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX}, + { DISPLAY_PORT_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_DISPLAY_PORT}, }; /* Track ASM playback & capture sessions of DAI */ @@ -2932,6 +2934,58 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), }; + +static const struct snd_kcontrol_new display_port_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + /* incall music delivery mixer */ static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX, @@ -5583,6 +5637,12 @@ static const struct snd_kcontrol_new hdmi_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new display_port_rx_port_mixer_controls[] = { + SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_DISPLAY_PORT_RX, + MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + static const struct snd_kcontrol_new sec_i2s_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SEC_I2S_RX, MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, @@ -7435,6 +7495,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0), + SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT", "Display Port Playback", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback", 0, 0, 0, 0), @@ -7709,6 +7771,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { slimbus_7_rx_mixer_controls, ARRAY_SIZE(slimbus_7_rx_mixer_controls)), SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)), + SND_SOC_DAPM_MIXER("DISPLAY_PORT Mixer", SND_SOC_NOPM, 0, 0, + display_port_mixer_controls, ARRAY_SIZE(display_port_mixer_controls)), SND_SOC_DAPM_MIXER("SPDIF_RX Audio Mixer", SND_SOC_NOPM, 0, 0, spdif_rx_mixer_controls, ARRAY_SIZE(spdif_rx_mixer_controls)), SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, @@ -7923,6 +7987,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("HDMI_RX Port Mixer", SND_SOC_NOPM, 0, 0, hdmi_rx_port_mixer_controls, ARRAY_SIZE(hdmi_rx_port_mixer_controls)), + SND_SOC_DAPM_MIXER("DISPLAY_PORT_RX Port Mixer", + SND_SOC_NOPM, 0, 0, display_port_rx_port_mixer_controls, + ARRAY_SIZE(display_port_rx_port_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_I2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, sec_i2s_rx_port_mixer_controls, ARRAY_SIZE(sec_i2s_rx_port_mixer_controls)), @@ -8114,6 +8181,24 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia16", "MM_DL16"}, {"HDMI", NULL, "HDMI Mixer"}, + {"DISPLAY_PORT Mixer", "MultiMedia1", "MM_DL1"}, + {"DISPLAY_PORT Mixer", "MultiMedia2", "MM_DL2"}, + {"DISPLAY_PORT Mixer", "MultiMedia3", "MM_DL3"}, + {"DISPLAY_PORT Mixer", "MultiMedia4", "MM_DL4"}, + {"DISPLAY_PORT Mixer", "MultiMedia5", "MM_DL5"}, + {"DISPLAY_PORT Mixer", "MultiMedia6", "MM_DL6"}, + {"DISPLAY_PORT Mixer", "MultiMedia7", "MM_DL7"}, + {"DISPLAY_PORT Mixer", "MultiMedia8", "MM_DL8"}, + {"DISPLAY_PORT Mixer", "MultiMedia9", "MM_DL9"}, + {"DISPLAY_PORT Mixer", "MultiMedia10", "MM_DL10"}, + {"DISPLAY_PORT Mixer", "MultiMedia11", "MM_DL11"}, + {"DISPLAY_PORT Mixer", "MultiMedia12", "MM_DL12"}, + {"DISPLAY_PORT Mixer", "MultiMedia13", "MM_DL13"}, + {"DISPLAY_PORT Mixer", "MultiMedia14", "MM_DL14"}, + {"DISPLAY_PORT Mixer", "MultiMedia15", "MM_DL15"}, + {"DISPLAY_PORT Mixer", "MultiMedia16", "MM_DL16"}, + {"DISPLAY_PORT", NULL, "DISPLAY_PORT Mixer"}, + {"SPDIF_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"SPDIF_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"SPDIF_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -9517,6 +9602,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"}, {"HDMI", NULL, "HDMI_RX Port Mixer"}, + {"DISPLAY_PORT_RX Port Mixer", "MI2S_TX", "MI2S_TX"}, + {"DISPLAY_PORT", NULL, "DISPLAY_PORT_RX Port Mixer"}, + {"SEC_I2S_RX Port Mixer", "MI2S_TX", "MI2S_TX"}, {"SEC_I2S_RX", NULL, "SEC_I2S_RX Port Mixer"}, @@ -9571,6 +9659,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "SLIMBUS_8_RX"}, {"BE_OUT", NULL, "USB_AUDIO_RX"}, {"BE_OUT", NULL, "HDMI"}, + {"BE_OUT", NULL, "DISPLAY_PORT"}, {"BE_OUT", NULL, "SPDIF_RX"}, {"BE_OUT", NULL, "MI2S_RX"}, {"BE_OUT", NULL, "QUAT_MI2S_RX"}, @@ -9886,7 +9975,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) pr_debug("%s: port_id %d, copp_idx %d\n", __func__, port_id, copp_idx); - if (port_id != HDMI_RX) { + if (port_id != HDMI_RX && port_id != DISPLAY_PORT_RX) { pr_err("%s: Device pp params on invalid port %d\n", __func__, port_id); return -EINVAL; @@ -9959,7 +10048,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) { port_id = msm_bedais[be_idx].port_id; - if (port_id == HDMI_RX) + if (port_id == HDMI_RX || port_id == DISPLAY_PORT_RX) break; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 009eebede28a..d8cec53c0d9e 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -18,6 +18,7 @@ #define LPASS_BE_SLIMBUS_0_RX "SLIMBUS_0_RX" #define LPASS_BE_SLIMBUS_0_TX "SLIMBUS_0_TX" #define LPASS_BE_HDMI "HDMI" +#define LPASS_BE_DISPLAY_PORT "DISPLAY_PORT" #define LPASS_BE_INT_BT_SCO_RX "INT_BT_SCO_RX" #define LPASS_BE_INT_BT_SCO_TX "INT_BT_SCO_TX" #define LPASS_BE_INT_BT_A2DP_RX "INT_BT_A2DP_RX" @@ -311,6 +312,7 @@ enum { MSM_BACKEND_DAI_SLIMBUS_8_TX, MSM_BACKEND_DAI_USB_RX, MSM_BACKEND_DAI_USB_TX, + MSM_BACKEND_DAI_DISPLAY_PORT_RX, MSM_BACKEND_DAI_MAX, }; @@ -339,7 +341,7 @@ enum { #define RELEASE_LOCK 0 #define ACQUIRE_LOCK 1 -#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 1 +#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 2 #define HDMI_RX_ID 0x8001 #define ADM_PP_PARAM_MUTE_ID 0 #define ADM_PP_PARAM_MUTE_BIT 1 diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 16c7ef4c0bf5..f6a687611f8a 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -423,6 +423,7 @@ int afe_get_port_type(u16 port_id) case SECONDARY_I2S_RX: case MI2S_RX: case HDMI_RX: + case DISPLAY_PORT_RX: case AFE_PORT_ID_SPDIF_RX: case SLIMBUS_0_RX: case SLIMBUS_1_RX: @@ -574,6 +575,7 @@ int afe_sizeof_cfg_cmd(u16 port_id) ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg); break; case HDMI_RX: + case DISPLAY_PORT_RX: ret_size = SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg); break; @@ -2897,6 +2899,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, cfg_type = AFE_PARAM_ID_I2S_CONFIG; break; case HDMI_RX: + case DISPLAY_PORT_RX: cfg_type = AFE_PARAM_ID_HDMI_CONFIG; break; case VOICE_PLAYBACK_TX: @@ -3073,6 +3076,7 @@ int afe_get_port_index(u16 port_id) case MI2S_RX: return IDX_MI2S_RX; case MI2S_TX: return IDX_MI2S_TX; case HDMI_RX: return IDX_HDMI_RX; + case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX; case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX; case RSVD_2: return IDX_RSVD_2; case RSVD_3: return IDX_RSVD_3; @@ -3352,6 +3356,7 @@ int afe_open(u16 port_id, cfg_type = AFE_PARAM_ID_I2S_CONFIG; break; case HDMI_RX: + case DISPLAY_PORT_RX: cfg_type = AFE_PARAM_ID_HDMI_CONFIG; break; case SLIMBUS_0_RX: @@ -4809,6 +4814,7 @@ int afe_validate_port(u16 port_id) case MI2S_RX: case MI2S_TX: case HDMI_RX: + case DISPLAY_PORT_RX: case AFE_PORT_ID_SPDIF_RX: case RSVD_2: case RSVD_3: @@ -5591,6 +5597,12 @@ int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi) goto done; } index = q6audio_get_port_index(port); + if (index < 0) { + pr_err("%s: invalid port 0x%x, index %d\n", + __func__, port, index); + ret = -EINVAL; + goto done; + } th_vi->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); th_vi->hdr.pkt_size = sizeof(*th_vi); diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c index 56dc6b58a646..a737a27cc327 100644 --- a/sound/soc/msm/qdsp6v2/q6audio-v2.c +++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c @@ -37,6 +37,7 @@ int q6audio_get_port_index(u16 port_id) case MI2S_RX: return IDX_MI2S_RX; case MI2S_TX: return IDX_MI2S_TX; case HDMI_RX: return IDX_HDMI_RX; + case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX; case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX; case RSVD_2: return IDX_RSVD_2; case RSVD_3: return IDX_RSVD_3; @@ -246,6 +247,8 @@ int q6audio_get_port_id(u16 port_id) case MI2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX; case MI2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX; case HDMI_RX: return AFE_PORT_ID_MULTICHAN_HDMI_RX; + case DISPLAY_PORT_RX: + return AFE_PORT_ID_HDMI_OVER_DP_RX; case AFE_PORT_ID_SPDIF_RX: return AFE_PORT_ID_SPDIF_RX; case RSVD_2: return IDX_RSVD_2; case RSVD_3: return IDX_RSVD_3; @@ -573,6 +576,7 @@ int q6audio_validate_port(u16 port_id) case MI2S_RX: case MI2S_TX: case HDMI_RX: + case DISPLAY_PORT_RX: case RSVD_2: case RSVD_3: case DIGI_MIC_TX: diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 53dd085d3ee2..a6884fd1e4b3 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -139,6 +139,9 @@ static int snd_soc_dummy_probe(struct platform_device *pdev) { int ret; + memset(&dummy_codec, 0, + sizeof(struct snd_soc_codec_driver)); + ret = snd_soc_register_codec(&pdev->dev, &dummy_codec, &dummy_dai, 1); if (ret < 0) return ret; |
