diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-09-09 12:21:06 -0600 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2016-09-09 12:21:07 -0600 |
| commit | a196e7fb0f40b552f688aef576c51310035e4c76 (patch) | |
| tree | 38691108d2ab615b612c1d7ab61e22b8c45e229e | |
| parent | 8d5060391f94d153a543f9387a63a3d4335bf873 (diff) | |
| parent | 3dc7ca5e82cc56abc0463e35f1851cd8e2eed97a (diff) | |
Promotion of kernel.lnx.4.4-160909.
CRs Change ID Subject
--------------------------------------------------------------------------------------------------------------
1045908 I28af6ada1d0d709d44cfd0da29de8775796a0bbc msm: sensor: Enable combo mode in 10NM CSI PHY
1057119 I01e2c9c8bafbb2be4c8d312a4212195c2a99f3ac ARM: dts: msm: add VDD_APC CPR speed-bin 1 configuration
1062953 Id6524b7ae3e82e10ca651a2ca0de9223c18109da tty : msm_serial: Remove the rtb logs of msm_serial writ
1064025 I08b3ffa1a027b3212b77fe661348f2852485ed0d ARM: dts: msm: Update debug uart support for msmfalcon
1054908 Ibc0656c878f1bac6ac9b3b7c9e7a471d969e2b8c ASoC: wcd934x: Use minimum phase for RX interpolation fi
1061427 Iac276eeec710a11e5feeb6899da121ca6324e19b ASoC: qdsp6v2: Add proper dependency for audio driver
1064040 Id4b5593a5ed3290684ba43ebebe2466ba0b730b6 PM / devfreq: bw_hwmon: Add HW offload support to govern
1064333 Ic83fe1607d5f62e0ceefd4497aae0c111a2727d7 defconfig: msm: Add MSMTRITON in defconfigs
1050042 I452a050298a6ab081f64aa2dcf295d2d257bcb32 qcom-charger: expose RRADC charger temp and usbin readin
1053503 I3b42ee147fd0883696f9783f0a38d5bef888a10a ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PARAMS
1026601 Iab61eb0333545a17fff85bd34e7cf0c489d85700 ARM: dts: msm: enable audio over Display Port on msmcoba
1046606 Ia490d15a51ad70759c917fbe7e84fdadaa140e20 ASoC: wcd9xxx: check impedance index before use
1061372 Ica925da95b5ab35f63bb0355470475733080a88c regulator: cpr3-regulator: correct CPR aging cleanup han
1060739 I75b83ce99f061104641188c0f0d3d6cd3e0cfb09 msm: mdss: Update MDP memory retention sequence for msmc
1052747 Ifcde1c6af624294cbd1944eaa9b526dd6dcc51de usb: Add support for reset controller framework
982871 Idbae7f95dfd56293805b58e3c6626f5f6e07d08a skb: printing port numbers with gso trace events
1064802 Ib959355264405ab779b24948f111a2ca61d367de sched: Further re-factor HMP specific code
1057119 I778e33b9de9947dd33f4cb7142be8771d4afc7cb regulator: cprh-kbss-regulator: increase number of suppo
1063805 I94ebf6366b75daf9102a50eb86e757139e6d4231 ARM: dts: msm: Add initial support for msmcobalt QRD VR1
1057119 Icf06fe334558bfc4e4dedc9b1f18d51c99987966 ARM: dts: msm: Update VDD_APC floor and ceiling voltages
1053705 Ic6e406254f9c20e89f40436cefa351002d18fd7b msm: camera: jpegdma: Reg values stored in array at alte
1026601 I4e85351226b30b97d58ffcec76398fb8cbf9e730 ASoC: msmcobalt: Add support for Display Port
1063393 I585f4c560f0920d3cb56cce009297b5665abb42e usb: composite: Draw 900mA on USB resume if speed is sup
1061372 I55d5fb0c799dfec73830e8e97dcff79cd045b29c ARM: dts: msm: add VDD_GFX CPR aging allowed register fo
1054539 I8c4ceaa2703c15c1f590befb9397d47da9f9c1e9 ARM: dts: msm: update VDD_GFX CPR ceiling voltages for m
1060507 Icf927ce1eb7107007e1cc5c7b5f0a63814510398 msm: ipa: add dma test suite
1052415 I5148ec4ce55a00f5130a60d0c088b3f0218d2261 scsi: ufs: export set_bus_vote ops
1061793 Ie522631fc0db7460a0031a5d52e547b594547d4b ARM: dts: msm: Add support for apqcobalt v2.1
1062365 If9f35626303321439286bd62e664e68c05ef19c5 regulator: cprh-kbss-regulator: add per-cluster fuse ref
1026601 I9fce9622ff0580bca2414a8d6625774ae3f2d6c0 ASoC: codecs: Add display port support in codec driver
1060019 Id8880caae81818fe72bf02f3a3a90a5650546182 ASoC: add sample rate macros upto 384KHz
1063482 I7ba2ef7baba673d4c06225e61df7a0922b82ba81 ARM: dts: msm: Add missing glink_pkt devices for MSMFALC
1060019 Iae32df7ce1fb42e0fa8e0259612a51c76bab1cb6 ASoC: msm: add 384KHz playback support
1058565 Ie3ed9fd8a4d58d4664fa71b2d3da320fabc6a05b msm: isp: buffer queue management specific flags
1059577 I3ac8f740d7b84212da1d799b563a6e8ef1c9b493 usb: gadget: gsi: Fix handling of MSG PACKET FILTER
1051259 Ifa2c4721a156c34c6d917ff950d648bea6cee50e msm: camera: sensor: Add state validation for flash
1061372 I7bcb88002bdc0609e835bc9ce29c84d93684e445 regulator: cpr3-regulator: add support for custom aging
1057115 I2c733a1f0ee4baf978c3715aa3bd74a6b46ee6c2 ARM: dts: msm: define perf cluster speed-bin 1 OSM LUT f
1046961 Ib0677ca792aea83ece1caf8a0afff341302747fb input: ft5x06: defer touch resume to workqueue
1026601 I4cd5b738caab4d40c1c118d3111c3f4af740c84e ASoC: msm: qdsp6v2: enable audio over display port
1062365 I9a8439d1f38a328a08590d2c5b11a611f11b4836 ARM: dts: msm: increase VDD_APC CPR LowSVS/SVS ceiling f
1062808 I5b8fa962718a5ae44dfd18a13285715580ee0dbc clk: msm: Select appropriate clock flags for 32-bit
1058826 Ifea3a6e8bf45481c65a4455ee64318304798fee2 misc: qcom: qdsp6v2: initialize config_32
1038431 I8fd8bf7326f1ea80df1c2fdbb08ebf73aa9e279c ASoC: wsa881x: Add a mixer control to control gain
1055047 I60d30192c55efd8b0d5dc455343464d29648281e msm: kgsl: Add trace for throttling counters
1053360 Ia66e005d04bf9eccb7febd8cb0733a67f9a4faf4 ext4: check if in-inode xattr is corrupted in ext4_expan
1046606 I8e359864508cc2307d9e9619f36c7c08cc3842f9 ALSA: timer: check if timer->card is null before using i
1054539 Ibc5da9bb1e47e32acb0268a15cea79d48907b106 ARM: dts: msm: update VDD_GFX CPR step quot values for m
985631 Ifbbdc69044fc64d7ea02509bf8113ed94eeece1e msm: kgsl: Improve logs for pagefaults on global buffers
1053360 Id3fc6ad39f771a0dbcab0c46a2df4f29cdb398f0 ext4 crypto: fix memleak in ext4_readdir()
1057383 I16556e1d6f4abe00e6f33b8375a5a1839dfca34e arm64: Prevent msm-rtb tracing in memcpy_{from,to}io and
1049594 I0501e9d40461c91d913175df6869966d0a0a8b5b ARM: dts: msm: Voter clocks for mmss_camss_jpeg0_clk for
1055867 I3ec0b8dce2b2bb1ccbcb5bdd7cd6621a5f9513f8 mfd: wcd9xxx: Reduce irqsoff latency
1059604 I8d39eaaa425e5e6fa97704c9bc15414f9a0f61ce msm: vidc: Enhance debug capabilities of video driver
1064333 Ia18a2f53fc3bf7ca459182dc197ad6a2078c7f5c ARM: dts: msm: Add initial device tree files for msmtrit
1008791 I5dc58b360b2bbce53493466a0bcd5363276c302a cfg80211: Add option to report the bss entry in connect
1063719 Ie6858243a666aeb21cc486208b9dd8221e9ad674 soc: qcom: irq-helper: Add comments to exposed APIs
1053505 I53aa15632e941199010aae670cefb65c8fd56833 ALSA: timer: Fix leak in events via snd_timer_user_tinte
1061372 I3c0dd344e0192a375f31fefea7ef6559fab0652d regulator: cpr3-mmss-regulator: change CPR aging sensor
1052787 Iedf7a3accbd14138ab7ed9e4e36a98fd7ca9a839 ASoC: utils: initialize dummy_codec before use
1057115 I9a864a2abb655e26fff5982b592b4f3c5dbfca24 clk: msm: osm: add support for speed-bin fuses
1026601 I7c2ace6dedc0cad34fe0ab46c6290526972824a1 ARM: dts: msm: rename codec child node of MSM external d
1053360 I64ea95854de3c633b17bea0b63ab658e1524befb ext4 crypto: revalidate dentry after adding or removing
1053505 I12949efac2aba669d302908704005fb94ba7efd7 ALSA: timer: Fix leak in events via snd_timer_user_ccall
1046606 Ia988b11ff7d03edc4ddd959571da1378da62077c ASoC: msm: qdsp6v2: check if buf is null before using it
1052854 I7d7517ab3f172016bb2f1c23fb2788bbd2d01086 power_supply: add two properties for step charging
1056610 I8d4267528068e36a648c328fbe6d6a35943f3810 msm: mdss: dsi: fix panel minimum refresh rate configura
1046606 Ib1af53ab52a65cca2ed9b3489359813e690b1cd6 ASoC: msm: qdsp6v2: check if index is out of range befor
1008791 If77035ca928bf5bc5a27230d9b3f6d56ea6c8b99 cfg80211: Define macro to indicate support for new cfg80
Change-Id: Id725fb8b5105b856e59ba90f0def8687b50cc711
CRs-Fixed: 1063805, 1063393, 1061372, 1062365, 1055047, 1060019, 1054908, 1062953, 1053705, 1057119, 1061427, 1060739, 1057115, 1054539, 1059604, 1046961, 1055867, 1053505, 1058826, 1053503, 1038431, 1063719, 1052854, 1058565, 1062808, 1056610, 1064333, 1049594, 1052747, 1060507, 982871, 1064040, 1064025, 985631, 1059577, 1061793, 1050042, 1057383, 1051259, 1053360, 1052415, 1046606, 1026601, 1064802, 1008791, 1063482, 1045908, 1052787
148 files changed, 4216 insertions, 964 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..bcdef5564066 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". + and "apcs_common". Optionally, "pwrcl_efuse" or + "perfcl_efuse". Must be specified in the same order as the corresponding addresses are specified in the reg property. 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 8e2f0908562a..ec8b08ad60e4 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt @@ -71,6 +71,7 @@ Optional properties: - focaltech,fw-name : specify the firmware file name - 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 Example: i2c@f9923000{ diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt index 38f2cfe1d649..510a824fda79 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt @@ -80,6 +80,22 @@ Charger specific properties: offset of charging current in uA, from -3100000 to 3200000. If the array is not present, step charging is disabled. +- io-channels + Usage: optional + Value type: List of <phandle u32> + Definition: List of phandle and IIO specifier pairs, one pair + for each IIO input to the device. Note: if the + IIO provider specifies '0' for #io-channel-cells, + then only the phandle portion of the pair will appear. + +- io-channel-names + Usage: optional + Value type: List of <string> + Definition: List of IIO input name strings sorted in the same + order as the io-channels property. Consumer drivers + will use io-channel-names to match IIO input names + with IIO specifiers. + ============================================= Second Level Nodes - SMB2 Charger Peripherals ============================================= @@ -110,6 +126,9 @@ pmicobalt_charger: qcom,qpnp-smb2 { #address-cells = <1>; #size-cells = <1>; + io-channels = <&pmic_rradc 0>; + io-channel-names = "rradc_batt_id"; + qcom,suspend-input; dpdm-supply = <&qusb_phy0>; 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 6b94608ee2c7..bffa21a06462 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -113,6 +113,7 @@ dtb-$(CONFIG_ARCH_MSMCOBALT) += msmcobalt-sim.dtb \ msmcobalt-v2-cdp.dtb \ msmcobalt-v2-qrd.dtb \ msmcobalt-qrd-skuk.dtb \ + msmcobalt-qrd-vr1.dtb \ apqcobalt-mtp.dtb \ apqcobalt-cdp.dtb \ apqcobalt-v2-mtp.dtb \ @@ -120,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/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index d99749a01f6c..7a1c075cdd76 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -145,6 +145,15 @@ qcom,pmic-revid = <&pmicobalt_revid>; + io-channels = <&pmicobalt_rradc 8>, + <&pmicobalt_rradc 10>, + <&pmicobalt_rradc 3>, + <&pmicobalt_rradc 4>; + io-channel-names = "charger_temp", + "charger_temp_max", + "usbin_i", + "usbin_v"; + dpdm-supply = <&qusb_phy0>; qcom,thermal-mitigation 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-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi index def8ed6e07a7..b4516f381c0c 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi @@ -752,7 +752,7 @@ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>, <&clock_mmss clk_mmss_camss_ahb_clk>, <&clock_mmss clk_mmss_camss_top_ahb_clk>, - <&clock_mmss clk_mmss_camss_jpeg0_clk>, + <&clock_mmss clk_mmss_camss_jpeg0_vote_clk>, <&clock_mmss clk_mmss_camss_jpeg_ahb_clk>, <&clock_mmss clk_mmss_camss_jpeg_axi_clk>; qcom,clock-rates = <0 0 0 0 0 0 480000000 0 0>; @@ -766,7 +766,7 @@ qcom,msm-bus,num-cases = <2>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <62 512 0 0>, - <62 512 666675 666675>; + <62 512 1920000 2880000>; status = "ok"; }; @@ -796,7 +796,7 @@ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>, <&clock_mmss clk_mmss_camss_ahb_clk>, <&clock_mmss clk_mmss_camss_top_ahb_clk>, - <&clock_mmss clk_mmss_camss_jpeg0_clk>, + <&clock_mmss clk_mmss_camss_jpeg0_dma_vote_clk>, <&clock_mmss clk_mmss_camss_jpeg_ahb_clk>, <&clock_mmss clk_mmss_camss_jpeg_axi_clk>; qcom,clock-rates = <0 0 0 0 0 0 480000000 0 0>; @@ -808,7 +808,7 @@ qcom,msm-bus,num-cases = <2>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <62 512 0 0>, - <62 512 666675 666675>; + <62 512 1920000 2880000>; qcom,max-ds-factor = <128>; status = "ok"; }; 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-qrd-vr1.dts b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dts new file mode 100644 index 000000000000..e53912071502 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dts @@ -0,0 +1,23 @@ +/* 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 "msmcobalt.dtsi" +#include "msmcobalt-qrd-vr1.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM COBALT VR1 Board"; + compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd"; + qcom,board-id = <0x02000b 0x80>; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi new file mode 100644 index 000000000000..c028ea0eeab3 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi @@ -0,0 +1,102 @@ +/* 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 <dt-bindings/interrupt-controller/irq.h> +#include "msmcobalt-pinctrl.dtsi" + +&blsp1_uart3_hs { + status = "ok"; +}; + +&ufsphy1 { + vdda-phy-supply = <&pmcobalt_l1>; + vdda-pll-supply = <&pmcobalt_l2>; + vddp-ref-clk-supply = <&pmcobalt_l26>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14600>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pmcobalt_l20>; + vccq-supply = <&pmcobalt_l26>; + vccq2-supply = <&pmcobalt_s4>; + vcc-max-microamp = <750000>; + vccq-max-microamp = <560000>; + vccq2-max-microamp = <750000>; + status = "ok"; +}; + +&ufs_ice { + status = "ok"; +}; + +&sdhc_2 { + vdd-supply = <&pmcobalt_l21>; + qcom,vdd-voltage-level = <2950000 2960000>; + qcom,vdd-current-level = <200 800000>; + + vdd-io-supply = <&pmcobalt_l13>; + qcom,vdd-io-voltage-level = <1808000 2960000>; + qcom,vdd-io-current-level = <200 22000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + qcom,clk-rates = <400000 20000000 25000000 + 50000000 100000000 200000000>; + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + + cd-gpios = <&tlmm 95 0x1>; + + status = "ok"; +}; + +&uartblsp2dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; + +&pmcobalt_gpios { + /* GPIO 6 for Vol+ Key */ + gpio@c500 { + status = "okay"; + qcom,mode = <0>; + qcom,pull = <0>; + qcom,vin-sel = <0>; + qcom,src-sel = <0>; + qcom,out-strength = <1>; + }; +}; + +&soc { + gpio_keys { + compatible = "gpio-keys"; + input-name = "gpio-keys"; + status = "okay"; + + vol_up { + label = "volume_up"; + gpios = <&pmcobalt_gpios 6 0x1>; + linux,input-type = <1>; + linux,code = <115>; + gpio-key,wakeup; + debounce-interval = <15>; + }; + }; +}; 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..8f4dc00101c5 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -804,12 +804,13 @@ 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>; reg-names = "osm", "pwrcl_pll", "perfcl_pll", - "apcs_common"; + "apcs_common", "perfcl_efuse"; vdd-pwrcl-supply = <&apc0_pwrcl_vreg>; vdd-perfcl-supply = <&apc1_perfcl_vreg>; @@ -1804,6 +1805,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 +1875,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 +2027,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-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts index 6631d31bac6d..0d694a6cd9fa 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts @@ -22,7 +22,7 @@ qcom,board-id = <15 0>; }; -&uartblsp2dm1 { +&uartblsp1dm1 { status = "ok"; pinctrl-names = "default"; pinctrl-0 = <&uart_console_active>; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts index 9840343fc3a7..eaaa1b407425 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts @@ -22,7 +22,7 @@ qcom,board-id = <16 0>; }; -&uartblsp2dm1 { +&uartblsp1dm1 { status = "ok"; pinctrl-names = "default"; pinctrl-0 = <&uart_console_active>; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index e46041cdd501..44d8e089837c 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -23,7 +23,7 @@ interrupt-parent = <&intc>; aliases { - serial0 = &uartblsp2dm1; + serial0 = &uartblsp1dm1; }; chosen { @@ -246,6 +246,16 @@ 3200 3200 3200 3200 3200 3200>; }; + 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>; @@ -472,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/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index 69261c70e1dd..d6ed9ac56bf1 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -16,6 +16,7 @@ config ARCH_MSMFALCON select MULTI_IRQ_HANDLER select HAVE_ARM_ARCH_TIMER select MAY_HAVE_SPARSE_IRQ + select COMMON_CLK_MSM select PINCTRL_MSM_TLMM select USE_PINCTRL_IRQ select MSM_PM if PM 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/Kconfig b/drivers/clk/msm/Kconfig index d94678e9e4fc..650a23ea1ead 100644 --- a/drivers/clk/msm/Kconfig +++ b/drivers/clk/msm/Kconfig @@ -2,6 +2,7 @@ config COMMON_CLK_MSM tristate "Support for MSM clock controllers" depends on OF depends on ARCH_QCOM + select RATIONAL help This support clock controller used by MSM devices which support global, mmss and gpu clock controller. diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c index 9d605503520f..78dde263d487 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,6 +209,11 @@ 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; #define lmh_lite_clk_src_source_val 1 @@ -913,6 +919,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 +2476,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 +2499,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 +2519,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/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c index e0f75b0022fc..b997e79e3d73 100644 --- a/drivers/devfreq/governor_bw_hwmon.c +++ b/drivers/devfreq/governor_bw_hwmon.c @@ -67,8 +67,6 @@ struct hwmon_node { unsigned long hyst_en; unsigned long above_low_power; unsigned long prev_req; - unsigned long up_wake_mbps; - unsigned long down_wake_mbps; unsigned int wake; unsigned int down_cnt; ktime_t prev_ts; @@ -191,7 +189,7 @@ static unsigned int mbps_to_bytes(unsigned long mbps, unsigned int ms) return mbps; } -static int __bw_hwmon_sample_end(struct bw_hwmon *hwmon) +static int __bw_hwmon_sw_sample_end(struct bw_hwmon *hwmon) { struct devfreq *df; struct hwmon_node *node; @@ -220,9 +218,9 @@ static int __bw_hwmon_sample_end(struct bw_hwmon *hwmon) * bandwidth usage and do the bandwidth calculation based on just * this micro sample. */ - if (mbps > node->up_wake_mbps) { + if (mbps > node->hw->up_wake_mbps) { wake = UP_WAKE; - } else if (mbps < node->down_wake_mbps) { + } else if (mbps < node->hw->down_wake_mbps) { if (node->down_cnt) node->down_cnt--; if (node->down_cnt <= 0) @@ -241,6 +239,50 @@ static int __bw_hwmon_sample_end(struct bw_hwmon *hwmon) return wake; } +static int __bw_hwmon_hw_sample_end(struct bw_hwmon *hwmon) +{ + struct devfreq *df; + struct hwmon_node *node; + unsigned long bytes, mbps; + int wake = 0; + + df = hwmon->df; + node = df->data; + + /* + * If this read is in response to an IRQ, the HW monitor should + * return the measurement in the micro sample that triggered the IRQ. + * Otherwise, it should return the maximum measured value in any + * micro sample since the last time we called get_bytes_and_clear() + */ + bytes = hwmon->get_bytes_and_clear(hwmon); + mbps = bytes_to_mbps(bytes, node->sample_ms * USEC_PER_MSEC); + node->max_mbps = mbps; + + if (mbps > node->hw->up_wake_mbps) + wake = UP_WAKE; + else if (mbps < node->hw->down_wake_mbps) + wake = DOWN_WAKE; + + node->wake = wake; + node->sampled = true; + + trace_bw_hwmon_meas(dev_name(df->dev.parent), + mbps, + node->sample_ms * USEC_PER_MSEC, + wake); + + return 1; +} + +static int __bw_hwmon_sample_end(struct bw_hwmon *hwmon) +{ + if (hwmon->set_hw_events) + return __bw_hwmon_hw_sample_end(hwmon); + else + return __bw_hwmon_sw_sample_end(hwmon); +} + int bw_hwmon_sample_end(struct bw_hwmon *hwmon) { unsigned long flags; @@ -275,12 +317,14 @@ static unsigned long get_bw_and_set_irq(struct hwmon_node *node, struct bw_hwmon *hw = node->hw; unsigned int new_bw, io_percent; ktime_t ts; - unsigned int ms; + unsigned int ms = 0; spin_lock_irqsave(&irq_lock, flags); - ts = ktime_get(); - ms = ktime_to_ms(ktime_sub(ts, node->prev_ts)); + if (!hw->set_hw_events) { + ts = ktime_get(); + ms = ktime_to_ms(ktime_sub(ts, node->prev_ts)); + } if (!node->sampled || ms >= node->sample_ms) __bw_hwmon_sample_end(node->hw); node->sampled = false; @@ -388,9 +432,10 @@ static unsigned long get_bw_and_set_irq(struct hwmon_node *node, /* Stretch the short sample window size, if the traffic is too low */ if (meas_mbps < MIN_MBPS) { - node->up_wake_mbps = (max(MIN_MBPS, req_mbps) + hw->up_wake_mbps = (max(MIN_MBPS, req_mbps) * (100 + node->up_thres)) / 100; - node->down_wake_mbps = 0; + hw->down_wake_mbps = 0; + hw->undo_over_req_mbps = 0; thres = mbps_to_bytes(max(MIN_MBPS, req_mbps / 2), node->sample_ms); } else { @@ -401,13 +446,22 @@ static unsigned long get_bw_and_set_irq(struct hwmon_node *node, * reduce the vote based on the measured mbps being less than * the previous measurement that caused the "over request". */ - node->up_wake_mbps = (req_mbps * (100 + node->up_thres)) / 100; - node->down_wake_mbps = (meas_mbps * node->down_thres) / 100; + hw->up_wake_mbps = (req_mbps * (100 + node->up_thres)) / 100; + hw->down_wake_mbps = (meas_mbps * node->down_thres) / 100; + if (node->wake == UP_WAKE) + hw->undo_over_req_mbps = min(req_mbps, meas_mbps_zone); + else + hw->undo_over_req_mbps = 0; thres = mbps_to_bytes(meas_mbps, node->sample_ms); } - node->down_cnt = node->down_count; - node->bytes = hw->set_thres(hw, thres); + if (hw->set_hw_events) { + hw->down_cnt = node->down_count; + hw->set_hw_events(hw, node->sample_ms); + } else { + node->down_cnt = node->down_count; + node->bytes = hw->set_thres(hw, thres); + } node->wake = 0; node->prev_req = req_mbps; @@ -432,8 +486,8 @@ static unsigned long get_bw_and_set_irq(struct hwmon_node *node, trace_bw_hwmon_update(dev_name(node->hw->df->dev.parent), new_bw, *freq, - node->up_wake_mbps, - node->down_wake_mbps); + hw->up_wake_mbps, + hw->down_wake_mbps); return req_mbps; } @@ -503,6 +557,9 @@ static int start_monitor(struct devfreq *df, bool init) node->resume_freq = 0; node->resume_ab = 0; mbps = (df->previous_freq * node->io_percent) / 100; + hw->up_wake_mbps = mbps; + hw->down_wake_mbps = MIN_MBPS; + hw->undo_over_req_mbps = 0; ret = hw->start_hwmon(hw, mbps); } else { ret = hw->resume_hwmon(hw); diff --git a/drivers/devfreq/governor_bw_hwmon.h b/drivers/devfreq/governor_bw_hwmon.h index 59bf48ac5af7..7578399cfb88 100644 --- a/drivers/devfreq/governor_bw_hwmon.h +++ b/drivers/devfreq/governor_bw_hwmon.h @@ -48,6 +48,8 @@ struct bw_hwmon { int (*suspend_hwmon)(struct bw_hwmon *hw); int (*resume_hwmon)(struct bw_hwmon *hw); unsigned long (*set_thres)(struct bw_hwmon *hw, unsigned long bytes); + unsigned long (*set_hw_events)(struct bw_hwmon *hw, + unsigned int sample_ms); unsigned long (*get_bytes_and_clear)(struct bw_hwmon *hw); int (*set_throttle_adj)(struct bw_hwmon *hw, uint adj); u32 (*get_throttle_adj)(struct bw_hwmon *hw); @@ -55,6 +57,11 @@ struct bw_hwmon { struct device_node *of_node; struct devfreq_governor *gov; + unsigned long up_wake_mbps; + unsigned long undo_over_req_mbps; + unsigned long down_wake_mbps; + unsigned int down_cnt; + struct devfreq *df; }; diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 18fdd400ac7a..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; @@ -1279,7 +1280,7 @@ static void _setup_throttling_counters(struct adreno_device *adreno_dev) static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev) { - int i; + int i, adj; uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS]; struct adreno_busy_data *busy = &adreno_dev->busy_data; @@ -1300,8 +1301,14 @@ static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev) adreno_dev->gpmu_throttle_counters[i], &busy->throttle_cycles[i]); } - i = th[CRC_MORE50PCT] - th[IDLE_10PCT]; - return th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (i < 0 ? 0 : i) * 3; + adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; + adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; + + trace_kgsl_clock_throttling( + th[IDLE_10PCT], th[CRC_50PCT], + th[CRC_MORE50PCT], th[CRC_LESS50PCT], + adj); + return adj; } static void _update_threshold_count(struct adreno_device *adreno_dev, 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/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h index 1b51eb591036..4ef9f80177d6 100644 --- a/drivers/gpu/msm/kgsl_trace.h +++ b/drivers/gpu/msm/kgsl_trace.h @@ -1192,6 +1192,41 @@ TRACE_EVENT(sparse_unbind, ); +TRACE_EVENT(kgsl_clock_throttling, + TP_PROTO( + int idle_10pct, + int crc_50pct, + int crc_more50pct, + int crc_less50pct, + int adj + ), + TP_ARGS( + idle_10pct, + crc_50pct, + crc_more50pct, + crc_less50pct, + adj + ), + TP_STRUCT__entry( + __field(int, idle_10pct) + __field(int, crc_50pct) + __field(int, crc_more50pct) + __field(int, crc_less50pct) + __field(int, adj) + ), + TP_fast_assign( + __entry->idle_10pct = idle_10pct; + __entry->crc_50pct = crc_50pct; + __entry->crc_more50pct = crc_more50pct; + __entry->crc_less50pct = crc_less50pct; + __entry->adj = adj; + ), + TP_printk("idle_10=%d crc_50=%d crc_more50=%d crc_less50=%d adj=%d", + __entry->idle_10pct, __entry->crc_50pct, __entry->crc_more50pct, + __entry->crc_less50pct, __entry->adj + ) +); + #endif /* _KGSL_TRACE_H */ /* This part must be outside protection */ diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c index b02e8ecf8608..17bce3d18d2f 100644 --- a/drivers/input/touchscreen/ft5x06_ts.c +++ b/drivers/input/touchscreen/ft5x06_ts.c @@ -253,6 +253,7 @@ struct ft5x06_ts_data { u8 fw_vendor_id; struct kobject ts_info_kobj; #if defined(CONFIG_FB) + struct work_struct fb_notify_work; struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; @@ -1137,6 +1138,13 @@ static int ft5x06_ts_resume(struct device *dev) #endif #if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work) +{ + struct ft5x06_ts_data *ft5x06_data = + container_of(work, struct ft5x06_ts_data, fb_notify_work); + ft5x06_ts_resume(&ft5x06_data->client->dev); +} + static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { @@ -1145,13 +1153,27 @@ static int fb_notifier_callback(struct notifier_block *self, struct ft5x06_ts_data *ft5x06_data = container_of(self, struct ft5x06_ts_data, fb_notif); - if (evdata && evdata->data && event == FB_EVENT_BLANK && - ft5x06_data && ft5x06_data->client) { + if (evdata && evdata->data && ft5x06_data && ft5x06_data->client) { blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - ft5x06_ts_resume(&ft5x06_data->client->dev); - else if (*blank == FB_BLANK_POWERDOWN) - ft5x06_ts_suspend(&ft5x06_data->client->dev); + if (ft5x06_data->pdata->resume_in_workqueue) { + if (event == FB_EARLY_EVENT_BLANK && + *blank == FB_BLANK_UNBLANK) + schedule_work(&ft5x06_data->fb_notify_work); + else if (event == FB_EVENT_BLANK && + *blank == FB_BLANK_POWERDOWN) { + flush_work(&ft5x06_data->fb_notify_work); + ft5x06_ts_suspend(&ft5x06_data->client->dev); + } + } else { + if (event == FB_EVENT_BLANK) { + if (*blank == FB_BLANK_UNBLANK) + ft5x06_ts_resume( + &ft5x06_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ft5x06_ts_suspend( + &ft5x06_data->client->dev); + } + } } return 0; @@ -1918,6 +1940,9 @@ static int ft5x06_parse_dt(struct device *dev, pdata->gesture_support = of_property_read_bool(np, "focaltech,gesture-support"); + pdata->resume_in_workqueue = of_property_read_bool(np, + "focaltech,resume-in-workqueue"); + rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; @@ -2269,6 +2294,7 @@ static int ft5x06_ts_probe(struct i2c_client *client, 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; err = fb_register_client(&data->fb_notif); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 572e3c637c7b..39a0845a886f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -951,7 +951,7 @@ void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type, spin_unlock_irqrestore(&vfe_dev->common_data-> common_dev_data_lock, flags); } else { - if (frame_src == VFE_PIX_0) { + if (frame_src <= VFE_RAW_2) { msm_isp_check_for_output_error(vfe_dev, ts, &event_data.u.sof_info); } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index fdee3cabd097..a4eb80f31984 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -370,9 +370,6 @@ void msm_isp_fetch_engine_done_notify(struct vfe_device *vfe_dev, struct msm_vfe_fetch_engine_info *fetch_engine_info) { struct msm_isp_event_data fe_rd_done_event; - if (!fetch_engine_info->is_busy) - return; - memset(&fe_rd_done_event, 0, sizeof(struct msm_isp_event_data)); fe_rd_done_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c index 2af70b2ee1bf..3b38882c4c45 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c @@ -1390,7 +1390,7 @@ int msm_jpegdma_hw_get_max_downscale(struct msm_jpegdma_device *dma) */ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma) { - int i; + int i, j; int ret; unsigned int cnt; const void *property; @@ -1401,32 +1401,37 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma) dev_dbg(dma->dev, "Missing qos settings\n"); return 0; } + cnt /= 4; + if (cnt % 2) + return -EINVAL; + + dma->qos_regs_num = cnt / 2; - dma->qos_regs = kzalloc((sizeof(*dma->qos_regs) * cnt), GFP_KERNEL); + dma->qos_regs = kzalloc((sizeof(struct jpegdma_reg_cfg) * + dma->qos_regs_num), GFP_KERNEL); if (!dma->qos_regs) return -ENOMEM; - for (i = 0; i < cnt; i = i + 2) { + for (i = 0, j = 0; i < cnt; i += 2, j++) { ret = of_property_read_u32_index(dma->dev->of_node, "qcom,qos-reg-settings", i, - &dma->qos_regs[i].reg); + &dma->qos_regs[j].reg); if (ret < 0) { - dev_err(dma->dev, "can not read qos reg %d\n", i); + dev_err(dma->dev, "can not read qos reg %d\n", j); goto error; } ret = of_property_read_u32_index(dma->dev->of_node, "qcom,qos-reg-settings", i + 1, - &dma->qos_regs[i].val); + &dma->qos_regs[j].val); if (ret < 0) { - dev_err(dma->dev, "can not read qos setting %d\n", i); + dev_err(dma->dev, "can not read qos setting %d\n", j); goto error; } - dev_dbg(dma->dev, "Qos idx %d, reg %x val %x\n", i, - dma->qos_regs[i].reg, dma->qos_regs[i].val); + dev_dbg(dma->dev, "Qos idx %d, reg %x val %x\n", j, + dma->qos_regs[j].reg, dma->qos_regs[j].val); } - dma->qos_regs_num = cnt; return 0; error: @@ -1452,7 +1457,7 @@ void msm_jpegdma_hw_put_qos(struct msm_jpegdma_device *dma) */ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma) { - int i; + int i, j; int ret; unsigned int cnt; const void *property; @@ -1463,33 +1468,38 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma) dev_dbg(dma->dev, "Missing vbif settings\n"); return 0; } + cnt /= 4; + if (cnt % 2) + return -EINVAL; - dma->vbif_regs = kzalloc((sizeof(*dma->vbif_regs) * cnt), GFP_KERNEL); + dma->vbif_regs_num = cnt / 2; + + dma->vbif_regs = kzalloc((sizeof(struct jpegdma_reg_cfg) * + dma->vbif_regs_num), GFP_KERNEL); if (!dma->vbif_regs) return -ENOMEM; - for (i = 0; i < cnt; i = i + 2) { + for (i = 0, j = 0; i < cnt; i += 2, j++) { ret = of_property_read_u32_index(dma->dev->of_node, "qcom,vbif-reg-settings", i, - &dma->vbif_regs[i].reg); + &dma->vbif_regs[j].reg); if (ret < 0) { - dev_err(dma->dev, "can not read vbif reg %d\n", i); + dev_err(dma->dev, "can not read vbif reg %d\n", j); goto error; } ret = of_property_read_u32_index(dma->dev->of_node, "qcom,vbif-reg-settings", i + 1, - &dma->vbif_regs[i].val); + &dma->vbif_regs[j].val); if (ret < 0) { - dev_err(dma->dev, "can not read vbif setting %d\n", i); + dev_err(dma->dev, "can not read vbif setting %d\n", j); goto error; } - dev_dbg(dma->dev, "Vbif idx %d, reg %x val %x\n", i, - dma->vbif_regs[i].reg, dma->vbif_regs[i].val); + dev_dbg(dma->dev, "Vbif idx %d, reg %x val %x\n", j, + dma->vbif_regs[j].reg, dma->vbif_regs[j].val); } - dma->vbif_regs_num = cnt; return 0; error: @@ -1515,7 +1525,7 @@ void msm_jpegdma_hw_put_vbif(struct msm_jpegdma_device *dma) */ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma) { - int i; + int i, j; int ret; unsigned int cnt; const void *property; @@ -1526,35 +1536,39 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma) dev_dbg(dma->dev, "Missing prefetch settings\n"); return 0; } + cnt /= 4; + if (cnt % 2) + return -EINVAL; + + dma->prefetch_regs_num = cnt / 2; - dma->prefetch_regs = kcalloc(cnt, sizeof(*dma->prefetch_regs), - GFP_KERNEL); + dma->prefetch_regs = kzalloc((sizeof(struct jpegdma_reg_cfg) * + dma->prefetch_regs_num), GFP_KERNEL); if (!dma->prefetch_regs) return -ENOMEM; - for (i = 0; i < cnt; i = i + 2) { + for (i = 0, j = 0; i < cnt; i += 2, j++) { ret = of_property_read_u32_index(dma->dev->of_node, "qcom,prefetch-reg-settings", i, - &dma->prefetch_regs[i].reg); + &dma->prefetch_regs[j].reg); if (ret < 0) { - dev_err(dma->dev, "can not read prefetch reg %d\n", i); + dev_err(dma->dev, "can not read prefetch reg %d\n", j); goto error; } ret = of_property_read_u32_index(dma->dev->of_node, "qcom,prefetch-reg-settings", i + 1, - &dma->prefetch_regs[i].val); + &dma->prefetch_regs[j].val); if (ret < 0) { dev_err(dma->dev, "can not read prefetch setting %d\n", - i); + j); goto error; } - dev_dbg(dma->dev, "Prefetch idx %d, reg %x val %x\n", i, - dma->prefetch_regs[i].reg, dma->prefetch_regs[i].val); + dev_dbg(dma->dev, "Prefetch idx %d, reg %x val %x\n", j, + dma->prefetch_regs[j].reg, dma->prefetch_regs[j].val); } - dma->prefetch_regs_num = cnt; return 0; error: diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h index c2b928d2b5d3..198d130b24fc 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h @@ -101,4 +101,61 @@ struct csiphy_reg_3ph_parms_t csiphy_v5_0_3ph = { {0x38, 0xFE}, {0x81c, 0x6}, }; + +struct csiphy_settings_t csiphy_combo_mode_v5_0 = { + { + {0x818, 0x1}, + {0x81c, 0x2}, + {0x004, 0x08}, + {0x704, 0x08}, + {0x204, 0x08}, + {0x404, 0x08}, + {0x604, 0x08}, + {0x02c, 0x1}, + {0x22c, 0x1}, + {0x42c, 0x1}, + {0x62c, 0x1}, + {0x72c, 0x1}, + {0x034, 0x0f}, + {0x234, 0x0f}, + {0x434, 0x0f}, + {0x634, 0x0f}, + {0x734, 0x0f}, + {0x01c, 0x0a}, + {0x21c, 0x0a}, + {0x41c, 0x0a}, + {0x61c, 0x0a}, + {0x71c, 0x0a}, + {0x014, 0x60}, + {0x214, 0x60}, + {0x414, 0x60}, + {0x614, 0x60}, + {0x714, 0x60}, + {0x728, 0x4}, + {0x428, 0x0a}, + {0x628, 0x0e}, + {0x03c, 0xb8}, + {0x73c, 0xb8}, + {0x23c, 0xb8}, + {0x43c, 0xb8}, + {0x63c, 0xb8}, + {0x000, 0x91}, + {0x700, 0x80}, + {0x200, 0x91}, + {0x400, 0x91}, + {0x600, 0x80}, + {0x70c, 0xA5}, + {0x60c, 0xA5}, + {0x010, 0x52}, + {0x710, 0x52}, + {0x210, 0x52}, + {0x410, 0x52}, + {0x610, 0x52}, + {0x038, 0xfe}, + {0x738, 0x1f}, + {0x238, 0xfe}, + {0x438, 0xfe}, + {0x638, 0x1f}, + } +}; #endif diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index 30af06dc64f5..bdee620e8d45 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -46,7 +46,7 @@ #define NUM_LANES_OFFSET 4 #define CSI_3PHASE_HW 1 -#define MAX_LANES 4 +#define MAX_DPHY_DATA_LN 4 #define CLOCK_OFFSET 0x700 #define CSIPHY_SOF_DEBUG_COUNT 2 @@ -55,6 +55,22 @@ static struct v4l2_file_operations msm_csiphy_v4l2_subdev_fops; +static void msm_csiphy_write_settings( + struct csiphy_device *csiphy_dev, + struct csiphy_settings_t csiphy_settings) +{ + int i = 0; + + for (i = 0; i < MAX_CSIPHY_SETTINGS; i++) { + if (csiphy_settings.settings[i].addr == 0 && + csiphy_settings.settings[i].data == 0) + break; + + msm_camera_io_w(csiphy_settings.settings[i].data, + csiphy_dev->base + csiphy_settings.settings[i].addr); + } +} + static void msm_csiphy_cphy_irq_config( struct csiphy_device *csiphy_dev, struct msm_camera_csiphy_params *csiphy_params) @@ -418,7 +434,7 @@ static int msm_csiphy_2phase_lane_config( csiphybase = csiphy_dev->base; lane_mask = csiphy_params->lane_mask & 0x1f; - for (i = 0; i < MAX_LANES; i++) { + for (i = 0; i < MAX_DPHY_DATA_LN; i++) { if (mask == 0x2) { if (lane_mask & mask) lane_enable |= 0x80; @@ -437,7 +453,7 @@ static int msm_csiphy_2phase_lane_config( csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. mipi_csiphy_3ph_cmn_ctrl6.addr); - for (i = 0, mask = 0x1; i < MAX_LANES; i++) { + for (i = 0, mask = 0x1; i < MAX_DPHY_DATA_LN; i++) { if (!(lane_mask & mask)) { if (mask == 0x2) i--; @@ -562,112 +578,134 @@ static int msm_csiphy_2phase_lane_config_v50( struct csiphy_device *csiphy_dev, struct msm_camera_csiphy_params *csiphy_params) { - uint32_t val = 0, lane_enable = 0, clk_lane, mask = 1; + uint32_t lane_enable = 0, mask = 1; uint16_t lane_mask = 0, i = 0, offset; void __iomem *csiphybase; csiphybase = csiphy_dev->base; lane_mask = csiphy_params->lane_mask & 0x1f; - for (i = 0; i < MAX_LANES; i++) { + + lane_enable = msm_camera_io_r(csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl5.addr); + + /* write settle count and lane_enable */ + for (i = 0; i < MAX_DPHY_DATA_LN; i++) { if (mask == 0x2) { if (lane_mask & mask) lane_enable |= 0x80; i--; - } else if (lane_mask & mask) + offset = CLOCK_OFFSET; + } else if (lane_mask & mask) { lane_enable |= 0x1 << (i<<1); + offset = 0x200*i; + } + + if (lane_mask & mask) + msm_camera_io_w((csiphy_params->settle_cnt & 0xFF), + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg2.addr + offset); mask <<= 1; } - CDBG("%s:%d lane_enable: %d\n", __func__, __LINE__, lane_enable); + CDBG("%s:%d lane_enable: 0x%x\n", __func__, __LINE__, lane_enable); msm_camera_io_w(lane_enable, csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. mipi_csiphy_3ph_cmn_ctrl5.addr); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_cmn_ctrl6.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_cmn_ctrl6.addr); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_cmn_ctrl7.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_cmn_ctrl7.addr); - - for (i = 0, mask = 0x1; i < MAX_LANES; i++) { - if (!(lane_mask & mask)) { - if (mask == 0x2) - i--; - mask <<= 0x1; - continue; - } - if (mask == 0x2) { - val = 4; - offset = CLOCK_OFFSET; - clk_lane = 1; - i--; - } else { - offset = 0x200*i; - val = 0; - clk_lane = 0; - } - if (csiphy_params->combo_mode == 1) { - val |= 0xA; - if (mask == csiphy_dev->ctrl_reg-> - csiphy_reg.combo_clk_mask) { - val |= 0x4; - clk_lane = 1; - } - } - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl11.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl11.addr + offset); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl13.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl13.addr + offset); + /* write mode specific settings */ + if (csiphy_params->combo_mode == 1) + msm_csiphy_write_settings(csiphy_dev, + csiphy_dev->ctrl_reg->csiphy_combo_mode_settings); + else { msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg7.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg7.addr + offset); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg5.data, + mipi_csiphy_3ph_cmn_ctrl6.data, csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg5.addr + offset); - if (clk_lane == 1) - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnck_ctrl10.data, - csiphybase + - csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnck_ctrl10.addr); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl15.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl15.addr + offset); - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl0.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl0.addr + offset); + mipi_csiphy_3ph_cmn_ctrl6.addr); msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg1.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg1.addr + offset); - msm_camera_io_w((csiphy_params->settle_cnt & 0xFF), + mipi_csiphy_3ph_cmn_ctrl7.data, csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg2.addr + offset); - if (clk_lane == 1) - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnck_ctrl3.data, csiphybase + - csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnck_ctrl3.addr); + mipi_csiphy_3ph_cmn_ctrl7.addr); msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg4.data, csiphybase + + mipi_csiphy_2ph_lnck_ctrl10.data, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_cfg4.addr + offset); + mipi_csiphy_2ph_lnck_ctrl10.addr); msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl14.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_2ph_lnn_ctrl14.addr + offset); - mask <<= 1; + mipi_csiphy_2ph_lnck_ctrl3.data, csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_2ph_lnck_ctrl3.addr); + + for (i = 0, mask = 0x1; i < MAX_DPHY_DATA_LN; i++) { + if (!(lane_mask & mask)) { + if (mask == 0x2) + i--; + mask <<= 0x1; + continue; + } + if (mask == 0x2) { + offset = CLOCK_OFFSET; + i--; + } else { + offset = 0x200*i; + } + + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl11.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl11.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl13.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl13.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg7.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg7.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg5.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg5.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl15.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl15.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl0.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl0.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg1.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg1.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg4.data, csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg4.addr + offset); + msm_camera_io_w(csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl14.data, + csiphybase + csiphy_dev->ctrl_reg-> + csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_ctrl14.addr + offset); + mask <<= 1; + } } msm_csiphy_cphy_irq_config(csiphy_dev, csiphy_params); return 0; @@ -986,19 +1024,20 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) } CDBG("%s:%d called\n", __func__, __LINE__); + if (csiphy_dev->ref_count++) { + CDBG("%s csiphy refcount = %d\n", __func__, + csiphy_dev->ref_count); + return rc; + } + + CDBG("%s:%d called\n", __func__, __LINE__); if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) { pr_err("%s: csiphy invalid state %d\n", __func__, csiphy_dev->csiphy_state); rc = -EINVAL; return rc; } - CDBG("%s:%d called\n", __func__, __LINE__); - if (csiphy_dev->ref_count++) { - CDBG("%s csiphy refcount = %d\n", __func__, - csiphy_dev->ref_count); - return rc; - } CDBG("%s:%d called\n", __func__, __LINE__); rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, @@ -1063,6 +1102,14 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) return rc; } csiphy_dev->csiphy_sof_debug_count = 0; + + CDBG("%s:%d called\n", __func__, __LINE__); + if (csiphy_dev->ref_count++) { + CDBG("%s csiphy refcount = %d\n", __func__, + csiphy_dev->ref_count); + return rc; + } + CDBG("%s:%d called\n", __func__, __LINE__); if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) { pr_err("%s: csiphy invalid state %d\n", __func__, @@ -1070,13 +1117,7 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) rc = -EINVAL; return rc; } - CDBG("%s:%d called\n", __func__, __LINE__); - if (csiphy_dev->ref_count++) { - CDBG("%s csiphy refcount = %d\n", __func__, - csiphy_dev->ref_count); - return rc; - } CDBG("%s:%d called\n", __func__, __LINE__); rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, CAM_AHB_SVS_VOTE); @@ -1651,6 +1692,8 @@ static int csiphy_probe(struct platform_device *pdev) new_csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v5_0; new_csiphy_dev->hw_dts_version = CSIPHY_VERSION_V50; new_csiphy_dev->csiphy_3phase = CSI_3PHASE_HW; + new_csiphy_dev->ctrl_reg->csiphy_combo_mode_settings = + csiphy_combo_mode_v5_0; } else { pr_err("%s:%d, invalid hw version : 0x%x\n", __func__, __LINE__, new_csiphy_dev->hw_dts_version); diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h index 4944ac606bc8..aba88da1157e 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h @@ -24,12 +24,17 @@ #define MAX_CSIPHY 3 #define CSIPHY_NUM_CLK_MAX 16 +#define MAX_CSIPHY_SETTINGS 120 struct csiphy_reg_t { uint32_t addr; uint32_t data; }; +struct csiphy_settings_t { + struct csiphy_reg_t settings[MAX_CSIPHY_SETTINGS]; +}; + struct csiphy_reg_parms_t { /*MIPI CSI PHY registers*/ uint32_t mipi_csiphy_lnn_cfg1_addr; @@ -140,6 +145,7 @@ struct csiphy_reg_3ph_parms_t { struct csiphy_ctrl_t { struct csiphy_reg_parms_t csiphy_reg; struct csiphy_reg_3ph_parms_t csiphy_3ph_reg; + struct csiphy_settings_t csiphy_combo_mode_settings; }; enum msm_csiphy_state_t { diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index 3124fd8a1777..5f749bd46273 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -631,11 +631,6 @@ static int32_t msm_flash_release( struct msm_flash_ctrl_t *flash_ctrl) { int32_t rc = 0; - if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_RELEASE) { - pr_err("%s:%d Invalid flash state = %d", - __func__, __LINE__, flash_ctrl->flash_state); - return 0; - } rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, NULL); if (rc < 0) { @@ -663,24 +658,49 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, rc = msm_flash_init(flash_ctrl, flash_data); break; case CFG_FLASH_RELEASE: - if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + if (flash_ctrl->flash_state != MSM_CAMERA_FLASH_RELEASE) { rc = flash_ctrl->func_tbl->camera_flash_release( flash_ctrl); + } else { + CDBG(pr_fmt("Invalid state : %d\n"), + flash_ctrl->flash_state); + } break; case CFG_FLASH_OFF: - if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + if ((flash_ctrl->flash_state != MSM_CAMERA_FLASH_RELEASE) && + (flash_ctrl->flash_state != MSM_CAMERA_FLASH_OFF)) { rc = flash_ctrl->func_tbl->camera_flash_off( flash_ctrl, flash_data); + if (!rc) + flash_ctrl->flash_state = MSM_CAMERA_FLASH_OFF; + } else { + CDBG(pr_fmt("Invalid state : %d\n"), + flash_ctrl->flash_state); + } break; case CFG_FLASH_LOW: - if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + if ((flash_ctrl->flash_state == MSM_CAMERA_FLASH_OFF) || + (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)) { rc = flash_ctrl->func_tbl->camera_flash_low( flash_ctrl, flash_data); + if (!rc) + flash_ctrl->flash_state = MSM_CAMERA_FLASH_LOW; + } else { + CDBG(pr_fmt("Invalid state : %d\n"), + flash_ctrl->flash_state); + } break; case CFG_FLASH_HIGH: - if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + if ((flash_ctrl->flash_state == MSM_CAMERA_FLASH_OFF) || + (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)) { rc = flash_ctrl->func_tbl->camera_flash_high( flash_ctrl, flash_data); + if (!rc) + flash_ctrl->flash_state = MSM_CAMERA_FLASH_HIGH; + } else { + CDBG(pr_fmt("Invalid state : %d\n"), + flash_ctrl->flash_state); + } break; default: rc = -EFAULT; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h index f6ac16f57080..ad619fa4eb63 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h @@ -27,6 +27,9 @@ enum msm_camera_flash_state_t { MSM_CAMERA_FLASH_INIT, + MSM_CAMERA_FLASH_OFF, + MSM_CAMERA_FLASH_LOW, + MSM_CAMERA_FLASH_HIGH, MSM_CAMERA_FLASH_RELEASE, }; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 566441e9c546..f0a3875a8f28 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -90,6 +90,7 @@ static void msm_comm_generate_session_error(struct msm_vidc_inst *inst); static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst); static void handle_session_error(enum hal_command_response cmd, void *data); static void msm_vidc_print_running_insts(struct msm_vidc_core *core); +static void msm_comm_print_debug_info(struct msm_vidc_inst *inst); bool msm_comm_turbo_session(struct msm_vidc_inst *inst) { @@ -905,7 +906,7 @@ static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst, call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "sess resp timeout can potentially crash the system\n"); - + msm_comm_print_debug_info(inst); BUG_ON(inst->core->resources.debug_timeout); rc = -EIO; } else { @@ -1601,6 +1602,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) struct msm_vidc_cb_cmd_done *response = data; struct msm_vidc_core *core = NULL; struct hfi_device *hdev = NULL; + struct msm_vidc_inst *inst = NULL; int rc = 0; subsystem_crashed("venus"); @@ -1640,6 +1642,19 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) dprintk(VIDC_ERR, "SYS_ERROR can potentially crash the system\n"); + /* + * For SYS_ERROR, there will not be any inst pointer. + * Just grab one of the inst from instances list and + * use it. + */ + + mutex_lock(&core->lock); + inst = list_first_entry(&core->instances, + struct msm_vidc_inst, list); + mutex_unlock(&core->lock); + + msm_comm_print_debug_info(inst); + BUG_ON(core->resources.debug_timeout); } @@ -2450,6 +2465,7 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst) call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "ABORT timeout can potentially crash the system\n"); + msm_comm_print_debug_info(inst); BUG_ON(inst->core->resources.debug_timeout); rc = -EBUSY; @@ -2522,6 +2538,7 @@ int msm_comm_check_core_init(struct msm_vidc_core *core) { int rc = 0; struct hfi_device *hdev; + struct msm_vidc_inst *inst = NULL; mutex_lock(&core->lock); if (core->state >= VIDC_CORE_INIT_DONE) { @@ -2540,6 +2557,17 @@ int msm_comm_check_core_init(struct msm_vidc_core *core) call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "SYS_INIT timeout can potentially crash the system\n"); + /* + * For SYS_INIT, there will not be any inst pointer. + * Just grab one of the inst from instances list and + * use it. + */ + inst = list_first_entry(&core->instances, + struct msm_vidc_inst, list); + + mutex_unlock(&core->lock); + msm_comm_print_debug_info(inst); + mutex_lock(&core->lock); BUG_ON(core->resources.debug_timeout); rc = -EIO; @@ -4017,6 +4045,8 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "SESS_PROP timeout can potentially crash the system\n"); + if (inst->core->resources.debug_timeout) + msm_comm_print_debug_info(inst); BUG_ON(inst->core->resources.debug_timeout); rc = -ETIMEDOUT; @@ -5232,3 +5262,92 @@ int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a) exit: return rc; } + +void msm_comm_print_inst_info(struct msm_vidc_inst *inst) +{ + struct buffer_info *temp; + struct internal_buf *buf; + int i = 0; + bool is_decode = false; + enum vidc_ports port; + + if (!inst) { + dprintk(VIDC_ERR, "%s - invalid param %p\n", + __func__, inst); + return; + } + + is_decode = inst->session_type == MSM_VIDC_DECODER; + port = is_decode ? OUTPUT_PORT : CAPTURE_PORT; + dprintk(VIDC_ERR, + "%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n", + is_decode ? "Decode" : "Encode", inst->fmts[port]->name, + inst->prop.height[port], inst->prop.width[port], + inst->prop.fps, inst->prop.bitrate, + !inst->bit_depth ? "8" : "10"); + + dprintk(VIDC_ERR, + "---Buffer details for inst: %p of type: %d---\n", + inst, inst->session_type); + mutex_lock(&inst->registeredbufs.lock); + dprintk(VIDC_ERR, "registered buffer list:\n"); + list_for_each_entry(temp, &inst->registeredbufs.list, list) + for (i = 0; i < temp->num_planes; i++) + dprintk(VIDC_ERR, + "type: %d plane: %d addr: %pa size: %d\n", + temp->type, i, &temp->device_addr[i], + temp->size[i]); + + mutex_unlock(&inst->registeredbufs.lock); + + mutex_lock(&inst->scratchbufs.lock); + dprintk(VIDC_ERR, "scratch buffer list:\n"); + list_for_each_entry(buf, &inst->scratchbufs.list, list) + dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", + buf->buffer_type, &buf->handle->device_addr, + buf->handle->size); + mutex_unlock(&inst->scratchbufs.lock); + + mutex_lock(&inst->persistbufs.lock); + dprintk(VIDC_ERR, "persist buffer list:\n"); + list_for_each_entry(buf, &inst->persistbufs.list, list) + dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", + buf->buffer_type, &buf->handle->device_addr, + buf->handle->size); + mutex_unlock(&inst->persistbufs.lock); + + mutex_lock(&inst->outputbufs.lock); + dprintk(VIDC_ERR, "dpb buffer list:\n"); + list_for_each_entry(buf, &inst->outputbufs.list, list) + dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", + buf->buffer_type, &buf->handle->device_addr, + buf->handle->size); + mutex_unlock(&inst->outputbufs.lock); +} + +static void msm_comm_print_debug_info(struct msm_vidc_inst *inst) +{ + struct msm_vidc_core *core = NULL; + struct msm_vidc_inst *temp = NULL; + + if (!inst || !inst->core) { + dprintk(VIDC_ERR, "%s - invalid param %p %p\n", + __func__, inst, core); + return; + } + core = inst->core; + + dprintk(VIDC_ERR, "Venus core frequency = %lu", + msm_comm_get_clock_rate(core)); + dprintk(VIDC_ERR, "Printing instance info that caused Error\n"); + msm_comm_print_inst_info(inst); + dprintk(VIDC_ERR, "Printing remaining instances info\n"); + mutex_lock(&core->lock); + list_for_each_entry(temp, &core->instances, list) { + /* inst already printed above. Hence don't repeat.*/ + if (temp == inst) + continue; + msm_comm_print_inst_info(temp); + } + mutex_unlock(&core->lock); +} diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index 337760508eb1..eac7f658eb31 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -98,4 +98,5 @@ int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst); void msm_comm_cleanup_internal_buffers(struct msm_vidc_inst *inst); int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a); bool msm_comm_turbo_session(struct msm_vidc_inst *inst); +void msm_comm_print_inst_info(struct msm_vidc_inst *inst); #endif diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index 1bdc5bf2c93d..25fccab99fb3 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -1238,11 +1238,6 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, { struct msm_vidc_core *core = token; struct msm_vidc_inst *inst; - struct buffer_info *temp; - struct internal_buf *buf; - int i = 0; - bool is_decode = false; - enum vidc_ports port; if (!domain || !core) { dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n", @@ -1257,52 +1252,7 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, mutex_lock(&core->lock); list_for_each_entry(inst, &core->instances, list) { - is_decode = inst->session_type == MSM_VIDC_DECODER; - port = is_decode ? OUTPUT_PORT : CAPTURE_PORT; - dprintk(VIDC_ERR, - "%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n", - is_decode ? "Decode" : "Encode", inst->fmts[port]->name, - inst->prop.height[port], inst->prop.width[port], - inst->prop.fps, inst->prop.bitrate, - !inst->bit_depth ? "8" : "10"); - - dprintk(VIDC_ERR, - "---Buffer details for inst: %pK of type: %d---\n", - inst, inst->session_type); - mutex_lock(&inst->registeredbufs.lock); - dprintk(VIDC_ERR, "registered buffer list:\n"); - list_for_each_entry(temp, &inst->registeredbufs.list, list) - for (i = 0; i < temp->num_planes; i++) - dprintk(VIDC_ERR, - "type: %d plane: %d addr: %pa size: %d\n", - temp->type, i, &temp->device_addr[i], - temp->size[i]); - - mutex_unlock(&inst->registeredbufs.lock); - - mutex_lock(&inst->scratchbufs.lock); - dprintk(VIDC_ERR, "scratch buffer list:\n"); - list_for_each_entry(buf, &inst->scratchbufs.list, list) - dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", - buf->buffer_type, &buf->handle->device_addr, - buf->handle->size); - mutex_unlock(&inst->scratchbufs.lock); - - mutex_lock(&inst->persistbufs.lock); - dprintk(VIDC_ERR, "persist buffer list:\n"); - list_for_each_entry(buf, &inst->persistbufs.list, list) - dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", - buf->buffer_type, &buf->handle->device_addr, - buf->handle->size); - mutex_unlock(&inst->persistbufs.lock); - - mutex_lock(&inst->outputbufs.lock); - dprintk(VIDC_ERR, "dpb buffer list:\n"); - list_for_each_entry(buf, &inst->outputbufs.list, list) - dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n", - buf->buffer_type, &buf->handle->device_addr, - buf->handle->size); - mutex_unlock(&inst->outputbufs.lock); + msm_comm_print_inst_info(inst); } core->smmu_fault_handled = true; mutex_unlock(&core->lock); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h index 23d84e9f7f7a..f6120dc7d1d5 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h @@ -16,6 +16,7 @@ #define DT_PARSE #include <linux/of.h> #include "msm_vidc_resources.h" +#include "msm_vidc_common.h" void msm_vidc_free_platform_resources( struct msm_vidc_platform_resources *res); diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 5a51fbcf9318..e0fb31de38ff 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -119,7 +119,7 @@ static inline bool __core_in_valid_state(struct venus_hfi_device *device) return device->state != VENUS_STATE_DEINIT; } -static void __dump_packet(u8 *packet) +static void __dump_packet(u8 *packet, enum vidc_msg_prio log_level) { u32 c = 0, packet_size = *(u32 *)packet; const int row_size = 32; @@ -132,7 +132,7 @@ static void __dump_packet(u8 *packet) packet_size % row_size : row_size; hex_dump_to_buffer(packet + c * row_size, bytes_to_read, row_size, 4, row, sizeof(row), false); - dprintk(VIDC_PKT, "%s\n", row); + dprintk(log_level, "%s\n", row); } } @@ -342,7 +342,7 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet, if (msm_vidc_debug & VIDC_PKT) { dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); - __dump_packet(packet); + __dump_packet(packet, VIDC_PKT); } packet_size_in_words = (*(u32 *)packet) >> 2; @@ -548,7 +548,7 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet, if (msm_vidc_debug & VIDC_PKT) { dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); - __dump_packet(packet); + __dump_packet(packet, VIDC_PKT); } return rc; @@ -2517,7 +2517,6 @@ static int venus_hfi_session_clean(void *session) mutex_lock(&device->lock); __session_clean(sess_close); - __flush_debug_queue(device, NULL); mutex_unlock(&device->lock); return 0; @@ -3337,6 +3336,7 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet) { bool local_packet = false; enum vidc_msg_prio log_level = VIDC_FW; + unsigned int pending_packet_count = 0; if (!device) { dprintk(VIDC_ERR, "%s: Invalid params\n", __func__); @@ -3361,6 +3361,23 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet) log_level = VIDC_ERR; } + /* + * In FATAL situation, print all the pending messages in msg + * queue. This is useful for debugging. At this time, message + * queues may be corrupted. Hence don't trust them and just print + * first max_packets packets. + */ + + if (local_packet) { + dprintk(VIDC_ERR, + "Printing all pending messages in message Queue\n"); + while (!__iface_msgq_read(device, packet) && + pending_packet_count < max_packets) { + __dump_packet(packet, log_level); + pending_packet_count++; + } + } + while (!__iface_dbgq_read(device, packet)) { struct hfi_msg_sys_coverage_packet *pkt = (struct hfi_msg_sys_coverage_packet *) packet; 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/platform/msm/ipa/test/Makefile b/drivers/platform/msm/ipa/test/Makefile index e1686e608906..c20fd2b42487 100644 --- a/drivers/platform/msm/ipa/test/Makefile +++ b/drivers/platform/msm/ipa/test/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o -ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o +ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o diff --git a/drivers/platform/msm/ipa/test/ipa_test_dma.c b/drivers/platform/msm/ipa/test/ipa_test_dma.c new file mode 100644 index 000000000000..af1b584b0d8c --- /dev/null +++ b/drivers/platform/msm/ipa/test/ipa_test_dma.c @@ -0,0 +1,931 @@ +/* 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 <linux/ipa.h> +#include "../ipa_v3/ipa_i.h" +#include "ipa_ut_framework.h" + +#define IPA_TEST_DMA_WQ_NAME_BUFF_SZ 64 +#define IPA_TEST_DMA_MT_TEST_NUM_WQ 500 +#define IPA_TEST_DMA_MEMCPY_BUFF_SIZE 16384 +#define IPA_TEST_DMA_MAX_PKT_SIZE 0xFF00 +#define IPA_DMA_TEST_LOOP_NUM 1000 +#define IPA_DMA_TEST_INT_LOOP_NUM 50 +#define IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM 128 +#define IPA_DMA_RUN_TEST_UNIT_IN_LOOP(test_unit, iters, rc, args...) \ + do { \ + int __i; \ + for (__i = 0; __i < iters; __i++) { \ + IPA_UT_LOG(#test_unit " START iter %d\n", __i); \ + rc = test_unit(args); \ + if (!rc) \ + continue; \ + IPA_UT_LOG(#test_unit " failed %d\n", rc); \ + break; \ + } \ + } while (0) + +/** + * struct ipa_test_dma_async_user_data - user_data structure for async memcpy + * @src_mem: source memory buffer + * @dest_mem: destination memory buffer + * @call_serial_number: Id of the caller + * @copy_done: Completion object + */ +struct ipa_test_dma_async_user_data { + struct ipa_mem_buffer src_mem; + struct ipa_mem_buffer dest_mem; + int call_serial_number; + struct completion copy_done; +}; + +/** + * ipa_test_dma_setup() - Suite setup function + */ +static int ipa_test_dma_setup(void **ppriv) +{ + int rc; + + IPA_UT_DBG("Start Setup\n"); + + if (!ipa3_ctx) { + IPA_UT_ERR("No IPA ctx\n"); + return -EINVAL; + } + + rc = ipa_dma_init(); + if (rc) + IPA_UT_ERR("Fail to init ipa_dma - return code %d\n", rc); + else + IPA_UT_DBG("ipa_dma_init() Completed successfully!\n"); + + *ppriv = NULL; + + return rc; +} + +/** + * ipa_test_dma_teardown() - Suite teardown function + */ +static int ipa_test_dma_teardown(void *priv) +{ + IPA_UT_DBG("Start Teardown\n"); + ipa_dma_destroy(); + return 0; +} + +static int ipa_test_dma_alloc_buffs(struct ipa_mem_buffer *src, + struct ipa_mem_buffer *dest, + int size) +{ + int i; + static int val = 1; + int rc; + + val++; + src->size = size; + src->base = dma_alloc_coherent(ipa3_ctx->pdev, src->size, + &src->phys_base, GFP_KERNEL); + if (!src->base) { + IPA_UT_LOG("fail to alloc dma mem %d bytes\n", size); + IPA_UT_TEST_FAIL_REPORT("fail to alloc dma mem"); + return -ENOMEM; + } + + dest->size = size; + dest->base = dma_alloc_coherent(ipa3_ctx->pdev, dest->size, + &dest->phys_base, GFP_KERNEL); + if (!dest->base) { + IPA_UT_LOG("fail to alloc dma mem %d bytes\n", size); + IPA_UT_TEST_FAIL_REPORT("fail to alloc dma mem"); + rc = -ENOMEM; + goto fail_alloc_dest; + } + + memset(dest->base, 0, dest->size); + for (i = 0; i < src->size; i++) + memset(src->base + i, (val + i) & 0xFF, 1); + rc = memcmp(dest->base, src->base, dest->size); + if (rc == 0) { + IPA_UT_LOG("dest & src buffers are equal\n"); + IPA_UT_TEST_FAIL_REPORT("dest & src buffers are equal"); + rc = -EFAULT; + goto fail_buf_cmp; + } + + return 0; + +fail_buf_cmp: + dma_free_coherent(ipa3_ctx->pdev, dest->size, dest->base, + dest->phys_base); +fail_alloc_dest: + dma_free_coherent(ipa3_ctx->pdev, src->size, src->base, + src->phys_base); + return rc; +} + +static void ipa_test_dma_destroy_buffs(struct ipa_mem_buffer *src, + struct ipa_mem_buffer *dest) +{ + dma_free_coherent(ipa3_ctx->pdev, src->size, src->base, + src->phys_base); + dma_free_coherent(ipa3_ctx->pdev, dest->size, dest->base, + dest->phys_base); +} + +/** + * ipa_test_dma_memcpy_sync() - memcpy in sync mode + * + * @size: buffer size + * @expect_fail: test expects the memcpy to fail + * + * To be run during tests + * 1. Alloc src and dst buffers + * 2. sync memcpy src to dst via dma + * 3. compare src and dts if memcpy succeeded as expected + */ +static int ipa_test_dma_memcpy_sync(int size, bool expect_fail) +{ + int rc = 0; + int i; + struct ipa_mem_buffer src_mem; + struct ipa_mem_buffer dest_mem; + u8 *src; + u8 *dest; + + rc = ipa_test_dma_alloc_buffs(&src_mem, &dest_mem, size); + if (rc) { + IPA_UT_LOG("fail to alloc buffers\n"); + IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers"); + return rc; + } + + rc = ipa_dma_sync_memcpy(dest_mem.phys_base, src_mem.phys_base, size); + if (!expect_fail && rc) { + IPA_UT_LOG("fail to sync memcpy - rc = %d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcpy failed"); + goto free_buffs; + } + if (expect_fail && !rc) { + IPA_UT_LOG("sync memcpy succeeded while expected to fail\n"); + IPA_UT_TEST_FAIL_REPORT( + "sync memcpy succeeded while expected to fail"); + rc = -EFAULT; + goto free_buffs; + } + + if (!rc) { + /* if memcpy succeeded, compare the buffers */ + rc = memcmp(dest_mem.base, src_mem.base, size); + if (rc) { + IPA_UT_LOG("BAD memcpy - buffs are not equals\n"); + IPA_UT_TEST_FAIL_REPORT( + "BAD memcpy - buffs are not equals"); + src = src_mem.base; + dest = dest_mem.base; + for (i = 0; i < size; i++) { + if (*(src + i) != *(dest + i)) { + IPA_UT_LOG("byte: %d 0x%x != 0x%x\n", + i, *(src + i), *(dest + i)); + } + } + } + } else { + /* if memcpy failed as expected, update the rc */ + rc = 0; + } + +free_buffs: + ipa_test_dma_destroy_buffs(&src_mem, &dest_mem); + return rc; +} + +static void ipa_test_dma_async_memcpy_cb(void *comp_obj) +{ + struct completion *xfer_done; + + if (!comp_obj) { + IPA_UT_ERR("Invalid Input\n"); + return; + } + xfer_done = (struct completion *)comp_obj; + complete(xfer_done); +} + +static void ipa_test_dma_async_memcpy_cb_user_data(void *user_param) +{ + int rc; + int i; + u8 *src; + u8 *dest; + struct ipa_test_dma_async_user_data *udata = + (struct ipa_test_dma_async_user_data *)user_param; + + if (!udata) { + IPA_UT_ERR("Invalid user param\n"); + return; + } + + rc = memcmp(udata->dest_mem.base, udata->src_mem.base, + udata->src_mem.size); + if (rc) { + IPA_UT_LOG("BAD memcpy - buffs are not equal sn=%d\n", + udata->call_serial_number); + IPA_UT_TEST_FAIL_REPORT( + "BAD memcpy - buffs are not equal"); + src = udata->src_mem.base; + dest = udata->dest_mem.base; + for (i = 0; i < udata->src_mem.size; i++) { + if (*(src + i) != *(dest + i)) { + IPA_UT_ERR("byte: %d 0x%x != 0x%x\n", i, + *(src + i), *(dest + i)); + } + } + return; + } + + IPA_UT_LOG("Notify on async memcopy sn=%d\n", + udata->call_serial_number); + complete(&(udata->copy_done)); +} + +/** + * ipa_test_dma_memcpy_async() - memcpy in async mode + * + * @size: buffer size + * @expect_fail: test expected the memcpy to fail + * + * To be run during tests + * 1. Alloc src and dst buffers + * 2. async memcpy src to dst via dma and wait for completion + * 3. compare src and dts if memcpy succeeded as expected + */ +static int ipa_test_dma_memcpy_async(int size, bool expect_fail) +{ + int rc = 0; + int i; + struct ipa_mem_buffer src_mem; + struct ipa_mem_buffer dest_mem; + u8 *src; + u8 *dest; + struct completion xfer_done; + + rc = ipa_test_dma_alloc_buffs(&src_mem, &dest_mem, size); + if (rc) { + IPA_UT_LOG("fail to alloc buffers\n"); + IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers"); + return rc; + } + + init_completion(&xfer_done); + rc = ipa_dma_async_memcpy(dest_mem.phys_base, src_mem.phys_base, size, + ipa_test_dma_async_memcpy_cb, &xfer_done); + if (!expect_fail && rc) { + IPA_UT_LOG("fail to initiate async memcpy - rc=%d\n", + rc); + IPA_UT_TEST_FAIL_REPORT("async memcpy initiate failed"); + goto free_buffs; + } + if (expect_fail && !rc) { + IPA_UT_LOG("async memcpy succeeded while expected to fail\n"); + IPA_UT_TEST_FAIL_REPORT( + "async memcpy succeeded while expected to fail"); + rc = -EFAULT; + goto free_buffs; + } + + if (!rc) { + /* if memcpy succeeded, compare the buffers */ + wait_for_completion(&xfer_done); + rc = memcmp(dest_mem.base, src_mem.base, size); + if (rc) { + IPA_UT_LOG("BAD memcpy - buffs are not equals\n"); + IPA_UT_TEST_FAIL_REPORT( + "BAD memcpy - buffs are not equals"); + src = src_mem.base; + dest = dest_mem.base; + for (i = 0; i < size; i++) { + if (*(src + i) != *(dest + i)) { + IPA_UT_LOG("byte: %d 0x%x != 0x%x\n", + i, *(src + i), *(dest + i)); + } + } + } + } else { + /* if memcpy failed as expected, update the rc */ + rc = 0; + } + +free_buffs: + ipa_test_dma_destroy_buffs(&src_mem, &dest_mem); + return rc; +} + +/** + * ipa_test_dma_sync_async_memcpy() - memcpy in sync and then async mode + * + * @size: buffer size + * + * To be run during tests + * 1. several sync memcopy in row + * 2. several async memcopy - + * back-to-back (next async try initiated after prev is completed) + */ +static int ipa_test_dma_sync_async_memcpy(int size) +{ + int rc; + + IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_sync, + IPA_DMA_TEST_INT_LOOP_NUM, rc, size, false); + if (rc) { + IPA_UT_LOG("sync memcopy fail rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcopy fail"); + return rc; + } + + IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_async, + IPA_DMA_TEST_INT_LOOP_NUM, rc, size, false); + if (rc) { + IPA_UT_LOG("async memcopy fail rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("async memcopy fail"); + return rc; + } + + return 0; +} + +/** + * TEST: test control API - enable/disable dma + * 1. enable dma + * 2. disable dma + */ +static int ipa_test_dma_control_api(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/** + * TEST: memcpy before dma enable + * + * 1. sync memcpy - should fail + * 2. async memcpy - should fail + */ +static int ipa_test_dma_memcpy_before_enable(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, true); + if (rc) { + IPA_UT_LOG("sync memcpy succeeded unexpectedly rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcpy succeeded unexpectedly"); + return rc; + } + + rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, true); + if (rc) { + IPA_UT_LOG("async memcpy succeeded unexpectedly rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcpy succeeded unexpectedly"); + return rc; + } + + return 0; +} + +/** + * TEST: Sync memory copy + * + * 1. dma enable + * 2. sync memcpy + * 3. dma disable + */ +static int ipa_test_dma_sync_memcpy(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("sync memcpy failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/** + * TEST: Async memory copy + * + * 1. dma enable + * 2. async memcpy + * 3. dma disable + */ +static int ipa_test_dma_async_memcpy(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("async memcpy failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("async memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/** + * TEST: Iteration of sync memory copy + * + * 1. dma enable + * 2. sync memcpy in loop - in row + * 3. dma disable + */ +static int ipa_test_dma_sync_memcpy_in_loop(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_sync, + IPA_DMA_TEST_LOOP_NUM, rc, + IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("Iterations of sync memcpy failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("Iterations of sync memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/** + * TEST: Iteration of async memory copy + * + * 1. dma enable + * 2. async memcpy in loop - back-to-back + * next async copy is initiated once previous one completed + * 3. dma disable + */ +static int ipa_test_dma_async_memcpy_in_loop(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_async, + IPA_DMA_TEST_LOOP_NUM, rc, + IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("Iterations of async memcpy failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("Iterations of async memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/** + * TEST: Iteration of interleaved sync and async memory copy + * + * 1. dma enable + * 2. sync and async memcpy in loop - interleaved + * 3. dma disable + */ +static int ipa_test_dma_interleaved_sync_async_memcpy_in_loop(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_sync_async_memcpy, + IPA_DMA_TEST_INT_LOOP_NUM, rc, + IPA_TEST_DMA_MEMCPY_BUFF_SIZE); + if (rc) { + IPA_UT_LOG( + "Iterations of interleaved sync async memcpy failed rc=%d\n" + , rc); + IPA_UT_TEST_FAIL_REPORT( + "Iterations of interleaved sync async memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +static atomic_t ipa_test_dma_mt_test_pass; + +static void ipa_test_dma_wrapper_test_one_sync(struct work_struct *work) +{ + int rc; + + rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("fail sync memcpy from thread rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail sync memcpy from thread"); + return; + } + atomic_inc(&ipa_test_dma_mt_test_pass); +} + +static void ipa_test_dma_wrapper_test_one_async(struct work_struct *work) +{ + int rc; + + rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false); + if (rc) { + IPA_UT_LOG("fail async memcpy from thread rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail async memcpy from thread"); + return; + } + atomic_inc(&ipa_test_dma_mt_test_pass); +} + +/** + * TEST: Multiple threads running sync and sync mem copy + * + * 1. dma enable + * 2. In-loop + * 2.1 create wq for sync memcpy + * 2.2 create wq for async memcpy + * 2.3 queue sync memcpy work + * 2.4 queue async memcoy work + * 3. In-loop + * 3.1 flush and destroy wq sync + * 3.2 flush and destroy wq async + * 3. dma disable + */ +static int ipa_test_dma_mt_sync_async(void *priv) +{ + int rc; + int i; + static struct workqueue_struct *wq_sync[IPA_TEST_DMA_MT_TEST_NUM_WQ]; + static struct workqueue_struct *wq_async[IPA_TEST_DMA_MT_TEST_NUM_WQ]; + static struct work_struct work_async[IPA_TEST_DMA_MT_TEST_NUM_WQ]; + static struct work_struct work_sync[IPA_TEST_DMA_MT_TEST_NUM_WQ]; + char buff[IPA_TEST_DMA_WQ_NAME_BUFF_SZ]; + + memset(wq_sync, 0, sizeof(wq_sync)); + memset(wq_sync, 0, sizeof(wq_async)); + memset(work_async, 0, sizeof(work_async)); + memset(work_sync, 0, sizeof(work_sync)); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + atomic_set(&ipa_test_dma_mt_test_pass, 0); + for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) { + snprintf(buff, sizeof(buff), "ipa_test_dmaSwq%d", i); + wq_sync[i] = create_singlethread_workqueue(buff); + if (!wq_sync[i]) { + IPA_UT_ERR("failed to create sync wq#%d\n", i); + rc = -EFAULT; + goto fail_create_wq; + } + snprintf(buff, IPA_RESOURCE_NAME_MAX, "ipa_test_dmaAwq%d", i); + wq_async[i] = create_singlethread_workqueue(buff); + if (!wq_async[i]) { + IPA_UT_ERR("failed to create async wq#%d\n", i); + rc = -EFAULT; + goto fail_create_wq; + } + + INIT_WORK(&work_sync[i], ipa_test_dma_wrapper_test_one_sync); + queue_work(wq_sync[i], &work_sync[i]); + INIT_WORK(&work_async[i], ipa_test_dma_wrapper_test_one_async); + queue_work(wq_async[i], &work_async[i]); + } + + for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) { + flush_workqueue(wq_sync[i]); + destroy_workqueue(wq_sync[i]); + flush_workqueue(wq_async[i]); + destroy_workqueue(wq_async[i]); + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + if ((2 * IPA_TEST_DMA_MT_TEST_NUM_WQ) != + atomic_read(&ipa_test_dma_mt_test_pass)) { + IPA_UT_LOG( + "Multi-threaded sync/async memcopy failed passed=%d\n" + , atomic_read(&ipa_test_dma_mt_test_pass)); + IPA_UT_TEST_FAIL_REPORT( + "Multi-threaded sync/async memcopy failed"); + return -EFAULT; + } + + return 0; + +fail_create_wq: + (void)ipa_dma_disable(); + for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) { + if (wq_sync[i]) + destroy_workqueue(wq_sync[i]); + if (wq_async[i]) + destroy_workqueue(wq_async[i]); + } + + return rc; +} + +/** + * TEST: Several parallel async memory copy iterations + * + * 1. create several user_data structures - one per iteration + * 2. allocate buffs. Give slice for each iteration + * 3. iterations of async mem copy + * 4. wait for all to complete + * 5. dma disable + */ +static int ipa_test_dma_parallel_async_memcpy_in_loop(void *priv) +{ + int rc; + struct ipa_test_dma_async_user_data *udata; + struct ipa_mem_buffer all_src_mem; + struct ipa_mem_buffer all_dest_mem; + int i; + bool is_fail = false; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + udata = kzalloc(IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM * + sizeof(struct ipa_test_dma_async_user_data), GFP_KERNEL); + if (!udata) { + IPA_UT_ERR("fail allocate user_data array\n"); + (void)ipa_dma_disable(); + return -ENOMEM; + } + + rc = ipa_test_dma_alloc_buffs(&all_src_mem, &all_dest_mem, + IPA_TEST_DMA_MEMCPY_BUFF_SIZE); + if (rc) { + IPA_UT_LOG("fail to alloc buffers\n"); + IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers"); + kfree(udata); + (void)ipa_dma_disable(); + return rc; + } + + for (i = 0 ; i < IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM ; i++) { + udata[i].src_mem.size = + IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM; + udata[i].src_mem.base = all_src_mem.base + i * + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM); + udata[i].src_mem.phys_base = all_src_mem.phys_base + i * + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM); + + udata[i].dest_mem.size = + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM); + udata[i].dest_mem.base = all_dest_mem.base + i * + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM); + udata[i].dest_mem.phys_base = all_dest_mem.phys_base + i * + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM); + + udata[i].call_serial_number = i + 1; + init_completion(&(udata[i].copy_done)); + rc = ipa_dma_async_memcpy(udata[i].dest_mem.phys_base, + udata[i].src_mem.phys_base, + (IPA_TEST_DMA_MEMCPY_BUFF_SIZE / + IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM), + ipa_test_dma_async_memcpy_cb_user_data, &udata[i]); + if (rc) { + IPA_UT_LOG("async memcpy initiation fail i=%d rc=%d\n", + i, rc); + is_fail = true; + } + } + + for (i = 0; i < IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM ; i++) + wait_for_completion(&udata[i].copy_done); + + ipa_test_dma_destroy_buffs(&all_src_mem, &all_dest_mem); + kfree(udata); + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + if (is_fail) { + IPA_UT_LOG("async memcopy failed\n"); + IPA_UT_TEST_FAIL_REPORT("async memcopy failed"); + return -EFAULT; + } + + return 0; +} + +/** + * TEST: Sync memory copy + * + * 1. dma enable + * 2. sync memcpy with max packet size + * 3. dma disable + */ +static int ipa_test_dma_sync_memcpy_max_pkt_size(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MAX_PKT_SIZE, false); + if (rc) { + IPA_UT_LOG("sync memcpy failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("sync memcpy failed"); + (void)ipa_dma_disable(); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + +/* Suite definition block */ +IPA_UT_DEFINE_SUITE_START(dma, "DMA for GSI", + ipa_test_dma_setup, ipa_test_dma_teardown) +{ + IPA_UT_ADD_TEST(control_api, + "Control API", + ipa_test_dma_control_api, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(memcpy_before_enable, + "Call memcpy before dma enable and expect it to fail", + ipa_test_dma_memcpy_before_enable, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(sync_memcpy, + "Sync memory copy", + ipa_test_dma_sync_memcpy, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(async_memcpy, + "Async memory copy", + ipa_test_dma_async_memcpy, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(sync_memcpy_in_loop, + "Several sync memory copy iterations", + ipa_test_dma_sync_memcpy_in_loop, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(async_memcpy_in_loop, + "Several async memory copy iterations", + ipa_test_dma_async_memcpy_in_loop, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(interleaved_sync_async_memcpy_in_loop, + "Several interleaved sync and async memory copy iterations", + ipa_test_dma_interleaved_sync_async_memcpy_in_loop, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(multi_threaded_multiple_sync_async_memcpy, + "Several multi-threaded sync and async memory copy iterations", + ipa_test_dma_mt_sync_async, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(parallel_async_memcpy_in_loop, + "Several parallel async memory copy iterations", + ipa_test_dma_parallel_async_memcpy_in_loop, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(sync_memcpy_max_pkt_size, + "Sync memory copy with max packet size", + ipa_test_dma_sync_memcpy_max_pkt_size, + true, IPA_HW_v3_0, IPA_HW_MAX), +} IPA_UT_DEFINE_SUITE_END(dma); diff --git a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h index 944800f8e4be..bbb8b771ba0b 100644 --- a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h +++ b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h @@ -21,6 +21,7 @@ * No importance for order. */ IPA_UT_DECLARE_SUITE(mhi); +IPA_UT_DECLARE_SUITE(dma); IPA_UT_DECLARE_SUITE(example); @@ -31,6 +32,7 @@ IPA_UT_DECLARE_SUITE(example); IPA_UT_DEFINE_ALL_SUITES_START { IPA_UT_REGISTER_SUITE(mhi), + IPA_UT_REGISTER_SUITE(dma), IPA_UT_REGISTER_SUITE(example), } IPA_UT_DEFINE_ALL_SUITES_END; diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index b1c3441b285a..545a1e684b25 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -227,6 +227,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(usb_otg), POWER_SUPPLY_ATTR(battery_charging_enabled), POWER_SUPPLY_ATTR(charging_enabled), + POWER_SUPPLY_ATTR(step_charging_enabled), + POWER_SUPPLY_ATTR(step_charging_step), POWER_SUPPLY_ATTR(pin_enabled), POWER_SUPPLY_ATTR(input_suspend), POWER_SUPPLY_ATTR(input_voltage_regulation), diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 2f439b11089f..0be535194b49 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -324,6 +324,7 @@ static enum power_supply_property smb2_usb_props[] = { POWER_SUPPLY_PROP_PD_ALLOWED, POWER_SUPPLY_PROP_PD_ACTIVE, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, + POWER_SUPPLY_PROP_INPUT_CURRENT_NOW, }; static int smb2_usb_get_prop(struct power_supply *psy, @@ -383,6 +384,9 @@ static int smb2_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED: rc = smblib_get_prop_input_current_settled(chg, val); break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW: + rc = smblib_get_prop_usb_current_now(chg, val); + break; default: pr_err("get prop %d is not supported\n", psp); rc = -EINVAL; @@ -582,42 +586,51 @@ static enum power_supply_property smb2_batt_props[] = { POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL, + POWER_SUPPLY_PROP_CHARGER_TEMP, + POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, }; static int smb2_batt_get_prop(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { + int rc; struct smb_charger *chg = power_supply_get_drvdata(psy); switch (psp) { case POWER_SUPPLY_PROP_STATUS: - smblib_get_prop_batt_status(chg, val); + rc = smblib_get_prop_batt_status(chg, val); break; case POWER_SUPPLY_PROP_HEALTH: - smblib_get_prop_batt_health(chg, val); + rc = smblib_get_prop_batt_health(chg, val); break; case POWER_SUPPLY_PROP_PRESENT: - smblib_get_prop_batt_present(chg, val); + rc = smblib_get_prop_batt_present(chg, val); break; case POWER_SUPPLY_PROP_INPUT_SUSPEND: - smblib_get_prop_input_suspend(chg, val); + rc = smblib_get_prop_input_suspend(chg, val); break; case POWER_SUPPLY_PROP_CHARGE_TYPE: - smblib_get_prop_batt_charge_type(chg, val); + rc = smblib_get_prop_batt_charge_type(chg, val); break; case POWER_SUPPLY_PROP_CAPACITY: - smblib_get_prop_batt_capacity(chg, val); + rc = smblib_get_prop_batt_capacity(chg, val); break; case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: - smblib_get_prop_system_temp_level(chg, val); + rc = smblib_get_prop_system_temp_level(chg, val); + break; + case POWER_SUPPLY_PROP_CHARGER_TEMP: + rc = smblib_get_prop_charger_temp(chg, val); + break; + case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: + rc = smblib_get_prop_charger_temp_max(chg, val); break; default: pr_err("batt power supply prop %d not supported\n", psp); return -EINVAL; } - return 0; + return rc; } static int smb2_batt_set_prop(struct power_supply *psy, @@ -1219,7 +1232,11 @@ static int smb2_probe(struct platform_device *pdev) return -EINVAL; } - smblib_init(chg); + rc = smblib_init(chg); + if (rc < 0) { + pr_err("Smblib_init failed rc=%d\n", rc); + goto cleanup; + } rc = smb2_parse_dt(chip); if (rc < 0) { diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 15f07ee7d36c..ee4f65430d8b 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -12,6 +12,7 @@ #include <linux/device.h> #include <linux/regmap.h> +#include <linux/iio/consumer.h> #include <linux/power_supply.h> #include <linux/regulator/driver.h> #include <linux/irq.h> @@ -1172,12 +1173,20 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, union power_supply_propval *val) { - if (chg->vbus_present) - val->intval = MICRO_5V; - else - val->intval = 0; + int rc = 0; - return 0; + rc = smblib_get_prop_usb_present(chg, val); + if (rc < 0 || !val->intval) + return rc; + + if (!chg->iio.usbin_v_chan || + PTR_ERR(chg->iio.usbin_v_chan) == -EPROBE_DEFER) + chg->iio.usbin_v_chan = iio_channel_get(chg->dev, "usbin_v"); + + if (IS_ERR(chg->iio.usbin_v_chan)) + return PTR_ERR(chg->iio.usbin_v_chan); + + return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval); } int smblib_get_prop_usb_current_max(struct smb_charger *chg, @@ -1187,6 +1196,59 @@ int smblib_get_prop_usb_current_max(struct smb_charger *chg, return 0; } +int smblib_get_prop_usb_current_now(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc = 0; + + rc = smblib_get_prop_usb_present(chg, val); + if (rc < 0 || !val->intval) + return rc; + + if (!chg->iio.usbin_i_chan || + PTR_ERR(chg->iio.usbin_i_chan) == -EPROBE_DEFER) + chg->iio.usbin_i_chan = iio_channel_get(chg->dev, "usbin_i"); + + if (IS_ERR(chg->iio.usbin_i_chan)) + return PTR_ERR(chg->iio.usbin_i_chan); + + return iio_read_channel_processed(chg->iio.usbin_i_chan, &val->intval); +} + +int smblib_get_prop_charger_temp(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc; + + if (!chg->iio.temp_chan || + PTR_ERR(chg->iio.temp_chan) == -EPROBE_DEFER) + chg->iio.temp_chan = iio_channel_get(chg->dev, "charger_temp"); + + if (IS_ERR(chg->iio.temp_chan)) + return PTR_ERR(chg->iio.temp_chan); + + rc = iio_read_channel_processed(chg->iio.temp_chan, &val->intval); + val->intval /= 100; + return rc; +} + +int smblib_get_prop_charger_temp_max(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc; + + if (!chg->iio.temp_max_chan || + PTR_ERR(chg->iio.temp_max_chan) == -EPROBE_DEFER) + chg->iio.temp_max_chan = iio_channel_get(chg->dev, + "charger_temp_max"); + if (IS_ERR(chg->iio.temp_max_chan)) + return PTR_ERR(chg->iio.temp_max_chan); + + rc = iio_read_channel_processed(chg->iio.temp_max_chan, &val->intval); + val->intval /= 100; + return rc; +} + int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg, union power_supply_propval *val) { @@ -1992,7 +2054,7 @@ done: vote(chg->awake_votable, PL_VOTER, false, 0); } -int smblib_create_votables(struct smb_charger *chg) +static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -2086,6 +2148,42 @@ int smblib_create_votables(struct smb_charger *chg) return rc; } +static void smblib_destroy_votables(struct smb_charger *chg) +{ + if (chg->usb_suspend_votable) + destroy_votable(chg->usb_suspend_votable); + if (chg->dc_suspend_votable) + destroy_votable(chg->dc_suspend_votable); + if (chg->fcc_max_votable) + destroy_votable(chg->fcc_max_votable); + if (chg->fcc_votable) + destroy_votable(chg->fcc_votable); + if (chg->fv_votable) + destroy_votable(chg->fv_votable); + if (chg->usb_icl_votable) + destroy_votable(chg->usb_icl_votable); + if (chg->dc_icl_votable) + destroy_votable(chg->dc_icl_votable); + if (chg->pd_allowed_votable) + destroy_votable(chg->pd_allowed_votable); + if (chg->awake_votable) + destroy_votable(chg->awake_votable); + if (chg->pl_disable_votable) + destroy_votable(chg->pl_disable_votable); +} + +static void smblib_iio_deinit(struct smb_charger *chg) +{ + if (!IS_ERR_OR_NULL(chg->iio.temp_chan)) + iio_channel_release(chg->iio.temp_chan); + if (!IS_ERR_OR_NULL(chg->iio.temp_max_chan)) + iio_channel_release(chg->iio.temp_max_chan); + if (!IS_ERR_OR_NULL(chg->iio.usbin_i_chan)) + iio_channel_release(chg->iio.usbin_i_chan); + if (!IS_ERR_OR_NULL(chg->iio.usbin_v_chan)) + iio_channel_release(chg->iio.usbin_v_chan); +} + int smblib_init(struct smb_charger *chg) { int rc = 0; @@ -2130,18 +2228,19 @@ int smblib_init(struct smb_charger *chg) int smblib_deinit(struct smb_charger *chg) { - destroy_votable(chg->usb_suspend_votable); - destroy_votable(chg->dc_suspend_votable); - destroy_votable(chg->fcc_max_votable); - destroy_votable(chg->fcc_votable); - destroy_votable(chg->fv_votable); - destroy_votable(chg->usb_icl_votable); - destroy_votable(chg->dc_icl_votable); - destroy_votable(chg->pd_allowed_votable); - destroy_votable(chg->awake_votable); - destroy_votable(chg->pl_disable_votable); - - power_supply_unreg_notifier(&chg->nb); + switch (chg->mode) { + case PARALLEL_MASTER: + power_supply_unreg_notifier(&chg->nb); + smblib_destroy_votables(chg); + break; + case PARALLEL_SLAVE: + break; + default: + dev_err(chg->dev, "Unsupported mode %d\n", chg->mode); + return -EINVAL; + } + + smblib_iio_deinit(chg); return 0; } diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 974dbc7f85dd..1b0c221b4764 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -88,10 +88,18 @@ struct parallel_params { int slave_fcc; }; +struct smb_iio { + struct iio_channel *temp_chan; + struct iio_channel *temp_max_chan; + struct iio_channel *usbin_i_chan; + struct iio_channel *usbin_v_chan; +}; + struct smb_charger { struct device *dev; struct regmap *regmap; struct smb_params param; + struct smb_iio iio; int *debug_mask; enum smb_mode mode; @@ -236,6 +244,8 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_current_max(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_usb_current_now(struct smb_charger *chg, + union power_supply_propval *val); int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_typec_mode(struct smb_charger *chg, @@ -246,6 +256,10 @@ int smblib_get_prop_pd_allowed(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_input_current_settled(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_charger_temp(struct smb_charger *chg, + union power_supply_propval *val); +int smblib_get_prop_charger_temp_max(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_usb_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_usb_voltage_min(struct smb_charger *chg, 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/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/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/composite.c b/drivers/usb/gadget/composite.c index 3d17fd93c787..a99405261306 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -27,6 +27,14 @@ #define SSUSB_GADGET_VBUS_DRAW_UNITS 8 #define HSUSB_GADGET_VBUS_DRAW_UNITS 2 +/* + * Based on enumerated USB speed, draw power with set_config and resume + * HSUSB: 500mA, SSUSB: 900mA + */ +#define USB_VBUS_DRAW(speed)\ + (speed == USB_SPEED_SUPER ?\ + SSUSB_GADGET_VBUS_DRAW : CONFIG_USB_GADGET_VBUS_DRAW) + static bool enable_l1_for_hs; module_param(enable_l1_for_hs, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(enable_l1_for_hs, "Enable support for L1 LPM for HS devices"); @@ -749,7 +757,6 @@ static int set_config(struct usb_composite_dev *cdev, struct usb_gadget *gadget = cdev->gadget; struct usb_configuration *c = NULL; int result = -EINVAL; - unsigned power = gadget_is_otg(gadget) ? 8 : 100; int tmp; /* @@ -863,14 +870,8 @@ static int set_config(struct usb_composite_dev *cdev, } } - /* Allow 900mA to draw with Super-Speed */ - if (gadget->speed == USB_SPEED_SUPER) - power = SSUSB_GADGET_VBUS_DRAW; - else - power = CONFIG_USB_GADGET_VBUS_DRAW; - done: - usb_gadget_vbus_draw(gadget, power); + usb_gadget_vbus_draw(gadget, USB_VBUS_DRAW(gadget->speed)); if (result >= 0 && cdev->delayed_status) result = USB_GADGET_DELAYED_STATUS; return result; @@ -2319,7 +2320,6 @@ void composite_resume(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - u16 maxpower; int ret; unsigned long flags; @@ -2352,10 +2352,7 @@ void composite_resume(struct usb_gadget *gadget) f->resume(f); } - maxpower = cdev->config->MaxPower; - - usb_gadget_vbus_draw(gadget, maxpower ? - maxpower : CONFIG_USB_GADGET_VBUS_DRAW); + usb_gadget_vbus_draw(gadget, USB_VBUS_DRAW(gadget->speed)); } spin_unlock_irqrestore(&cdev->lock, flags); 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/fs/ext4/crypto.c b/fs/ext4/crypto.c index 1a0835073663..1acac7fd21b2 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -469,3 +469,59 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size) return size; return 0; } + +/* + * Validate dentries for encrypted directories to make sure we aren't + * potentially caching stale data after a key has been added or + * removed. + */ +static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + struct inode *dir = d_inode(dentry->d_parent); + struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info; + int dir_has_key, cached_with_key; + + if (!ext4_encrypted_inode(dir)) + return 0; + + if (ci && ci->ci_keyring_key && + (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED) | + (1 << KEY_FLAG_DEAD)))) + ci = NULL; + + /* this should eventually be an flag in d_flags */ + cached_with_key = dentry->d_fsdata != NULL; + dir_has_key = (ci != NULL); + + /* + * If the dentry was cached without the key, and it is a + * negative dentry, it might be a valid name. We can't check + * if the key has since been made available due to locking + * reasons, so we fail the validation so ext4_lookup() can do + * this check. + * + * We also fail the validation if the dentry was created with + * the key present, but we no longer have the key, or vice versa. + */ + if ((!cached_with_key && d_is_negative(dentry)) || + (!cached_with_key && dir_has_key) || + (cached_with_key && !dir_has_key)) { +#if 0 /* Revalidation debug */ + char buf[80]; + char *cp = simple_dname(dentry, buf, sizeof(buf)); + + if (IS_ERR(cp)) + cp = (char *) "???"; + pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata, + cached_with_key, d_is_negative(dentry), + dir_has_key); +#endif + return 0; + } + return 1; +} + +const struct dentry_operations ext4_encrypted_d_ops = { + .d_revalidate = ext4_d_revalidate, +}; diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 1d1bca74f844..33f5e2a50cf8 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) int dir_has_error = 0; struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; + if (ext4_encrypted_inode(inode)) { + err = ext4_get_encryption_info(inode); + if (err && err != -ENOKEY) + return err; + } + if (is_dx_dir(inode)) { err = ext4_dx_readdir(file, ctx); if (err != ERR_BAD_DX_DIR) { @@ -157,8 +163,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) index, 1); file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; bh = ext4_bread(NULL, inode, map.m_lblk, 0); - if (IS_ERR(bh)) - return PTR_ERR(bh); + if (IS_ERR(bh)) { + err = PTR_ERR(bh); + bh = NULL; + goto errout; + } } if (!bh) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 614b79c4576e..c1b4f6ab2148 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2258,6 +2258,7 @@ struct page *ext4_encrypt(struct inode *inode, struct page *plaintext_page); int ext4_decrypt(struct page *page); int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex); +extern const struct dentry_operations ext4_encrypted_d_ops; #ifdef CONFIG_EXT4_FS_ENCRYPTION int ext4_init_crypto(void); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 06c3afcbfac8..c9aad3b8951f 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1558,6 +1558,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi struct ext4_dir_entry_2 *de; struct buffer_head *bh; + if (ext4_encrypted_inode(dir)) { + int res = ext4_get_encryption_info(dir); + + /* + * This should be a properly defined flag for + * dentry->d_flags when we uplift this to the VFS. + * d_fsdata is set to (void *) 1 if if the dentry is + * created while the directory was encrypted and we + * don't have access to the key. + */ + dentry->d_fsdata = NULL; + if (ext4_encryption_info(dir)) + dentry->d_fsdata = (void *) 1; + d_set_d_op(dentry, &ext4_encrypted_d_ops); + if (res && res != -ENOKEY) + return ERR_PTR(res); + } + if (dentry->d_name.len > EXT4_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 6b6b3e751f8c..06fd5f7f993d 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -232,6 +232,27 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) return error; } +static int +__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, + void *end, const char *function, unsigned int line) +{ + struct ext4_xattr_entry *entry = IFIRST(header); + int error = -EFSCORRUPTED; + + if (((void *) header >= end) || + (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC))) + goto errout; + error = ext4_xattr_check_names(entry, end, entry); +errout: + if (error) + __ext4_error_inode(inode, function, line, 0, + "corrupted in-inode xattr"); + return error; +} + +#define xattr_check_inode(inode, header, end) \ + __xattr_check_inode((inode), (header), (end), __func__, __LINE__) + static inline int ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) { @@ -343,7 +364,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, header = IHDR(inode, raw_inode); entry = IFIRST(header); end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; - error = ext4_xattr_check_names(entry, end, entry); + error = xattr_check_inode(inode, header, end); if (error) goto cleanup; error = ext4_xattr_find_entry(&entry, name_index, name, @@ -474,7 +495,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) raw_inode = ext4_raw_inode(&iloc); header = IHDR(inode, raw_inode); end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; - error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); + error = xattr_check_inode(inode, header, end); if (error) goto cleanup; error = ext4_xattr_list_entries(dentry, IFIRST(header), @@ -990,8 +1011,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, is->s.here = is->s.first; is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { - error = ext4_xattr_check_names(IFIRST(header), is->s.end, - IFIRST(header)); + error = xattr_check_inode(inode, header, is->s.end); if (error) return error; /* Find the named attribute. */ @@ -1288,6 +1308,10 @@ retry: last = entry; total_ino = sizeof(struct ext4_xattr_ibody_header); + error = xattr_check_inode(inode, header, end); + if (error) + goto cleanup; + free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); if (free >= new_extra_isize) { entry = IFIRST(header); diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h index 3825f9d1e68c..ad95957d9189 100644 --- a/include/linux/input/ft5x06_ts.h +++ b/include/linux/input/ft5x06_ts.h @@ -69,6 +69,7 @@ struct ft5x06_ts_platform_data { bool i2c_pull_up; bool ignore_id_check; bool gesture_support; + bool resume_in_workqueue; int (*power_init)(bool); int (*power_on)(bool); }; 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/power_supply.h b/include/linux/power_supply.h index 56e78254286e..03853d956b41 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -176,6 +176,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_USB_OTG, POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED, POWER_SUPPLY_PROP_CHARGING_ENABLED, + POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, + POWER_SUPPLY_PROP_STEP_CHARGING_STEP, POWER_SUPPLY_PROP_PIN_ENABLED, POWER_SUPPLY_PROP_INPUT_SUSPEND, POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION, 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/pcm.h b/include/sound/pcm.h index e1f4920053ed..2b6e8f8240d9 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -141,7 +141,8 @@ struct snd_pcm_ops { #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ -#define SNDRV_PCM_RATE_384000 (1<<13) /* 384000Hz */ +#define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */ +#define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */ #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ @@ -154,6 +155,9 @@ struct snd_pcm_ops { SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ SNDRV_PCM_RATE_192000) +#define SNDRV_PCM_RATE_8000_384000 (SNDRV_PCM_RATE_8000_192000|\ + SNDRV_PCM_RATE_352800|\ + SNDRV_PCM_RATE_384000) #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) 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/include/trace/events/skb.h b/include/trace/events/skb.h index 95ca6e841212..b2e3c3b91f72 100644 --- a/include/trace/events/skb.h +++ b/include/trace/events/skb.h @@ -52,24 +52,29 @@ TRACE_EVENT(consume_skb, TRACE_EVENT(print_skb_gso, - TP_PROTO(struct sk_buff *skb), + TP_PROTO(struct sk_buff *skb, __be16 src, __be16 dest), - TP_ARGS(skb), + TP_ARGS(skb, src, dest), TP_STRUCT__entry( __field(void *, skbaddr) __field(int , len) __field(int , data_len) + __field(__be16, src) + __field(__be16, dest) ), TP_fast_assign( __entry->skbaddr = skb; __entry->len = skb->len; __entry->data_len = skb->data_len; + __entry->src = src; + __entry->dest = dest; ), - TP_printk("GSO: skbaddr=%p, len=%d, data_len=%d", - __entry->skbaddr, __entry->len, __entry->data_len) + TP_printk("GSO: skbaddr=%pK, len=%d, data_len=%d, src=%u, dest=%u", + __entry->skbaddr, __entry->len, __entry->data_len, + be16_to_cpu(__entry->src), be16_to_cpu(__entry->dest)) ); TRACE_EVENT(skb_copy_datagram_iovec, diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index 82e0bdd9209d..cdb85170919a 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -18,6 +18,9 @@ #define ISP_META_CHANNEL_BIT (0x10000 << 3) #define ISP_SCRATCH_BUF_BIT (0x10000 << 4) #define ISP_OFFLINE_STATS_BIT (0x10000 << 5) +#define ISP_SVHDR_IN_BIT (0x10000 << 6) /* RDI hw stream for SVHDR */ +#define ISP_SVHDR_OUT_BIT (0x10000 << 7) /* SVHDR output bufq stream*/ + #define ISP_STATS_STREAM_BIT 0x80000000 struct msm_vfe_cfg_cmd_list; 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/core/dev.c b/net/core/dev.c index ffd178b5f381..a299c3956daa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -137,6 +137,8 @@ #include <linux/errqueue.h> #include <linux/hrtimer.h> #include <linux/netfilter_ingress.h> +#include <linux/tcp.h> +#include <net/tcp.h> #include "net-sysfs.h" @@ -2773,7 +2775,10 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device if (netif_needs_gso(skb, features)) { struct sk_buff *segs; - trace_print_skb_gso(skb); + __be16 src_port = tcp_hdr(skb)->source; + __be16 dest_port = tcp_hdr(skb)->dest; + + trace_print_skb_gso(skb, src_port, dest_port); segs = skb_gso_segment(skb, features); if (IS_ERR(segs)) { goto out_kfree_skb; 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/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 0171810803a9..b97b73dc4191 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -90,6 +90,7 @@ struct wsa881x_priv { bool comp_enable; bool boost_enable; bool visense_enable; + u8 pa_gain; struct swr_port port[WSA881X_MAX_SWR_PORTS]; int pd_gpio; struct wsa881x_tz_priv tz_pdata; @@ -134,6 +135,47 @@ static unsigned int devnum; static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec, bool enable); +static const char * const wsa_pa_gain_text[] = { + "G_18_DB", "G_16P5_DB", "G_15_DB", "G_13P5_DB", "G_12_DB", "G_10P5_DB", + "G_9_DB", "G_7P5_DB", "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", + "G_0_DB" +}; + +static const struct soc_enum wsa_pa_gain_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_pa_gain_text), wsa_pa_gain_text); + +static int wsa_pa_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = wsa881x->pa_gain; + + dev_dbg(codec->dev, "%s: PA gain = 0x%x\n", __func__, wsa881x->pa_gain); + + return 0; +} + +static int wsa_pa_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + wsa881x->pa_gain = ucontrol->value.integer.value[0]; + + return 0; +} + +static const struct snd_kcontrol_new wsa_analog_gain_controls[] = { + SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum, + wsa_pa_gain_get, wsa_pa_gain_put), +}; + static int codec_debug_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -775,6 +817,7 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec); + int min_gain, max_gain; dev_dbg(codec->dev, "%s: %s %d\n", __func__, w->name, event); switch (event) { @@ -786,15 +829,32 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, swr_slvdev_datapath_control(wsa881x->swr_slave, wsa881x->swr_slave->dev_num, true); + /* Set register mode if compander is not enabled */ + if (!wsa881x->comp_enable) + snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, + 0x08, 0x08); + else + snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, + 0x08, 0x00); + break; case SND_SOC_DAPM_POST_PMU: if (!wsa881x->comp_enable) { + max_gain = wsa881x->pa_gain; + /* + * Gain has to set incrementally in 4 steps + * as per HW sequence + */ + if (max_gain > G_4P5DB) + min_gain = G_0DB; + else + min_gain = max_gain + 3; /* * 1ms delay is needed before change in gain * as per HW requirement. */ usleep_range(1000, 1010); - wsa881x_ramp_pa_gain(codec, G_13P5DB, G_18DB, 1000); + wsa881x_ramp_pa_gain(codec, min_gain, max_gain, 1000); } if (wsa881x->visense_enable) { wsa881x_visense_txfe_ctrl(codec, ENABLE, @@ -987,6 +1047,8 @@ static int wsa881x_probe(struct snd_soc_codec *codec) wsa881x->tz_pdata.codec = codec; wsa881x->tz_pdata.wsa_temp_reg_read = wsa881x_temp_reg_read; wsa881x_init_thermal(&wsa881x->tz_pdata); + snd_soc_add_codec_controls(codec, wsa_analog_gain_controls, + ARRAY_SIZE(wsa_analog_gain_controls)); INIT_DELAYED_WORK(&wsa881x->ocp_ctl_work, wsa881x_ocp_ctl_work); return 0; } 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/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 85fa45ff400f..4cb62a6b3e7d 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -25,7 +25,7 @@ static struct snd_soc_dai_ops msm_fe_dai_ops = {}; /* Conventional and unconventional sample rate supported */ static unsigned int supported_sample_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 88200, 96000, 176400, 192000 + 88200, 96000, 176400, 192000, 352800, 384000 }; static struct snd_pcm_hw_constraint_list constraints_sample_rates = { @@ -92,7 +92,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia1 Playback", .aif_name = "MM_DL1", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -100,12 +100,12 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia1 Capture", .aif_name = "MM_UL1", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE| @@ -123,7 +123,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia2 Playback", .aif_name = "MM_DL2", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -131,12 +131,12 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia2 Capture", .aif_name = "MM_UL2", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -206,7 +206,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia3 Playback", .aif_name = "MM_DL3", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -214,12 +214,12 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 6, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia3 Capture", .aif_name = "MM_UL3", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), @@ -236,7 +236,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia4 Playback", .aif_name = "MM_DL4", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -244,7 +244,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -255,7 +255,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia5 Playback", .aif_name = "MM_DL5", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -263,7 +263,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia5 Capture", @@ -286,7 +286,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia6 Playback", .aif_name = "MM_DL6", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -294,7 +294,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia6 Capture", @@ -317,7 +317,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia7 Playback", .aif_name = "MM_DL7", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -325,7 +325,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -336,7 +336,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia8 Playback", .aif_name = "MM_DL8", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -344,7 +344,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia8 Capture", @@ -368,13 +368,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS0_HOSTLESS Playback", .aif_name = "SLIM0_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "SLIMBUS0_HOSTLESS Capture", @@ -386,7 +386,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "SLIMBUS0_HOSTLESS", @@ -396,13 +396,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS1_HOSTLESS Playback", .aif_name = "SLIM1_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "SLIMBUS1_HOSTLESS Capture", @@ -423,13 +423,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS3_HOSTLESS Playback", .aif_name = "SLIM3_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "SLIMBUS3_HOSTLESS Capture", @@ -450,13 +450,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS4_HOSTLESS Playback", .aif_name = "SLIM4_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "SLIMBUS4_HOSTLESS Capture", @@ -477,13 +477,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS6_HOSTLESS Playback", .aif_name = "SLIM6_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "SLIMBUS6_HOSTLESS", @@ -493,24 +493,24 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "SLIMBUS8_HOSTLESS Playback", .aif_name = "SLIM8_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "SLIMBUS8_HOSTLESS Capture", .aif_name = "SLIM8_UL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "SLIMBUS8_HOSTLESS", @@ -747,13 +747,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "Primary MI2S_RX Hostless Playback", .aif_name = "PRI_MI2S_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "PRI_MI2S_RX_HOSTLESS", @@ -779,13 +779,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "Secondary MI2S_RX Hostless Playback", .aif_name = "SEC_MI2S_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "SEC_MI2S_RX_HOSTLESS", @@ -811,13 +811,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "Tertiary MI2S_RX Hostless Playback", .aif_name = "TERT_MI2S_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "TERT_MI2S_RX_HOSTLESS", @@ -843,13 +843,13 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "Quaternary MI2S_RX Hostless Playback", .aif_name = "QUAT_MI2S_DL_HL", - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_8000_384000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_dai_ops, .name = "QUAT_MI2S_RX_HOSTLESS", @@ -2016,7 +2016,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia9 Playback", .aif_name = "MM_DL9", - .rates = (SNDRV_PCM_RATE_8000_192000| + .rates = (SNDRV_PCM_RATE_8000_384000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2024,7 +2024,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "MultiMedia9 Capture", @@ -2216,7 +2216,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia10 Playback", .aif_name = "MM_DL10", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2224,7 +2224,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2235,7 +2235,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia11 Playback", .aif_name = "MM_DL11", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2243,7 +2243,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2254,7 +2254,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia12 Playback", .aif_name = "MM_DL12", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2262,7 +2262,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2273,7 +2273,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia13 Playback", .aif_name = "MM_DL13", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2281,7 +2281,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2292,7 +2292,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia14 Playback", .aif_name = "MM_DL14", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2300,7 +2300,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2311,7 +2311,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia15 Playback", .aif_name = "MM_DL15", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2319,7 +2319,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, @@ -2330,7 +2330,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .playback = { .stream_name = "MultiMedia16 Playback", .aif_name = "MM_DL16", - .rates = (SNDRV_PCM_RATE_8000_192000 | + .rates = (SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -2338,7 +2338,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, .compress_new = snd_soc_new_compress, 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-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 51ebd039d96b..a898532643ae 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -37,6 +37,10 @@ #define CHANNEL_STATUS_MASK 0x4 #define AFE_API_VERSION_CLOCK_SET 1 +#define DAI_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + enum { ENC_FMT_NONE, ENC_FMT_SBC = ASM_MEDIA_FMT_SBC, @@ -2808,15 +2812,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus Playback", .aif_name = "SLIMBUS_0_RX", - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_0_RX, @@ -2827,15 +2828,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus1 Playback", .aif_name = "SLIMBUS_1_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_1_RX, @@ -2846,15 +2844,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus2 Playback", .aif_name = "SLIMBUS_2_RX", - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_2_RX, @@ -2865,15 +2860,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus3 Playback", .aif_name = "SLIMBUS_3_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_3_RX, @@ -2884,15 +2876,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus4 Playback", .aif_name = "SLIMBUS_4_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_4_RX, @@ -2903,15 +2892,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus6 Playback", .aif_name = "SLIMBUS_6_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_6_RX, @@ -2922,15 +2908,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus5 Playback", .aif_name = "SLIMBUS_5_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 2, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_5_RX, @@ -2941,15 +2924,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus7 Playback", .aif_name = "SLIMBUS_7_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_7_RX, @@ -2960,15 +2940,12 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = { .playback = { .stream_name = "Slimbus8 Playback", .aif_name = "SLIMBUS_8_RX", - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + .rates = SNDRV_PCM_RATE_8000_384000, + .formats = DAI_FORMATS_S16_S24_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .ops = &msm_dai_q6_ops, .id = SLIMBUS_8_RX, 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; |
